Memory 在OpenCL/CUDA中,每种内存访问类型有多少个内存延迟周期?

Memory 在OpenCL/CUDA中,每种内存访问类型有多少个内存延迟周期?,memory,cuda,opencl,latency,nvidia,Memory,Cuda,Opencl,Latency,Nvidia,我浏览了《编程指南》和《最佳实践指南》,其中提到全局内存访问需要400-600个周期。我没有看到其他内存类型,如纹理缓存、常量缓存、共享内存。寄存器的内存延迟为0 我认为,如果所有线程在常量缓存中使用相同的地址,那么常量缓存与寄存器是相同的。最坏的情况我不太确定 共享内存与寄存器相同,只要没有银行冲突?如果有,那么延迟是如何展开的 纹理缓存呢?共享/恒定/纹理内存的延迟很小,取决于您使用的设备。一般来说,尽管GPU被设计为吞吐量架构,这意味着通过创建足够多的线程,可以隐藏对内存(包括全局内存)的

我浏览了《编程指南》和《最佳实践指南》,其中提到全局内存访问需要400-600个周期。我没有看到其他内存类型,如纹理缓存、常量缓存、共享内存。寄存器的内存延迟为0

我认为,如果所有线程在常量缓存中使用相同的地址,那么常量缓存与寄存器是相同的。最坏的情况我不太确定

共享内存与寄存器相同,只要没有银行冲突?如果有,那么延迟是如何展开的


纹理缓存呢?

共享/恒定/纹理内存的延迟很小,取决于您使用的设备。一般来说,尽管GPU被设计为吞吐量架构,这意味着通过创建足够多的线程,可以隐藏对内存(包括全局内存)的延迟

指南讨论全局内存延迟的原因是,延迟比其他内存的延迟高几个数量级,这意味着它是优化时要考虑的主要延迟

您特别提到了常量缓存。如果一个warp中的所有线程(即32个线程组成的组)访问相同的地址,那么就没有惩罚,即从缓存中读取该值并同时广播到所有线程,这是非常正确的。但是,如果线程访问不同的地址,那么访问必须序列化,因为缓存一次只能提供一个值。如果您正在使用CUDA探查器,那么它将显示在序列化计数器下

与常量缓存不同,共享内存可以提供更高的带宽。有关银行冲突及其影响的更多详细信息和解释,请查看谈话。

对于(开普勒)特斯拉K20,延迟如下所示:

全局内存:440个时钟
恒定内存
L1:48个时钟
L2:120个时钟
共享内存:48个时钟
纹理记忆
L1:108个时钟
L2:240个时钟

我怎么知道?我运行了本书作者描述的微基准测试。它们为较旧的GTX 280提供了类似的结果

这是在Linux集群上测量的,我运行基准测试的计算节点没有被任何其他用户使用,也没有运行任何其他进程。它是BULLX linux,具有一对8核Xeons和64 GB RAM,nvcc 6.5.12。我将
sm_20
更改为
sm_35
进行编译


PTX ISA中也有一章,虽然它不是很有帮助,但它只是重申了您已经期望的内容,而没有给出精确的数字。

如果所有线程都访问1000个浮点值,那么仍然值得使用常量缓存吗?这会像从寄存器读取1000次一样吗?指南说,以这种方式使用常量缓存是线性扩展的吗?如果所有线程在循环的任何给定迭代中访问相同的值,那么您可以使用常量缓存。由于空间局部性,常量缓存将提供一些好处(在费米上,一级缓存可能实现相同的功能,但这使一级缓存可以自由地用于其他数据)。话虽如此,我的目标大多是费米,从不使用常量,我只是经常使用常量,让编译器来解决它!例如,在您的例子中,我将内核参数作为
const float*const myfloatarray
传递。我建议您始终运行Visual Profiler来检查序列化,以防遗漏某些内容。您可以补充一点,缓存线对于L1(L2)是128字节(32字节),因此我们讨论的是地址落在相同的行中(不一定是相同的地址)。可以找到其他延迟的一些数字。我也在使用特斯拉K20,我试着运行你提到的同一个微基准。您是否能够毫无问题地运行
global.cu
?我问这个问题是因为我面临非法内存访问的问题——我已经发布了这个问题。我想知道您是否对内核代码做了任何更改以使其适合您?@kv.333这是很久以前的事了。我记得有一些问题,并不是所有的基准都运行。我不记得是哪一个了。