SYCL buffers have the fun effect where when they are destroyed they may write back into the host memory from which they were formed. This is specified in 3.9.8.1 of the sycl 2020 standard:
Buffer destruction: The destructors for sycl::buffer, sycl::unsampled_image and sycl::sampled_image objects wait for all submitted work on those objects to complete and to copy the data back to host memory before returning. These destructors only wait if the object was constructed with attached host memory and if data needs to be copied back to the host.
sycl::buffer, has many constructors:
buffer(const sycl::range<dimensions> &bufferRange,
const sycl::property_list &propList = {});
...
buffer(T *hostData, const sycl::range<dimensions> &bufferRange,
AllocatorT allocator, const sycl::property_list &propList = {});
buffer(const T *hostData, const sycl::range<dimensions> &bufferRange,
const sycl::property_list &propList = {});
buffer(const T *hostData, const sycl::range<dimensions> &bufferRange,
AllocatorT allocator, const sycl::property_list &propList = {});
buffer(const shared_ptr_class<T> &hostData,
const sycl::range<dimensions> &bufferRange, AllocatorT allocator,
const sycl::property_list &propList = {});
...
template <class InputIterator>
buffer<T, 1>(InputIterator first, InputIterator last, AllocatorT allocator,
const sycl::property_list &propList = {});
template <class InputIterator>
buffer<T, 1>(InputIterator first, InputIterator last,
const sycl::property_list &propList = {});
buffer(cl_mem clMemObject, const sycl::context &syclContext,
event availableEvent = {});
But it does not specify directly, which ones do the copy on destruction method. For example, the iterator constructor, could be used with a range:
std::vector<int> some_nums;
// .. Fill the vector
auto values = some_nums | ranges::filter([](int v) { return v % 2};
sycl::buffer<int, 1> buf{std::begin(values), std::end(values)};
This could be used to fill the buffer with all odd values. But if on buffer destruction the sycl subsystem attempts to write back to the range, this would be disastrous.
How do we know which constructors cause this write to host on destruction?