OpenCL Nvidia GPU上的恒定小内存

时间:2020-07-24 20:13:24

标签: opencl

我有以下用于矩阵乘法的代码,为简单起见缩写。我计划使用block_size*block_size的本地内存来保存一个子矩阵块。在NVIDIA GPU上运行时,我不断在-52中收到错误代码clEnqueueNDRangeKernel。经过研究后,我发现NVIDIA gpu的恒定内存大小非常小。

主机:

    cl::Buffer a_buf{ context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, a.bytes(), a.data };
    cl::Buffer b_buf{ context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, a.bytes(), bT.data };
    cl::Buffer result_buf{ context, CL_MEM_READ_WRITE , result.bytes(), nullptr }; //for memory mapping
    kernel.setArg(0, a_buf);
    kernel.setArg(1, b_buf);
    kernel.setArg(2, local_size*local_size* sizeof(float), nullptr);
    kernel.setArg(3, local_size*local_size* sizeof(float), nullptr);
    kernel.setArg(4, result_buf);
    queue.enqueueNDRangeKernel(kernel, { 0,0 }, { a.rows, a.rows }, {local_size, local_size});
                                        //  ^ offset   ^global work size  ^local work size

内核:

__kernel void matrixMul(__constant float* a,
    __constant float* b,    //storing the original matrix data
    __local float* a_local, 
    __local float* b_local, //storing a sub-matrix block for the work-group
    __global float* result)
 {...}

使用CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,我的 RX580 返回几乎所有可用的VRAM,但是我的 GTX1650 仅返回64KB。当使用__constant而非__global时,我的RX580确实获得了显着的性能提升。 我做错了什么吗?还是碰巧是这样,所以我需要准备不同的内核才能在AMD和NVIDIA GPU上运行?

编辑:我在github here上发现了一个相关问题 所以我更改了__constant float* a-> __global const float* restrict a,就可以了。

1 个答案:

答案 0 :(得分:2)

NVIDIA GPU上的恒定内存大小确实很小,只有64KB(我检查了Titan Xp,GTX 960M,RTX 2080 Ti,Tesla K20c,Tesla K40m)。在AMD Radeon VII上,恒定内存大小要大得多,为14GB。在Intel CPU(i7-8700K,Xeon E5-2680 v2)上,恒定内存大小为128KB。这是驱动程序的限制,解决方法是使用global const float* restrict(对于类型为restrict的所有其他内核参数使用float*)而不是constant float*,如您所知。

如果AMD GPU的性能差异很大,则可以对AMD和NVIDIA GPU使用不同的内核声明。您可以在编译OpenCL代码之前通过#ifdef或在运行时通过string进行切换。这样,您不必在代码中包含整个内核两次,而只需包含内核参数声明的行即可。