ARTICLE DETAIL

资讯详情

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

nVIDIA SLI与Multi-GPU:并行显卡拓扑、CUDA多卡与NCCL排错

nVIDIA SLI与Multi-GPU:并行显卡拓扑、CUDA多卡与NCCL排错 简介围绕并行显卡与nVIDIA SLI Multi-GPU技术展开的这份PDF文献面向图形硬件研究者、GPU架构学习者及对显卡发展史感兴趣的开发者。内容从多处理器并行概念切入回顾3Dfx Voodoo、ATI Rage FURY MAXX等早期多GPU方案因高价受挫的历程进而梳理nVIDIA推出SLI的市场动机与技术架构剖析主副卡分工、负载共享、PCI-Express通道连接及画面完整性保障等关键环节。文中对SLI如何协调两块显卡、确保数据传输高效、避免画面撕裂等机制有细致说明也讨论了市场接受度与价格对技术普及的制约兼具参考文献与专业指导价值对关注多GPU未来演进方向也有参考意义。资源包共1个PDF文件大小约1.27MB页面内容完整便于下载后直接阅读或归档。目前已有177人学习适合需要系统理解SLI演进脉络、对比多GPU技术差异或为图形性能优化寻找历史依据的读者。1. 从「插两张卡就变快」说起SLI 与 Multi-GPU 的真实边界很多人第一次装并行显卡是冲着「显存翻倍、算力翻倍」去的结果插上两张卡游戏帧率没涨训练脚本还是只认一张卡。nVIDIA SLI 作为早期 Multi-GPU 消费级方案用主从卡加桥接器显存是镜像而不是叠加帧生成靠 AFR 交替渲染驱动兼容位不对就直接黑屏或闪退。到了 CUDA 时代并行显卡的玩法变了SLI 退到游戏和部分 OpenGL 场景计算侧靠 NCCL、DDP、MPS 和 NVLink 把多卡真正串起来。这个标题不只是在翻旧技术更是在问手里两张 nVIDIA 卡怎么判断该走 SLI、NVLink 还是纯 CUDA 多进程下面按硬件识别、驱动配置、多卡通信和排错四层拆开每个环节给可复现命令。2. nVIDIA SLI 硬件原理与并行显卡拓扑识别2.1 SLI 桥接器、AFR/SFR 与显存镜像的取舍nVIDIA SLI 的核心不是让两张卡共享显存而是让两张卡分工渲染同一帧或交替渲染不同帧。早期需要 SLI 桥接器连接卡顶金手指后来部分型号走 PCIe 总线传输同步信号。桥接器的作用是降低帧同步数据对 PCIe 带宽的占用尤其是 4K 分辨率下几何数据和纹理每帧都要同步走 PCIe 会明显增加延迟。渲染模式决定了并行显卡的收益边界。AFRAlternate Frame Rendering让两张卡交替渲染整帧理论吞吐接近两倍但帧生成时间不均匀容易产生微卡顿SFRSplit Frame Rendering把一帧切成上下或左右两半负载均衡依赖驱动启发式遇到复杂场景容易一卡忙一卡闲SLI AA 让两张卡各做部分抗锯齿采样只对特定抗锯齿模式有效。更关键的是这些模式都要求两张卡持有相同的纹理、几何和着色器数据所以显存容量不叠加两张 8GB 卡在 SLI 下有效显存仍是 8GB。模式渲染分工显存占用适用场景常见问题AFR两卡交替渲染整帧每卡镜像一份资源游戏、OpenGL帧延迟高、微卡顿SFR每卡渲染画面一部分同样镜像早期专业卡负载不均SLI AA两卡分担抗锯齿采样镜像高分辨率抗锯齿新驱动支持少纯 CUDA 多进程每卡独立进程/流各自独立训练、推理需要 NCCL/DDP 协调如果你手里有一份讲 SLI Multi-GPU 的老文档再现它的时候最容易卡在两点一是把 SLI 当成显存叠加二是忽略桥接器版本和驱动分支。常见做法是先在 Windows 的 nVIDIA 控制面板里确认「SLI 配置」是否出现再进游戏用 nVIDIA Profile Inspector 检查该游戏的 SLI 兼容位。Linux 下 SLI 支持更窄多数计算场景直接放弃 SLI改用 CUDA 多卡。2.2 用 nvidia-smi topo -m 看清 Multi-GPU 互联拓扑并行显卡能不能跑出线性加速拓扑比卡的数量更重要。两张卡插在同一条 PCIe 交换芯片下和分别插在 CPU 直连的 PCIe 槽上P2P 带宽差一倍以上。nvidia-smi topo -m会输出一个矩阵用缩写表示两卡之间的连接方式NV#表示经过 NVLinkPIX表示同一 PCIe 交换芯片PXB表示同一 PCIe 桥PHB表示同一 NUMA 节点下的 PCIe 主机桥SYS表示跨 NUMA 节点走系统总线。# 查看显卡列表、驱动版本、显存占用 nvidia-smi # 查看多卡互联拓扑矩阵中每个单元格表示行卡与列卡的连接方式 nvidia-smi topo -m # 查看每张卡的 PCI 总线号和 lspci 对照 nvidia-smi --query-gpuindex,name,pci.bus_id --formatcsv # 查看详细能力包括是否支持 P2P、ECC、MIG nvidia-smi -q | grep -E P2P|Peer|ECC|MIG逻辑说明nvidia-smi是驱动暴露的用户态工具它能不能正常输出直接反映内核模块nvidia是否加载成功。topo -m读的是驱动采集的 PCIe 和 NVLink 拓扑不是操作系统猜的。参数说明--query-gpu支持按字段输出 CSV适合写进巡检脚本-q输出完整属性配合grep能快速过滤 P2P 能力。如果矩阵里两张卡之间是SYS说明它们跨了 NUMA 节点NCCL 通信会退化到走主机内存训练时建议用numactl绑核或者把进程绑到对应 CPU 节点。注意nvidia-smi topo -m里的NV#只代表物理链路存在不代表应用一定用上了。CUDA 程序里还要检查cudaDeviceCanAccessPeerNCCL 也要在NCCL_DEBUGINFO下确认它选择了 NVLink 还是 PCIe。2.3 Ubuntu 安装 nvidia 显卡驱动与 nvidia-smi 通信失败修复Ubuntu 22.04 和 24.04 下装 nVIDIA 驱动最稳的路径不是去官网下.run包而是用发行版仓库的ubuntu-drivers。它会根据显卡型号和内核版本推荐驱动分支避免手装时 DKMS 编译失败。并行显卡场景还要注意先装驱动再插第二张卡或者两张卡都插好后一次性装避免先装一张卡后驱动只绑定了一张。# 列出显卡和可用的驱动版本recommended 那一行是推荐分支 ubuntu-drivers devices # 自动安装推荐驱动Ubuntu 22.04/24.04 通用 sudo ubuntu-drivers autoinstall # 重启让新内核模块生效 sudo reboot # 重启后确认内核模块已加载 lsmod | grep nvidia # 确认 nvidia-smi 能通信并看到两张卡 nvidia-smi逻辑说明ubuntu-drivers devices会输出driver : nvidia-driver-XXX - recommendedautoinstall直接装推荐版本省去手动选版本。lsmod | grep nvidia看的是内核模块如果只有nvidia没有nvidia_uvmCUDA 程序会报找不到设备。参数说明如果nvidia-smi报nvidia-smi has failed because it couldnt communicate with the nvidia driver先看lsmod再看dmesg | grep -i nvidia。常见原因是 Secure Boot 没关导致模块签名失败或者内核升级后 DKMS 没自动重编。离线环境可以用apt download把驱动和依赖包下载到本地再dpkg -i安装但要注意linux-headers-$(uname -r)必须本地可用。3. 从 SLI 到通用 Multi-GPUCUDA 多卡编程与 NCCL 集合通信3.1 CUDA_VISIBLE_DEVICES 与并行显卡设备枚举SLI 是驱动层把多卡伪装成一张卡给游戏用CUDA 多卡则相反每张卡都是独立设备由应用决定怎么分工。CUDA_VISIBLE_DEVICES是控制进程可见设备的第一道开关它按物理序号过滤过滤后逻辑序号会重新排列。比如物理卡 0 和 1设置CUDA_VISIBLE_DEVICES1后进程里cuda:0实际对应物理卡 1。这个机制在排错时非常有用怀疑某张卡故障可以先屏蔽它做对照。# 让进程只看到物理 0 号和 1 号卡逻辑编号变成 0 和 1 CUDA_VISIBLE_DEVICES0,1 python train.py # 只让进程看到物理 1 号卡逻辑编号变成 0 CUDA_VISIBLE_DEVICES1 python train.py # 在 Python 里确认实际可见设备 python -c import torch; print(torch.cuda.device_count()); print(torch.cuda.get_device_name(0))逻辑说明CUDA_VISIBLE_DEVICES在 CUDA 运行时初始化前生效PyTorch、TensorFlow 都遵循这个约定。参数说明用逗号分隔物理序号支持0,2这种跳号写法也支持CUDA_VISIBLE_DEVICES0,1和CUDA_VISIBLE_DEVICES0,1,2,3。注意不要和torch.cuda.set_device()的逻辑编号混淆set_device(1)设置的是可见设备里的第 2 张卡不是物理 1 号卡。环境变量作用范围常见取值注意点CUDA_VISIBLE_DEVICESCUDA 运行时0,1、1、空空字符串会屏蔽所有卡NCCL_DEBUGNCCL 通信库INFO、WARNINFO会打印选中的拓扑NCCL_P2P_DISABLEP2P 直连0、1设为 1 可绕过 P2P 报错OMP_NUM_THREADSCPU 线程8、16多卡训练时防止 CPU 争抢3.2 PyTorch DDP 最小可复现多卡训练脚本Multi-GPU 训练最稳的模式是 DDPDistributedDataParallel每个进程管一张卡梯度通过 NCCL 做 all-reduce。它比 DataParallel 单进程多线程更高效因为 DataParallel 会把一张卡的输出 gather 到主卡主卡显存和计算容易成瓶颈。下面这段脚本只保留 DDP 骨架方便直接改成自己的模型。import os import torch import torch.distributed as dist from torch.nn.parallel import DistributedDataParallel as DDP def main(): # torchrun 会注入 LOCAL_RANK表示本机第几张卡 local_rank int(os.environ[LOCAL_RANK]) # 初始化 NCCL 后端多卡训练默认用 nccl dist.init_process_group(backendnccl) torch.cuda.set_device(local_rank) model torch.nn.Linear(1024, 1024).cuda(local_rank) ddp_model DDP(model, device_ids[local_rank]) # 模拟一个 batch实际使用时用 DistributedSampler 切分数据 x torch.randn(32, 1024).cuda(local_rank) y ddp_model(x) loss y.sum() loss.backward() # 只在 rank 0 打印避免多进程日志刷屏 if dist.get_rank() 0: print(loss:, loss.item()) dist.destroy_process_group() if __name__ __main__: main()逻辑说明dist.init_process_group(backendnccl)会建立进程组DDP 在backward()时自动触发 all-reduce。参数说明LOCAL_RANK由torchrun注入范围是0到nproc_per_node-1device_ids必须和torch.cuda.set_device保持一致否则 DDP 会报设备不匹配。启动命令如下# 单机两张卡每个进程绑定一张卡 torchrun --nproc_per_node2 --master_port29500 train_ddp.py--nproc_per_node2表示本机起两个进程--master_port是进程组通信端口多机训练时还要加--nnodes和--node_rank。如果启动后卡在init_process_group先用NCCL_DEBUGINFO看它选了哪条链路再检查防火墙是否放行该端口。3.3 NCCL 环境变量与 nvidia-container-toolkit 容器多卡直通容器里跑多卡训练需要 nvidia-container-toolkit 把 GPU 设备和驱动库挂进容器。只装 Docker 不够--gpus all依赖 toolkit 的运行时钩子。装好后容器内的nvidia-smi和宿主机输出一致CUDA 程序才能枚举到多张卡。# 安装 nvidia-container-toolkit 后配置 Docker 运行时 sudo nvidia-ctk runtime configure --runtimedocker sudo systemctl restart docker # 启动容器--ipchost 让 NCCL 使用共享内存--gpus all 直通所有卡 docker run --gpus all --ipchost \ -e NCCL_DEBUGINFO \ -e NCCL_P2P_DISABLE0 \ -v $PWD:/workspace -w /workspace \ nvcr.io/nvidia/pytorch:latest \ torchrun --nproc_per_node2 train_ddp.py逻辑说明nvidia-ctk runtime configure把 toolkit 注册为 Docker 运行时--gpus all才会生效。参数说明--ipchost避免容器内 NCCL 因/dev/shm太小而回退到 socketNCCL_P2P_DISABLE0表示允许 P2P如果主板不支持 P2P 导致卡死改成1强制走主机内存。注意容器内驱动版本来自宿主机镜像里的 CUDA 版本只要不高于驱动支持的上限即可不需要在容器里重装 nVIDIA 驱动。4. SLI 配置、nvidia profile inspector 与并行显卡故障排查4.1 nvidia 控制面板找不到了时如何启用 SLIWindows 下装完驱动后桌面右键没有「nVIDIA 控制面板」或者控制面板里没有「SLI 配置」选项通常不是驱动没装好而是显示输出走了核显、驱动分支不对或者 SLI 桥接器没插紧。先确认设备管理器里两张卡都正常再确认显示器接在独立显卡上。如果用的是笔记本 Optimus 或桌面核显输出控制面板可能被隐藏。Linux 下 SLI 配置更依赖 Xorg。Ubuntu 22.04 默认 Wayland 会话下nvidia-settings的 SLI 选项经常灰掉需要切到 Xorg 会话再配置。常见做法是用nvidia-xconfig生成基础配置再手动加 SLI 参数。# 安装设置面板和 Xorg 配置工具 sudo apt install nvidia-settings nvidia-xconfig # 查看当前会话是 Wayland 还是 X11 echo $XDG_SESSION_TYPE # 生成 Xorg 配置并尝试打开 SLI sudo nvidia-xconfig --slion # 重启显示管理器 sudo systemctl restart gdm3逻辑说明nvidia-xconfig --slion会往/etc/X11/xorg.conf写入Option SLI On但只有驱动和桥接器都支持时才生效。参数说明--slion对应 AFR 模式部分驱动还支持--sliAuto。如果重启后进不了桌面按CtrlAltF3进 TTY把xorg.conf里的 SLI 行删掉再重启。注意Wayland 下 SLI 支持有限配置前先切 Xorg否则会看到「nvidia 无法应用选定的设置」。4.2 nvidia profile inspector 强制 SLI 兼容位与「nvidia 无法应用选定的设置」游戏不支持 SLI 时nVIDIA 控制面板里不会出现该游戏的 SLI 配置。nvidia profile inspector 可以直接改驱动数据库里的兼容位强制某个游戏使用 AFR 或 SFR。操作路径是打开工具选中目标游戏配置文件找到SLI compatibility bits和SLI rendering mode填入社区验证过的值再点 Apply。改完后进游戏用 MSI Afterburner 或游戏内叠加层看两张卡的占用率是否都上来了。常见现象可能原因处理方式控制面板没有 SLI 选项桥接器未插、核显输出、驱动分支不支持重插桥接器确认显示器接独显换 Game Ready 驱动游戏内一张卡满载一张卡空闲兼容位不对或游戏不支持 AFR用 nvidia profile inspector 改 SLI 兼容位改完设置点应用报「nvidia 无法应用选定的设置」驱动数据库被占用或权限不足以管理员运行关掉游戏和叠加层再应用开启 SLI 后帧率反而下降AFR 帧同步开销大、PCIe 带宽不足换 SFR 模式或降低分辨率/纹理质量新驱动找不到 SLI 配置新分支砍掉旧 SLI 支持回退到 nvidia 历史驱动中支持 SLI 的版本逻辑说明nvidia profile inspector 改的是驱动内置的 profile 数据库不修改游戏文件。参数说明SLI compatibility bits是十六进制掩码不同游戏引擎值不同抄作业前先确认显卡代际和驱动分支一致。注意强制 SLI 可能导致反作弊误判竞技类游戏不建议改。4.3 nvidia-smi has failed 与 nvrm: cant find an irq 的排查路径nvidia-smi has failed because it couldnt communicate with the nvidia driver是 Linux 下最常见的驱动故障。它说明用户态工具连不上内核模块不一定是卡坏了。排查顺序是先看模块加载再看内核日志最后看 DKMS 和 Secure Boot。另一类报错nvrm: cant find an irq for your nvidia card通常和 BIOS 里的 Above 4G Decoding、Resizable BAR 或中断分配有关多卡场景更容易触发。# 查看 nvidia 内核模块是否加载 lsmod | grep nvidia # 查看内核日志中的 nvidia 报错 dmesg | grep -i nvidia | tail -50 # 查看 DKMS 状态确认模块是否为当前内核编译 dkms status # 如果内核升级后模块丢失重装内核头文件和驱动 sudo apt install --reinstall linux-headers-$(uname -r) sudo apt install --reinstall nvidia-dkms-XXX # 手动加载模块并观察报错 sudo modprobe nvidia sudo modprobe nvidia_uvm逻辑说明lsmod看模块是否在内存中dmesg看加载失败原因dkms status看模块有没有为当前内核版本编译。参数说明nvidia-dkms-XXX里的XXX要和ubuntu-drivers devices推荐的版本一致。如果是 Secure Boot 导致签名失败dmesg会出现Loading of module with unavailable key is rejected此时要么在 BIOS 关 Secure Boot要么给模块签名。nvrm: cant find an irq的常见处理是进 BIOS 打开 Above 4G Decoding关闭 Resizable BAR 做对照或者把两张卡换到不同 PCIe 槽避免共享中断。多卡机器还要确认电源功率足够瞬时功耗触发保护也会让卡从总线上掉下来。5. 并行显卡带宽验证与多卡推理渲染的选型技巧配好多卡后别急着上大模型先用 nccl-tests 量一下实际 all-reduce 带宽。拓扑输出是理论链路真实带宽受 PCIe 代际、NUMA 绑定和 NCCL 算法影响。编译 nccl-tests 后用all_reduce_perf从 8 字节扫到 128MB看曲线在哪个尺寸达到平台期。如果小消息延迟高检查NCCL_ALGO和NCCL_PROTO如果大消息带宽只有理论值一半检查两张卡是否跨了 NUMA。# 编译 nccl-tests 后用两张卡测 all-reduce ./build/all_reduce_perf -b 8 -e 128M -f 2 -g 2 # 强制走 NVLink 或 PCIe观察带宽差异 NCCL_P2P_LEVELSYS ./build/all_reduce_perf -b 8 -e 128M -f 2 -g 2 NCCL_P2P_LEVELPIX ./build/all_reduce_perf -b 8 -e 128M -f 2 -g 2参数说明-b是起始消息大小-e是结束大小-f是倍增因子-g是 GPU 数量。逻辑说明平台期带宽接近 NVLink 标称值说明 P2P 生效如果带宽明显偏低用nvidia-smi topo -m回看拓扑再用numactl --cpunodebind把进程绑到对应 NUMA 节点。场景推荐并行方式关键检查项游戏 SLIAFR 桥接器兼容位、帧生成时间多卡训练DDP NCCL拓扑、P2P、NUMA 绑定多卡推理每卡独立进程或 TensorRT 多流显存占用、PCIe 带宽容器多卡nvidia-container-toolkit --gpus all/dev/shm、NCCL 版本渲染农场每卡独立任务驱动分支、Xorg 会话如果拓扑输出里两张卡之间是SYS而不是NV#把 batch size 调小、开启梯度累积通常比硬上大 batch 更稳推理场景则优先把模型按层切到不同卡减少跨卡激活传输。本文还有配套的精品资源点击获取
返回列表