资讯详情

Strix Halo本地跑大模型,SSD写入量暴增256GiB?排查与优化实战

📅 2026/9/25 3:51:38 | 华诺云谱 👁 阅读
Strix Halo本地跑大模型,SSD写入量暴增256GiB?排查与优化实战
上个月我的Strix Halo主机终于到货就是大家讨论的Ryzen AI Max那一套128GB统一内存官方标称内存带宽到256GB/s级别。我买它的目的很直接本地跑Qwen3.8 Flash Next这种级别的模型不用再跟远程GPU较劲。系统装好后把模型跑通、连续推理了一天多结果第二天顺手用smartctl看了一眼系统盘SMART数据直接懵了——盘上“数据单元写入计数”一天涨了将近256GiB。按这个速度一年下来100TB打底哪怕是大容量NVMe盘也熬不了几年。这篇就完整梳理一下我当时的排查链路、最终根因以及优化后把单日写入压到12GiB的具体配置。如果你的部署环境也是Strix Halo这类AMD统一内存平台或者你在任何大内存机器上跑本地大模型这份经验应该能帮你少走不少弯路。1. 256GiB被写掉的一天发现硬盘异常的过程1.1 用SMART给写入量画一条基线先说结论无论你用的是Ollama、llama.cpp还是别的推理框架以文件系统层的读写统计作为判断依据都不够可靠。要确认硬盘的真实写入量最靠谱的是盘上固件自己的计数——NVMe SMARTA里那个data_units_written字段。查看命令非常简单sudo nvme smart-log /dev/nvme0n1 # 或者 sudo smartctl -a /dev/nvme0n1但这里有个非常容易踩的坑data_units_written的单位不是字节而是“512字节×1000”也就是每个计数单位约等于0.477GiB。很多教程没提这一点我第一次换算就错了差点以为自己看的是个没意义的数字。正确做法是先记录当前值过一段时间比如1小时或第二天同一时刻再记录一次两次差值才是这段时间的真实写入量。我当时就是开机跑了一天模型之后再和装机当天晚上的记录做对比换算出来新增写入约256GiB。刚开始我还以为是计算错误又用nvme smart-log连续蹲了俩小时发现每小时仍在增长10GiB左右折算下来一整天确实是200多GiB的量级。这不是偶发一次下载或拷贝而是持续不断的背景写入。1.2 这个数字在NVMe盘上意味着什么256GiB换算成十进制大约是275GB如果按这个速度跑一年就是100TB左右。现在市面上常见的1TB NVMe盘标称TBW总写入量通常在300到800TBW之间。理论上算下来哪怕每天256GiB一块600TBW的盘也能撑六七年听起来似乎不致命。但问题不是“这块盘最终能不能用六年”而是“一个看起来正常的本地推理任务为什么会让SSD进入这种持续高速写入状态”。这种状态可能不只是硬盘寿命问题底层大概率存在着内存回收异常、进程反复崩溃、日志风暴等问题。继续跑下去盘没写穿系统也可能先被拖垮。另一个值得记录的细节是smartctl -a里的Percentage Used字段那个百分比反映的是固态盘寿命消耗程度。我的盘当天这个数字涨了可不止一点点虽然绝对值仍在可接受范围但趋势已经足够刺眼。走到这一步如果不干预后面就是温水煮青蛙。2. 从NVMe到进程完整的四步取证链发现写入量异常之后最忌讳的就是直接去开各种监控工具猜。我的习惯是一层层往下锁先确认设备层面在持续写入再抓进程再抓具体文件最后把日志和数据库也算进总账。2.1 第一层确认设备连续写入这一步主要是排除“某一次大文件拷贝”之类的偶发现象。我是用一条简单的循环命令来观察写入速度的while true; do sudo nvme smart-log /dev/nvme0n1 | grep data_units_written sleep 3600 done配合iostat -x 1观看更细粒度的瞬间速率sudo iostat -x /dev/nvme0n1 1当时iostat的输出里wkB/s这一列经常跳到几MB到十几MB偶尔还冲到几十MB。这说明写入不是平均分摊的反而更像某些任务周期性触发的大块落盘——这个特征很重要后面解释根因时还会用到。有意思的是这个环节用图形化工具反而容易误判。GNOME磁盘工具里的“SMART数据”页面也能看写入量但它既没有可保存的时间戳也没有连续两个时点的对比功能。更坑的是它里面还有个“坏块测试/写入测试”功能如果你手滑点了可能自己就先制造了一大把写入量干扰排查。命令行虽然丑但每一步都可复验。2.2 第二层用iotop与fatrace抓现行确认设备持续写入之后就该看是谁在写。先用iotop按进程看sudo iotop -o -P -k-o只显示有IO活动的进程-P显示进程而不是线程-k用KB/s显示。我当时在列表里看到了systemd-journald持续占写入还有推理进程本身也有写盘动作但这些都不足以单独解释每小时10GiB的体量。单纯的进程级写入统计有个盲区page cache的延迟回写、某些进程的mmap写回未必都能清晰归因到某个具体进程上。所以还得往下一层看文件。这时候fatrace是神器。它基于fanotify能实时显示哪个进程在打开、读、写哪个文件sudo fatrace --timestamp跑几分钟输出基本就是这样的画风13:02:31 journald(812): W /var/log/journal/.../system.journal 13:02:32 python(1567): W /home/me/.cache/huggingface/.../model.safetensors 13:02:33 node(3144): C /tmp/tmp_123/model.bin一跑就看到问题了第一systemd-journald确实在疯狂写它的journal第二某个临时目录里不断有新的模型文件被创建出来这几乎可以肯定是某个加载器把模型文件复制到了临时目录再读取第三还有一个崩溃转储目录里躺着巨大的core文件——这块后面细说。2.3 第三层把日志和数据库算进总账很多人在这一步会被journald的量吓到。journalctl --disk-usage一查好家伙占了十几GB。但这些日志其实只是“汇总表”真正制造内容的另有其人。我当时检查了这几个地方systemd-coredump目录ls -lh /var/lib/systemd/coredump/。如果你推理过程中进程崩溃过内核默认会dump整个进程内存。8B模型启动后的RSS动辄几十GB一次崩溃就能写几十GiB出去。崩溃个三五次200GiB就没了。coredumpctl list看崩溃时间点和大小这个直接能对上“某时段写入飙高”的现象。docker容器日志如果博客或API服务用容器部署/var/lib/docker/containers里每个容器的json日志默认是无上限增长的。我这边虽然没重点查但如果你还套了dify这类工作流应用它的SQLite数据库、上传附件、容器日志全都是写盘大户。把所有明显来源加起来我当场算了一笔账core dump文件贡献了一大块journald占了一部分推理框架往临时目录反复复制模型又占了一部分。但把它们加起来离256GiB还差了一截。剩下的那部分就是真正的主角——swap。3. Strix Halo统一内存架构下SSD为什么会变成swap垃圾桶3.1 128GB看起来很大但显存也在这块内存里Strix Halo最大的卖点就是统一内存CPU、GPU、NPU共享同一片物理内存没有独立显存。好处很明显模型权重不用从显存搬到内存再搬回来带宽直接到顶这也是本地跑LLM性能好的原因。但副作用也很隐蔽128GB里的一部分会被GPU/NPU预留。BIOS里通常能设置预留量常见是8GB到32GB不等有时候系统里看着可用内存是“128GB”实际上OS能自由支配的只剩110GB甚至更少。如果再开个桌面环境、浏览器、开发工具就要再减掉十几GB。这时跑一个动态占用大的推理任务尤其开了长上下文或者多个并发请求内存压力会迅速上升。CPU端推理需要访问模型权重和KV cacheGPU端也在这同一片内存里划地盘两边一起抢内核的kswapd就该上班了。3.2 256GiB写入量的滚雪球逻辑很多人的直觉是128GB内存怎么可能swap但swap触发与否看的是“可用内存”和“内存回收压力”不是物理总量。当推理进程申请了70GBGPU又占着二三十GB系统为了满足内存申请不得不把一些不常用的内存页搬到磁盘上当作swap。内存明明足够为什么还需要因为操作系统不会等你把所有内存用满了才开始换页它会提前把旧页挪走给未来可能的大申请腾地方。而LLM推理是典型的反复随机访问场景每次生成一个tokenCPU端都要访问模型权重、past KV cache、中间激活值。只要这些页面中有部分被swap到磁盘每次访问就是一次缺页中断从SSD读进来读进来的旧页又可能把别的页挤出去再写回SSD。一进一出写入量就滚起来了。我当时半夜观察时看到的就是一个典型的抖动状态swap used在几GB到几十GB之间反复横跳free -h里swap这一栏每几秒都在变。结合推理时的活跃页访问模式一天滚出256GiB完全有可能。说得直白点你把SSD当成了内存的水库推理进程每次上下浮动都在抽水放水水表自然转得飞快。3.3 为什么N卡部署经验在UMA平台上容易翻车网上随手搜“qwen3.8 flash next部署”排在前面的大多是NVIDIA方案。N卡有独立显存显存是显存内存是内存显存不够时最多跑慢或OOM系统盘被疯狂swap的场景很少见。但到了Strix Halo这类AMD统一内存平台上推理框架、驱动、操作系统三者对内存的争夺都发生在同一个池子里。如果直接照搬N卡教程那边的默认配置不加锁页、不调内存回收策略甚至拿N卡教程里的CUDA参数硬套一个Vulkan/ROCm后端踩中swap坑的概率非常高。不是说AMD平台不行而是它的内存管理模型和N卡完全不同。你当然可以把Strix Halo当大号NUC来玩但最好先理解它的内存池是怎么运作的否则便宜大碗的优势就会变成硬盘杀手。4. 止血方案把单日写入从256GiB压到12GiB定位清楚之后剩下的就是逐个消除写盘来源。我的思路很简单让模型住进锁页内存让磁盘swap靠边站把日志、崩溃转储、临时文件这些“附带伤害”全部按需瘦身。4.1 内存层给模型“锁页”把swap请出场第一个动作是调整内核swap倾向这一步只花一分钟sudo sysctl -w vm.swappiness10持久化可以写进/etc/sysctl.d/99-swap.confvm.swappiness10 vm.vfs_cache_pressure50但这只是降低内核用swap的积极性更重要的是让推理进程把自己的内存页锁住告诉内核这些页你别动。对llama.cpp系来说sudo ulimit -l unlimited ./llama-server -m /models/qwen3.8-flash-next.gguf --mlock -c 32768如果是systemd托管需要在service文件里加LimitMEMLOCKinfinity锁页之后模型权重和活跃内存页就不会被换出swap触发概率大幅下降。注意不要盲目贪长上下文锁定多少就是多少如果模型加上下文超过物理可用内存MLOCK会让进程直接OOM。Strix Halo 128GB跑8B模型加32K上下文完全没压力但如果只有64GB版本还是要保守一点。另外如果业务场景确实需要保留swap强烈建议用zram代替磁盘swap。zram把swap数据压缩后放在内存里速度快最重要的是不会写SSDsudo modprobe zram sudo zramctl /dev/zram0 --size 32G sudo mkswap /dev/zram0 sudo swapon -p 100 /dev/zram0优先级100高于普通磁盘swap内核会优先用zram。128GB机器给32G zram完全合理64GB机器建议给16G左右别让zram反过来吃光了内存。4.2 系统层日志、缓存与临时目录统一瘦身内存策略调整完之后再回来收拾日志和缓存这些“明细账”。journald先限制体积我直接改成volatile模式日志放tmpfs重启即丢sudo mkdir -p /etc/systemd/journald.conf.d cat EOF /etc/systemd/journald.conf.d/size-limit.conf [Journal] Storagevolatile SystemMaxUse200M MaxRetentionSec1day EOF sudo systemctl restart systemd-journald如果你需要持久化日志做审计那Storagevolatile要谨慎折中方案是把SystemMaxUse设小一点保留持久化但别让它无上限膨胀。崩溃转储这块我的处理是限制大小而不是彻底关闭。完全关掉coredump对排障不友好但机器上那个三四十GB的core文件实在没必要存。配置cat EOF /etc/systemd/coredump.conf.d/size-limit.conf [Coredump] Storageexternal ExternalSizeMax50M EOF这样再崩溃转储会被截断到50MB以内能保留关键信息又不会撑爆硬盘。docker容器日志也要限流否则光是一个dify工作流就能在后台慢慢磨掉你几十GB写入量。在/etc/docker/daemon.json里加{ log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 } }然后重启docker。旧日志可以清一次docker system prune和truncate -s 0 /var/lib/docker/containers/*/*-json.log注意测试环境执行生产环境谨慎。模型缓存这块我做了两条优化。第一条下载好的模型文件改成只读chmod a-w /models/*.gguf防止有些加载器启动时去改写文件或生成缓存。第二条临时目录确认是tmpfsdf -h /tmp如果结果显示你的/tmp还在磁盘上建议用tmpfs挂载mount -t tmpfs tmpfs /tmp -o size16G,mode1777或者systemctl enable tmp.mount让系统默认配置生效。这样推理框架往临时目录写中间文件时内存扛下来完全不落盘。4.3 优化前后数据对照与副作用提醒上面这一套全部落地之后我把系统重新跑了一整天同一个模型、同样的工作负载对比效果非常明显项目优化前优化后单日新增写入约256GiB约12GiBjournald日志落盘多GB级重启即失小于100MBcore dump数十GB级限制50MB内swap写盘主要来源基本为0推理响应速度偶发卡顿稳定12GiB里主要剩什么一些正常的journald落盘、页面缓存正常回写、系统日常元数据更新。这些属于正常损耗完全符合预期。不过有几个副作用要提醒Storagevolatile会让重启后没有旧日志遇到系统级故障需要复盘时会有点难查coredump限制了大小崩溃时拿不到完整堆栈调试时要靠框架自己的日志和gdb去复现zram虽然不写盘但它要占用内存做压缩内存紧张时反而会加剧回收压力。每一项都要根据自己的场景权衡不要无脑照抄。5. 跑Strix Halo本地LLM之前建议先做这三件事5.1 建立TBW基线心里有数再开机现在系统稳定了我养成了一个习惯新机器到手第一件事不是装模型而是先查一次SMART写入基线。sudo smartctl -a /dev/nvme0n1 | grep -E Data Units Written|Percentage Used|Power On Hours把这三个数据存下来设个cron每天记录一次。正常状态下一台只跑本地办公服务的机器一天写入量通常在几GB以内。如果哪一天突然出现“今天写了20GiB”“明天写了50GiB”说明又有什么流程在作妖可以趁早抓。选盘上我也补了两句如果是专门跑LLM的Strix Halo主机系统盘尽量选TLC别贪便宜上QLCOEM盘尤其要查清楚TBW标称值因为很多联想、惠普、戴尔机器里带的原厂NVMe盘TBW标得很保守。模型和数据集这种大体积、大读取、几乎不修改的资源放机械盘或大容量SSD都行没必要占着系统盘的写入寿命。5.2 用zram替磁盘swap当缓冲有些朋友可能会问既然锁页mlock已经搞定了为什么还要留着swap我的看法是swap本身不是毒药它是一个“防护垫”。内存真的被某个突发进程吃爆时没有swap系统只能直接OOM kill那种体验更糟。关键是让这个防护垫不落在SSD上。zram本质上就是内存里的压缩分区数据压缩完了放RAM里swap的时候不需要碰磁盘优先级调高之后平时磁盘swap几乎不参与工作。我现在的配置是128GB物理内存zram开32G普通磁盘swap保留一个最小的兜底分区但优先级极低。这样既不会被OOM杀到也不会让SSD成为swap的牺牲品。5.3 把“磁盘写入审计”变成日常习惯最后分享一个简单的脚本思路我目前就放在cron里每天跑一次#!/bin/bash LOG/var/log/ssd_daily_rw.log echo $(date) $LOG nvme smart-log /dev/nvme0n1 | grep -E data_units_written|percentage_used $LOG这样每天都能看到写入量和寿命消耗的累计值一周下来就能估算出长期趋势。如果某天数值异常翻倍至少知道是从哪一天开始的配合journald、容器日志很快就能定位到具体任务。说句实在话跑本地LLM的机器性能偶尔不行可以接受硬盘被偷偷写爆才是真的疼。Strix Halo这套平台性价比很高本地推理体验也确实好但在这种统一内存架构上跑模型内存策略和硬盘健康监控不是可有可无的优化项而是必做的功课。希望这份从一天256GiB写入量排查到12GiB的完整过程能帮你避开同样的大坑。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑