当前位置: 首页 > news >正文

CUDA NCU Occupancy学习笔记

占用率是每个多处理器的活跃 Warp 数量与最大可能活跃 Warp 数量的比率。另一种查看占用率的方式是,硬件处理 Warp 的能力中,实际使用 Warp 的百分比。较高的占用率并不一定能带来更高的性能,然而,较低的占用率总是会降低隐藏延迟的能力,从而导致整体性能下降。执行过程中,理论占用率与实际占用率之间的巨大差异通常表明工作负载高度不平衡。 

https://www.bilibili.com/video/BV1WNrHY5EeP

https://blog.csdn.net/feng__shuai/article/details/125665305

occupancy:占用率

一个SM中理论最大能支持M个active warp,实际上受限于SM中的资源只能支持N个

occupancy = N / M

  • 占用率指的是 某个 GPU Streaming Multiprocessor(SM) 上实际处于活动状态的 warp 数,占该 SM 理论上能同时容纳的最大 warp 数的百分比。
  • warp 就是一组 32 条线程的集合;在一个 SM 里同时挂起的 warp 越多,就越能在一次指令延迟(如访存)期间切换到其他 warp,从而隐藏延迟、提高并行度。

SM可以同时处理多个warp,受限于资源(执行单元、寄存器、共享内存等),并不是所有的warp都能同时活跃。

active warp是指正在执行指令的warp,可能处于不同的执行阶段:

(1)正在执行计算任务;

(2)正在等待内存访问结果

(3)正在执行控制流指令

上面是Ada架构(NVIDIA RTX4060、RTX4090等系列GPU)的SM内部结构,一个SM中有128个Core,所以至少能放下128个线程,对应4个warp。

为了隐藏延迟,需要在一个SM中放入更多的warp。

根据显卡架构的不同,可以计算出一个SM中最多承载的warp数量。

(1) 设置的block的大小。

同一个block必须跑在同一个SM中,同一个block不能跑在不同的SM上。同一个SM中可以容纳多个block。

(2)SM中寄存器文件的大小

CUDA延迟隐藏机制为:当一个warp处于等待状态,会立刻切换到下一个warp,保证SM中的计算单元cuda core上始终存在warp在执行,不至于cuda core存在空闲的时刻。GPU有大量的寄存器,每个thread都有自己的寄存器,不存在线程切换时切换上下文的开销,CUDA中warp切换的开销约为0。 

(3)SM中共享内存的大小

 (1)(2)(3)可以分别计算出一个SM中最多承载的warp数量,取三者之间的最小值。

可以使用CUDA Occupancy Calculator(CUDA 占用率计算器)计算Occupancy

一颗 GPU 里有很多 SM(Streaming Multiprocessor),每个 SM 像一间教室,里面坐着学生(线程)分组(warp)上课。每项上限就是教室的“消防规章”,决定一次能塞多少人、发多少书(寄存器)、用多大黑板(共享内存)。你写 kernel 时的线程块(block) 就得在这些规章内排座位,否则编译器/驱动直接报 “out of resources”。

#Property (截图原文)物理含义对 kernel/占用率(occupancy) 的影响
1Threads per Warp = 32CUDA 规定 32 条线程组成一个执行单元 warp,硬件线程调度都是以 warp 为粒度。决定了许多数值必须是 32 的倍数(如寄存器分配、分支同步)。
2Max Warps per Multiprocessor = 48一个 SM 最多同时“挂起”48 个 warp。48 warp × 32 线程 ≈ 1536 线程/SM 就是下条上限。若寄存器/共享内存用太多导致只能挂更少 warp,occupancy 会降。docs.nvidia.com
3Max Thread Blocks per Multiprocessor = 24每个 SM 最多可驻留 24 个线程块(block)。如果你的 block 很小,理论上 24 个也封顶;如果很大,往往被寄存器或线程数先卡住。docs.nvidia.com
4Max Threads per Multiprocessor = 153648 warp×32 线程 = 1536。硬件能同时保留这么多线程上下文。这是占用率 100 % 时的“天花板”。线程多≠更快,超过隐藏延迟所需就没收益。
5Maximum Thread Block Size = 1024单个 block 里线程总数上限。典型调参:128 - 512 之间试;要破 1024 只能改算法拆块。
6Registers per Multiprocessor = 65536 (32-bit)每个 SM 共有 64 K 个 32 位寄存器。大内存还债最贵?不是,全局访存才贵。寄存器是最快的,但总量固定——线程太多或每线程寄存器太多都会抢这个池子。docs.nvidia.com
7Max Registers per Thread Block = 65536同一个 block 能分到的寄存器总量上限(也是全部 64 K)。如果 block 本身就把 64 K 寄存器吃光,只能独占 SM,occupancy 直接锁死到 1 块。
8Max Registers per Thread = 255单线程能用的寄存器数上限(编译器会给 256 向上取整)。>255 时编译报错。高寄存器/线程可能触发溢出(spill),把寄存器内容写到慢得多的本地内存。docs.nvidia.com
9Shared Memory per Multiprocessor = 102 400 B (≈100 KB)每个 SM 可用的共享内存总量(Ada 架构把它和 L1 Cache 共享,可动态“分房间”)。这 100 KB 由所有驻留块瓜分,算 occupancy 时必须够用。docs.nvidia.com
10Max Shared Memory per Block = 102 400 B单个 block 能申请的共享内存。Runtime 还会帮你占掉 1 KB(见条 14),所以有效是 100 KB-1 KB ≈ 99 KB。如果你申请 >48 KB,需要 cudaFuncSetAttribute 显式“开闸”才能发射 kernel。docs.nvidia.com
11Register Allocation Unit Size = 256寄存器按 256 个为最小“页” 分配给 一个 warp。不够整页会向上取整。例:一个 warp 真正只需 33 ×寄存器,硬件仍按 256 给;浪费越多,可驻留 warp 就越少。forums.developer.nvidia.com
12Register Allocation Granularity = warp寄存器配额以 warp 为粒度,而不是线程或 block。这就是为啥上一条要整页向上取整。forums.developer.nvidia.com
13Shared Memory Allocation Unit Size = 128 B共享内存也是按 128 字节对齐、向上取整。所以即便你只用 1 字节,也会吃掉 128 B,可能让多个 block 无法并存。hanhaowen.github.io
14Warp Allocation Granularity = 4当计算寄存器 & 共享内存限制时,warp 数会向上取到 4 的倍数举例:21 warp → 硬件按 24 warp 计;多出来的“幽灵 warp”仍要算寄存器,所以占用率计算会更紧。forums.developer.nvidia.com
15Shared Memory Per Block (CUDA runtime use) = 1024 BCUDA 运行时保留的 1 KB“私房钱”,用于内部参数、动态调度数据等。实际可用共享内存 = 条 10 上限 − 1024 B。保证 kernel 不会把自己撑爆。docs.nvidia.com

block_size对SM可启动warp数量的限制

由上表可知

(1)每一个block必须分配到一个SM中;

(2)一个warp中有32个线程;

(3)每一个SM最多可以放48个warp(1536个线程);

(4)每一个SM最多可以放24个block。

假设设置的一个block中的线程数量为70,则一个block中的warp数量为3,由于每一个SM中最多可以放48个warp,因此一个SM中有16个block。

(16 block / SM * 3 warp / block) / 48 warp / SM = 100%

假设设置的一个block中的线程数量为32,则一个block中的warp数量为1,由于每一个SM中最多可以放48个warp,因此一个SM中有48个block。而每一个SM中最多可以放24个block,所以一个SM中有24个block,24个block总共24个warp。

(24 block / SM * 1 warp / block) / 48 warp / SM = 50%

假设设置的一个block中的线程数量为256,则一个block中的warp数量为8,由于每一个SM中最多可以放48个warp,因此一个SM中有6个block。而每一个SM中最多可以放24个block,所以一个SM中有6个block,6个block总共48个warp。

(6 block / SM * 8 warp / block) / 48 warp / SM = 100%

假设设置的一个block中的线程数量为160,则一个block中的warp数量为5,由于每一个SM中最多可以放48个warp,因此一个SM中有9个block。而每一个SM中最多可以放24个block,所以一个SM中有9个block,9个block总共45个warp。

(9 block / SM * 5 warp / block) / 48 warp / SM = 93.75%

register对SM可启动warp数量的限制

由上表可知:

(1)每一个SM有65536个寄存器,64KB大小;

(2)寄存器的最小分配单元是256个;

(3)寄存器的分割粒度是warp;

(4)warp的分配粒度是4(如果warp allocation granularity为4,那么即使一个内核配置只需要3个warp的寄存器资源,硬件也会按照4个warp来分配寄存器资源)。

假设每个线程需要51个寄存器,一个block中的线程总数为128个线程

每个线程需要51个寄存器,每个warp需要51 * 32 = 1632个寄存器,1632个寄存器按照256粒度分配,1632 / 256向上取整 = 7,总共需要7 * 256 = 1792个寄存器

一个SM中总共有65536个寄存器,每个warp需要1792个寄存器,一个SM中的warp数量为36.57个warp,向下取整为36个warp

occupancy = 36 / 48 = 75 %

假设每个线程需要90个寄存器,一个block中的线程总数为128个线程

每个线程需要90个寄存器,每个warp需要90 * 32 = 2880个寄存器,1632个寄存器按照256粒度分配,1632 / 256向上取整 = 12,总共需要12 * 256 = 3072个寄存器

一个SM中总共有65536个寄存器,每个warp需要3072个寄存器,一个SM中的warp数量为21.33个warp,向下取整为21个warp

warp的分配粒度是4,但是分配24个warp需要的寄存器资源,一个SM的资源不够,因此只能分配20个warp。

occupancy = 20 / 48 = 41.66 %

共享内存(smem)对SM可启动warp数量的限制

由上表可知:

(1)每一个SM有102400 bytes大小的共享内存

(2)共享内存的分配单元大小是128 bytes

(3)每个SM必须分配1024 bytes共享内存

假设一个block中有128个线程,每个block需要5000 bytes共享内存

每个block需要共享内存大小1024 + 5000 = 6024 bytes

按照128 byte粒度分配,6024 / 128 = 47.0625,向上取整 48 * 128 = 6144 bytes,所以每个block实际需要6144 bytes共享内存。

每个SM中总共有102400 bytes共享内存,102400 / 6144 = 16.667个block,即一个SM中只能存放16个block。

16个block对应16 * 4 = 64个warp,超过了一个SM中只能最多48个warp的规定,因此,一个SM中有48个warp,对应12个block

occupancy = 48 / 48 = 100 %

http://www.lryc.cn/news/574566.html

相关文章:

  • 触觉智能RK3506核心板/开发板-开源鸿蒙+星闪分享(上)
  • Web Worker 通信封装与实战应用详解
  • .NET Core充血模型
  • go语言 *和
  • 配置自己的NTP 服务器做时间同步
  • HTML炫酷烟花
  • 知乎-AI大模型全栈工程师课程1~12期(已完结)
  • 通义灵码2.5智能体模式实战———集成高德MCP 10分钟生成周边服务地图应用
  • 同城信息发布 app 交流互动系统框架设计
  • WPF 几种绑定 (笔记)
  • maven:迁移到 Maven Central 后 pom.xml的配置步骤
  • pdf转图片(png,jpg)的python脚本
  • 发布 npm 包完整指南(含账号注册、发布撤销与注意事项)
  • 【云计算】云测试
  • 成交量流动策略
  • Unity3D仿星露谷物语开发70之背景音乐
  • 软件测试报告机构如何保障软件质量与安全性?作用有哪些?
  • 使用 PyFluent 自动化 CFD
  • 用 Python 打造立体数据世界:3D 堆叠条形图绘制全解析
  • 【Pandas】pandas DataFrame update
  • 华为云Flexus+DeepSeek征文 | 华为云MaaS平台上的智能客服Agent开发:多渠道融合应用案例
  • 《C++初阶之类和对象》【初始化列表 + 自定义类型转换 + static成员】
  • 在 centos7部署kubephere
  • TortoiseSVN 安装教程
  • prometheus+grafana+MySQL监控
  • 云原生周刊:Argo CD v3.1 正式发布
  • 工程优化——WebSocket、WSS(WebSocket Secure)和SSE(Server-Sent Events)通信对比
  • Jenkins+Jmeter+Ant接口持续集成
  • 【人工智能agent】--dify实现文档内容的自动抽取
  • 论文阅读:2025 arxiv Qwen3 Technical Report