如何计算 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 内核的实现带宽的主要内容,如果未能解决你的问题,请参考以下文章

如何计算正在启动的 CUDA 线程数?

并行计算程序设计(CUDA C)

mtensor一个tensor计算库,支持cuda延迟计算

如何计算理论上的最大 CPU-RAM 带宽?

如何设置专用 GPU 以对 CUDA 内核进行基准测试?

CUDA 计算和复制引擎队列限制