作为在GPU上运行的算法分析的一部分,我觉得我已经达到了内存带宽。
我有几个复杂的内核执行一些复杂的操作(稀疏矩阵乘法,减少等)和一些非常简单的操作,当我计算读取/写入的总数据时,似乎所有(重要的)都达到~79GB / s带宽墙对于它们中的每一个,无论它们的复杂程度如何,而理论GPU带宽为112GB / s(nVidia GTX 960)
对于~10,000,000个浮点条目的向量,数据集非常大,因此我在clGetEventProfilingInfo
和COMMAND_START
之间得到了COMMAND_END
的良好测量/统计数据。在算法运行期间,所有数据都保留在GPU内存中,因此几乎没有主机/设备内存传输(也不是通过分析计数器来测量)
即使对于一个非常简单的内核(见下文)解决x=x+alpha*b
,其中x和b是~10,000,000个条目的大向量,我也不接近理论带宽(112GB / s)但是而是运行在最大值的约70%(~79GB / s)
__kernel void add_vectors(int N,__global float *x,__global float const *b,float factor)
{
int gid = get_global_id(0);
if(gid < N)
x[gid]+=b[gid]*factor;
}
我计算每次运行此特定内核的数据传输为N *(2 + 1)* 4:
我预计对于这样一个简单的内核我需要更接近带宽限制,我会错过什么?
P.S。:我从同一算法的CUDA实现中得到类似的数字
答案 0 :(得分:2)
我认为评估您是否达到峰值带宽的更现实的方法是将您获得的内容与简单的D2D副本进行比较。
例如,你的内核读取x和b一次并写入x一次,因此执行时间的上限应该是从b复制到x一次的1.5倍时间。如果你发现时间远远超过1.5倍,那就意味着你可能有改进的空间。在这个内核中,工作非常简单,开销(开始和结束函数,计算索引等)可能会限制性能。如果这是一个问题,您可能会发现通过网格跨步循环帮助增加每个线程的工作。
https://devblogs.nvidia.com/parallelforall/cuda-pro-tip-write-flexible-kernels-grid-stride-loops/
至于理论带宽,至少应该考虑ECC的开销(如果已启用)。