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

sz *_*ter 5 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
Run Code Online (Sandbox Code Playgroud)

核心:

__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)
 {...}
Run Code Online (Sandbox Code Playgroud)

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

编辑:我在这里在 github 上发现了一个相关问题 所以我改变了__constant float* a-> __global const float* restrict a,它有效。

Pro*_*ysX 3

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这样,您就不必在代码中两次使用整个内核,而只需在包含内核参数声明的行中使用。