`clEnqueueFillBuffer()` 仅随机正确填充缓冲区

`clEnqueueFillBuffer()` fills a buffer correctly only at random

我试图用默认值 ({-1, -2}) 填充 OpenCL cl_int2 缓冲区,但是 OpenCL 函数 clEnqueueFillBuffer()不同 值每次我 运行 它 - 缓冲区仅随机填充预期值。函数returns 错误码0.

多个 运行s 的片段输出示例:

我正在 运行ning OS X 10.11.6,配备 Radeon HD 6750M 和 OpenCL 1.2 版。

clbParticle_hashmap_lookup_table = clCreateBuffer(context,
                                                  CL_MEM_READ_WRITE,
                                                  sizeof(cl_int2)*this->CUBE_CELLS,
                                                  nullptr,
                                                  &err_code);

// ...

cl_int2 default_hashmap_pattern = { .s = {-1, -2} };

clEnqueueFillBuffer(queue,
                    clbParticle_hashmap_lookup_table,
                    &default_hashmap_pattern,
                    sizeof(cl_int2),
                    0,
                    sizeof(cl_int2)*this->CUBE_CELLS,
                    0,
                    nullptr, nullptr);

clFinish(queue);

// copy and print the data:
size_t   hashmap_lookup_table_size  = sizeof(cl_int2)*this->CUBE_CELLS;
cl_int2* hashmap_lookup_table_bytes = (cl_int2*) malloc(hashmap_lookup_table_size);

clEnqueueReadBuffer(queue,
                    clbParticle_hashmap_lookup_table,
                    CL_TRUE,
                    0,
                    hashmap_lookup_table_size,
                    hashmap_lookup_table_bytes,
                    0,
                    nullptr, nullptr);

clFinish(queue);

cout << endl << "Lookup table: " << endl;
for (int i=0; i<this->CUBE_CELLS; i++)
    cout << setw(10) << hashmap_lookup_table_bytes[i].s[0] << " : "
         << setw(10) << hashmap_lookup_table_bytes[i].s[1] << endl;

我可以重现这个。在配备 Radeon Pro 450 的 Macbook Sierra 上,执行以下脚本:

int N = 100000;

float *a = new float[N];

cl_mem a_gpu = clCreateBuffer(context, CL_MEM_READ_WRITE, N * sizeof(float), 0, &err);
checkError(err);
for(int it = 0; it < 100; it++) {

    float value = 123.0f + it;
    err = clEnqueueFillBuffer(queue, a_gpu, &value, sizeof(value), 0, N * sizeof(float), 0, 0, 0);
    checkError(err);
    clFinish(queue);

    err = clEnqueueReadBuffer(queue, a_gpu, CL_TRUE, 0,
                                         sizeof(cl_float) * N, a, 0, NULL, NULL);
    checkError(err);
    clFinish(queue);

    cout << it << " a[N - 1]=" << a[N - 1] << endl;
}
delete[] a;

给出如下结果:

Using Apple , OpenCL platform: Apple Using OpenCL device: AMD Radeon Pro 450 Compute Engine 0 a[N - 1]=-1.39445e-31 1 a[N - 1]=0 2 a[N - 1]=0 3 a[N - 1]=0 4 a[N - 1]=0 5 a[N - 1]=0 6 a[N - 1]=129 7 a[N - 1]=0 8 a[N - 1]=131 9 a[N - 1]=132 10 a[N - 1]=133 11 a[N - 1]=134 12 a[N - 1]=135 13 a[N - 1]=0 14 a[N - 1]=0 15 a[N - 1]=0 16 a[N - 1]=0 17 a[N - 1]=0 18 a[N - 1]=0 19 a[N - 1]=0 20 a[N - 1]=0 21 a[N - 1]=0 22 a[N - 1]=0 23 a[N - 1]=0 24 a[N - 1]=0 25 a[N - 1]=0 26 a[N - 1]=0 27 a[N - 1]=0 28 a[N - 1]=0 29 a[N - 1]=0 30 a[N - 1]=0 31 a[N - 1]=154 32 a[N - 1]=0

问题是您的填充图案对于您的 GPU 来说太大了。我 运行 遇到了同样的问题,试图用 cl_double 填充一个模式,就像你的 cl_int2 一样是 64 位。我认为 clEnqueueFillBuffer 正在调用一个不允许模式

的内置内核

自从 2017 年 3 月我开始学习 OpenCL(当时不记得 macOS 版本)以来,我只在 macOS 上遇到过这个错误。 GPU 是 GT 750M(这可能是无关紧要的),patterncl_double2。 GTX 760 Linux 上的相同例程没有这样的问题。我怀疑这是因为 macOS 上的 OpenCL 1.2 支持不完整,因为 clinfo(在 macOS 上编译和执行)警告:

NOTE:   your OpenCL library only supports OpenCL 1.0,
        but some installed platforms support OpenCL 1.2.
        Programs using 1.2 features may crash
        or behave unexpectedly

"corresponding" CUDA API、cudaMemset 只能接受 int 大小的模式。但是,该限制在 CUDA 文档中有说明,而 OpenCL 文档明确使用 cl_float4(与 cl_double2 大小相同)作为示例。所以这显然是一个错误,而不是一个未记录的功能。

但我猜 Apple 已经在 macOS 10.14 中解决了这个问题,因为他们正在弃用 OPENCL!