前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CUDA优化冷知识20|不改变代码本身如何提升性能?

CUDA优化冷知识20|不改变代码本身如何提升性能?

作者头像
GPUS Lady
发布2021-03-12 16:32:34
4200
发布2021-03-12 16:32:34
举报
文章被收录于专栏:GPUS开发者

这一系列文章面向CUDA开发者来解读《CUDA C Best Practices Guide》 (CUDA C最佳实践指南)

大家可以访问:

https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html


因为GPU的SM是海量超线程的, 远比常见的CPU的一个物理核心的2个或者4个超线程(HT)要多的多, GPU依靠这种海量的超线程数量来提供最大可能的吞吐率(这点我们稍后说)。而这种海量的超线程, 当你每个线程的寄存器资源用的比较多的时候, 则SM上能同时驻留的线程数量就越少, 从而影响了GPU的这种海量的超线程的能力, 从而潜在的可能影响了性能的发挥,所以有的时候我们不能肆无忌惮的使用寄存器资源,而是需要通过某种手段去限制编译器生成的代码中, 对寄存器的具体使用数量。

在日常的应用中, 不改变代码本身, 而是简单的改变每个线程的寄存器资源使用数量(变多或者变少), 就有可能提升性能,所以这是一种常见的优化方式, 具体到今天的手册章节, 手册提出了两种做法:

一种做法是编译的时候, 对每个具体的.cu的CUDA源代码文件, 使用nvcc -maxrregcount=N的参数来编译。这种做法将会把此文件中的所有的kernel, 都统一限定成最多使用N个寄存器。

注意这里有需要注意的地方, 首先是这种限制是以源代码文件为单位生效的, 如果你文件中存在不止一个kernel, 则所有的kernel的限制都是一样的, 你有的时候可能不得不拆分源代码成多个文件, 从而使得每个文件里面只有1个kernel, 从而能单独的用-maxrregcount=N的参数来限定。

其次则是这种做法限定的是Regular Registers, 注意到参数中是maxrreg, 而不是maxreg了么, 中间多了一个r. 而其他种类的寄存器, 例如predicate register或者uniform register(计算能力7.5+), 则无法通过这种方式限制, 但好在一般我们也不需要限制后两种寄存器的数量。

这是手册今天告诉我们的第一种限制方法, 简单明快的限定成N这种具体值, 比较直接.

而手册中说到的另外的一种限制方式, 则是通过__launch__bounds__()来修饰kernel本身,将此行放置在kernel的最前面, 即可限制该kernel的寄存器使用数量。

注意这种方式可以每个kernel单独放置一种修饰, 甚至可以每个kernel根据编译时候的计算能力选择, 放置多种修饰. 控制性比较强,因为它不想-maxrregcount那样的是整个文件一起来的, 人家是单个kernel, 甚至单个kernel的单个计算能力编译下的效果来的, 所以可以很精细的指控。

但是坏处是, __launch__bounds__()无法直接指定一个具体的寄存器用量N, 而是间接的指定我需要1个SM上最少有XX个YY线程的Blocks, 然后编译器再自动计算一下, 这个XX个是需要限制到多少个寄存器的情况下, 才能满足约束, 类似这种的. 比较晦涩一点。

所以实际使用中, 这两种方式可以根据需要来, 一个直接的粗糙的; 一个间接的精细的. 读者们可以尝试根据实际需要使用.

这是我们今天所说的, 通过限制寄存器数量来尝试优化性能的两种具体做法.

下一篇, 我们会说一下菱形启动符号, 也就是<<<>>>这种, 和其他一些方面, 能带来的性能变化。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GPUS开发者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档