我认为有两点导致您目前遇到的问题:
- 缓冲区对象定义中的第二个模板参数应该是缓冲区的维度(维度计数,应该是 1、2 或 3),而不是维度本身。
- 缓冲区的构造函数应该包含缓冲区的实际尺寸,或者您希望缓冲区具有的数据和尺寸。要传递维度,您需要将 cl::sycl::range 对象传递给构造函数
据我了解,您正在尝试初始化一个维度为 1 且维度为 { 100, 1, 1 } 的缓冲区。为此, a 的定义应更改为:
cl::sycl::buffer < float, 1 > a(cl::sycl::range< 1 >(n_threads));
此外,由于可以从范围模板参数中推断出维度,因此您可以通过以下方式实现相同的效果:
cl::sycl::buffer< float > a (cl::sycl::range< 1 >(n_threads));
至于使用 std::iota 初始化缓冲区,您有 3 个选项:
- 使用数组初始化具有iota用法的数据并将它们传递给sycl缓冲区(案例A),
- 使用访问器直接为主机写入缓冲区 - 仅限 CPU(情况 B),或
- 使用带有 parallel_for 的访问器在主机或 OpenCL 设备上执行(案例 C)。
访问器不应用作迭代器(使用 .begin()、.end())
案例一:
std::vector<float> data(n_threads); // or std::array<float, n_threads> data;
std::iota(data.begin(), data.end(), 0); // this will create the data { 0, 1, 2, 3, ... }
cl::sycl::buffer<float> a(data.data(), cl::sycl::range<1>(n_threads));
// The data in a are already initialized, you can create an accessor to use them directly
案例B:
cl::sycl::buffer<float> a(cl::sycl::range<1>(n_threads));
{
auto ba = a.get_access<cl::sycl::access::mode::write>();
for(size_t i=0; i< n_threads; i++) {
ba[i] = i;
}
}
案例C:
cl::sycl::buffer<float> a(cl::sycl::range<1>(n_threads));
cl::sycl::queue q{cl::sycl::default_selector()}; // create a command queue for host or device execution
q.Submit([&](cl::sycl::handler& cgh) {
auto ba = a.get_access<cl::sycl::access::mode::write>();
cgh.parallel_for<class kernel_name>([=](cl::sycl::id<1> i){
ba[i] = i.get(0);
});
});
q.wait_and_throw(); // wait until kernel execution completes
另请查看 SYCL 1.2.1 规范https://www.khronos.org/registry/SYCL/specs/sycl-1.2.1.pdf的第 4.8 章,因为它有一个 iota 示例