如何计算 CUDA 内核的实现带宽
Posted
技术标签:
【中文标题】如何计算 CUDA 内核的实现带宽【英文标题】:How to calculate the achieved bandwidth of a CUDA kernel 【发布时间】:2011-12-14 03:07:18 【问题描述】:我想要衡量我的内核存档的峰值内存带宽有多少。
假设我有一个 NVIDIA Tesla C1060,它有一个 max Bandwidth of 102.4 GB/s。在我的内核中,我可以访问以下全局内存:
...
for(int k=0;k>4000;k++)
float result = (in_data[index]-loc_mem[k]) * (in_data[index]-loc_mem[k]);
....
out_data[index]=result;
out_data2[index]=sqrt(result);
...
我计算每个线程 4000*2+2 次访问全局内存。拥有 1.000.000 个线程并且所有访问都是浮动的,我有大约 32GB 的全局内存访问(添加了入站和出站)。由于我的内核只需要 0.1 秒,我将归档 ~320GB/s,这高于最大带宽,因此我的计算/假设存在错误。我假设,CUDA 做了一些缓存,所以并不是所有的内存访问都计算在内。现在我的问题:
我的错误是什么? 对全局内存的哪些访问被缓存,哪些不被缓存? 不计算对寄存器、本地、共享和常量内存的访问是否正确? 我可以使用 CUDA 分析器获得更简单、更准确的结果吗?我需要使用哪些计数器?我需要如何解释它们?分析器输出:
method gputime cputime occupancy instruction warp_serial memtransfer
memcpyHtoD 10.944 17 16384
fill 64.32 93 1 14556 0
fill 64.224 83 1 14556 0
memcpyHtoD 10.656 11 16384
fill 64.064 82 1 14556 0
memcpyHtoD 1172.96 1309 4194304
memcpyHtoD 10.688 12 16384
cu_more_regT 93223.906 93241 1 40716656 0
memcpyDtoH 1276.672 1974 4194304
memcpyDtoH 1291.072 2019 4194304
memcpyDtoH 1278.72 2003 4194304
memcpyDtoH 1840 3172 4194304
新问题:
- 当 4194304Bytes = 4Bytes * 1024*1024 数据点 = 4MB 和 gpu_time
~= 0.1 s 时,我实现了 10*40MB/s = 400MB/s 的带宽。这似乎很低。哪里出错了?
附言如果您需要其他计数器来回答,请告诉我。
妹子提问:How to calculate Gflops of a kernel
【问题讨论】:
这些分析器时间以微秒为单位,因此 4.0Mb / 0.00176s = 3134 Mb/s,大约是正确的数量级。 【参考方案1】: 您实际上并没有同时运行 1.000.000 个线程。您执行约 32GB 的全局内存访问,其中带宽将由 SM 中运行(读取)的当前线程和读取的数据大小决定。 除非您向编译器指定未缓存的数据,否则全局内存中的所有访问都缓存在 L1 和 L2 中。 我想是的。实现的带宽与全局内存有关。 我建议使用可视化分析器来查看读/写/全局内存带宽。如果你发布你的结果会很有趣:)。Visual Profiler 中的默认计数器为您提供了足够的信息来了解您的内核(内存带宽、共享内存库冲突、执行的指令......)。
关于您的问题,计算实现的全局内存吞吐量:
计算视觉分析器。 DU-05162-001_v02 | 2010 年 10 月。用户指南。第 56 页,表 7。支持的派生统计数据。
全局内存读取吞吐量(以千兆字节/秒为单位)。对于 计算能力 ,其计算公式为 (((gld_32*32) + (gld_64*64) + (gld_128*128)) * TPC) / gputime 对于 计算能力 >= 2.0 这计算为 ((DRAM reads) * 32) / gputime
希望对您有所帮助。
【讨论】:
正如@talonmies 评论的那样,这些分析器时间以微秒为单位。我没有从命令行使用分析器,但可视化界面为您做了很多计算,即它显示了全局内存读/写/整体吞吐量。以上是关于如何计算 CUDA 内核的实现带宽的主要内容,如果未能解决你的问题,请参考以下文章