运行更多线程时,CUDA性能会提高

时间:2012-12-07 14:46:42

标签: c++ cuda opencl

为什么每个块运行超过32个线程时性能会提高?

我的显卡有480个CUDA核心(15 MS * 32 SP)。

3 个答案:

答案 0 :(得分:7)

每个SM有1-4个warp调度程序(Tesla = 1,Fermi = 2,Kepler = 4)。每个warp调度程序负责执行分配给SM的warp的子集。每个warp调度程序都维护一个符合条件的warp列表。如果warp可以在下一个周期发出指令,则该warp是合格的。如果warp在数据依赖项上停顿,等待获取和指令,或者下一条指令的执行单元忙,则warp不符合条件。在每个循环中,每个warp调度程序将从符合条件的warp列表中选择一个warp并发出1或2条指令。

每个SM的更活跃的warp,每个warp调度程序在每个循环中必须选择的warp数越大。在大多数情况下,当每个SM有足够的活动warp时,每个周期每个warp调度程序有一个符合条件的warp,就可以实现最佳性能。超出此点的占用率增加不会提高性能并可能降低性能。

有源经线的典型目标是SM的最大经线的50-66%。由发射配置支持的经线与最大经线的比率称为理论占用率。每个循环的活动扭曲与每个循环的最大扭曲的运行时间比率是达到占用率。对于GTX480(CC 2.0设备),设计内核的良好起点是理论占用率为50-66%。 CC 2.0 SM最多可以有48个经线。 50%的占用率意味着每个SM有24个经线或768个线程。

Nsight Visual Studio Edition中的CUDA性能分析活动可以显示理论占用率,实现占用率,每个SM的活动warp,符合条件的每个SM的warp和停顿原因。

CUDA Visual Profiler,nvprof和命令行分析器可以显示理论占用率,活动扭曲和实现占用率。

注意:CUDA核心数应仅用于比较类似架构的卡,计算理论FLOPS,并可能比较架构之间的差异。在设计算法时不要使用计数。

答案 1 :(得分:5)

欢迎使用Stack Overflow。原因是CUDA核心是流水线的。在费米,管道长约20个时钟。这意味着要使GPU饱和,每个核心最多可能需要20个线程。

答案 2 :(得分:1)

主要原因是CUDA的内存延迟隐藏模型。大多数现代CPU使用缓存来隐藏主存储器的延迟。这导致大量的芯片资源用于缓存。大多数台式机和服务器处理器在裸片上有几兆字节的缓存,实际上占据了大部分裸片空间。为了打包具有相同能量使用和散热特性的更多内核,基于CUDA的芯片反而将其芯片空间用于投入大量CUDA内核(大多数只是浮点ALU)。由于缓存非常少,他们反而依赖于准备好运行更多线程,而其他线程正在等待内存访问返回以隐藏该延迟。这为内核提供了一些工作效率,而一些warp正在等待内存访问。每SM的扭曲越多,其中一个在任何给定时间都可以运行的机会越多。

CUDA还具有零成本线程切换功能,以帮助实现这种内存延迟隐藏方案。由于需要将正在切换的线程的所有寄存器值存储到堆栈中,然后为线程加载所有的线程,正常的CPU会产生很大的开销从一个线程的执行切换到下一个线程正在转向。 CUDA SM只有大量的寄存器,所以每个线程都有自己的一组物理寄存器,通过线程的生命周期分配给它。由于不需要存储和加载寄存器值,因此每个SM可以在一个时钟周期内从一个warp执行线程,并在下一个时钟周期执行不同warp的线程。