AI服务器如何规划本地存储?模型文件、数据集与高速缓存配置指南

很多人配 AI 服务器时把预算全砸在 GPU 上,存储随便配几块大盘了事,结果模型加载一次要十几分钟,训练时 GPU 利用率长期偏低,DataLoader 成了瓶颈。等到发现不对再回头改,往往要重新规划分区、迁移数据,折腾得不轻。

AI 场景的存储和普通业务很不一样:它面对的是超大文件、极高顺序读吞吐、海量小文件随机读这三种反差极大的负载。模型文件动辄几十上百 GB,是顺序大文件;数据集是海量小文件随机读;训练过程中的检查点(checkpoint)是周期性大写入。三种负载对存储的要求完全不同,用一种盘包打天下必然顾此失彼。

这篇文章按"模型文件 → 数据集 → 训练缓存 → 检查点 → 系统盘"的顺序,讲清每类数据的存储特性与容量规划方法,给出分区、挂载、文件系统与性能测试的真实命令(区分 RHEL/CentOS/Rocky 与 Debian/Ubuntu),并用表格对比不同存储介质的选型。文中容量、吞吐数字为经验量级,用于建立直觉,具体以实测为准。

先分清四类数据

第一类:模型文件。 特点是单个文件大、读多写少、一旦加载进显存就很少再读。要求是高顺序读带宽和足够容量。一次推理服务启动可能只读一次,但训练时可能反复加载。容量上要按"单个模型大小 × 保留版本数"规划,多版本共存很常见。

第二类:数据集。 特点是小文件多、随机读、需要高 IOPS 和低延迟,训练时被反复遍历。这是最容易成为瓶颈的一类。千万级小文件放在单块机械盘上,训练会慢到无法忍受。要求本地 NVMe 或高性能分布式存储。

第三类:训练缓存/临时目录。 包括数据预处理缓存、编译缓存、临时文件。特点是写入频繁、生命周期短、可丢弃。要求高写入带宽,适合 NVMe。

第四类:检查点。 特点是周期性大写入(每个 epoch 或每 N 步一次),文件也很大。要防止写入时争抢带宽影响训练,建议单独放一块盘或错峰写入。

除此之外还有系统盘,只放操作系统和软件,不要和数据混在一起,避免日志写满导致系统异常。

容量规划:给一个可用的算法

容量规划没有标准答案,但可以按这个顺序算:

  1. 模型容量 = 单模型大小 × 版本数 × 冗余系数。量化后的模型更小,但通常同时保留原始和量化两版。
  2. 数据集容量 = 原始数据 × 副本数 × 预处理后膨胀系数。图像、音频、文本的膨胀系数差异很大,预处理后的格式有时比原始大好几倍。
  3. 检查点容量 = 单检查点大小 × 保留个数。大模型检查点可达数百 GB,保留策略要明确。
  4. 缓存与临时空间 = 数据集的百分之十到三十(经验值,视预处理而定)。
  5. 留出增长空间 = 以上总和再乘以一点五左右,别把盘写满。

一个实用原则:训练机优先保证数据集与缓存落在 NVMe 上,检查点可以放更便宜的盘甚至网络存储。

存储介质对比

介质 顺序读吞吐量级 随机 IOPS 量级 延迟 单 GB 成本 适用
SATA HDD 百 MB/s 级 百级 毫秒级 最低 冷数据、归档、备份
SATA SSD 数百 MB/s 数万 百微秒级 中等 系统盘、一般数据
NVMe SSD(PCIe 4.0) 数 GB/s 数十万 数十微秒 较高 数据集、缓存、检查点
NVMe SSD(PCIe 5.0) 更高 更高 更低 高 高吞吐训练
内存盘/大内存缓存 极高 极高 纳秒级 很贵 热点小文件缓存
分布式存储 视网络而定 视后端而定 百微秒到毫秒 按需 共享数据集、多机训练

经验上,训练数据集放 NVMe 相比放机械盘,DataLoader 等待时间能下降一个数量级,GPU 利用率显著提升。这不是玄学,是 IOPS 差距的直接体现。

分区与挂载实操

先看清现有磁盘与分区:

# 列出块设备
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE

# 查看 NVMe 设备列表
nvme list

# 查看挂载与容量
df -hT

# 查看磁盘型号与转速
lsblk -d -o NAME,SIZE,ROTA,MODEL

ROTA 为 1 表示机械盘,0 表示固态(注意某些虚拟化环境该字段不准)。

对一块新盘做分区、格式化并挂载(以下操作会清除数据,务必确认设备名正确):

# 确认目标盘,例如 /dev/nvme1n1。切记核对,写错设备会丢数据
lsblk /dev/nvme1n1

# 用 GPT 分区表建一个分区
sudo parted -s /dev/nvme1n1 mklabel gpt
sudo parted -s /dev/nvme1n1 mkpart primary 0% 100%

# 格式化为 XFS(RHEL 系默认推荐)或 ext4
sudo mkfs.xfs -f /dev/nvme1n1p1
# 或 sudo mkfs.ext4 /dev/nvme1n1p1

# 创建挂载点并挂载
sudo mkdir -p /data/dataset
sudo mount /dev/nvme1n1p1 /data/dataset

# 写入 fstab 实现开机自动挂载,建议用 UUID
sudo blkid /dev/nvme1n1p1

编辑 /etc/fstab 加入一行(用 UUID,避免设备名变化):

UUID=<你的UUID>  /data/dataset  xfs  defaults,noatime,nodiratime  0 0

noatime 减少元数据写入,对读多的数据集有帮助。改 fstab 有风险,改完先执行 sudo mount -a 验证,确认无误再重启,否则可能导致系统无法启动。

文件系统与挂载参数选择

  • XFS:大文件顺序读写性能好,RHEL/CentOS/Rocky 默认,适合模型文件和检查点。
  • ext4:兼容性好、稳定,适合系统盘和一般用途。
  • 小文件海量场景:可考虑把数据集打包成顺序文件(如 WebDataset、TFRecord、LMDB),把海量小文件问题转化为大文件顺序读问题,效果往往立竿见影。

针对数据集盘的挂载优化示例:

UUID=  /data/dataset  xfs  defaults,noatime,logbufs=8,logbsize=256k  0 0

训练临时目录可以放到 NVMe 上用 tmpfs 挂载(注意占内存):

# 用内存盘做临时目录,容量按内存情况设定
sudo mkdir -p /dev/shm/tmp && chmod 1777 /dev/shm/tmp
export TMPDIR=/dev/shm/tmp

/dev/shm 本身就是 tmpfs,通常已足够大,很多训练框架默认会用它做共享内存。多进程训练时共享内存不足是常见报错,需要调大:

# 查看当前大小
df -h /dev/shm

# 临时调大(重启失效)
sudo mount -o remount,size=64G /dev/shm

# 永久调大:编辑 /etc/fstab
# tmpfs  /dev/shm  tmpfs  defaults,size=64G  0 0

性能测试:别只看规格

装完盘一定要实测,规格参数和实际表现常有差距。

# 顺序读写测试:写 10GB,块大小 1M,直接 IO
sudo dd if=/dev/zero of=/data/testfile bs=1M count=10240 oflag=direct
sync
# 读测试:先清缓存,再读
sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
sudo dd if=/data/testfile of=/dev/null bs=1M iflag=direct
sudo rm -f /data/testfile

注意 oflag=direct 绕过页缓存,测的是真实盘速;drop_caches 是全局操作,生产机上慎用。

更专业的测试工具 fio。RHEL/CentOS/Rocky:

sudo dnf install -y fio

Debian/Ubuntu:

sudo apt install -y fio

随机读测试(模拟数据集小文件读):

fio --name=randread --filename=/data/testfile \
    --size=8G --rw=randread --bs=4k --iodepth=32 \
    --numjobs=8 --ioengine=libaio --direct=1 --runtime=60 --group_reporting

顺序读测试(模拟模型加载):

fio --name=seqread --filename=/data/testfile \
    --size=20G --rw=read --bs=1M --iodepth=16 \
    --numjobs=4 --ioengine=libaio --direct=1 --runtime=60 --group_reporting

重点看 IOPS、bw(带宽)和 lat(延迟)三个指标。NVMe 盘随机 4K 读通常应有数十万 IOPS、顺序读应有数 GB/s 量级(均属经验值)。

监控与容量告警

# 磁盘空间与 inode(小文件多时 inode 也会耗尽)
df -h
df -i

# 磁盘 IO 实时监控
iostat -xz 1

# 查看哪个进程在读写
iotop -o

# inotify 句柄数(海量小文件监控可能不足)
sysctl fs.inotify.max_user_watches

别忘了 df -i。 海量小文件场景下,磁盘空间还剩很多,但 inode 先耗尽,同样会导致写入失败。普通 ext4 与 XFS 在创建文件系统时就已经确定 inode 总量,后期难以在线增加,所以规划小文件数据集时要么预留足够的 inode,要么就把它们打包成大文件。

建议把监控做起来:写一个简单脚本定时采集 df -h、df -i、iostat -x 的关键字段并落库或告警,容量用到百分之八十就提醒扩容,别等到写满再处理。训练任务因磁盘写满而中断,往往意味着数小时的算力打了水漂。

常见问题

Q1:模型文件放网络存储行不行?
可以,但加载速度取决于网络带宽。几十 GB 的模型走千兆网络要很久。常见做法是网络存原始版本,加载时复制到本地 NVMe 缓存。

Q2:数据集能不能放机械盘?
能用但会很慢,训练时 GPU 大部分时间在等数据。建议至少放 SSD,海量小文件务必放 NVMe 或做打包优化。

Q3:检查点为什么建议单独放一块盘?
避免写检查点时争抢带宽,影响训练数据读取。错峰或独立盘能减少抖动。

Q4:/dev/shm 报 shared memory 不足怎么处理?
调大 tmpfs size,见上文 mount -o remount,size=...,或在 fstab 中永久配置。

Q5:磁盘够大但写不进去是什么原因?
先查 df -i 看 inode 是否耗尽,再查是否有配额限制(quota)、只读挂载或文件系统错误。用 dmesg 看内核是否报 I/O 错误。

总结

  • AI 存储面对大文件顺序读、小文件随机读、周期性大写入三类负载,应分开规划而不是一块盘通吃。
  • 容量按"模型版本 + 数据集 + 预处理膨胀 + 检查点 + 缓存"逐项累加,再留百分之五十增长空间。
  • 数据集与训练缓存放 NVMe,模型与检查点可用性价比更高的盘或网络存储,系统盘独立。
  • 用 lsblk、blkid、fstab 正确挂载,noatime 优化读性能;海量小文件建议打包成大文件以绕过 IOPS 瓶颈。
  • 装完必测:用 dd 和 fio 验证真实吞吐与 IOPS,日常用 iostat、iotop、df -i 监控,警惕 inode 耗尽与共享内存不足。