-
Notifications
You must be signed in to change notification settings - Fork 776
[SYCL] Implement buffer constructor with iterators in accordance with spec #66
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
Changes from all commits
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 |
---|---|---|
|
@@ -99,23 +99,52 @@ template <typename AllocatorT> class buffer_impl { | |
} | ||
} | ||
|
||
template <typename Iterator> struct is_const_iterator { | ||
using pointer = typename std::iterator_traits<Iterator>::pointer; | ||
static constexpr bool value = | ||
std::is_const<typename std::remove_pointer<pointer>::type>::value; | ||
}; | ||
|
||
template <typename Iterator> | ||
using EnableIfConstIterator = | ||
typename std::enable_if<is_const_iterator<Iterator>::value, | ||
Iterator>::type; | ||
|
||
template <typename Iterator> | ||
using EnableIfNotConstIterator = | ||
typename std::enable_if<!is_const_iterator<Iterator>::value, | ||
Iterator>::type; | ||
|
||
template <class InputIterator> | ||
buffer_impl(InputIterator first, InputIterator last, const size_t sizeInBytes, | ||
const property_list &propList, | ||
buffer_impl(EnableIfNotConstIterator<InputIterator> first, InputIterator last, | ||
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.
What about something like
so you clearly separate the SFINAE mechanics from the argument declaration? 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. Hm, it will not work because I will get two function templates that differ only in their default template arguments. (c'tors with EnableIfNotConstIterator and EnableIfConstIterator). You can see note from here: https://en.cppreference.com/w/cpp/types/enable_if 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. Ah, interesting, you found the exact explanation! Great. |
||
const size_t sizeInBytes, const property_list &propList, | ||
AllocatorT allocator = AllocatorT()) | ||
: SizeInBytes(sizeInBytes), Props(propList), MAllocator(allocator) { | ||
if (Props.has_property<property::buffer::use_host_ptr>()) { | ||
// TODO next line looks unsafe | ||
BufPtr = &*first; | ||
} else { | ||
BufData.resize(get_size()); | ||
BufPtr = reinterpret_cast<void *>(BufData.data()); | ||
// We need cast BufPtr to pointer to the iteration type to get correct | ||
// offset in std::copy when it will increment destination pointer. | ||
auto *Ptr = reinterpret_cast< | ||
typename std::iterator_traits<InputIterator>::pointer>(BufPtr); | ||
std::copy(first, last, Ptr); | ||
} | ||
BufData.resize(get_size()); | ||
BufPtr = reinterpret_cast<void *>(BufData.data()); | ||
// We need cast BufPtr to pointer to the iteration type to get correct | ||
// offset in std::copy when it will increment destination pointer. | ||
Fznamznon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
auto *Ptr = | ||
reinterpret_cast<typename std::iterator_traits<InputIterator>::pointer>( | ||
BufPtr); | ||
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 am lost here. Why the intermediate 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. BufPtr is not only intermediate reinterpret_cast<void *>. It also buffer_impl's field and currently we use it instead of BufData. BufData is needed only for memory allocation... 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. Ah sorry, I missed that. Good point. |
||
std::copy(first, last, Ptr); | ||
// Data is written back if InputIterator is not a const iterator. | ||
set_final_data(first); | ||
} | ||
|
||
template <class InputIterator> | ||
buffer_impl(EnableIfConstIterator<InputIterator> first, InputIterator last, | ||
const size_t sizeInBytes, const property_list &propList, | ||
AllocatorT allocator = AllocatorT()) | ||
: SizeInBytes(sizeInBytes), Props(propList), MAllocator(allocator) { | ||
BufData.resize(get_size()); | ||
BufPtr = reinterpret_cast<void *>(BufData.data()); | ||
// We need cast BufPtr to pointer to the iteration type to get correct | ||
// offset in std::copy when it will increment destination pointer. | ||
typedef typename std::iterator_traits<InputIterator>::value_type value; | ||
auto *Ptr = reinterpret_cast<typename std::add_pointer< | ||
typename std::remove_const<value>::type>::type>(BufPtr); | ||
std::copy(first, last, Ptr); | ||
} | ||
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. All this seems code duplication at first sight. 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. No, It is not possible to have a single version without using of some C++17 if constexpr because I can't add line with "set_final_data(first);" to c'tor with const iterators - compiler fails in instantiation of std::copy inside the set_final_data. I'm not sure that we are ready to C++17 in our codebase so I'm using SFINAE. 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. Yes, unfortunately that makes sense. |
||
|
||
buffer_impl(cl_mem MemObject, const context &SyclContext, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -403,8 +403,29 @@ int main() { | |
range<1>{3}, [=](id<1> index) { B[index] = 20; }); | ||
}); | ||
} | ||
// Data is not copied back in the desctruction of the buffer created from | ||
// pair of iterators | ||
// Data is copied back in the desctruction of the buffer created from | ||
// pair of non-const iterators | ||
for (int i = 0; i < 2; i++) | ||
assert(data1[i] == -1); | ||
for (int i = 2; i < 5; i++) | ||
assert(data1[i] == 20); | ||
for (int i = 5; i < 10; i++) | ||
assert(data1[i] == -1); | ||
} | ||
|
||
// Check that data is not copied back in the desctruction of the buffer | ||
// created from pair of const iterators | ||
{ | ||
std::vector<int> data1(10, -1); | ||
Fznamznon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
buffer<int, 1> b(data1.cbegin() + 2, data1.cbegin() + 5); | ||
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.
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. Hmm, It's really big test and in all buffer constructions 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. Yes you are right. It is cosmetic change. |
||
queue myQueue; | ||
myQueue.submit([&](handler &cgh) { | ||
auto B = b.get_access<access::mode::read_write>(cgh); | ||
cgh.parallel_for<class const_iter_constuctor>( | ||
range<1>{3}, [=](id<1> index) { B[index] = 20; }); | ||
}); | ||
} | ||
for (int i = 0; i < 10; i++) | ||
assert(data1[i] == -1); | ||
} | ||
|
@@ -435,24 +456,23 @@ int main() { | |
// created from pair of iterators | ||
{ | ||
std::vector<int> data1(10, -1); | ||
std::vector<int> data2(10, -1); | ||
{ | ||
buffer<int, 1> b(data1.begin() + 2, data1.begin() + 5); | ||
Fznamznon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
b.set_final_data(data1.begin() + 2); | ||
b.set_final_data(data2.begin() + 2); | ||
queue myQueue; | ||
myQueue.submit([&](handler &cgh) { | ||
auto B = b.get_access<access::mode::read_write>(cgh); | ||
cgh.parallel_for<class iter_constuctor_set_final_data>( | ||
range<1>{3}, [=](id<1> index) { B[index] = 20; }); | ||
}); | ||
} | ||
// Data is not copied back in the desctruction of the buffer created from | ||
// pair of iterators | ||
for (int i = 0; i < 2; i++) | ||
assert(data1[i] == -1); | ||
assert(data2[i] == -1); | ||
for (int i = 2; i < 5; i++) | ||
assert(data1[i] == 20); | ||
assert(data2[i] == 20); | ||
for (int i = 5; i < 10; i++) | ||
assert(data1[i] == -1); | ||
assert(data2[i] == -1); | ||
} | ||
|
||
// Check that data is copied back after forcing write-back using | ||
|
Uh oh!
There was an error while loading. Please reload this page.