这一系列文章面向CUDA开发者来解读《CUDA C Best Practices Guide》 (CUDA C最佳实践指南)
大家可以访问:
https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html 来阅读原文。
这是一本很经典的手册。
CUDA优化的冷知识18| texture和surface
CUDA优化的冷知识19|constant和寄存器
CUDA优化冷知识20|不改变代码本身如何提升性能?
在今天的手册上, 这些统称为对kernel的执行(环境)配置, 来调节性能.
首先是, 手册提出了occupancy的概念, 和这个概念的重要性, 以及, 观察从而能设定occupancy的3种方式.
各位读者, 只要是用CUDA的, 就一定遭遇过occupancy这个词, 俗称"SM占用率"。这是一个百分比值, 例如某kernel在某卡上运行, 取得了90%的占用率; 而某某kernel, 则在此卡上, 只有30%的占用率, 等等。
你的同学, 同事, 朋友, 总在会尝试劝告你说, 一定要提高这个占用率啊, occupancy高了才能性能好啊, 否则你就在浪费你的卡啊, 类似这种说法.
这种说法对也不对。
首先手册说了为何这种说法对:
因为我们的GPU是一个吞吐率为设计目标的处理器, 每一个晶体管都是尽量为了最大化的提供性能而存在, 而不像CPU那样, 为了延迟而设计, 很多晶体管都在为尽快做好1件事情而努力. 这点我们之前说过.
所以为了这点, GPU需要用海量的线程在SM上执行着, 当某些线程(精确的说, warp)卡住了, GPU从而能切换到另外一些线程去执行. 用这种简单的方式, 最大化的发挥性能. 等于我同时在洗衣, 做饭, 看娃多种任务同时进行, 一旦我卡在了等待洗衣机运转上, 我就可以切换去做饭, 一旦做饭正在煮着了, 我就可以去给娃喂奶. 用这种方式反复横向切换, 从而能最大化的利用我的时间(GPU的性能).
而Occupancy则代表了, GPU的SM上能驻留的线程数量(我今天在干的活的数量), 和该SM的最大能驻留的线程数量的(我累死最大能同时干的活的数量)的比值。这是occupancy的定义(实际上略微有差异, 特别是涉及到achieved occupancy的时候)。
100%的occupancy可以看成我一共能干10件事同时, 我今天就是在同时干10件事,而20%的occupancy则是我一共能干10件事今天, 但是我今天只同时干两件事。所以你看到, 一般情况下来说, 越高的occupancy(接近100%), 往往会越可能的发挥性能; 而越低的occupancy, 则往往会可能造成设备的低效运转。
这是今天手册上说, 为何为何尽量提高occupancy, 往往会提高性能的原因, 也是你的同事, 朋友, 同学往往会建议你这样提升的原因,但是事情不是那么绝对的, 有的时候, 较低的occupancy反而可能会带来更好的性能, 这点在历届GTC的演讲中都有提到过, 网上也能搜索到很多案例。
手册这里总的说法是, 因为当SM里的总资源固定的时候(想想成你家的面积好了), 较低的occupancy(想想成今天你只干2件事好了), 会给每件事带来更多的资源(想想成, 你需要一个手工画一个图, 较大的桌子可能让你干的更起劲, 从而比你同时用小桌子绘图憋屈, 同时在煮饭的总产出要好)。
下文我们会和手册一起, 对具体SM里的资源进行逐方面的分解, 看看occupancy vs 资源 vs 性能变化的具体讨论.