公司动态
Blackwell GPGPU卡实战:多卡并发启动、训练与推理
这批卡到货那天我干的第一件事不是跑分而是把八张基于NVIDIA Blackwell架构的高性能GPGPU卡同时装进同一台机器按下电源看系统能不能在一个启动周期里把所有设备全部点亮。这个动作听起来很基础但做过GPU集群运维的朋友应该懂很多卡单张跑起来没有任何问题一旦多张同时上电、同时被驱动加载、同时接受CUDA runtime的任务下发就容易出现各种灵异事件——驱动加载超时、PCIe设备枚举失败、某个设备突然从拓扑里消失。而多卡并发启动恰恰是我这段时间一直在验证的核心能力。这篇文章想聊的是这套基于Blackwell架构的GPGPU卡在实际落地中的表现以及我在它身上完成的单卡、多卡、训练、推理、HPC调优工作。内容不写宣传话术只写机房里实际验证过的路径和踩过的坑。如果你正在做AI基础设施、训练集群、推理平台或者HPC资源池这篇应该对你有用如果你只是刚接触GPU计算里面关于驱动、CUDA、MIG的细节也可以当一份入门笔记来翻。1. Blackwell架构为何把GPGPU并发能力抬上了一个台阶1.1 硬件层面从双die互联到HBM3e先补一个背景。GPGPU卡的发展轨迹这些年基本就是围绕如何让更多计算单元和更多数据同时在片上流动展开的。Blackwell架构在这个方向上做的一件关键事是采用双die封装设计把两个相对较小的计算die通过高速互联封装在一起。这个设计解决了先进制程下单个大die良率不足的问题也让单张卡的SM数量、张量核心数量、显存控制器数量可以在封装层面继续堆叠。从这个角度理解Blackwell的GPGPU卡天生就有并发优势。过去单die时代所有SM都挤在一个die里访问同一组显存控制器到了双die时代两个die之间需要持续通信操作系统和CUDA runtime看到的是一整张卡而物理上这张卡内部已经存在两个并行计算域。如何把这两个域在驱动和运行时层面统一成一个逻辑设备同时还能让上层并发任务高效利用这非常考验软件栈的成熟度。我实测下来驱动和CUDA runtime在任务调度上确实把双die整合得比较平滑。HBM3e的引入是并发能力的另一个硬支撑。显存带宽决定了计算单元在并发执行时会不会因为等数据而空转。Blackwell架构的GPGPU卡在公开规格里普遍搭配更大容量、更高带宽的HBM3e这对多kernel并发、多实例并发有直接影响——数据能喂得进来计算单元才不会闲着。我跑训练任务时明显感觉到同样一批参数更新以前卡在H2D/D2H拷贝上的时间变短了显存控制器利用率的饱和度也更高了。1.2 并发启动提升的来龙去脉MIG、NVLink与SM调度把Concurrent Launches这个词细拆可以理解为三层含义。第一层是设备层面的并发启动也就是系统起来之后驱动能一次性加载并识别全部多张卡第二层是任务层面的并发启动即多个CUDA上下文、多个kernel或者多个进程能够在同一时刻真正并行执行而不是排队等待第三层是实例层面的并发启动即通过MIG把一张物理卡切成多个隔离实例每个实例都能作为一个独立设备被上层调度。Blackwell架构在任务层面的并发调度上强化了同一GPU内部多stream之间真正重叠执行的能力。说人话就是如果你在同一个CUDA stream里连续提交多个kernel它们不一定能重叠但如果你用多个stream提交并且每个kernel的资源需求没有把GPU占满现代架构就可以让它们真正在SM上并发执行。Blackwell的调度器和片上资源分配逻辑在这方面比前代更积极实测多stream并发时GPU利用率更容易拉满。第三层MIG我也重点测了。Blackwell架构继续支持并增强了MIG它能把一张物理卡切成多路实例每一路都有独立的显存带宽、独立计算份额和独立错误隔离域。这对推理服务尤其重要一个实例跑一个模型副本多个副本在同一张卡上并发运行一个实例上的问题不会波及其他实例。后面我在推理场景会专门讲实例划分时的注意点。1.3 为什么GPGPU卡和游戏卡在这件事上分道扬镳经常有人问我为什么A100、H100、Blackwell这些卡卖这么贵同价位的游戏卡不能拿来训练和推理核心原因之一就是并发能力。GPGPU卡需要同时被几十个用户、几千个进程、成千上万个kernel分享它必须提供大容量显存、ECC纠错、完整的内存保护、可预测的显存带宽隔离、更长的故障恢复窗口——这些都不是游戏卡的设计目标。游戏卡更关注低延迟帧渲染和单用户独占它的驱动和调度器在多进程长时间并发时性能可能回落甚至出现稳定性问题。另一个关键差异是互联能力。GPGPU卡有NVLink、有NVSwitch支持的直接GPU-GPU通信游戏卡几乎没有对等的直连方案多卡协同主要靠PCIe。当你要做8卡数据并行训练时每步迭代每个GPU都要和另外7个GPU交换梯度NVLink的带宽和拓扑结构直接决定同步开销。Blackwell架构的NVLink迭代到第五代单卡互联带宽相比第四代又有明显提升这对多卡并发是一个非常硬性的优势。没有这套互联体系游戏卡在集群场景里基本走不通。2. 从通电点亮到8卡并发压测的完整落地过程2.1 装机与BIOS/供电准备说实话第一次把8张卡装进机箱时最容易被低估的环节是供电。Blackwell架构的高性能GPGPU卡功耗不低单卡满载功耗在数百瓦级别8张卡同时跑起来整机瞬时功耗会非常惊人。所以我装机前会先确认电源的12V输出能力、PCIe供电线规格、主板插槽的供电走线以及机房里这一路PDU的电流上限。很多多卡并发点亮失败的问题根源不是驱动而是供电瞬间跌落导致设备掉卡。BIOS设置方面也有几个经验值打开Above 4G Decoding和Resizable BAR关闭CSM否则PCIe设备地址空间分配可能不够导致部分卡在系统启动后不被枚举。如果主板有多组PCIe switch尽量让8张卡分散开来避免全部挤在同一个switch下——虽然它们能工作但跨switch访问的延迟会变高GPU之间的P2P可能退化成PCIe路径而不是NVLink路径。这个物理拓扑层面的问题后面用nvidia-smi topo -m一眼就能看到。2.2 驱动、CUDA运行时与nvidia-smi验证装驱动我推荐用官方runfile方式配合DKMS。对GPGPU卡来说用稳定的长生命周期发行版配合新一点的驱动分支基本是标准组合。安装前先装好内核头文件和build-essential否则runfile会失败或者装完无法编译内核模块。命令大概是这样sudo apt update sudo apt install -y build-essential dkms linux-headers-$(uname -r) wget https://us.download.nvidia.com/XFree86/Linux-x86_64/版本/NVIDIA-Linux-x86_64-版本.run sudo bash NVIDIA-Linux-x86_64-版本.run --dkms --no-cc-version-check具体版本号请以官网驱动下载页为准数据中心卡优先选Data Center / Tesla分类下的长期支持分支。驱动装完先别急着重启检查一下模块是否生成lsmod | grep nvidia能看到nvidia、nvidia_modeset、nvidia_uvm这几个模块才算正常。然后重启再跑nvidia-smi能看到每个GPU的温度、功耗、利用率、显存时驱动这一关就算过了。顺便把nvcc -V和nvidia-smi的区别讲透。很多人被这两个东西绕晕。nvidia-smi里显示的CUDA Version是驱动接口所能支持的最高CUDA运行时版本nvcc -V显示的是CUDA Toolkit的编译器版本。驱动提供运行环境Toolkit提供编译工具链。只要驱动支持的CUDA版本不低于你项目编译需要的版本编译器版本高一点低一点通常不影响反过来如果驱动版本太低而编译器太高运行时会报driver API版本不足之类的错误。所以查版本时先分清你是在查驱动还是在查Toolkit。装完CUDA Toolkit后把环境变量写进/etc/profile.d/cuda.sh让所有用户都能用export PATH/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda/lib64:${LD_LIBRARY_PATH:-}2.3 八卡并发压测的启动脚本与观察点硬件和驱动就绪后真正的挑战来了8张卡同时开工。我的习惯是先把所有卡的持久化模式打开然后一次性启动8个计算进程每张卡一个sudo nvidia-smi -pm 1 for i in $(seq 0 7); do CUDA_VISIBLE_DEVICES$i ./bench --gpu $i /tmp/gpu_$i.log 21 done wait这里有个容易被忽略的点CUDA_VISIBLE_DEVICES$i只让进程看到对应物理卡但系统调度器很可能把多个进程扔到同一个CPU核心上尤其是可用的CPU核不够多时。这会造成一种假象GPU利用率看似正常但kernel启动和提交总在等待CPU资源。所以生产环境我会用taskset绑定CPU核或者用numactl --cpunodebind绑定NUMA节点。并发启动时我重点观察三个指标。第一nvidia-smi dmon -s pucm实时输出中每个GPU的利用率、显存控制器利用率和内存利用率是否同时爬升第二启动阶段是否有设备报ERR_SW_NOTIFICATION或设备掉线第三持续运行一段时间后模块温度、功耗是否稳定在预期区间。第一次压测时我就遇到过一张卡在启动后第3秒突然变成ERR!状态最后排查出来是供电线虚接。所以数据记录一定要有别只盯着屏幕看。2.4 拓扑、NUMA与CPU绑定多卡并发不只是8开而是要让8张卡和对应的CPU形成合理的互访路径。用nvidia-smi topo -m可以查看GPU之间以及GPU与CPU/NIC之间的拓扑关系。如果两张卡挂在不同CPU socket下它们通过PCIe通信的代价通常会比同一socket内的卡高一个量级除非它们的P2P路径能走NVLink。对于训练集群我的建议是让通信最频繁的GPU尽量落在同一NVLink域内然后通过numactl --cpunodebind把GPU进程绑定到离它最近的CPU node上。这一步看起来老生常谈但每次都能有效降低kernel launch和D2D拷贝的延迟。8卡并发压测里如果没有做NUMA绑定简单设置的bench跑出来可能差10%到20%。3. 驱动、容器与开机配置我把踩过的坑整理成了一份排错清单3.1 nvidia-smi无法与驱动通信的完整排查链路这是GPU服务器上最常见的报错原文是nvidia-smi has failed because it couldnt communicate with the nvidia driver. Make sure that the latest nvidia driver is installed and running.我自己的排查链路是这样的。第一步看内核模块有没有加载lsmod | grep nvidia如果一条输出都没有大概率是内核模块没装上或者内核升级后没有重建。直接试sudo modprobe nvidia如果报错说明编译产物和当前内核版本不匹配或者模块签名被拒绝。第二步看系统日志dmesg | grep -i nvidia如果看到nvidia: disagrees about version of symbol module_layout这类提示就是模块和内核版本对不上需要通过DKMS重新编译。第三步检查Secure Boot状态。UEFI安全启动开启时没有签名的NVIDIA内核模块会被拒绝加载。要么在BIOS里关掉Secure Boot要么用MOK管理工具给模块签名并注册。第四步如果之前安装过多个驱动版本建议卸载干净再装避免新旧模块文件混在一起。先执行sudo nvidia-uninstall再手动清理/lib/modules/$(uname -r)/kernel/drivers/video/nvidia*相关文件最后重新安装。3.2 重装驱动后重启失效DKMS与Secure Boot很多人遇到过这种情况Ubuntu或CentOS上新装驱动当时一切正常重启之后nvidia-smi又炸。核心原因通常是内核被升级了而驱动模块没有跟随新内核重新编译。解决这个问题的稳办法就是用DKMS。安装驱动时加--dkms参数让内核模块源码注册到DKMS体系之后内核升级时DKMS会在新内核构建过程中自动编译匹配的模块。顺带一个经验生产环境里我习惯锁定内核版本避免自动升级。Ubuntu上可以把linux-image-generic这些包设置成hold或者收紧unattended-upgrades的更新策略。GPU节点最怕半夜自动升级内核第二天早上起来发现全部掉线。不是不能自动升级而是要有计划、有窗口、有回滚方案。3.3 nvcc版本与驱动版本别再被这哥俩搞晕关于nvcc -V和nvidia-smi版本不一致的困惑我再补充一点。驱动是向后兼容的老驱动跑新Toolkit不一定行但新驱动跑老Toolkit一般没问题。所以你在一个集群里可以只升级驱动而CUDA Toolkit在用户层各管各的。很多开发环境里用户用conda装了自己的CUDA Toolkit完全没问题只要系统驱动的CUDA主版本号不比他需要的版本低就行。如果是多用户共享服务器建议保留系统级CUDA的同时让用户通过虚拟环境或容器自己管理Toolkit版本。这样能避免这个项目需要CUDA 11.x那个项目需要CUDA 12.x的冲突。我的做法是在每台GPU节点上装一个相对较新的系统级CUDA同时开放容器通道用户要什么版本都在自己的镜像里解决。3.4 给GPU做开机功率限制服务很多GPU服务器都有这个需求每次重启后功率上限又回到默认值。对Blackwell这类大功耗卡来说尤其需要提前规划机房供电。我习惯写一个systemd服务开机自动设置持久化模式和功率上限[Unit] DescriptionSet NVIDIA GPU persistence and power limit Aftermulti-user.target [Service] Typeoneshot ExecStart/usr/bin/nvidia-smi -pm 1 ExecStart/usr/bin/nvidia-smi -pl 300 [Install] WantedBymulti-user.target保存到/etc/systemd/system/nvidia-power.service然后执行sudo systemctl daemon-reload sudo systemctl enable --now nvidia-power.service注意-pl后面的数值要参考具体卡的最大功率限制不要拍脑袋填。可以用nvidia-smi -q -d POWER查看Max Power Limit。我习惯把功率上限设置在最大值的80%左右既保证性能又给机房供电留出安全余量。3.5 容器环境下的GPU透传配置现在跑训练和推理基本都是容器化NVIDIA Container Toolkit是标配。最常见的问题是宿主机驱动正常容器里看不到GPU或者docker run --gpus all报一堆错误。解决办法是重新配置容器runtimesudo nvidia-ctk runtime configure --runtimedocker sudo systemctl restart docker如果是Docker较老的版本还要检查/etc/docker/daemon.json里default-runtime是否切换成了nvidia。Kubernetes集群则要确保nvidia-device-plugin正常工作并且Device Plugin的版本和驱动版本兼容。我这里吃过一个亏升级了宿主机驱动但node上的device-plugin还是老版本导致K8s一直报Allocate失败。所以容器栈和驱动要一起纳入版本管理不能只盯着驱动一个组件。4. 训练、推理、HPC三种模式下这张卡的正确打开方式4.1 训练并行策略与NCCL环境先放一张公开规格对比表便于理解Blackwell架构卡在训练场景中的位置具体数值以官方发布为准项目A100 (Ampere)H100/H200 (Hopper)Blackwell显存类型/容量HBM2e40/80GBHBM3/HBM3e80GB/141GBHBM3e公开容量更高内存带宽约2TB/s3.35~4.8TB/s带宽进一步提升重点加速精度FP16/BF16引入FP8强化FP8与FP4NVLink代际第三代第四代第五代训练大模型时数据并行、张量并行、流水线并行都会用到多卡并发。Blackwell在FP8/FP4上的强化意味着如果训练管线能安全使用低精度同样的卡就能容纳更大的模型或更大的batch。如果跑分布式训练请重点确认NCCL的P2P路径是否走NVLinkexport NCCL_DEBUGINFO export NCCL_P2P_DISABLE0 export NCCL_P2P_LEVELNV不要盲从网上禁用P2P以保稳定的旧建议。NVLink域连接健康时P2P是首选只有确认P2P退化成PCIe路径并且性能严重下降时才考虑关闭。我用nvidia-smi topo -m观察过8张卡如果都落在同一个NVLink域里NCCL的AllReduce耗时能比跨PCIe路径低一个数量级。4.2 推理MIG切分与并发调度推理场景和训练差异很大。训练要的是单任务最大化吞吐推理要的是多个请求并发、低延迟、稳定输出。Blackwell的MIG能力在这里特别有用。通过MIG把一张物理卡切成多个实例每个实例独立加载模型实例之间互不干扰这在多租户推理服务里是很实用的方案。典型流程如下前提是驱动和硬件支持MIGsudo nvidia-smi -i 0 -mig 1 sudo nvidia-smi mig -i 0 -lgi # 查看可用实例配置 sudo nvidia-smi mig -i 0 -cgi 配置ID -C切完后进程通过CUDA_VISIBLE_DEVICESMIG设备地址使用指定实例。有一个容易忽略的点MIG实例隔离的不只是算力和显存容量还包括显存带宽和L2缓存分片。规划实例时不能只看模型能塞进多大的显存还要看模型对带宽的敏感度。一个带宽敏感的模型被分到带宽份额较小的实例里跑起来可能比预期慢很多。所以MIG配置最好根据实际业务的benchmark来定不要只看数字分配合不合理。推理引擎方面TensorRT-LLM和vLLM都已在快速适配Blackwell架构。使用这些框架时请把CUDA、TensorRT和框架版本升级到官方推荐的新版本旧版本可能在SM调度或低精度计算路径上没法利用新卡特性。并发调度上建议启用continuous batching让GPU在等待生成token时不至于空转这个调整对吞吐的提升非常明显。4.3 HPCFP64、CUDA-aware MPI与作业调度HPC场景看中的是双精度性能和长时间稳定运行能力。Blackwell的GPGPU卡在HPC里的角色通常是和CPU集群混合的加速节点。和训练不同HPC任务经常是各自独立的进程通过MPI通信因此并发更多表现为多节点、多进程在同一个资源池里的并发调度而不是单张卡内多个stream的重叠。关键配置有三个。第一CUDA-aware MPI。OpenMPI和MPICH在编译时开启CUDA支持后MPI收发缓冲区可以直接指向GPU显存避免先拷贝到主机内存再发送这对大规模科学计算能省掉一大笔数据搬运开销。第二作业调度。Slurm集群里--gpus8和--gresgpu:8要配合cgroup配置确保不同作业不会抢占同一张卡。第三统一内存和UVA。某些科学计算任务对H2D/D2H拷贝非常敏感合理使用cudaMallocManaged或CUDA_MANAGED_FORCE_DEVICE_ALLOC可以减少手工搬运。5. 并发启动之外更值得关注的几个运维细节5.1 调度平台如何感知多卡实例如果你用Kubernetes调度GPU需要确保Device Plugin看到的设备数量与物理卡/MIG实例数量匹配。Blackwell支持MIGK8s里可以按实例粒度调度但前提是nvidia-device-plugin启动参数里配置了正确的MIG策略比如--mig-strategysingle或mixed。设备插拔和节点重新注册也会影响调度稳定性建议给节点打上明确的GPU拓扑label比如NVLink域、MIG模式、显存总量等方便调度器做精细化分配。5.2 温度与功耗墙持续性负载下的隐形瓶颈这里我要特别强调很多并发压测跑几分钟看起来很好但跑几小时就出问题这通常是长期重负载导致的温度墙或功耗墙。Blackwell卡的散热设计和功率管理逻辑会把温度作为重要降频依据。如果机箱内风流不畅8张卡满载时很容易撞到温度墙表现是核心频率周期性波动、显存频率降低、推理延迟抖动增加。建议至少用nvidia-smi dmon -s pucm -o DT记录温度和功耗曲线观察长时间运行后的趋势必要时调整机箱风道。5.3 软件栈的跟进节奏Blackwell是较新的架构官方软件栈更新频繁。过老的CUDA、TensorRT、NCCL、container toolkit可能连卡都识别不全更别说发挥新特性。我的做法是新卡到手后先看官方发布说明确认驱动、CUDA、推荐容器镜像的最低版本然后在自己的环境里建一个发布追踪清单官方每次出新版本先在测试节点上验证再推向生产。这个习惯帮我避开了很多为什么