OpenCL Nvidia GPU 上的小常量内存大小

标签 opencl

我有以下矩阵乘法代码,为简单起见缩写。我打算使用 block_size*block_size 的本地内存保存一个子矩阵块。我不断收到错误代码 -52clEnqueueNDRangeKernel当我在 NVIDIA GPU 上运行它时。经过一番研究,我发现 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 时,我确实从我的 RX580 中获得了显着的性能提升而不是 __global . 是我做错了什么,还是碰巧我需要准备不同的内核才能在 AMD 和 NVIDIA gpu 上运行?
编辑:我在 github here 上发现了一个相关问题
所以我改了__constant float* a -> __global const float* restrict a , 有用。

最佳答案

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 GPU 和 NVIDIA GPU 使用不同的内核声明。您可以通过 #ifdef 在它们之间切换或在运行时通过 string在编译 OpenCL 代码之前进行连接;这样您就不必在代码中包含两次整个内核,而只需要包含内核参数声明的那一行。

关于OpenCL Nvidia GPU 上的小常量内存大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63080816/

相关文章:

python - PyOpenCL 多维数组

c++ - 检测 Windows TDR 并从中恢复?

opencl - 是否可以将异步回调/延续附加到 SYCL 内核?

c++ - 如何查找系统上的所有 opencl 设备?

opencl - 调用 clEnqueueNDRangeKernel 时出现错误 CL_INVALID_PROGRAM_EXECUTABLE

math - OpenCL 向量类型是否使用 SIMD

c++ - clSetKernelArg 抛出 EXC_BAD_ACCESS

opencl - 使用 QT5 编译 QtOpenCL

linux - 在 Linux 的多个平台上启用 OpenCL?如何处理 ICD 文件?

c++ - 如何在内核中传递数组,做一些事情然后返回它 - OpenCL