queue.wait() 和等待缓冲区销毁有什么区别

问题描述

考虑这个例子,我用 gpuQueue.wait() 等待完成:

  constexpr unsigned dataSize = 1024;
  
  std::vector<float> in1 (dataSize,0); std::iota(in1.begin(),in1.end(),0 );
  std::vector<float> in2 (dataSize,0); std::iota(in2.begin(),in2.end(),25);
  std::vector<float> out (dataSize,0);

  float coeff1 = 4;

  cl::sycl::buffer<float,1> bufIn1(in1.data(),dataSize);
  cl::sycl::buffer<float,1> bufIn2(in2.data(),1> bufOut(out.data(),dataSize);

  cl::sycl::queue gpuQueue{cl::sycl::gpu_selector()};
  gpuQueue.submit([&](cl::sycl::handler &cgh) {
    auto in1  = bufIn1.get_access<cl::sycl::access::mode::read> (cgh);
    auto in2  = bufIn2.get_access<cl::sycl::access::mode::read> (cgh);
    auto temp = bufOut.get_access<cl::sycl::access::mode::write>(cgh);

    auto kernel = [=](cl::sycl::id<1> id) {
      temp[id] = in1[id] * in2[id] + coeff1;
    };
    cgh.parallel_for<floatIteration>(cl::sycl::range<1>(dataSize),kernel);

  });

  gpuQueue.wait();
  
  for( unsigned i = 0; i < dataSize; ++i )
    std::cout << out[i] <<  "  " << (in1[i] * in2[i] + coeff1) << "\n";

在这个例子中,缓冲区在一个嵌套的作用域中并且没有等待:

  constexpr unsigned dataSize = 1024;
  
  std::vector<float> in1 (dataSize,0);

  float coeff1 = 4;
  {
    cl::sycl::buffer<float,dataSize);
    cl::sycl::buffer<float,dataSize);

    cl::sycl::queue gpuQueue{cl::sycl::gpu_selector()};
    gpuQueue.submit([&](cl::sycl::handler &cgh) {
        auto in1 = bufIn1.get_access<cl::sycl::access::mode::read>(cgh);
        auto in2 = bufIn2.get_access<cl::sycl::access::mode::read>(cgh);
        auto temp = bufOut.get_access<cl::sycl::access::mode::write>(cgh);

        auto kernel = [=](cl::sycl::id<1> id) {
            temp[id] = in1[id] * in2[id] + coeff1;
        };
        cgh.parallel_for<floatIteration>(cl::sycl::range<1>(dataSize),kernel);

    });

  }
  for( unsigned i = 0; i < dataSize; ++i )
    std::cout << out[i] <<  "  " << (in1[i] * in2[i] + coeff1) << "\n";

两者的输出为:

queue.wait() 嵌套作用域
0 4 4 4
0 30 30 30
0 58 58 58

为什么 queue.wait() 不等待将缓冲区中的数据复制回主机?

解决方法

module.exports = { plugins: [ { resolve: `gatsby-plugin-manifest`,options: { name: `GatsbyJS`,short_name: `GatsbyJS`,start_url: `/`,background_color: `#f7f0eb`,theme_color: `#a2466c`,display: `standalone`,icon: `src/images/icon.png`,// This path is relative to the root of the site. icons: [ { src: `/favicons/android-chrome-192x192.png`,sizes: `192x192`,type: `image/png`,},{ src: `/favicons/android-chrome-512x512.png`,sizes: `512x512`,],// Add or remove icon sizes as desired },} 等待所有队列操作完成,在这种情况下,使用 queue.wait() 内核执行命令组。 但是,您真正需要的是在主机端查看操作的副作用。在 SYCL 中,当您通过缓冲区对象写入时,您使用的主机内存不一定与用作输入的主机内存相同(例如 floatIteration))。仅当缓冲区范围结束时,或者当存在需要对主机的副作用可见的命令组(例如,显式复制回主机)时,才保证在主机中更新数据。

第二个代码是正确的,你只在拷贝完成后读取主机中的数据。第一个在等待正确之前需要显式复制操作。