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

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

本文关键字:缓冲区 填充 clEnqueueFillBuffer 随机      更新时间:2023-10-16

我正在尝试用默认值({-1, -2}(填充 OpenCL cl_int2缓冲区,但是 OpenCL 函数每次运行时clEnqueueFillBuffer()不同的值填充我的缓冲区——缓冲区仅随机填充预期值。该函数返回错误代码0

代码段在多次运行时的输出示例:

  • 0 : -268435456
  • 0 : -2147483648
  • 0 : -536870912
  • 0 : 268435456
  • 0 : 0
  • 0 : -1342177280
  • -1: -2

我运行的是带有Radeon HD 6750M和OpenCL 1.2版本的OS X 10.11.6。

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;

问题是您的填充模式对于您的 GPU 来说太大了。我在尝试用像您的cl_int2一样 64 位的cl_double填充模式时遇到了同样的问题。我认为clEnqueueFillBuffer正在调用一个不允许模式的内置内核

我可以重现这一点。在装有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

自 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

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

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