OpenCL 和 std::vector<bool> 不兼容

OpenCL and std::vector<bool> incompatibility

我有一个形成为 std::vector 的 C++ 输入,我想将它传递给我的 OpenCL 内核(Nvidia 平台)。

但是当执行以下命令时,我总是遇到分段错误:

queue.enqueueReadBuffer(dev_input, CL_TRUE, 0, sizeof(bool) * input.size(), &input);

因此,我尝试将我的 std::vector<bool> 复制到 bool[] 并且一切正常。但是,将向量转换为C数组的常用方法(&input[0], input.data())根本不起作用。

您对 ReadBuffer 或对 C 数组的快速赋值有什么建议吗?

谢谢!

两个问题。

  1. 实现可以(可选)优化 std::vector<bool> 以提高 space 效率,可能是通过将值打包到内存的各个位中。这将不匹配 bool.

  2. 数组的布局
  3. 不能像传递数组一样传递向量的地址。

    std::vector<bool> input;
    queue.enqueueReadBuffer(
        dev_input, CL_TRUE, 0,
        sizeof(bool) * input.size(), &input);
    //                               ^^^^^^ wrong
    

    如果你想将向量作为指针传递,你必须使用 input.data() 或类似 &input[0] 的东西。这些不起作用的原因是因为 std::vector<bool> 旨在防止它,因为实现可能会被优化(参见第 #1 点)。

这基本上是 C++ 库中的一个 "wart",随着时间的推移已经融入其中。

解决这个问题很痛苦。

// One way to do things...
struct Bool { bool value; }
std::vector<Bool> input;

// Another way to do things...
// (You have to choose the right type here, it depends
// on your platform)
std::vector<int> input;

// Yet another way...
bool *input = new bool[N];

这就是为什么这是一个这么大的臭疣。

一种可能是使用 copy() algorithm provided by Boost.Compute

基本上,您可以这样做:

// vector of bools on the host
std::vector<bool> host_vec = { ... };

// vector of bools on the device (each represented with a uchar)
boost::compute::vector<uchar_> gpu_vec(host_vec.size(), ctx);

// copy bool values on host to the device
boost::compute::copy(host_vec.begin(), host_vec.end(), gpu_vec.begin(), queue);

并且 Boost.Compute 将负责将数据正确复制到计算设备。

再补充一点:

不保证 OpenCL 内核中的

Type bool 与任何主机端类型匹配。 Host-Device 互联一般应避免使用 boolean 类型。