-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve default allocator wording #649
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4918,8 +4918,10 @@ STL-based libraries (e.g, Intel's TBB provides an allocator). | |
==== Default allocators | ||
|
||
A default allocator is always defined by the implementation. | ||
For allocations greater than size zero, when successful it is guaranteed to | ||
return non-[code]#nullptr# and new memory positions every call. | ||
For successful allocations of size greater than zero, the default allocator must | ||
return a pointer to a contiguous, exclusive region of memory of at least the | ||
requested size. | ||
For unsuccessful allocations, the default allocator must return [code]#nullptr#. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this is not the way allocators normally handle out-of-memory. A C++ allocator normally throws an exception in this case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that named requirement: Allocator implies that the only alternative an allocator has to providing the requested memory is throwing. A few lines earlier in the SYCL spec (L 4892), it says:
So I guess either the SYCL spec expect more C-like behavior (in which case default allocators are not actually There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The SYCL spec should not invent some new way for C++ allocators to work. I think the previous statement about returning |
||
The default allocator for const buffers will remove the const-ness of the type | ||
(therefore, the default allocator for a buffer of type [code]#const int# will be | ||
an [code]#Allocator<int>)#. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we instead removing this wording? The table below already says that the default allocator meets the C++ requirement for Allocator, and C++ defines the behavior of Allocator quite precisely.
If you ask me, the most confusing part of this section is this statement:
It would be good to figure out what we meant here and clarify this. Or, maybe it should be deleted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My best guess is that it's talking about the
buffer
constructor overloads that accept both a host pointer and an allocator:The
buffer
ownshostData
during its lifetime, so I guess it might be safe sometimes forallocator
to returnhostData
(or other pointers within the range). But I don't know why that's useful, and I don't know how the user can avoid race conditions. Maybeuse_mutex
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's my best guess too. However, this seems to assume that
buffer
will only callallocator
in order to create a host buffer that containshostData
, and it won't callallocator
for any other purpose. This is not specified anywhere, and it's contrary to the way the standard C++ library functions use allocators. When a class from the standard C++ library takes an allocator, I think it uses the allocator to allocate all the dynamic memory that it needs.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd also prefer to just remove the sentence and not replace it with anything.
I interpreted that as saying that a user could use an allocator for the user's own purposes (whatever those may be) and that same allocator could be passed to a buffer constructor. I.e., the act of giving an allocator to a buffer doesn't disallow the user from using the same allocator. Given that the SYCL runtime might choose to allocate memory using the allocator asynchronously, the user must put some locking mechanism into the allocator to avoid races.
Which seems reasonable to me, but I don't know if that's what was intended.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not how I interpret that sentence, but I think we all agree that the sentence is confusing. Personally, I'd be happy to delete it.
The issue about thread safety is interesting. Is it legal for the implementation to call the user's allocator simultaneously from different threads even if the application has only one thread? (Or only one thread calling SYCL APIs?) For example, could an implementation have a background thread that potentially calls the allocator at the same time as the application's main thread?
If we think this is a valid implementation, the specification should make it clear that the allocator must be written to be thread safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I skimmed the C++ spec, and I couldn't find anything on allocator thread safety one way or another. I could well have missed something, though.
I'm not convinced
std::allocator
is intended to be thread-safe. It's specified as stateless, and I'd hazard a guess that any mutex or such inside the allocator could qualify as state. Also,std::allocator
s get rebound inside the standard library (and elsewhere), which implies constructing different allocator objects. A mutex data member wouldn't provide thread-safety. Ifstd::allocator
does have a thread-safety guarantee, I'd expect it to be provided by whatever plumbingstd::allocator
relies on, which could be implementation-defined.For SYCL, I think there are two ways of looking at it:
Both of these seem entirely reasonable to me, but only one is consistent with C++. Problem is, we don't know which one it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't say "thread-safe", but allocator.members says:
I agree that both of these are reasonable interpretations. I have a preference for 2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
std::allocator
is guaranteed thread-safe (at least as far as acquiring/releasing memory) because it is specified to call::operator new
which in turn is specified to callmalloc
oraligned_malloc
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. With option 1, a SYCL runtime needs to conservatively assume that any user-supplied allocator could race with any other, which hurts performance. Also, more similar to C++.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, option 2 seems reasonable too.