【问题标题】:How to create an array of cl::sycl::buffers?如何创建一个 cl::sycl::buffers 数组?
【发布时间】:2018-02-04 17:39:10
【问题描述】:

我正在使用 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++ 编程的新手。所以我无法弄清楚执行此操作的确切方法。

【问题讨论】:

    标签: c++ opencl sycl


    【解决方案1】:

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

    1. 缓冲区对象定义中的第二个模板参数应该是缓冲区的维度(维度计数,应该是 1、2 或 3),而不是维度本身。
    2. 缓冲区的构造函数应包含缓冲区的实际尺寸,或您希望缓冲区具有的数据和尺寸。要传递维度,您需要将 cl::sycl::range 对象传递给构造函数

    据我了解,您正在尝试初始化一个维度为 1 且维度为 { 100, 1, 1 } 的缓冲区。为此,a 的定义应更改为:

    cl::sycl::buffer a(cl::sycl::range(n_threads));

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

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

    【讨论】:

    • 感谢@Marios。这很有帮助,而且奏效了。我没有使用cl::sycl::range
    • 我仍然遇到这个问题。我需要创建 100 个缓冲区,每个缓冲区大小为 6。如果超过 3,则会出现尺寸错误。我正在使用 cl::sycl::range&lt;6&gt;
    • 要设置大小,您应该尝试 cl::sycl::range(6)
    • 据我了解:cl::sycl::buffer&lt; float &gt; a (cl::sycl::range&lt; 1 &gt;(6)) 将给我与cl::sycl::buffer&lt;float&gt; a { 6 } 相同的缓冲区大小。我不明白的是如何创建一个包含 100 个 size 6 的此类缓冲区的数组
    • 也许你想要一个二维缓冲区?在这种情况下, range{100,6} 可以完成这项工作......
    【解决方案2】:

    免责声明:triSYCL 目前是一个研究项目。请使用 ComputeCpp 处理任何严重问题。 :-)

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

    作为一种变体,您可以使用 std::vector&lt;cl::sycl::buffer&lt;float&gt;&gt;std::array&lt;cl::sycl::buffer&lt;float&gt;, n_threads&gt; 并使用来自 cl::sycl::buffer&lt;float&gt; { T } 的循环进行初始化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      相关资源
      最近更新 更多