2010-11-04 86 views
5

我翻阅了编程指南和最佳实践指南,它提到全局内存访问需要400-600个周期。我没有看到像纹理缓存,常量缓存,共享内存等其他内存类型。寄存器有0个内存延迟。OpenCL/CUDA中每个内存访问类型有多少内存延迟周期?

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

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

纹理缓存怎么样?

回答

4

共享/常量/纹理存储器的延迟很小,取决于您拥有的设备。通常,虽然GPU被设计为吞吐量架构,这意味着通过创建足够的线程,隐藏了包括全局内存在内的内存延迟。

指南中提到的全局存储器延迟的原因是,延迟比其他存储器的延迟高出几个数量级,这意味着它是优化考虑的主要延迟。

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

与常量缓存不同,共享内存可以提供更高的带宽。查看CUDA Optimization讨论,了解更多细节和银行冲突及其影响的解释。

+0

如果例如所有线程都访问1000浮点数,它仍然值得使用常量缓存吗?这是否会像一个1000从注册表中读取?该指南表示这种常量缓存的使用以这种方式线性扩展了吗? – smuggledPancakes 2010-11-04 16:56:44

+0

如果所有线程在循环的任何给定迭代中访问* same *值,则可以使用常量缓存。由于空间局部性,常量缓存将提供一些好处(在Fermi上,L1缓存可能达到同样的效果,但这会使L1免费用于其他数据)。话虽如此,我主要针对费米,并且从不使用'__constant__',我只是使用const并让编译器弄清楚它!例如在你的情况下,我会将内核参数作为'const float * const myfloatarray'来传递。我建议你总是运行Visual Profiler来检查序列化,以防万一你错过了某些东西。 – Tom 2010-11-05 08:03:30

+0

有人可能会说,L1(L2)的高速缓存行为128byte(32byte),所以我们讨论的是地址落入相同的行(不一定是相同的地址)。有些其他延迟的数字可以在[这里]找到(http://stackoverflow.com/questions/6744101/fermi-l2-cache-hit-latency)。 – 2012-09-09 15:03:52

6

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

全局存储器:440个时钟
常量存储器
        L1:48个时钟
        L2:120时钟
共享内存:48个时钟
纹理内存
        L1:108个时钟
        L2:240个时钟

我怎么知道?我运行了Demystifying GPU Microarchitecture through Microbenchmarking的作者描述的微基准。它们为旧版GTX 280提供了类似的结果。

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

PTX ISA中还有一个operands cost章节,虽然它不是很有帮助,但它只是重申了你的期望,却没有给出精确的数字。

+0

我也在使用特斯拉K20,并试图运行您提到的同一个微基准。你是否能够毫无问题地运行'global.cu'?我问,因为我面临非法内存访问问题 - 我已经发布了这个问题[这里](http://stackoverflow.com/questions/36416843/how-to-write-a-pointer-chasing-benchmark-using- 64位指针合CUDA)。我想知道你是否对内核代码做了任何更改以使其适用于你? – Kajal 2016-04-05 18:56:12

+0

@ kv.333它是前一段时间。我记得有一些问题,并没有全部的基准。我不记得哪些。 – 2016-04-11 07:17:59