1

我使用 intel dpc++ 编译器编译并运行了以下代码。使用 cpu 选择器时我得到了正确的结果,但 gpu 选择器给出了垃圾值。

我的代码所做的只是将一个名为 data 的数组初始化为全 1。在 sycl 内核中,对该数组的访问器乘以 3 并保存到结果数组中。我尝试在结果数组中打印值,该数组预计将全部为 3,但我得到了垃圾值。

因为我在 gpu 上执行代码时得到垃圾值。我尝试在 cpu selector 上运行,这里的代码没有问题。

我在linux和windows上试过这个。编译器版本 dpcpp 2021.3

#include "iostream"
#include<CL/sycl.hpp>
#include <array>
using namespace std;
using namespace sycl;
int main() {        
    
    sycl::gpu_selector selector;   
    //using cpu selector as in the line below works
    //sycl::cpu_selector selector;    
    sycl::queue q = sycl::queue(selector);
    std::cout << q.get_device().get_info<sycl::info::device::name>();    
    constexpr int size = 3;
    std::array<int, size> data{1,1,1};
    std::array<int, size> resultarray;
    range<1> num_items{ size };
    buffer<int, 1> data_buff(data.data(), num_items);
    buffer<int, 1> result(resultarray.data(), num_items);

    
    
    q.submit([&](sycl::handler& cgh) 
        {
        auto dataAccess = data_buff.get_access<access::mode::read_write>(cgh);
        auto resultAccess = result.get_access<access::mode::write>(cgh);
        cgh.parallel_for(num_items, [=](id<1>  i)
            {
                resultAccess[i] = dataAccess[i] * 3;
            });

        }).wait();


    std::cout <<"||"<< resultarray[0]<<"||"; //expected result ||3||
}

有人可以帮助为什么代码会在 GPU 上给出错误的结果吗?

4

1 回答 1

2

您不会触发复制回主机。大概在 CPU 上,您的 SYCL 实现只是决定直接对输入指针进行操作,因此您看不到问题所在。

想一想:SYCL 实现如何知道resultarray您正在使用它cout并且必须将数据复制回来?它不能,因为这种内存访问不通过任何 SYCL 构造。因此它无法知道它必须将数据复制回来。唯一的wait()原因是主机等待内核完成,它不会触发副本。

触发必要副本的最重要方法是:

  • 使用缓冲区回写:默认情况下,从主机指针构造的缓冲区会将其在缓冲区析构函数中的内容写回到构造它们的数据指针(缓冲区中还有成员函数可以手动启用/禁用此功能)。在您的情况下,将缓冲区声明和内核额外包装{ }就足够了,因为这样缓冲区将在您之前超出范围cout,并触发回写。
  • 使用 ahost_accessor而不是直接访问resultarray
  • 使用显式handler::copy()
于 2021-08-30T13:57:42.303 回答