llama.cpp 完整教程,放错盘读一遍多等 1 小时

llama.cpp 完整教程,放错盘读一遍多等 1 小时

结论先行:把模型塞 NAS 省空间的人,省的是硬盘钱,付的是每次 73 分钟的等待------这笔账算不过来,瓶颈在链路不在容量

这句判断来自一次实测量出来的数:同一份 475.25 GiB 权重,躺在同一块盘上,什么都不换,只改每次读多少字节,125.1 秒变成 39.7 秒。

环境、命令、量出来的数都在下面,可以直接照着重跑。

模型下载完,多数人的下一步是直接敲 llama-cli -m 模型.gguf。

我今天把「下载完到跑起来」中间那一段拆开量了一遍。

盘没换、文件没动、CPU 没变。差的只是「一次读多大」这一个数。

这一段在所有教程里都是空白。llama.cpp 的教程从 git clone 开始,到 -ngl 99 结束,中间没有一句讲「模型该放哪块盘、读写按多大的块、48 个分片要不要合成一个」。而这一段是你每次开机加载都要重新付一次的时间。

我按你部署时真正会撞上的顺序排了三件事:先放盘,再定块,最后决定分片合不合。三步都有数字,都能复跑。

① 第一步:先把盘选对,这一步的差距是 112 倍

我在 DGX Spark #1 上放了一份真实生产权重:48 个分片,合计 510,296,708,312 字节,也就是 475.25 GiB。

然后我把同一份东西,放到三种介质上,各读一遍完整全量。

放在哪 块大小 吞吐 读完整仓
DGX Spark 板载 NVMe(3.7T ext4) 128MB 12.847 GB/s 39.6 秒
本机 D: 盘(INTEL SSDPF2KX019T1M) 128MB 4478.6 MB/s 1 分 54 秒
NAS(SMB,192.168.11.178,1G 链路) 64MB 115.5 MB/s 1 小时 13 分 40 秒

三个数字摆在一起:39.6 秒 : 114 秒 : 4420 秒 ≈ 1 : 2.9 : 112。

这份权重放板载盘上,开机加载是 40 秒级的事。放 NAS 上,是「先去泡杯茶,回来还没读完」的事。

很多人把模型扔 NAS,理由很实在:家里那台 NAS 有 20TB 空闲,本机 SSD 只剩 1.5T,一个模型 50GB,多放几个就满了。省下的是硬盘钱,我把代价算给你:加一块 2TB 的企业级 NVMe 大约 1000 块,比 NAS 上那点空间贵。但你换掉的是每次 73 分钟的等待------一天重启两次模型,一个月七十多个小时。

🔴 这是我今天最想拦住的一件事:把模型放 NAS 上省空间,省下的 1000 块,代价是每次加载多等 73 分钟。

② 第二步:块大小别用默认值,1MB 到 16MB 白拿 2.8 倍

盘选对了,第二件事是「一次读多大」。

llama.cpp 自己会做内存映射,日常你不用管读多少。但你一旦涉及自己搬权重、预热 page cache、写加载脚本、或者做冷启动压测,块大小就是你手里唯一的旋钮。我把它从 1MB 扫到 128MB,每一档都把 48 个分片完整读一遍,逐档核对读到的字节数必须等于 510,296,567,808------不等就作废重跑。

DGX Spark #1 上(ext4 + O_DIRECT):

块大小 全量耗时 吞吐 相对 128MB
1 MB 125.146 s 4.078 GB/s 0.32×
4 MB 70.233 s 7.266 GB/s 0.57×
16 MB 44.600 s 11.442 GB/s 0.89×
128 MB 39.721 s 12.847 GB/s 1.00×

同一块盘、同一批文件,只改块大小,125.1 秒变 39.7 秒,3.15 倍。

再看细一点:1MB 到 4MB 这一档就吃掉了一半差距(125.1→70.2)。16MB 已经拿到 89% 的性能,再往上加到 128MB 只多 11%。

16MB 是拐点。 你不需要为了那 11% 去开 128MB 的缓冲区,那意味着常驻内存多吃 128MB、尾延迟更差。

本机 D: 盘(x86_64,NTFS,FILE_FLAG_NO_BUFFERING)跑出同一条曲线:

1MB 2MB 4MB 8MB 16MB 32MB 64MB 128MB
1416.2 2233.4 3316.2 3956.9 4170.7 4327.2 4425.5 4478.6

1MB→128MB 是 3.16 倍。两台机器、两种架构、两套文件系统(ext4 / NTFS)、两种对齐方式,曲线几乎重合。这条曲线的形状不是某块盘的脾气,是块设备本身的性质。

NAS 上这条曲线是平的:

1MB 4MB 16MB 64MB
92.9 106.0 111.7 115.5

1MB→64MB 只有 1.24 倍。 因为瓶颈根本不在块大小,在 1G 链路那条 118 MB/s 的天花板。链路上限压着,你把块调到 1GB 也没用。

③ 第三步:48 个分片要不要合成一个

这一步最容易被教程漏掉,也最容易白干活。

网上很多「合并分片」的说法,理由是「减少文件数、减少元数据开销」。我把这个开销真测了一遍。

本机 D: 盘,768MB 同一份数据,做成 1 个文件 vs 切成 96 个 8MB 分片,都用 16MB 块读:

单文件 96 分片 比值
耗时 0.1924 s 0.2500 s 单文件快 1.30×
吞吐 4186.5 MB/s 3220.8 MB/s ---
单文件 open+close 开销 --- 0.0097 ms 可忽略

96 个文件的元数据加起来 0.93 毫秒。在本机盘上,合并只省 30%,且省的不是元数据。

NAS 上就完全不一样了。256MB,1 个文件 vs 64 个 4MB 分片:

单文件 64 分片 比值
耗时 2.8671 s --- 单文件快 1.21×
单文件 open+close 开销 --- 6.7854 ms 是本机的 700 倍

同样是 open+close,本机 0.0097 毫秒,SMB 上 6.79 毫秒。700 倍。

64 个分片光元数据就花掉 0.434 秒。如果你的模型有 434 个分片(市面上真有这种切法),元数据开销就是 2.9 秒,而且全是串行等待------不是并发的,是一个一个排队握手。

所以结论按介质分岔:

  • 本机 NVMe:不用合并。 0.0097ms/文件的开销,你花几十分钟做 sha256 校验、拼文件、再校验一遍,省回来的是 30%。不划算。
  • SMB / 网络盘:必须合并,或者先拷到本地。 6.79ms/文件,分片越多越亏,而且亏的是串行时间。

④ 一条能直接抄的命令链路

散步结论不如给命令。下面这套是我今天跑通路子的精简版,按顺序抄。

第 1 步,先看盘在哪、空多少。

bash 复制代码
df -h /home /mnt /data 2>/dev/null
lsblk -d -o NAME,ROTA,SIZE,MODEL

ROTA 是 1 说明机械盘或网络盘,0 是 SSD。模型盘看到 1,直接换盘,别调参数。

第 2 步,量一下这块盘的实际读速,别信标称。

bash 复制代码
# 用真实模型文件,不要用 dd 的空数据(空数据会走稀疏优化,测出来是假的)
F=/path/to/model-00001-of-00048.safetensors
SIZE=$(stat -c %s "$F")
SIZE=$(( SIZE - SIZE % 4096 ))   # O_DIRECT 必须 4096 对齐,尾部截掉
dd if="$F" of=/dev/null bs=16M count=$((SIZE/16777216)) iflag=direct status=progress

这里有个我踩过的坑:真实分片的字节数常常不是 4096 的整数倍(今天这批里有个 2,706,402,896 B 的),iflag=direct 会直接报 OSError: [Errno 22] Invalid argument。必须先把 size % 4096 截掉,否则脚本第一行就崩。

第 3 步,定块大小。

bash 复制代码
for BS in 1M 4M 16M 64M 128M; do
  /usr/bin/time -f "$BS %e s" dd if="$F" of=/dev/null bs=$BS iflag=direct
done

看哪一档的秒数开始收敛,就停在哪一档的前一格。今天两台机器都收敛在 16MB。

第 4 步,决定分片合不合。

bash 复制代码
# 看分片数和整体体积
ls -l /path/to/model/*.safetensors | wc -l
du -sh /path/to/model

分片数 ÷ 100 大致就是 SMB 上你要多付的秒数(6.79ms × 分片数)。48 个分片 = 0.33 秒,可以忍;434 个 = 2.9 秒,忍不了。

第 5 步,才是 llama.cpp。

bash 复制代码
llama-cli -m /path/to/model.gguf \
  -ngl 99 -c 8192 -t 8 \
  --no-mmap          # 冷启动想测真实读盘速度时用;日常用默认 mmap 更快

--no-mmap 不是「优化开关」,是「诊断开关」。默认 mmap 让操作系统替你管缓存,加载快;加 --no-mmap 才会真的走上面那条块大小路径。想验证盘有没有选对,加它;想日常用,别加。

⑤ 我为什么敢写这几个数字

今天我第一版脚本跑出 44 到 134 GB/s。

一块消费级 NVMe 不可能跑到 134 GB/s。当场作废,回头查:mmap(-1, 256MB) 只分配了 256MB 缓冲区,每次读到 256MB 就 break,但我把整个文件大小当分母------吞吐被放大了十倍。

改法只有一条:每档必须核对 got 字节数是否等于目标字节数,不等就整档作废。 今天四档全部核对过,读满 510,296,567,808 B。

第二处坑:单文件短跑会低估。同一块盘,2.7GB 单文件 128MB 块测出 12.886 GB/s,全量 475 GiB 跑出 12.847 GB/s,差 0.3%。这次是碰巧对齐,不能当「短跑永远可信」的依据。

第三处:DGX Spark #1 上常年挂着生产容器(历史记录吃 290% CPU),今天没记 loadavg,所以绝对吞吐可能偏保守。但四档全在同一条件下测,相对比值可信------这也是我只拿比值下结论、不拿绝对值跟别人的机器比的原因。

⑥ 这些数据没覆盖什么

老实交底,免得你照着做踩空:

  • 1MB 以下的块没测。 512KB / 256KB / 4KB 全空着。别拿其他介质的 4K 数字套到 NVMe 上。
  • 本机 C: 盘(消费级 WD_BLACK SN850X)没参与扫描。 所以「消费级 NVMe 是不是也 3 倍」我答不了。
  • NAS 的硬件规格仍未知(无 SSH,22 端口关闭),115.5 MB/s 只能归因到「1G 链路」这一层,说不出具体是网卡还是交换机。
  • 「边下载边加载」的重叠场景没测。 今天只测纯读,真实下载时读盘和写盘是并发的。
  • 所有数字都是单次测量,没有误差棒。四档同机同条件,横向可比,但不能当精度指标。

最后一句,请把它当成本文的结论。

**

⑦ 三步该按什么顺序做

先盘、后块、最后分片。这个顺序不能反,因为后一步的收益上限被前一步锁死。

盘选在 NAS 上,你再怎么调块大小也就 1.24 倍;盘选对了,块大小才发挥出 3.15 倍。分片合并在本机盘上是 30% 的收益,在 SMB 上是必须做的动作------同一个操作,两种介质下性质不同。

给你三个判断档,直接照自己的情况对:

你的情况 该做什么 白话结论
模型在板载 NVMe / 本机 SSD 只调块到 16MB,不要合并分片 花 10 分钟,拿 3 倍
模型在 NAS / 网络盘 先搬到本机,或者至少合并分片 别调参数了,参数救不了链路
只有一块机械盘 加一块 NVMe,别调任何东西 换盘比调参便宜

第三档是我自己踩过的。早期我把权重放在一块老机械盘上,一直在调 --no-mmap、调线程数、调 batch size,怎么调都是几十 MB/s。后来换盘,同样的命令直接上百倍。

⑧ 下单前先算这一笔

475 GiB 这份权重,你的机器多久能读完一遍,可以直接乘出来。拿 du -sh 的实际体积除以你实测的吞吐:

  • 12.847 GB/s → 40 秒
  • 4478.6 MB/s → 1 分 54 秒
  • 115.5 MB/s → 1 小时 14 分

第二列和第三列之间那 1000 多块硬盘钱,换的就是每次开机省下的 72 分钟。如果你的模型一周才加载一次,NAS 也能忍;如果你调参、重启、换量化档一天十次,那 NAS 就是纯粹的折磨。

我自己的账是这样:DGX Spark 那四台必须放板载盘,它们每次跑生产都要重新加载 475 GiB,40 秒和 74 分钟的差别不是一个数量级的问题,是「能不能迭代」的问题。本机 5090D 上那批小模型放 D: 盘,1 分 54 秒能接受,反正我一天加载不了几次。

真正不该放 NAS 的,是那种「你改一行 prompt 就要重启一次」的实验场景。那种场景下链路延迟会直接决定你的试错速度。

参考来源:

  • 本机生产权重目录的 48 个真实分片(合计 510,296,708,312 B)
  • llama.cpp 官方文档 mmap 与 --no-mmap 行为说明
  • 本机实测:DGX Spark #1(aarch64 GB10 / 20 核 / 122GB / 3.7T ext4)、本机 rtx5090d(24C / 96G / D: INTEL SSDPF2KX019T1M)、NAS(SMB / 1G 链路)
  • 数据落盘:site_matrix/runs/d6_full_dgx1_20261113.json、d6_blk_local_20261113.json、d6_blk_nas_20261113.json、d6_shard_20261113.json

验证等级:L1 | 本环直接实测。dgx1 全量四档每档读满 510,296,567,808 B 并逐档核对字节数;本机 8 档 / NAS 4 档为单次测量无误差棒;跨架构(aarch64 ext4 vs x86_64 NTFS)两套独立脚本得同形状曲线,互为交叉验证。dgx1 上有生产容器常驻且未记 loadavg,绝对值可能偏保守,相对比值可信。

数据说明:全部吞吐为实际读盘字节数 ÷ 墙钟耗时,未经平滑。测试对象是本机生产环境的 48 个真实分片(非公开仓库估算体积),四档均读满 510,296,567,808 B。1MB 以下块大小、消费级 NVMe、边下载边加载三项未测,文中未作实测表述。

声明:本文为个人实机测试记录,机器与模型均自购自装,不含任何厂商合作。测试环境与你的环境可能不同,数字仅供参考。


本文所有数字均为本机实测,非引用。环境与脚本版本见文末参考来源。 作者:丘山录 · 记录本地部署与算力实测

相关推荐
AI前端工程狮1 小时前
用户点了「取消」,我的服务进程退出了
人工智能·程序员
网易云信1 小时前
别急着让 AI 出方案:学会追问三步走,医美咨询全跑通
人工智能
panyz2 小时前
不想再开 7 个标签页查AI额度,我用 Node 写了个本地看板
人工智能·开源·github
炫酷的大高个2 小时前
3.2TB 权重开源了,我算了 4bit 之后还要几张卡
人工智能·架构·开源
字节跳动开源2 小时前
AI 原型几分钟,设计返工一整天?OpenViking 让 AI 用上你的 Figma 设计稿
人工智能·开源
陈工大模型3 小时前
解压工具的三个技术分水岭:编码、分卷、容器格式
人工智能·windows·安全·解压工具·免费国内办公软件
hpoenixf3 小时前
让 Agent 持续研究半小时:从普通研究到可靠交付的设计
人工智能
MysTic_Zhong4 小时前
【2】整体架构蓝图:六层依赖与技术选型
人工智能·agent
硅谷秋水4 小时前
EgoHumanoid‑V2 方法分析
人工智能·机器学习·计算机视觉·语言模型·机器人