我有一个被多次调用的内核。在每次调用中,大约 240 KB 的常量数据将由线程共享和处理。线程像映射函数一样独立工作。线程的停顿时间相当长。其背后的原因可能是内存读取的银行冲突。我该如何处理?(我有 GTX 1080 ti)
opencl 的“const global”可以处理这个吗? (因为cuda中常量内存限制为64kb)
最佳答案
在 CUDA 中,我认为最好的建议是使用所谓的“只读”缓存。与 __constant__
内存/常量缓存系统相比,这至少有两个可能的好处:
- 它不像
__constant__
内存那样限制为 64kB。 - 它不像常量缓存那样期望或要求“统一访问”,以提供完整的访问带宽/最佳性能。统一访问指的是 warp 中的所有线程都访问相同的位置或相同的常量内存值(每个读取周期/指令)。
只读缓存记录在 the CUDA programming guide 中.可能最简单的使用方法是 decorate your pointers使用 __restrict__
传递给 CUDA 内核(假设您是 not aliasing between pointers )并使用 const ... __restrict__
装饰指向大常量数据的指针。这将允许编译器生成适当的 LDG 指令以访问常量数据,通过只读缓存机制拉取它。
此只读缓存机制仅在 cc 3.5 或更高版本的 GPU 上受支持,但它涵盖了 Kepler 一代中的部分 GPU 以及 Maxwell、Pascal(包括您的 GTX 1080 ti)、Volta 和 Turing 几代中的所有 GPU。
如果您的 GPU 低于 cc3.5,为了获得类似的好处(大于 __const__
,不需要统一访问)可能最好的建议是使用纹理内存。这也记录在编程指南的其他地方,有各种 CUDA 示例代码演示了纹理内存的使用,这里还有很多关于覆盖它的 SO cuda
标签的问题。
关于c++ - 在 cuda 线程之间共享大量常量数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53149193/