#include<sycl/sycl.hpp>
#include<vector>
int main() {
int N = 5;
std::vector<int> ints(N);
std::vector<int> checkVec{0, 1, 2, 3, 4};
sycl::queue q;
{ // create a code block so the buffer goes out of scope
// and the destructor is called automatically
// Create buffer pointing to ints.
sycl::buffer<int, 1> buf{ints.data(), sycl::range<1>{ints.size()}};
// Do some computation on device. Use accessors to access buffer
q.submit([&](sycl::handler& cgh) {
sycl::accessor wAcc{buf, cgh, sycl::write_only, sycl::no_init};
// Initialize the contents of the vector
cgh.parallel_for(N, [=](sycl::id<1> idx){
wAcc[idx] = idx;
});
});
} // ints updated here
assert(ints == checkVec);
}
* Constructing a `buffer` and `accessor` involves several template arguments and properties
* CTAD can infer many of these from the data and buffer
* Each argument controls how data is managed and accessed
* A buffer is associated with a type, range and dimensionality. Dimensionality must be
either 1, 2 or 3
* Usually type and dimensionality can be inferred using CTAD.
* If a buffer is associated with some allocation in host memory, the host memory will be
updated only once the buffer goes out of scope
* There are many different ways to use the `accessor`
class
* Accessing data on a device
* Accessing data immediately in the host application
* Allocating local memory
* For now we are going to focus on accessing data on a
device
* There are many ways to construct an `accessor`
* Accessors are complicated templates with many template arguments,
representing the data type, dimensionality, access mode etc
* The `accessor` class supports CTAD so it's not
necessary to specify all of the template arguments
* The most common way to construct an `accessor` is from
a `buffer` and a `handler` associated with the command
group function you are within
* The element type and dimensionality are inferred from
the `buffer`
* When constructing an `accessor` you will likely also
want to specify the `access_mode`
* You can do this by passing one of the CTAD tags:
* `read_only` will result in `access_mode::read`.
* `write_only` will result in `access_mode::write`
* The `access_mode` is defaulted to
`access_mode::read_write`
* When constructing an `accessor` you may also want to
discard the original data of a `buffer`
* You can do this by passing the `no_init` property
* As well as specifying data dependencies an `accessor`
can also be used to access the data from within a kernel
function
* You can do this by calling `operator[]` on the
`accessor`
* `operator[]` for accessors can take a
multi-dimensional `sycl::id` or a `size_t`