NVSwitch Fabric Manager 服务运维:配置、启动顺序与 SXid 故障处置
一句话:在没有 NVSwitch 的机器上,GPU 之间的 NVLink 是"点对点直连";一旦上了 NVSwitch,GPU 之间能不能互相看见、带宽能不能跑满,就不再由驱动单独决定,而是由一个叫 Fabric Manager 的常驻进程在启动时把整块 switch 配成一张共享 fabric——它没起来,8 张卡在拓扑上就是 8 座孤岛。
一、Fabric Manager 到底在做什么
NVSwitch 把一台服务器里所有 GPU 连成一张全互联网络:任意两张卡之间都能通过 switch 通信,而不必依赖 GPU 之间的直连链路。但这张网络不是插上就能用——它需要被初始化、被路由、被监控。核心软件栈由两部分组成:
- NVSwitch 内核驱动:响应 FM 的请求,做底层的硬件管理;
- Fabric Manager(FM):一个特权用户态进程,负责把 NVSwitch 配置成所有 GPU 共享的单一内存 fabric、下发路由、与 GPU 驱动协同完成初始化,并监控 NVLink / NVSwitch 的错误。
官方文档对它的定位是"NVSwitch 管理的核心软件栈",同时提供带内与带外两种监控手段来上报 NVSwitch 与 GPU 的错误和状态。这个定位决定了三件运维事实:
- FM 是服务,不是工具。它得常驻、开机自启、有日志、有状态文件;
- 它有严格的启动前提。GPU 与 NVSwitch 必须先绑定到
nvidia.ko,FM 才能接管; - 它一旦退出,CUDA 作业的语义会立刻变化。默认配置下 FM 退出会中止正在跑的 CUDA 作业(
ABORT_CUDA_JOBS_ON_FM_EXIT=1)。
二、四代平台:先确认你在哪一代上干活
不同代际的 NVSwitch 平台,组件构成和运维动作差别很大。这不是背景知识,而是决定"该改哪个配置项、该看哪个日志"的前提:
| 平台 | NVSwitch 数量与代际 | 关键差异 |
|---|---|---|
| HGX-2 / V100 | 6 个第一代 NVSwitch,16 GPU 分布在双基板 | 双基板通过 Trunk 端口互联 |
| HGX A100 | 6 个第二代 NVSwitch | Trunk 故障有专门的高可用降级模式 |
| HGX H100 | 4 个第三代 NVSwitch | 不支持双基板互联;NVLink 由 ALI 在硬件层训练 |
| HGX B200 / B300 / B100 | 2 个第四代 NVSwitch | NVSwitch 不再作为 PCIe 设备出现,改走 ConnectX-7 的 Bridge 呈现 |
第四代是一次架构断点,带来三个连锁变化:
- 新增 NVLSM。第四代引入 NVLink Subnet Manager(源自 InfiniBand 的子网管理器),专门负责 NVSwitch 的路由表与 PKEY;FM 负责 GPU 侧路由与分区 API,两者通过 IPC 协作,socket 默认在
/var/run/nvidia-fabricmanager/fm_sm_ipc.socket; - 日志分家。FM 的日志在
/var/log/fabricmanager.log,NVLSM 的日志默认落到/var/log/opensm.log(log_flags 0x3,即 ERROR + INFO); - 包与内核要求变化。第四代改用
nvidia-open-<branch>加nvlink5-<branch>(RHEL 侧是nvidia-driver-<branch>-open与nvlink-<branch>),并要求内核不低于 5.17,另外需要libibumad3、infiniband-diags。
三、服务面:命令、单元、包
FM 以标准 systemd 服务运行,这套命令是运维日常:
systemctl status nvidia-fabricmanager
systemctl start nvidia-fabricmanager
systemctl stop nvidia-fabricmanager
systemctl enable nvidia-fabricmanager
journalctl -u nvidia-fabricmanager --since "30 min ago"单元文件在 /lib/systemd/system/nvidia-fabricmanager.service,它并不直接拉起 nv-fabricmanager,而是调用 /usr/bin/nv-fabricmanager-start.sh——这个脚本按平台决定拉起 FM、NVLSM,还是两者都拉。所以"服务 active"里去判断"到底哪几个进程在跑",别只看 systemctl 的状态色。
二进制本身是 nv-fabricmanager,可用参数不多但都用得上:
| 参数 | 用途 |
|---|---|
-c / --config | 指定非默认配置文件 |
-r / --restart | 多租户场景下的 resiliency 重启流程(等价 FABRIC_MODE_RESTART=1) |
-d / --database | 单机 HGX/DGX 不要用,官方明确不适用 |
安装方式按发行版分三类:
# Ubuntu / Debian
apt-get install cuda-drivers-fabricmanager-<branch>
# RHEL 系
dnf module install nvidia-driver:<branch>/fm
# SUSE
zypper install cuda-drivers-fabricmanager-<branch>最低驱动版本随代际递增:HGX-2/A100 是 450.xx,H100 是 525.xx,B200/B300/B100 是 570.xx。DGX 系列随机预装并已自启,HGX 系列要自己装、自己 enable、自己 start——这一条是"新机器插上卡却跑不出 P2P"的最常见原因。
包结构也值得知道:nvidia-fabricmanager-<version> 是核心包,含 FM 服务进程、服务单元文件和拓扑文件,裸金属只装它就够;nvidia-fabricmanager-devel-<version> 是 SDK 与库,做 Shared NVSwitch 或 vGPU 多租户时才需要。
四、fabricmanager.cfg:真正要调的只有几项
默认配置在 /usr/share/nvidia/nvswitch/fabricmanager.cfg。改完必须重启服务才生效——配置文件是在服务启动时读取的。
| 配置项 | 默认值 | 说明 |
|---|---|---|
LOG_FILE_NAME | /var/log/fabricmanager.log | 日志路径,最长 255 字符 |
LOG_LEVEL | 4 | 0 关闭,1 CRITICAL,2 ERROR,3 WARNING,4 INFO 及以上 |
LOG_APPEND_TO_LOG | 1 | 每次启动追加而非覆盖 |
LOG_FILE_MAX_SIZE | 1024 | 单位 MB,达到上限后停止写日志(不是滚动) |
LOG_MAX_ROTATE_COUNT | 3 | 非 0 才滚动,总日志量约为 MAX_SIZE × (COUNT + 1) |
LOG_USE_SYSLOG | 0 | 置 1 则改投 syslog |
FABRIC_MODE | 0 | 0 裸金属/全透传,1 Shared NVSwitch 多租户,2 vGPU 多租户 |
FABRIC_MODE_RESTART | 0 | 置 1 走多租户 resiliency 重启序列 |
FM_CMD_BIND_INTERFACE | 127.0.0.1 | FM SDK/API 监听接口(多租户用) |
FM_CMD_PORT_NUMBER | 6666 | FM SDK/API 的 TCP 端口(多租户用) |
STARTING_TCP_PORT | 16000 | FM 内部通信/IPC 起始端口 |
STATE_FILE_NAME | /tmp/fabricmanager.state | 多租户 resiliency 的状态文件 |
DAEMONIZE | 1 | 以后台守护方式运行 |
ABORT_CUDA_JOBS_ON_FM_EXIT | 1 | FM 退出时中止 CUDA 作业 |
三条实践结论:
LOG_FILE_MAX_SIZE的行为要看清:达到上限后 FM 是"跳过后续日志",不是自动滚动。如果LOG_MAX_ROTATE_COUNT被设成 0,一个 1 GB 的日志写满之后你会在最需要证据的时刻失去日志。官方建议就是保持 INFO 级别、保留滚动;STATE_FILE_NAME落在/tmp。重启后/tmp被清掉,多租户的 resiliency 状态就断了。生产上应把它挪到持久目录;ABORT_CUDA_JOBS_ON_FM_EXIT只对 H100 之前有效。官方注明该行为在 H100 及以后不再适用,且只在裸金属/全透传模式下有意义。
第四代平台还有一项要配对改:FM_SM_IPC_INTERFACE(默认的 unix socket 路径),以及 NVLSM 侧 plugin_options grpc_mgr --grpc_server_address 必须指向同一个路径。改了一边没改另一边,两个进程握不上手,fabric 起不来。
五、初始化语义:三种"起不来"的形态
FM 的启动不是"进程在就算成功",判断标准要落到 fabric 状态上。
5.1 版本不兼容直接 abort
FM 启动时会校验内核驱动栈的版本。不兼容时它不会降级运行,而是直接中止。所以"服务起不来"的第一现场永远是:
journalctl -u nvidia-fabricmanager -n 100 --no-pager
grep -i "version\|abort" /var/log/fabricmanager.log | tail驱动分支(-<branch>)与 FM 包分支必须一致,这是安装阶段就该配平的事。
5.2 CUDA 抢跑:cudaErrorSystemNotReady
FM 还没完成初始化就提交 CUDA 作业,应用拿到的不是"卡忙"而是 cudaErrorSystemNotReady。这个错误的语义很明确:fabric 还没就绪。它不该被当作硬件故障排队报修,而是应该回到启动顺序上找原因。
5.3 H100 及以后:GPU 必须向 fabric 注册
H100 起,NVLink 由 ALI 在硬件层训练,GPU 需要主动向 fabric 注册;注册失败的 GPU 会失去 P2P 能力。验收命令:
nvidia-smi -q -i 0 | grep -i -A2 Fabric
# 期望看到 State: Completed
# Status: Success逐卡跑一遍,任何一张不是 Completed / Success,就先别谈性能基线——那张卡的 P2P 路径根本没建立。
六、重启的正确顺序(H100 及以后)
这是 FM 运维里唯一一个"顺序错了就会把作业打死"的动作。官方给出的顺序是:
# 1. 停掉所有 CUDA 应用与 GPU 相关服务
# (nvidia-persistenced 可以留着,DCGM 必须停)
systemctl stop nvidia-dcgm
# 2. 停 FM
systemctl stop nvidia-fabricmanager
# 3. GPU 复位
nvidia-smi -r
# 4. 起 FM,等 fabric 就绪
systemctl start nvidia-fabricmanager
nvidia-smi -q -i 0 | grep -i -A2 Fabric
# 5. 恢复被停掉的服务
# 6. 再跑 CUDA 作业反过来做会怎样:先 nvidia-smi -r 再停 FM,复位过程中 FM 仍持有 fabric 状态,注册关系被打断;或者 FM 停了不等 fabric 就绪就拉起 CUDA,拿到一片 cudaErrorSystemNotReady。
还有一条来自官方文档的心态建议:FM 不需要频繁重启。它是个稳态服务,重启的合理触发点是驱动升级、配置变更、以及下面要讲的致命错误恢复,而不是"感觉不太对就重启一下"。
七、故障语义:GPU 报 Xid,NVSwitch 报 SXid
两套错误码必须分开看:
- GPU 侧是
Xid,来自 NVIDIA 驱动的标准错误码体系; - NVSwitch 侧是
SXid,格式形如:
nvidia-nvswitch0: SXid (PCI:0000:0a:00.0): 12008, Fatal, Link 12一行里包含四个关键信息:哪个 switch、PCI 地址、错误值、致命还是非致命、以及涉及的链路号。
7.1 非致命 SXid:只记账,不杀作业
非致命 SXid 只做提示,不会中止正在运行的作业。它适合进监控告警、做趋势对比——比如同一条链路反复出非致命错误,就值得在下个维护窗口换件,而不是等到它变致命。
7.2 致命 SXid(GPU ↔ NVSwitch 端口):杀该卡上的作业
当致命 SXid 出现在 GPU 与 NVSwitch 之间的端口上时,FM 会杀掉跑在那张 GPU 上的作业,并且可能连带产生 Xid 74 / Xid 45。恢复顺序:
nvidia-smi -r # 先复位
# 如果复位不解决问题 → 重启整机7.3 致命 SXid(跨基板 Trunk 端口):杀掉全部 CUDA 作业
这是最重的一档。当致命 SXid 出现在跨基板的 Trunk 端口时,FM 会杀掉机器上所有 CUDA 作业——因为 fabric 的部分路径已经不可信,继续跑只会得到静默的数据错误。官方给的恢复序列是:
systemctl stop nvidia-fabricmanager # 停 FM
# 停掉所有使用 GPU 的应用与服务
nvidia-smi -r # 注意:不要带 -i / -id
systemctl start nvidia-fabricmanager # 起 FM
# 仍不恢复 → 重启 / 断电重上nvidia-smi -r 不带 -i/-id 是有意的:Trunk 级故障不是单卡问题,只复位一张卡不会重建 fabric。
7.4 第四代平台:SXid 机制不再适用
B200/B300 上这套 SXid 上报机制已经不再适用,错误观测改为由 DCGM 通过 NVSDM 读取端口与 ASIC 计数器。这意味着运维栈要跟着换:靠 dmesg 抓 SXid 的老办法在新平台上抓不到东西,得把 NVSwitch/端口级遥测接进 DCGM 侧。
八、高可用降级模式:A100 世代的遗产
FM 有三个降级开关,用来决定"链路坏了是退出还是降级运行":
| 配置项 | 作用 | 取值语义 |
|---|---|---|
ACCESS_LINK_FAILURE_MODE | GPU ↔ NVSwitch 接入链路故障 | 0 = 把故障 GPU 移出 fabric(保留非 P2P 用途)或退出 FM;1 = 降级继续 |
TRUNK_LINK_FAILURE_MODE | 跨基板 Trunk 链路故障 | 同上 |
NVSWITCH_FAILURE_MODE | 整颗 NVSwitch 故障 | 1 = 禁用该 switch 及其对端,带宽降到 5/6 |
这三个开关只在 A100 世代有效,H100 及以后被忽略。所以从 A100 集群迁到 H100 集群时,那些为了"尽量不停机"调过的降级参数会静默失效——不是配置丢了,是新平台不再走这条路径。这一点在迁移评审里必须写进变更单。
九、MIG 互操作与权限边界
9.1 MIG 与 NVLink/P2P
开 MIG 会禁用(或不使用)GPU 的 NVLink,随之失去 P2P。代际差异在这件事上很明显:
- H100 及以后:MIG 期间 NVLink 保持 active;
- A100:关闭 MIG 之后,要靠 FM 在运行才能恢复 P2P。
所以 A100 上"关掉 MIG 但 P2P 还是不通",先看 FM 是不是活的,而不是先怀疑卡。
9.2 非 root 运行 FM
FM 支持非 root 运行,但要显式授权这些路径与设备:
目录:/var/run/nvidia-fabricmanager、/var/log/、/usr/share/nvidia/nvswitch
proc:/proc/driver/nvidia-nvlink/capabilities/fabric-mgmt
设备:/dev/nvidia-nvlink、/dev/nvidia-nvswitchctl、
/dev/nvidia-nvswitchX、/dev/nvidiactl、/dev/nvidiaX第四代(B200 等)还要加上 /dev/infiniband/umadX、/dev/infiniband/issmX,以及对 /sys/class/infiniband/mlx5_X/device/vpd 的读权限。麻烦之处在于:驱动重载或重启后,/proc 下的条目会重建,权限随之丢失。所以这些授权必须做成 udev 规则自动化,否则每次升级驱动都要人工补一遍。
另外一条边界:在 ConnectX 端口上使用 infiniband 工具是不受支持的,别拿 ibstat 那套去诊断 NVSwitch 侧的问题。
上线验收清单
systemctl is-enabled nvidia-fabricmanager与is-active双绿,HGX 机器确认是自己 enable 过的;nvidia-smi -q -i N | grep -A2 Fabric逐卡Completed / Success;FABRIC_MODE与业务形态匹配(裸金属/透传=0,多租户=1/2),改过就重启过;- 第四代平台核对
FM_SM_IPC_INTERFACE与 NVLSMgrpc_server_address指向同一路径; LOG_LEVEL=4、LOG_MAX_ROTATE_COUNT非 0,日志能在满盘前滚动;STATE_FILE_NAME已从/tmp挪到持久目录(多租户场景);- 驱动升级后跑一遍 restart 顺序脚本,并确认 udev 规则把非 root 权限补回来了;
- 监控侧已接
SXid(三代及以前)或 DCGM 的 NVSwitch 端口计数器(四代)。
收口三句
- FM 不是可选的监控组件,是 fabric 的初始化者:它没起来,卡再多也只是点对点;
cudaErrorSystemNotReady要往启动顺序里查,不要当硬件故障; - 重启有唯一正确顺序:停 CUDA 与 GPU 服务 → 停 FM →
nvidia-smi -r→ 起 FM → 恢复服务,顺序错了就是把作业打死; - SXid 的致命级别决定爆炸半径:端口级只影响单卡作业,Trunk 级会让 FM 杀掉全部 CUDA 作业,第四代则完全换了观测通道(DCGM + NVSDM)。