#CUDA: Occupancy(占用率)详解

占用率是指每个多处理器(Streaming Multiprocessor,SM)的活动线程束(warps)数量与实际的活动warps数量的比率。
高的占用率不一定能提升性能,但低的占用率会降低内存延迟隐藏的作用,

Higher occupancy does not always equate to higher performance-there is a point above which additional occupancy does not improve performance. However, low occupancy always interferes with the ability to hide memory latency, resulting in performance degradation. 1

通常认为:一个SM中所有的线程在同时工作,那么这个SM的效率或占用率就是100%,在这种情况下,处理程序的速度是最快的,效率是最高的。如果实际中由于资源的限制(如,共享内存,寄存器),不是所有的线程都同时工作,这时,称正在运行的线程为活跃(actived)或常驻(resident)线程。

占用率一般受三个条件的限制:
1.SM最大并发线程数,SM最大并发Warp数,SM最大并发块数
2.共享内存资源限制
3.寄存器资源限制

以上三个资源跟硬件的计算能力相关,见 1 Table14
每个SM是GPU处理数据的最基本单元,它们运行都是独立并行的,SM的数量通常最直观地体现了GPU硬件的能力。

##SM最大并发线程数,SM最大并发Warp数,SM最大并发块数
SM最大并发线程数:即一个SM中最多同时执行的线程个数。
SM最大并发Warp数:即每个SM中最多执行的Warp数。
SM最大并发块数:即每个SM中最多执行的并发数。

这些参数决定了SM可最大并发线程数的理论值以及在不考虑资源(寄存器,共享内存)的情况下怎么分配块以达到最大的理论值。

由于每个Warp必然包括32个线程,我们假设每个块的线程数是32的倍数(一般都这样做),则线程数 = warp数×32。所以前两个指标是完全相关的。可以看作一问题或参数考虑。

SM最大并发的块数,块本身是个逻辑上的概念,也是编程中可控制的参数,反映到实际或物理上,其实是Warp每块。块的大小影响会直接影响占用率,有时会通过共享内存间接影响占用率。

举个例子:
GTX1050Ti中
SM最大并发线程数,SM最大并发Warp数,SM最大并发块数分别为:2048,64,32。
如上所说,让2048个线程同时运行即完成了达到了最优的占用率。为实现这一目标,假设在资源(寄存器和共享内存)允许的情况下:可以有很多中实现的情况,如:
2个1024大小的块
4个512大小的块
8个256大小的块

64个32大小的块

即SM最大的并发的线程数是2048,在不考虑资源的情况,其分配有6种情况。

##寄存器资源的限制

寄存器资源属于片上资源,具有很低的延迟,它作为一种稀有资源有时会成为占用率提高的瓶颈,所有的SM中的线程共享一定数量的寄存器资源,寄存器一次分配给一整个块,所以,如果一个块使用了一定数量的寄存器,SM上的常驻的寄存器数量就会减少。当一个块使用的寄存器数量超过了一定阈值(这根阈值由硬件决定,下面会讲到),寄存器不足以被所有块平均分配,此时,每个SM所能活跃或常驻的块就不能达到理论值或理想值,理论的占用率就不能达到100%。
One of several factors that determine occupancy is register availability. Register storage enables threads to keep local variables nearby for low-latency access. However, the set of registers (known as the register file) is a limited commodity that all threads resident on a multiprocessor must share. Registers are allocated to an entire block all at once. So, if each thread block uses many registers, the number of thread blocks that can be resident on a multiprocessor is reduced, thereby lowering the occupancy of the multiprocessor.

那么寄存器的阈值有那些呢?

  • Number of 32-bit registers per multiprocessor
    64 K
  • Maximum number of 32-bit registers per thread block
    32 K
  • Maximum number of 32-bit registers per thread
    255

即:
1.每个SM含有的寄存器数:
2.每个块最多含有的寄存器数
3.每个线程最多含有的寄存器数

首先,每个SM含有的寄存器数64KB,如果SM中每个线程都满载,每个线程可以分到32个32位寄存器,占用率是100%。每个块最大数量的寄存器是32K,但在这种情况下,只有块的大小是1024,也就是每个线程是32个寄存器的情况,SM中的线程才能被占满,占用率才能达到100%。每个线程最大的寄存器数255个,是一个线程所能有的寄存器的最大值。
每个块最多含有的寄存器数,每个线程最多含有的寄存器数都是块和线程所能拥有的寄存器的极限值,但这并不是最优值。达到极限值不能使占用率达到100%。而每个SM含有的寄存器数,决定了达到最优值的每个线程寄存器的上限(32个)。

总之,在不考虑共享内存,且块分配合理(见上6中分配方式)的情况下,只要核函数寄存器的数目小于32,理论上占用率就可以达到100%。

不能不提的是,有时占用率高并不意味这程序就快,有时低的占用率,使用更多的寄存器是更优的选择。(全局内存(或L2缓存)访问延迟非常之高)

##共享内存资源限制
首先明确的是,共享内存是块内的资源,其基本考虑单元是块。
每个块内线程要根据自己的索引操作共享内存,但注意的是使用__syncthreads()进行同步。
那么共享内存的阈值有那些呢?

  • Maximum amount of shared memory per multiprocessor
    96 KB
  • Maximum amount of shared memory per thread block
    48 KB

每个SM最大的共享内存数:96KB
每个块最大的共享内存数:48KB

每个SM最大的共享内存数:96KB,意味这如果2048个线程同时工作,每个线程可以分到48个字节,
的共享内存。每个块最大的共享内存数:48KB,意味这一个块内所限制的共享内存数为48KB。

总之,在不考虑寄存器,且块分配合理(见上6中分配方式)的情况下,如果每个线程使用的共享内存多于48个字节,则占用率会下降。

不能不提的是,有时占用率高并不意味这程序就快,有时低的占用率,使用更多的共享内存是更优的选择。(全局内存(或L2缓存)访问延迟非常之高)

##占用率的作用
GPUs thrive on parallelism and do so by covering memory latency with work from other threads2.
或见CUDA:延迟隐藏详解


修改(补充):
单个核函数内的计算耗时,可以隐藏其它内核内读取内存的时间,因此如果占用率越高,越有机会隐藏延迟


  1. https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html ↩︎ ↩︎

  2. https://stackoverflow.com/questions/12167926/forcing-cuda-to-use-register-for-a-variable ↩︎

CUDA: Occupancy(占用率)详解相关推荐

  1. Linux网站访问的电脑占CPU,详解Linux如何查看当前占用CPU或内存最多的几个进程...

    命令ps -aux | sort -k4nr | head -N 命令详解: 1.head:-N可以指定显示的行数,默认显示10行. 2.ps:参数a指代all--所有的进程,u指代userid--执 ...

  2. CUDA之nvidia-smi命令详解---gpu

    nvidia-smi是用来查看GPU使用情况的.我常用这个命令判断哪几块GPU空闲,但是最近的GPU使用状态让我很困惑,于是把nvidia-smi命令显示的GPU使用表中各个内容的具体含义解释一下. ...

  3. CUDA之nvidia-smi命令详解

    nvidia-smi是用来查看GPU使用情况的.我常用这个命令判断哪几块GPU空闲,但是最近的GPU使用状态让我很困惑,于是把nvidia-smi命令显示的GPU使用表中各个内容的具体含义解释一下. ...

  4. 显卡,显卡驱动,nvcc, cuda driver,cudatoolkit,cudnn详解

    在使用深度学习框架的过程中一定会经常碰到这些东西,虽然anaconda有时会帮助我们自动地解决这些设置,但是有些特殊的库却还是需要我们手动配置环境. GPU型号含义 参考[GPU编程系列之一]从深度学 ...

  5. CUDA占用率计算方法

    通常认为:一个SM中所有的线程在同时工作,那么这个SM的效率或占用率就是100%,在这种情况下,处理程序的速度是最快的,效率是最高的.如果实际中由于资源的限制(如共享内存,寄存器),不是所有的线程都同 ...

  6. tensorflow对应的python版本_详解Tensorflow不同版本要求与CUDA及CUDNN版本对应关系

    参考官网地址: Windows端:https://tensorflow.google.cn/install/source_windows CPU Version Python version Comp ...

  7. 详解CUDA核函数及运行时参数

    详解CUDA核函数及运行时参数 核函数是GPU每个thread上运行的程序.必须通过__gloabl__函数类型限定符定义.形式如下: __global__ void kernel(param lis ...

  8. 64位 int 占几个字节_面试常考,项目易错,长文详解C/C++中的字节对齐

    面试常考,项目易错,长文详解C/C++中的字节对齐​mp.weixin.qq.com 引入主题,看代码 我们先来看看以下程序 //编译器:https://tool.lu/coderunner/ //来 ...

  9. PE新物种:从投基金到投管理机构,详解GP Stake-投资占股模式

    PE新物种:从投基金到投管理机构,详解GP Stake-投资占股模式 原创: 周晨琦 FOFweekly 昨天 周晨琦 | 作者 朱东霞 | 编辑 引 例 ▼ Bridgepoint将其公司的少数股权 ...

最新文章

  1. 简明python教程 豆瓣-福利分享:个人整理的Python书单,从基础到进阶
  2. Android的开机流程及对应源码位置分析
  3. Hadoop Yarn任务优先级(作业优先级、应用优先级)设置
  4. 【优化SQL Server循环更新、插入耗时长的问题】
  5. 剖析Disruptor:为什么会这么快?(一)锁的缺点
  6. linux音量模块,Linux下的音量控制器alsamixer
  7. dbms_xplan之display_cursor函数的使用
  8. C# 读取app.config配置文件 节点键值,提示 配置系统未能初始化 错误的解决方案...
  9. HDU 4404 Worms(多边形和圆相交)
  10. hunnu11543:小明的烦恼——分糖果
  11. c 语言程序设计形考任务一,C语言程序设计形考任务.doc
  12. ubuntu安装python
  13. 蓝桥杯题目练习 提升篇 [蓝桥杯2018初赛]三体攻击
  14. Java爬虫入门(一)
  15. 小米原生浏览器标识.
  16. SDN(软件定义网络)简史-早期
  17. 计算机中求声音传输时间公式,混响时间常用的几种计算公式
  18. 通过抓包来看http三次握手的具体细节
  19. 数字电路设计: FPGA实现倍频
  20. Usability Engineering

热门文章

  1. RK3399支持5G-WiFi热点
  2. 互联网中的视频/音频服务
  3. deepin下安装mysql_deepin系统安装mysql
  4. duilib--corner属性总结
  5. 5G将给普通人,带来哪些黄金红利期?
  6. 牛客多校4J二分答案连续子段最大平均值
  7. 【提升coding能力】100道Python练习题11-20
  8. android studio评论功能,Android Studio 使用技巧
  9. WD --蓝盘绿盘黑盘红盘的区别
  10. 奥迪坚技术革新带动信用卡呼叫中心管理升级