ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

GPU 架构速览:SM / SP / Tensor Core 与 AI

GPU 架构速览:SM / SP / Tensor Core 与 AI 为什么这篇值得先读硬件决定了你能写多快很多人学 CUDA 一上来就写 kernel结果调了半天发现「为什么我这个写法这么慢」。根子往往不在代码技巧而在没建立硬件心智模型——你优化的对象SM、寄存器、共享内存、Tensor Core长什么样、谁快谁慢你脑子里没有地图。根据 CUDA Programming Guide 的GPU Hardware Model我们可以抽象出一条物理约束GPU 把晶体管花在了「大量简单计算通道 充足片上存储」上而非「单线程跑得更快」上。这条约束不是经验归纳而是芯片面积分配的直接结果——它决定了本文后面所有结论。本文路线图从「为什么是这种结构」一路推到「怎么用结构指导选型与写法」是一条因果链不是知识清单。一、CPU 思维 vs GPU 思维从「核」到「SM」先纠正一个最常见的错误认知「GPU 有很多核」这句话是错的至少是误导性的。维度CPU 思维GPU 思维基本单位几个「胖核」大缓存 乱序执行很多「SM」小工厂内含 SP 阵列 Tensor Core优化目标降低单线程延迟latency提高整体吞吐throughput缓存多级 cache 对程序员透明共享内存是可编程 SRAM要你显式管理并行单位几十线程上百万线程thread block关键转变别再想「几个核」要开始想「几十到上百个 SM每个 SM 同时跑一个 block」。根据 Programming Guide一次 kernel launch 可能有上百万个 block而 GPU 只有几十~上百个 SM——所以编程模型硬性要求不同 block 之间不能有数据依赖它们会以任意顺序被调度。 隐性知识SM 不是「一个核」而是「一个能同时跑很多线程的小工厂」。把 SM 当成核会让你错误地用「核数」去估算力后面会看到这有多坑。二、最小实现用 30 行看清「我的 GPU 是什么」理解架构最快的方式是亲手问 GPU 要属性。最小实现只打印四个最关键的字段名字、计算能力、SM 数量、显存。// v0_naive.cu —— 最小设备查询自包含不依赖 Windows 头文件 #include cuda_runtime.h #include cstdio int main() { // 先统计当前环境可见的 CUDA 设备数量 int deviceCount 0; // 查询当前环境可见的 CUDA 设备数量 cudaGetDeviceCount(deviceCount); // 没有设备时单独提示便于区分环境问题 if (deviceCount 0) { std::printf(无可用 CUDA 设备\n); return 1; } // 读取 0 号 GPU 的硬件属性 cudaDeviceProp prop; cudaGetDeviceProperties(prop, 0); printf(GPU 名称 : %s\n, prop.name); printf(Compute Capability : %d.%d\n, prop.major, prop.minor); printf(SM 数量 : %d\n, prop.multiProcessorCount); printf(全局内存 : %.2f GB\n, prop.totalGlobalMem / (1024.0f*1024.0f*1024.0f)); return 0; }cudaGetDeviceProperties把设备的全部属性填进cudaDeviceProp。注意这里没有错误宏、没有多卡遍历——它是「最小」只为建立「SM 数 / CC / 显存」的直观认知。在 N 卡机器上nvcc -archsm_90a v0_naive.cu -o /tmp/v0 /tmp/v0即可运行。三、性能优化版SM 内部解剖 代际识别最小版只问了「是什么」优化版要回答「凭什么」——哪些硬件资源直接约束你的 Kernel 写法。3.1 先分清三个词SM、SP、Tensor Core这三个词在后面几十篇里会反复出现先把它们的关系一次说清避免边学边混。SPStreaming Processor流式处理器GPU 里最小的执行单元负责执行单个线程的标量运算FP32/INT32。你常听到的「CUDA Core」指的就是 SP——两个词是同一个东西NVIDIA 营销材料爱用后者技术文档多用前者。一个线程在硬件上就跑在一个 SP 上。SMStreaming Multiprocessor流式多处理器由一组 SP、若干 Tensor Core、Warp Scheduler 和寄存器文件组成的执行单元——就是前文说的「小工厂」。它不是「一个核」而是一群核的容器。Tensor Core专做矩阵乘加的加速单元。普通 SP 一次算一个数Tensor Core 一条指令完成一小块矩阵如 16×8×16的乘累加且以warp 为单位调用——32 个线程共同发起一条矩阵指令而不是每线程各算各的。这就是为什么 AI 算力看 Tensor Core不看 CUDA Core 数。三者的包含关系一图收拢一句话记住分工thread 由 SP 执行warp 是调度单位Tensor Core 被 warp 整体调用来加速矩阵运算。这条「谁调用谁」的关系是后续 wmma 编程、Tensor Core Utilization 指标解读的前提。SP 与 Tensor Core 的分工对比维度SP / CUDA CoreTensor Core计算粒度标量一次算 1 个数矩阵一条指令完成一小块乘累加调用主体每线程独立执行整个 warp 共同发起擅长通用并行逻辑、地址计算、非矩阵运算GEMM、Attention、卷积等大模型核心算子吞吐密度低相对高一个数量级以上同精度下一个 SM 里到底有什么这张图是后面整本专栏的「底色」寄存器、共享内存、Tensor Core 是你所有优化的物理舞台。上面是抽象图下面这张是 NVIDIA 官方的硬件结构总览可对照看 GPU 如何由 GPC 组织 SM、SM 内又含哪些功能单元对照上图每个部件如何约束写法寄存器文件每线程寄存器数 × block 线程数 ≤ SM 寄存器总量超了 block 无法 launch后续 Register Pressure 专题细讲。SP 阵列标量算力 SM 数量 × 每 SM SP 数。Warp Scheduler靠「多 warp 轮转」隐藏访存延迟——这就是 GPU 吞吐哲学的硬件实现。统一 Data Cache物理上同时承载 L1 与 shared memory两者共享 SRAM比例可运行时配置。Shared Memory同 block 线程可协作访问的可编程SRAM是后续 shared memory 文章的主战场。3.2 层级链Grid → Block → Warp → Thread记住这条链你写的 thread 永远属于某个 warp32 个warp 永远属于某个 blockblock 被整体丢给一个 SM。下图是 CUDA Programming Guide 给出的 Grid / Block 实际组织示意一个跨所有当前 NVIDIA GPU 架构的不变量warp 大小恒为 32从 G80 到 Blackwell 一直如此。所以 block 的线程数最好取 32 的倍数——不是倍数时最后一个 warp 有空闲 lane白白浪费功能单元与带宽。这也是后续所有 grid-stride loop、向量化、warp-level reduce 的锚点。warp 分支发散是 SIMTSingle Instruction Multiple Thread单指令多线程——一条指令由 warp 内 32 个线程在各自数据上同时执行的关键陷阱同一 warp 内线程走不同if/else分支时不匹配的分支会被 mask 掉、串行执行GPU 利用率下降。下图展示了偶数线程执行 if 主体、其余被 mask 的情形机制级展开利用率最大化的条件是「同一 warp 内线程走相同控制流」——这正是warp 分支发散优化专题的出发点。3.3 用 Compute Capability 识别 Tensor Core 代际光看名字不够真正决定 AI 算力的是Tensor Core 代际。下面这个函数把CC(major.minor)映射成语义// 根据 Compute Capability 判断 Tensor Core 的代际能力 const char* tensor_core_generation(int major, int minor) { // Volta 之前的架构没有 Tensor Core if (major 7) return 无 Tensor Core; if (major 7 minor 0) return Volta: FP16; if (major 7) return Turing: INT8/INT4; if (major 8 minor 9) return Ada: FP8(E4M3/E5M2); if (major 8) return Ampere: TF32/BF16/稀疏; if (major 9 minor 0) return Hopper: FP8 Transformer Engine; if (major 10) return Blackwell: FP4/FP6; return 未知代际(需核对官方文档); } 隐性知识CC 的 minor 版本常被忽视但它常常扩展 Tensor Core 的精度支持比如 FP8 在 Ada 8.9 与 Hopper 9.0 才出现。选精度前先看 minor别只记 major。⚠️一个容易被合并掉的细节FP64 Tensor Core 只有CC 8.0A100真正具备消费级 Ampere如 RTX 30 系列CC 8.6没有这个能力。上面的函数按大版本号把 8.0 和 8.6 都归成Ampere是为了速览简洁精确判断某张卡是否支持某个精度务必去查官方 Compute Capability 表不要只信 major 版本号。代际演进时间线精度以 NVIDIA 官方 Compute Capability 文档为准各代际具体支持以官网最新说明为准3.4 工业版多卡遍历 错误宏真实工程不会只看 0 号设备。v2 用CUDA_CHECK宏统一处理错误、遍历所有 GPU、用cudaDeviceGetAttribute取细粒度属性。核心差异是把裸调用包成// 统一检查 CUDA API 返回值失败时输出文件、行号和错误原因 #define CUDA_CHECK(call) do { \ cudaError_t e (call); \ if (e ! cudaSuccess) { \ fprintf(stderr, CUDA 错误 %s:%d — %s\n, \ __FILE__, __LINE__, cudaGetErrorString(e)); \ return -1; \ } \ } while (0)这个宏把每次 CUDA API 调用的错误检查集中到一个入口一旦调用失败会立即打印文件、行号和错误原因避免程序继续使用无效结果。后续遍历设备或读取属性时可以用CUDA_CHECK(...)包裹对应调用。四、Benchmark 与 Nsight本篇为何没有本文是概念篇GPU World / Phase 0配套代码是「设备属性查询」不含任何计算密集 kernel因此没有可测量的时间/带宽/TFLOPS也没有 kernel 可供 Nsight profile。这不是偷懒而是概念篇的合理边界——量化指标从后续的访存微基准和向量加法 kernel 文章才真正登场。本篇用「选型速查表 代际对照表」代替速度数字给你决策信息而非速度数字更符合概念篇定位。理由与完整说明见本文配套的 benchmark 与 nsight 说明文档。五、工业应用H100 / A100 / 4090 怎么选写法怎么变同样的模型换张卡写法可能完全不同。关键不在「谁跑分高」而在三点资源差异维度A100 (sm_80)H100 (sm_90)RTX 4090 (sm_89)显存40/80 GB HBM2e80 GB HBM324 GB GDDR6X带宽~2 TB/s~3 TB/s~1 TB/sNVLink✅✅ 4代❌FP8❌✅ Transformer Engine✅无 TE 调度ECC✅✅❌统一决策框架选型或优化一个 Kernel 前先看三件事——![[Pasted image 20260813171930.png]]这三点直接映射你的写法block 尺寸受 ② 约束精度选择受 ③ 约束能铺多开受 ① 约束。落到实际以下结论为推断需在 N 卡实测或官方文档中核对大模型训练H100 的 FP8 TE 3TB/s NVLink 是代差优势A100 靠 BF16/TF32 仍可靠带宽约 2TB/s与 H100 相比约有 1.5~1.7 倍差距。消费级推理4090 单卡算力惊人但 24GB 装不下大权重、无 NVLink 难多卡线性扩展、无 ECC——这就是它「跑分高、落地难」的根因。写法影响H100 上优先用 FP8 paged/fused 路径4090 上要更激进地做算子融合掩盖 GDDR6X 的相对带宽劣势A100 上 BF16 GEMM 大 tiling 是甜点。反例别把桌面显卡的「CUDA Core 数」即 3.1 节说的 SP 数直接当算力指标去和数据中心卡比。4090 的 CUDA Core 比 A100 多大模型推理却常掉队——根因是 HBM 带宽/容量与 NVLink 缺失而非 SP 数量。回到 3.1 的关系图就明白了CUDA Core 只是 SM 里跑标量运算的通道矩阵运算走的是 Tensor Core标量通道再多也替代不了后者。 隐性知识AI 算力真正的来源是Tensor Core 数量 × 代际精度 × 显存带宽不是 CUDA CoreSP数量。这是营销话术与工程事实之间最常踩的坑。六、面试题Compute Capability 与硬件特性如何对应答CCX.Y中 X 是架构代际SM 重新设计Y 常扩展 Tensor Core 精度支持CC 直接对应 SM 版本如 12.0→sm_120决定可编译特性。minor 版本别忽略——FP8 就在 8.9/9.0 才出现FP64 Tensor Core 更是只有 8.0A100才有8.6 的消费级 Ampere 并不具备。GPU 里为什么是很多 SM 而不是更少更大的「核」答吞吐优化的物理体现——用大量简单通道 多 warp 轮转隐藏延迟而非降低单线程延迟。SM 多意味着可并行 block 多、延迟隐藏能力强。warp 大小为什么重要答32 是当前所有 NVIDIA GPU 架构的不变量block 线程数取 32 倍数才不浪费 lane所有 lock-step 优化向量化、warp reduce都以它为基础。七、延伸阅读GPU Memory Hierarchy后续文章register → shared → L2 → HBM——本专栏的底层地图所有性能概念的根Warp 与 SIMT 执行模型后续文章、warp 分支发散优化外部NVIDIA CUDA GPU Compute Capability 页面CC 与特性权威表外部CUDA架构与原理.mdcuda-tutorial 仓库配套文档本篇延伸阅读的锚点内容收藏 讨论 速查表建议收藏SPCUDA Core执行单线程的最小单元SM小工厂内含 SP 阵列 Tensor Core Warp Schedulerthread 由 SP 执行Tensor Core 由 warp 整体调用warp32 不变量CC 的 minor 扩展 Tensor Core 精度FP64 Tensor Core 只有 A100 有选型看 SM 数 / 每 SM 资源 / Tensor Core 代际三点AI 算力看 Tensor Core×精度×带宽不是 CUDA Core 数。 下一篇预告《GPU Memory Hierarchy》——为什么 shared memory 比 global 快所有后续优化合并访问 / tiling / 融合其实是同一件事的不同层级表达。 开放问题如果你要在「单机 4×4090」和「单机 1×A100 80G」之间选一个跑 70B 推理你会怎么选理由里的「带宽 / 容量 / NVLink」哪一项权重最高欢迎在评论区聊。
返回列表