我想了解当我创建一个具有只读属性的缓冲区并将其与内核中的__constant
地址空间限定符一起使用或与const __global
地址空间限定符一起使用时的区别。
我已经发现这些不是我问题的真正答案,但它们包含一些有用的信息:
http://www.khronos.org/message_boards/showthread.php/6466-__constant-vs-const-__global
Is the access performance of __constant memory as same as __global memory on OpenCL
如果我理解的话,GPU内存中的分配发生在clCreateBuffer函数调用中。所以我不明白的是编译器如何决定缓冲区是在常量内存(有64 KB的限制)还是在全局内存中。 (我知道在大多数情况下,常量内存是全局内存空间的一部分。)如果它取决于地址限定符,则意味着可以使用const __global
忽略64 KB限制。
__constant
和const __global
之间的效果有何不同? __global内存可以被缓存,因此它们都是只读的并且(可能)被缓存。
(来源:3.3内存模型/全局内存部分和图3.3; http://www.khronos.org/registry/cl/specs/opencl-1.x-latest.pdf#page=24)
答案 0 :(得分:3)
根据我的经验,两者之间没有概念上的区别,它们都暗示指向的数据是只读的。根据供应商使用的实施情况,差异才会明显。
例如在nvidia GPU上标记有__constant的内存被缓存(每个多处理器的缓存大小为8KB,我相信所有当前设备)。需要注意的一点是,如果不同的工作项访问不同的地址,则会对这个缓存的访问进行序列化,因此我发现它对于传递工作组中常量的参数结构非常有用。如果你看一下CUDA编程指南中关于常量内存的部分,你会更好地了解它是如何工作的。标记为const __global的内存未缓存我相信,如果您尝试更改指向的值,它只会告诉编译器抛出错误。
我不确定AMD是否会在硬件上进行类似的缓存
希望有所帮助
答案 1 :(得分:0)
对于AMD的OpenCL实现,请参阅此处的说明: https://github.com/RadeonOpenCompute/ROCm/issues/203
基本上,常量具有隐式限制的效果。 因此常量int * p 大部分等同于 const global int * restrict p 。
答案 2 :(得分:0)
对于FPGA上用于OpenCL的英特尔(以前为Altera的)SDK,常量存储器被加载到片上常量缓存中,并由所有工作组共享。默认情况下,此缓存的大小为16 KB,但是如果在-const-cache-bytes=<N>
命令中添加<N>
(其中aoc
是常量缓存大小,以字节为单位)标志,则可以更改。他们的Best Practices Guide页138还提到以下内容:
与具有额外硬件以容忍长内存的全局内存访问不同 延迟,恒定高速缓存会因高速缓存未命中而遭受较大的性能损失。如果 的
__constant
您的OpenCL内核代码中的参数无法容纳在缓存中,您 可能会获得更好的性能__global const
参数。