如何创建cl :: sycl :: buffers数组?

时间:2018-02-04 17:39:11

标签: 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 ++编程的新手。所以我无法弄清楚这样做的确切方法。

2 个答案:

答案 0 :(得分:3)

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

  1. 缓冲区对象定义中的第二个模板参数应该是缓冲区的维度(维度的数量,应该是1,2或3),而不是维度本身。
  2. 缓冲区的构造函数应包含缓冲区的实际尺寸,或者您希望缓冲区具有的数据和尺寸。要传递维度,需要将cl :: sycl :: range对象传递给构造函数
  3. 据我了解,您正在尝试初始化维度1的缓冲区,其维度为{100,1,1}。为此,a的定义应更改为:

      

    cl :: sycl :: buffer&lt; float,1&gt; a(cl :: sycl :: range&lt; 1&gt;(n_threads));

    此外,由于维度可以从范围模板参数中推导出来,因此您可以通过以下方式实现相同的效果:

      

    CL :: sycl ::缓冲&LT;浮动&gt; a(cl :: sycl :: range&lt; 1&gt;(n_threads));

    至于用std :: iota初始化缓冲区,你有3个选项:

    1. 使用数组初始化带有iota用法的数据并将它们传递给sycl缓冲区(案例A),
    2. 使用访问者直接为主机写入缓冲区 - 仅限CPU(案例B)或
    3. 使用带有parallel_for的访问者在主机或OpenCL设备上执行(案例C)。
    4. 不应将访问器用作迭代器(使用.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规范https://www.khronos.org/registry/SYCL/specs/sycl-1.2.1.pdf的第4.8章,因为它有一个iota的例子

答案 1 :(得分:1)

免责声明:triSYCL目前是一个研究项目。请使用ComputeCpp进行任何严肃的事情。 : - )

如果你真的需要buffer的数组,我想你可以使用与Is there a way I can create an array of cl::sycl::pipe?类似的东西

作为变体,您可以使用std::vector<cl::sycl::buffer<float>>std::array<cl::sycl::buffer<float>, n_threads>并使用cl::sycl::buffer<float> { T }中的循环进行初始化。