GPU资源基础:GPU硬件架构、显存层次、计算单元、流多处理器(SM)与并发执行原理
在进入TensorRT多模型共享GPU资源调度实战之前,必须先建立对GPU硬件底层的清晰认知。很多调度策略的制定——例如为什么某些模型适合共享显存、为什么并发执行时吞吐量不随核数线性增长、为什么显存带宽往往比算力更早成为瓶颈——其根源都在硬件架构的设计之中。本章将从GPU的整体硬件架构出发,依次剖析显存层次、计算单元、流多处理器(SM)的内部结构,以及并发执行的核心机制,为后续的TensorRT显存池化、多流调度和模型并发推理打下坚实的理论基础。
2.1 GPU整体硬件架构:从PCIe到SM阵列
现代独立GPU(如NVIDIA A100、H100、L40S等)通过PCIe总线或NVLink与主机CPU相连。从资源调度的视角看,GPU是一个拥有独立显存、独立计算单元和独立调度器的异构协处理器。主机侧通过CUDA API(如cudaMemcpy)将输入数据拷贝到GPU显存,再通过内核启动(Kernel Launch)将计算任务提交到GPU执行。GPU内部由多个图形处理簇(GPC)组成,每个GPC包含若干流多处理器(SM),SM是GPU最基本的计算单元。
| 层级 | 名称 | 容量/数量(以A100为例) | 延迟 | 调度视角作用 |
|---|---|---|---|---|
| L1 | 寄存器文件 | 每SM 256KB | ~1个时钟周期 | 线程私有数据,超分配导致寄存器溢出 |
| L2 | 共享内存 | 每SM 192KB(可配置) | ~20-30周期 | 块内线程共享,TensorRT算子融合常用 |
| L3 | L2缓存 | 40MB(A100) | ~200周期 | 跨SM共享,多模型并发时竞争热点 |
| L4 | 全局显存 | 40-80GB HBM2e | ~400-800周期 | 模型权重、激活值、TensorRT引擎序列化数据 |
2.2 显存层次与带宽瓶颈
显存层次是GPU性能调优的核心战场。全局显存(Global Memory)容量最大但延迟最高,L2缓存次之,共享内存和寄存器最快但容量极小。TensorRT在构建引擎时,会尽可能将权重和中间激活值驻留在寄存器或共享内存中,减少对全局显存的访问。然而,当多个模型共享GPU时,每个模型都会占用一部分L2缓存和显存带宽,导致缓存命中率下降和访存延迟增加。
nvidia-smi dmon或ncu(NVIDIA Nsight Compute)监测内存吞吐量。如果发现Memory Throughput接近100%而SM Activity较低,说明瓶颈在显存带宽而非计算单元。此时,多模型并发调度的重点应放在减少同时访问显存的模型数量,或通过TensorRT的setMaxWorkspaceSize限制每个模型的显存占用。
2.3 流多处理器(SM)内部结构与Warp调度
每个SM包含多个CUDA核心、Tensor Core、特殊功能单元(SFU)、共享内存和寄存器文件。以A100的SM为例,包含64个FP32 CUDA核心、64个INT32核心、4个第三代Tensor Core、以及4个Warp调度器。每个Warp调度器每时钟周期可以发射一条指令到一个Warp组(每组包含16个CUDA核心)。当某个Warp因访存等待而阻塞时,调度器会立即切换到另一个就绪的Warp,这种机制称为“延迟隐藏”。
// 查看GPU SM架构信息(Linux环境)
nvidia-smi -q | grep -A 20 "CUDA"
// 输出示例:
// CUDA Cores: 6912
// SM Count: 108
// Warp Size: 32
// Max Threads Per SM: 2048
// Max Threads Per Block: 1024
在TensorRT多模型共享场景中,SM资源的分配直接决定并发性能。如果两个模型分别占用不同的SM子集,它们可以真正并行执行;如果共享同一组SM,则通过Warp调度器的时间片轮转实现“伪并行”。TensorRT的ExecutionContext可以绑定到特定的CUDA Stream,而Stream的优先级和SM分配策略可以通过cudaStreamCreateWithPriority控制。
2.4 并发执行原理:Stream、Grid与Block
GPU并发执行的核心机制是CUDA Stream。一个Stream代表一个按顺序执行的操作序列,不同Stream之间的操作可以重叠执行。当多个模型分别运行在不同的Stream上时,GPU的调度器会尝试将它们的任务分配到空闲的SM上。然而,并发执行并非没有代价:每个Stream的上下文切换需要保存和恢复寄存器状态,且L2缓存和显存带宽是共享资源,过度并发会导致资源争抢。
2.5 案例拆解:多模型共享GPU时的资源争抢分析
假设某AI推理平台需要在单张A100(40GB显存,108个SM)上同时部署三个TensorRT引擎:一个BERT-Large(NLP,显存占用4GB,计算密集)、一个ResNet-152(CV,显存占用2GB,访存密集)、一个GPT-2(生成式,显存占用8GB,计算和访存均衡)。初始方案是三个模型各分配一个Stream,直接并发运行。
初始现象:整体吞吐量仅为单独运行时的2.1倍,远低于理论上的3倍。通过ncu分析发现:BERT-Large的SM利用率达到92%,但ResNet-152的SM利用率仅为35%,而GPT-2的L2缓存命中率从单独运行时的85%下降到61%。
分析判断:ResNet-152的卷积层需要频繁读取全局显存中的权重,而BERT-Large和GPT-2的Transformer层也在同时访问L2缓存,导致ResNet-152的缓存行被频繁驱逐。同时,三个模型的Kernel启动时间重叠,SM的Warp调度器需要频繁切换不同模型的线程块,增加了指令发射延迟。
优化操作:
- 将ResNet-152的Stream优先级设为高(
cudaStreamCreateWithPriority),确保其访存请求优先获得L2缓存行。 - 为BERT-Large和GPT-2分别创建两个Stream,并将它们的计算任务拆分为更小的Grid,以便在SM空闲时插入执行。
- 使用TensorRT的
setMaxWorkspaceSize将BERT-Large的工作空间从默认的1GB限制为512MB,减少L2缓存占用。 - 启用CUDA Graphs(
cudaGraphInstantiate)将每个模型的多个Kernel合并为一个图,减少Kernel启动开销。
结果对比:优化后,整体吞吐量提升至单独运行时的2.7倍,ResNet-152的SM利用率提升至68%,L2缓存命中率回升至78%。代价是BERT-Large的P99延迟增加了约8%,因为其部分计算被ResNet-152的高优先级Stream抢占。
复盘经验:多模型共享GPU时,不能只看总SM数量,必须分析每个模型的访存特征和计算特征。访存密集模型应优先获得L2缓存和显存带宽,计算密集模型应优先获得SM配额。TensorRT的IExecutionContext支持setInputTensorAddress和enqueueV2,配合CUDA Stream优先级和Graph机制,可以实现精细化的资源调度。
2.6 总结与关键要点
| 资源类型 | 关键参数 | TensorRT对应控制手段 | 多模型共享时的风险 |
|---|---|---|---|
| SM计算单元 | SM数量、Warp调度器数 | Stream优先级、Grid尺寸 | Warp切换开销增加 |
| 共享内存 | 每SM 192KB(可配置) | 算子融合、setMaxWorkspaceSize |
块间竞争导致bank冲突 |
| L2缓存 | 40MB(A100) | 缓存访问策略(cudaAccessPolicyWindow) |
缓存行驱逐,命中率下降 |
| 全局显存 | 40GB HBM2e | 显存池化、cudaMallocAsync |
带宽饱和,PCIe拷贝阻塞 |