GPU服务器磁盘带宽监测

在 GPU 服务器上,监测 NVMe 实际读写带宽,最直接、最可靠的是 iostat。GPU 型号不会改变 Linux 块设备监控方法;重点是找到底层 nvme设备。

1. 找到挂载目录对应的 NVMe

例如你的数据目录是 /data0

findmnt -T /data0 -o TARGET,SOURCE,FSTYPE,OPTIONS

可能得到:

nvme2n1  disk  7T  SOLIDIGM ...  /data0

后续监测 /dev/nvme2n1。对于 bind mount,应监测底层 NVMe 块设备,而不是 /data0 这个目录。

2. 实时监测每块 NVMe 带宽

查看指定磁盘实时带宽:

iostat -dxm -y nvme2n1 1

其中:

字段含义
rMB/s实际从磁盘读取的 MiB/s
wMB/s实际写入磁盘的 MiB/s
r/sw/s每秒读写 IOPS
rareq-szwareq-sz平均读写请求大小,KiB
r_awaitw_await读写请求平均延迟,包含排队时间,单位 ms
aqu-sz平均请求队列深度
%util设备存在未完成 I/O 的时间比例

iostat -m 输出名义上是 MB/s,实际采用 MiB/s,即 1024×1024 字节。现代 NVMe 可以并行处理多个请求,因此 %util 接近 100% 不等于已经达到带宽上限;需要结合带宽、延迟和队列深度判断。

推荐重点观察:

rMB/s  wMB/s  r_await  w_await  aqu-sz

一般来说,如果出现:

带宽不再增长
+ aqu-sz 持续增长
+ await 明显升高

通常说明磁盘、PCIe 链路或上游 I/O 路径已经接近瓶颈。

获取某个磁盘每分钟读取和写入累积量

下面脚本每隔 60 秒读取一次 /sys/class/block/<device>/stat,输出:

  • 最近一分钟的读取量、写入量
  • 从脚本启动以来的累计读取量、写入量
#!/usr/bin/env bash
set -euo pipefail

# 用法:
#   bash disk_io_per_minute.sh /dev/nvme0n1
#   bash disk_io_per_minute.sh nvme0n1
#
# 可选:指定采样周期,默认 60 秒
#   bash disk_io_per_minute.sh nvme0n1 60

device="${1:-}"
interval="${2:-60}"

if [[ -z "$device" ]]; then
    echo "Usage: $0 <device> [interval_seconds]"
    echo "Example: $0 /dev/nvme0n1 60"
    exit 1
fi

device="$(basename "$device")"
stat_file="/sys/class/block/${device}/stat"

if [[ ! -r "$stat_file" ]]; then
    echo "Error: cannot read ${stat_file}"
    exit 1
fi

# /sys/class/block/<device>/stat:
# 第 3 个字段:累计读取扇区数
# 第 7 个字段:累计写入扇区数
# Linux 块设备统计中的每个扇区按 512 字节计算
read_io_stats() {
    local fields
    read -ra fields < "$stat_file"

    read_sectors="${fields[2]}"
    write_sectors="${fields[6]}"
}

format_mib() {
    awk -v sectors="$1" \
        'BEGIN { printf "%.2f", sectors * 512 / 1024 / 1024 }'
}

read_io_stats

previous_read="$read_sectors"
previous_write="$write_sectors"

total_read=0
total_write=0

printf "%-19s %15s %15s %18s %18s\n" \
    "Time" "Read MiB/min" "Write MiB/min" \
    "Total Read MiB" "Total Write MiB"

while sleep "$interval"; do
    read_io_stats

    current_read="$read_sectors"
    current_write="$write_sectors"

    # 处理设备统计计数器重置的情况
    if (( current_read >= previous_read )); then
        delta_read=$((current_read - previous_read))
    else
        delta_read=0
    fi

    if (( current_write >= previous_write )); then
        delta_write=$((current_write - previous_write))
    else
        delta_write=0
    fi

    total_read=$((total_read + delta_read))
    total_write=$((total_write + delta_write))

    printf "%-19s %15s %15s %18s %18s\n" \
        "$(date '+%F %T')" \
        "$(format_mib "$delta_read")" \
        "$(format_mib "$delta_write")" \
        "$(format_mib "$total_read")" \
        "$(format_mib "$total_write")"

    previous_read="$current_read"
    previous_write="$current_write"
done

保存并运行:

chmod +x disk_io_per_minute.sh
./disk_io_per_minute.sh /dev/nvme0n1

示例输出:

Time                   Read MiB/min   Write MiB/min     Total Read MiB    Total Write MiB
2026-07-03 15:01:00         1024.50          256.25            1024.50             256.25
2026-07-03 15:02:00         2048.00          512.00            3072.50             768.25
2026-07-03 15:03:00          128.00           64.00            3200.50             832.25

这里的 Read MiB/minWrite MiB/min 是该采样周期内底层磁盘实际完成的 I/O 量,不是文件系统层面的文件大小变化。

3. 查看是哪个进程在读写

使用 pidstat

pidstat -d -p ALL 1

只监测特定进程:

pidstat -d -p <PID> 1

主要字段:

kB_rd/s    进程触发的磁盘读取速度
kB_wr/s    进程触发或将要触发的磁盘写入速度

pidstat -d 提供进程级磁盘 I/O 统计,但写入可能经过 page cache,因此它与底层磁盘瞬时带宽不一定完全同步。

使用 iotop

iotop -oPa

参数含义:

-o   只显示存在 I/O 的进程
-P   按进程聚合,而不是线程
-a   显示累计 I/O

查看实时值可以用:

iotop -oP

iotop 支持在进程、线程、当前速率和累计量之间切换。

4. 同时观察所有 NVMe 的简化命令

watch -n 1 '
iostat -dxm -y 1 1 |
awk "NR==1 || /^Device/ || /^nvme/"
'

也可以同时观察磁盘和进程:

# 终端 1:物理磁盘带宽
iostat -dxm -y 1

# 终端 2:进程 I/O
pidstat -d -p ALL 1

这是排查推理服务、模型加载、KV Cache 落盘、checkpoint 加载等 I/O 问题时最实用的组合。

5. 查看 NVMe SMART 和累计读写量

nvme list
nvme smart-log /dev/nvme2

持续查看:

watch -n 5 '
nvme smart-log /dev/nvme2 |
grep -E "data_units_read|data_units_written|temperature|percentage_used|media_errors"
'

这里的 data_units_readdata_units_written 是累计值,不是瞬时带宽。每个 data unit 对应 1000 × 512 字节,可以通过两次采样的差值计算较长时间窗口的平均带宽。SMART 更适合观察累计写入量、温度、寿命和错误,不适合替代 iostat 做秒级监控。NVIDIA 官方说明 DGX 默认预装了 nvme-cli

6. 检查 PCIe 链路是否降速

先查看 NVMe 控制器:

lspci -D | grep -i 'Non-Volatile memory'

例如设备地址是 0000:41:00.0

lspci -s 0000:41:00.0 -vv |
grep -E 'LnkCap:|LnkSta:'

重点关注:

LnkCap: Speed 32GT/s, Width x4
LnkSta: Speed 32GT/s, Width x4

如果能力是 x4,实际却变成 x2;或者能力支持更高速度但实际协商速度较低,就可能存在插槽、转接板、BIOS、固件或链路问题。

注意:LnkSta 只表示当前 PCIe 协商速率和宽度,不是实时 PCIe 流量

7. 检查 NVMe 的 NUMA 归属

GPU服务器通常有多个 CPU Socket、PCIe Root Port 和多块 NVMe。I/O 进程跑在远端 NUMA 节点时,可能增加跨 Socket 流量。

查看 NVMe 对应 NUMA 节点:

cat /sys/class/nvme/nvme2/device/numa_node

查看系统 NUMA:

numactl -H

查看 PCIe 拓扑:

lspci -tv

查看进程 CPU 位置:

ps -o pid,psr,comm -p <PID>

将压测或 I/O 进程绑定到 NVMe 所在 NUMA 节点:

numactl --cpunodebind=1 --membind=1 <command>

NVIDIA 的 GPU参考架构强调将 PCIe 连接分散到不同 CPU Socket 和 Root Port;当多块盘同时读写时,应分别观察每块 NVMe,而不是只看总带宽。

8. 不依赖 iostat,直接读取内核计数器

Linux 在下面的位置提供块设备累计统计:

cat /sys/block/nvme2n1/stat

其中第 3 个字段是累计读取扇区数,第 7 个字段是累计写入扇区数;内核统计中的扇区固定按 512 字节计算。对两次采样做差即可计算带宽。

一个简单的每秒监测脚本:

#!/usr/bin/env bash

dev="${1:-nvme2n1}"
interval="${2:-1}"
stat="/sys/block/${dev}/stat"

read_stats() {
    read -r _ _ read_sectors _ _ _ write_sectors _ _ < "$stat"
}

read_stats
prev_read=$read_sectors
prev_write=$write_sectors

while sleep "$interval"; do
    read_stats

    read_mib=$(awk -v now="$read_sectors" \
        -v prev="$prev_read" -v sec="$interval" \
        'BEGIN { printf "%.2f", (now-prev)*512/1024/1024/sec }')

    write_mib=$(awk -v now="$write_sectors" \
        -v prev="$prev_write" -v sec="$interval" \
        'BEGIN { printf "%.2f", (now-prev)*512/1024/1024/sec }')

    printf '%s read=%10s MiB/s write=%10s MiB/s\n' \
        "$(date '+%F %T')" "$read_mib" "$write_mib"

    prev_read=$read_sectors
    prev_write=$write_sectors
done

运行:

bash nvme_bw.sh nvme2n1 1

建议直接使用的组合

# 查看磁盘对应关系
lsblk -o NAME,TYPE,SIZE,MODEL,MOUNTPOINTS

# 每块盘的实际带宽、延迟和队列
iostat -dxm -y 1

# 查找产生 I/O 的进程
pidstat -d -p ALL 1

# 检查 NVMe 温度、寿命和错误
nvme smart-log /dev/nvme2

# 检查 PCIe 链路
lspci -s <NVME_PCI_BDF> -vv | grep -E 'LnkCap:|LnkSta:'

其中,判断 NVMe 实时读写带宽以 iostatrMB/swMB/s 为准pidstat/iotop 用于定位进程,nvme smart-log 用于健康和累计量,lspci 用于排查链路降速。

sysstat介绍

 如需安装 iostat(sysstat)

# Ubuntu/Debian
apt install -y sysstat

# RHEL/Rocky/CentOS
dnf install -y sysstat

每秒刷新一次:

iostat -dxm -y 1

只看 NVMe:

iostat -dxm -y 1 | grep --line-buffered -E '^Device|^nvme'

当你安装了 sysstat 之后,除了 iostat ,你还会获得以下用于检测 Linux 性能的常用武器: [1, 2]

  • sar :系统活动报告器,可以说是 sysstat 的核心,负责收集、汇报并存储系统的历史性能数据。
  • mpstat :专门用来监控多处理器(Multi-Processor)中每一个核心的 CPU 利用率。
  • pidstat :用来监控具体某一个进程的 CPU、内存、线程及 I/O 状态。
  • cifsiostat :用于监控 CIFS(通用因特网文件系统)的网络文件 I/O 状态。

sysstat 提供了覆盖全系统的 Linux 性能监控能力。它不仅能进行实时状态查看 ,还能通过后台守护进程(sysstat.service )自动收集历史性能数据

以下是 sysstat 的 6 大核心监控维度及对应工具:

1. 中央处理器 (CPU) 监控

  • 整体与多核状态 :监控整体 CPU 使用率(用户态、内核态、空闲、等待 I/O 等),并能展示每个独立 CPU 核心的负载。
  • 进程与线程级监控 :追踪单个进程或线程的 CPU 消耗、上下文切换次数(Context Switches)。
  • 对应工具 mpstat sar -u pidstat -u

2. 存储与输入/输出 (I/O) 监控

  • 磁盘设备吞吐 :监控每个块设备的读写速度(kB/s)、每秒读写次数(IOPS)。
  • 磁盘饱和度分析 :查看磁盘队列长度、服务时间、单个 I/O 请求的平均等待时间以及磁盘利用率(%util)
  • 文件系统与网络文件系统 :支持监控 Linux 文件系统节点,以及 NFS / CIFS 等网络文件系统的 I/O 状态。
  • 对应工具 iostat sar -d pidstat -d nfsiostat cifsiostat

3. 内存与交换分区 (Memory & Swap)

  • 内存利用率 :监控物理内存的空闲、已用、缓冲(Buffer)和缓存(Cache)大小。
  • 大页内存与脏页 :监控系统 Anonymous Huge Pages 的使用情况,以及等待刷入磁盘的脏页(Dirty Pages)数量。
  • 交换分区活跃度 :监控 Swap 分区的使用量,以及每秒内存页入/页出(Paging)的速率。
  • 对应工具 sar -r sar -R sar -W pidstat -r

4. 网络 (Network) 监控

  • 网卡吞吐与报文 :监控每个网络接口(如 eth0, wlan0)每秒接收和发送的数据量(kB/s)及数据包数量。
  • 网络错误与丢包 :统计网卡接收/发送时的错误数、丢包数和帧对齐错误。
  • 网络协议栈统计 :监控 TCP、UDP、ICMP 等传输层和网络层协议的流量、错误段及重传率。
  • 套接字 (Sockets) :统计当前系统处于使用中、监听中或处于特定状态的 TCP/UDP 套接字数量。
  • 对应工具 sar -n DEV sar -n EDEV sar -n TCP sar -n SOCK

5. 系统负载与内核参数

6. 电源管理与硬件(特定平台)

  • 队列长度与负载:统计系统运行队列长度(Run Queue)、进程总数以及 1/5/15 分钟的系统平均负载(Load Average)。
  • 内核资源限制 :监控当前系统已打开的文件句柄数(File Handles)、Inode 状态和伪终端数量。
  • 对应工具 sar -q sar -v
  • 设备能耗 :在支持的硬件上,监控 CPU 频率、温度以及风扇转速。
  • 对应工具 sadc (底层收集器)、sar -m

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Luchang-Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值