c++ - 如何创建一个 cl::sycl::buffers 数组?

标签 c++ opencl sycl

我正在使用 Xilinx 的 triSYCL github 实现,https://github.com/triSYCL/triSYCL .

我正在尝试创建一个包含 100 个生产者/消费者的设计,以从 100 个管道读取/写入。 我不确定的是,如何创建 cl::sycl::buffer 的数组并使用 std::iota 对其进行初始化.

这是我的代码:

constexpr size_t T=6;
constexpr size_t n_threads=100;

cl::sycl::buffer<float, n_threads> a { T };
  for (int i=0; i<n_threads; i++)
  {
    auto ba = a[i].get_access<cl::sycl::access::mode::write>();
    // Initialize buffer a with increasing integer numbers starting at 0
    std::iota(ba.begin(), ba.end(), i*T);
  }

我收到以下错误: error: no matching function for call to ‘cl::sycl::buffer<float, 2>::buffer(<brace-enclosed initializer list>)’ cl::sycl::buffer<float, n_threads> a { T };

我是 C++ 编程新手。所以我无法找出执行此操作的确切方法。

最佳答案

我认为有两点导致您目前遇到的问题:

  1. 缓冲区对象定义中的第二个模板参数应该是缓冲区的维度(维度计数,应该是 1、2 或 3),而不是维度本身。
  2. 缓冲区的构造函数应该包含缓冲区的实际尺寸,或者您希望缓冲区具有的数据和尺寸。要传递尺寸,您需要将 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 个选择:

  1. 使用数组初始化iota用法的数据并将它们传递到sycl缓冲区(案例A),
  2. 使用访问器直接为主机写入缓冲区 - 仅 CPU(情况 B),或
  3. 使用带有 parallel_for 的访问器在主机或 OpenCL 设备上执行(案例 C)。

访问器不应用作迭代器(使用 .begin()、.end())

案例 A:

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 规范的第 4.8 章 https://www.khronos.org/registry/SYCL/specs/sycl-1.2.1.pdf因为它有一个 iota 的例子

关于c++ - 如何创建一个 cl::sycl::buffers 数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48611089/

相关文章:

opencv - 用于构建 OpenCV 的 OpenCL 内核错误生成

sycl - 在 dpc++ malloc_shared 中,我们可以在 2 个 GPU 之间共享缓冲区吗

opencl - 是否可以将异步回调/延续附加到 SYCL 内核?

c++ - 我如何使用 boost::lexical_cast 和 std::boolalpha?即 boost::lexical_cast< bool > ("true")

c++ - OS X 上的 printf 和 %llu 对比 %lu

c++ - 头尾打印比检查结束或开始更有效吗?

c++ - 使用 odeint 和 VexCL 在不同设备上产生不同结果的 Lorenz 示例

c++ - 使用 C++ 进行低级系统编程

c++11 - 继承和 OpenCL 的问题

c++ - 无法为自定义对象oneAPI创建数据缓冲区