GPU 核心执行单元 SM 入门:一条指令在 Turing SM 里怎么流动
文章目录SM (Streaming Multiprocessor) architecture1. Instruction scheduling/front-end1Warp scheduler2Dispatch2. Register File3. Execution unit layer1FP3232-bit Floating Point2INT3232-bit Integer3Tensor CORES4SFUSpecial Function Unit5LD/STLoad/Store4. Data Layer1L1 Data Cache / Shared Memory2Tex Texture 5. RT (Ray Tracing) CoreSM (Streaming Multiprocessor) architectureTU102 系架构为基准说明在每个时钟周期上的协作调度scheduler→ 取数RF/L1→ Compute/访存各单元→ writebackRF/内存→ 下一条指令多段流水在时间上重叠调度器每周期可尝试 issue但单条指令从发射到写回往往多周期至少 2 cycle。官方应以 Turing Whitepaper Figure 4 Turing Tuning Guide 文字说明为准常见 TU102 SM 示意图通常省略了 FP64 单元而 Turing 实际上每个 SM 仍有 2 个 FP64 units。1. Instruction scheduling/front-endSM 顶层是 4 个小调度器每个负责自己那一块算力资源。Dispatch按类型选具体硬件单元Warp Scheduler按 warp 选指令类型读取 warp 状态筛出 ready warps选择某个 warp 下一条指令类型是否FP32INT32LD/STTensorSFU是否是否是否是否是否Warp 池(PC / 依赖 / 掩码 / 状态)Warp SchedulerReady Warp 集合本拍是否 issue发射 1 条指令(warp 指令类型)本拍空转不发指令指令入口选择目标管线类型选择具体 FP32 pipe选择具体 INT32 pipe选择具体 LD/ST pipe选择具体 Tensor Core选择具体 SFUFP32 pipe本拍可用INT32 pipe本拍可用LD/ST pipe本拍可用Tensor Core本拍可用SFU pipe本拍可用FP32 执行管线INT32 执行管线LD/ST 执行管线Tensor Core 执行管线SFU 执行管线结构冲突/已满延后到下一拍结构冲突/已满延后到下一拍结构冲突/已满延后到下一拍结构冲突/已满延后到下一拍结构冲突/已满延后到下一拍1Warp scheduler选 warp 指令**管理对象**维护自己名下的一组 warp PC[^program counter]、寄存器依赖、是否 stall 等。核心动作a. 在这组 warp 里选择ready 的 warp没有 数据/结构/控制依赖冲突b. 取出这个 warp 的下一条指令做基本的依赖/掩码检查c. 在当前这个时钟周期warp scheduler 要不要 issue 一条指令以及从哪个 warp、哪种类型的指令来 issue。粒度工作在warp 级不关心具体是哪一条 FP32 ALU 或哪一个 Tensor Core只是决定“本拍发一条 FP32 指令 / INT32 指令 / LD/ST 指令 / Tensor 指令”。2Dispatch指令怎么发到具体的硬件**输入**warp scheduler 给出的结果哪个 warp这条指令的类型FP32、INT32、Tensor Core、LD/ST、SFU 等输出把这条指令路由到对应的执行pipeline某条 FP32 pipe、某条 INT32 pipe、某个 Tensor Core、某个 LD/ST pipe 等处理结果冲突比如该类型管线本拍已满/有冲突就会让这条指令延后等下一条可用周期再发。特点同一个 warp scheduler 下面挂着一组具体算术/访存单元dispatch 决定这一拍这些单元各自收到哪条指令2. Register FileWarp Scheduler │ │ Issue instruction ▼ ┌──────────────────────────┐ │ Register File │ ← High-speed workspace / data staging hub │ 16,384 × 32-bit × 4 │ └──────────────────────────┘ ▲ ▲ │ Read operands │ Write results │ │ │ ┌──────────────────────────────┐ └─────▶│ FP32 / INT32 / Tensor Cores │ │ SFU / LD/ST and other │ │ execution units │ └──────────────────────────────┘ ▲ │ LD/ST moves data from L1/Shared or lower memory levels into registers寄存器是 SM 内所有算力单元共享的“高速工作台”数据在这里周转。Register File16384 x 32 bit1每个子块都有专属的 16384 x 32-bit 寄存器。协作关系warp scheduler 决定执行一条指令时 会从寄存器里文件读出这条指令所需的源操作数这步就是“取指”。执行单元算完后再把结果写回寄存器访存指令通过 LD/ST 从 L1/Shared 或更下层把数据搬进寄存器后续算术指令再从寄存器取。3. Execution unit layerWarp scheduler 先从 register file 取操作数并决定发哪一条指令dispatch 再按指令类型把它分发到对应的 pipeline各 pipeline 完成计算或数据搬运后再把结果写回 register file。1FP3232-bit Floating Point执行所有单精度浮点single-precision floating-point算术指令比如FADD/FFMA[^fused floating multiply-add]/FMUL[^floating-point multiply] 等是Graphics shader 和 CUDA浮点运算的计算单元。每个时钟周期warp scheduler 会把 warp 的 FP32 指令发到这个区域执行实现向量化的32线程并行浮点运算。2INT3232-bit Integer负责Integer and pointer运算地址计算循环计数等。Turing 的特点是FP32 和 INT32 单元是独立的可以在同一周期同时跑一条 FP32 指令 一条 INT32 指令提高资源利用率。3Tensor CORES每个 SM 有8 个 Tensor Cores通过专门的矩阵指令wmma/mma被调用用于 FP16/INT8 等矩阵乘加结果可累加到 FP32。Scheduler 看到是“矩阵指令”就把它下发到 Tensor Cores而不是普通 FP32 块。4SFUSpecial Function Unit图里红色的SFU负责sin/cos/rcp/rsqrt等特殊函数和插值。调度上也是一类独立的 pipelinewarp 里遇到这种指令就会发到 SFU。5LD/STLoad/Store┌─── SM (Streaming Multiprocessor) ──────────────────────────────┐ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ Register File (每线程的寄存器) │ │ │ │ R0, R1, R2, R3 ... │ │ │ └────────┬──────────────────────┬──────────────────┘ │ │ │ │ │ │ │ 数据 │ 数据 │ │ ▼ ▼ │ │ ┌────────────────┐ ┌─────────────────┐ │ │ │ CUDA Core │ │ Tensor Core │ │ │ │ INT / FP │ │ MMA │ │ │ │ 算术运算 │ │ 矩阵运算 │ │ │ │ │ │ │ │ │ │ R4 R1 R2 │ │ D A*B C │ │ │ └────────────────┘ └─────────────────┘ │ │ │ │ ※ 计算单元只能读写 Register不能直接碰 Memory │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ Register File │ │ │ └────────┬──────────────────────┬──────────────────┘ │ │ │ ▲ │ │ Store │ RF → Mem Load │ Mem → RF │ │ ▼ │ │ │ ┌────────────────────────────────────────────┐ │ │ │ LD/ST Unit │ │ │ │ 地址生成 / 数据搬运 / Atomic 操作 │ │ │ └────────┬──────────────────────┬─────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────────┐ ┌──────────────────┐ │ │ │ Shared Memory │ │ L1 Cache │ │ │ │ (SMEM) │ │ │ │ │ │ SM 内共享 │ │ L1 Hit → 返回 │ │ │ └──────────────┘ │ L1 Miss ↓ │ │ │ └────────┬─────────┘ │ │ │ │ └─────────────────────────────────┼────────────────────────────────┘ │ SM 外部 ▼ ┌──────────────────┐ │ Crossbar / NoC │ └────────┬─────────┘ ▼ ┌──────────────────┐ │ L2 Cache │ └────────┬─────────┘ ▼ ┌──────────────────┐ │ Memory Controller│ └────────┬─────────┘ ▼ ┌──────────────────┐ │ HBM (Global Mem) | |___________________|Load/Store 单元负责从向Register与L1/Shared/global memory之间搬数据1本身不做ALU算术指令只做地址生成和内存访问。4. Data LayerSM 内部的“本地存储与局部缓存”和执行单元通过 LD/ST/Tex 单元粘在一起。1L1 Data Cache / Shared Memory图中绿色块下面的青色条96KB L1 Data Cache / Shared Memory是 Turing 把 L1 cache 和 Shared Memory 合在一起的设计。协作LD/ST 单元访问时优先在本 SM 的这 96KB 里命中可能是作为 L1、也可能是 Shared没命中再通过跨 SM 的 L2 cache、显存去取。2Tex Texture 纹理单元就是 GPU 里专门负责“按坐标从贴图里取出颜色”的那部分硬件。L1 下面蓝色的四个Tex方块是纹理单元带有自己的纹理 cache。图形/光线追踪着色时着色器Shader 会发起纹理采样请求请求进 Tex 单元 → 在 Texture cache/L1/L2/显存里取纹理像素texel → 把结果送回寄存器再喂给上面 FP32 块做后续计算。5. RT (Ray Tracing) Core挂在 SM 旁边的一个专用“光线求交ALU”通过特定指令被调用然后把结果写回到 SM 使用的寄存器/内存中。底部大黄块RT CORE是光线追踪专用硬件。协作模型Shader运行在 SM 的 FP32/INT32 等上发起 ray tracing 指令比如求交RT Core负责在 BVH 结构里做光线与三角形/包围盒求交效率远高于在 FP32 core 上软件算求交完成后把结果命中信息、距离等返回给 SM由 SM 继续后续着色计算。LD/ST 单元只和 SM 内部的 L1 Cache / Shared Memory 物理相连。访问 Global Memory 时LD/ST 发出地址请求L1 cache miss 后由片上网络 (NoC/Crossbar) → L2 → Memory Controller → HBM逐级完成。对 LD/ST 来说Global Memory 访问只是一次延迟很长的 L1 miss。 ↩︎ ↩︎