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

Posted

技术标签:

【中文标题】queue.wait() 和等待缓冲区销毁有啥区别【英文标题】:What's the difference between queue.wait() and waiting on a buffer to destructqueue.wait() 和等待缓冲区销毁有什么区别 【发布时间】:2021-01-08 21:09:14 【问题描述】:

考虑这个我用 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(), dataSize);
  cl::sycl::buffer<float, 1> bufOut(out.data(), dataSize);

  cl::sycl::queue gpuQueuecl::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); 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(), dataSize);
    cl::sycl::buffer<float, 1> bufOut(out.data(), dataSize);

    cl::sycl::queue gpuQueuecl::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() nested scope
0 4 4 4
0 30 30 30
0 58 58 58

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

【问题讨论】:

【参考方案1】:

queue.wait() 等待所有队列操作完成,在这种情况下,使用floatIteration 内核执行命令组。 但是,您真正需要的是在主机端查看操作的副作用。在 SYCL 中,当您通过缓冲区对象写入时,您不一定使用与输入相同的主机内存(例如 in1.data())。仅当缓冲区范围结束时,或者存在需要对主机的副作用可见的命令组(例如,显式复制回主机)时,才能保证在主机中更新数据。

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

【讨论】:

以上是关于queue.wait() 和等待缓冲区销毁有啥区别的主要内容,如果未能解决你的问题,请参考以下文章

c语言中的getch与getchar 有啥区别?

等待队列_睡眠和唤醒

vim中的缓冲区和寄存器有啥区别?

open() 的缓冲参数和迭代文件时使用的硬编码预读缓冲区大小有啥区别?

Go中缓冲通道和非缓冲通道的测距有啥区别?

单缓冲和双缓冲 有啥区别