Naive-N0.5-Flash 准备本地跑,先把权重落到本地目录再验分片完整

文章导读
想在本机跑 Naive-N0.5-Flash,卡住的地方通常不是显存也不是算力,而是权重文件本身:分片放错目录、少下一片、或者某一片在传输中截断。这些问题的特点是——如果不在加载前确认,你会在推理启动阶段收到一条含糊的报错,然后花时间怀疑框架版本和显卡驱动。更省事的顺序是先把权重完整落到本地目录,用命令核对分片字节数与哈希,再进最小配置加载,观察报错出现在哪一层。
📋 目录
  1. Ⅰ 在本地划出权重存放目录并列出全部分片文件
  2. Ⅱ 用校验命令核对每个分片的字节数与哈希
  3. Ⅲ 在最小配置下加载模型,观察加载阶段报错位置
  4. Ⅳ 记录一次完整启动的耗时与显存峰值
A A

想在本机跑 Naive-N0.5-Flash,卡住的地方通常不是显存也不是算力,而是权重文件本身:分片放错目录、少下一片、或者某一片在传输中截断。这些问题的特点是——如果不在加载前确认,你会在推理启动阶段收到一条含糊的报错,然后花时间怀疑框架版本和显卡驱动。更省事的顺序是先把权重完整落到本地目录,用命令核对分片字节数与哈希,再进最小配置加载,观察报错出现在哪一层。

本地跑 Naive-N0.5-Flash 的建议顺序是:先确定权重根目录结构,让分片文件和索引文件在同一个目录下;再用 sha256sum、wc -c 逐片核对字节数与哈希,把传输损坏和模型本身的问题分开;然后以最小配置加载,看日志报错是文件层还是显存层。若分片缺失或损坏,先重传再查索引,不要先改配置。具体目录名、索引文件名和分片数量需以你获取到的权重包为准。

在本地划出权重存放目录并列出全部分片文件

先给权重单独留一个目录,不要让权重和其他模型、数据集、日志混在同一层。常见做法是在挂载盘下建一个模型名目录,再按版本或量化规格分子目录。索引文件(一般是类似 model.safetensors.index.json 的 json)和它索引的全部分片文件必须放在同一层,加载器按索引里的相对路径去找分片,分片被挪到子目录就会直接找不到。

通用目录结构大致是这样,目录名可以按自己的习惯改,但层级关系建议保持一致:

weights/
└── Naive-N0.5-Flash/
    ├── config.json
    ├── tokenizer.json
    ├── tokenizer_config.json
    ├── model.safetensors.index.json
    ├── model-00001-of-0000N.safetensors
    ├── model-00002-of-0000N.safetensors
    └── ...(按 N 补足到最后一片)

分片命名按通用约定是「前缀-五位序号-of-总片数」:序号从 00001 开始,五位补零;总片数也是五位补零,且同一组文件里总片数必须一致。索引文件里会给出 weight_map,把每个权重张量名映射到某个分片文件名。核对齐全性的动作就是:读出索引里的分片文件名去重集合,再和目录里实际存在的分片做差集。先在本地列出实际文件:

Naive-N0.5-Flash 准备本地跑,先把权重落到本地目录再验分片完整
ls -1 weights/Naive-N0.5-Flash/model-*.safetensors | sort
ls -1 weights/Naive-N0.5-Flash/ | wc -l

如果索引里引用了 model-00007-of-00012.safetensors,而 ls 结果里没有这一片,就属于缺片。缺片时不要用同名前缀的其他文件顶替,常见表现是加载阶段报 KeyError 或找不到某个权重张量,而不是报文件缺失,因为加载器是顺着索引找张量的。

用校验命令核对每个分片的字节数与哈希

字节数和哈希是两个不同层面的检查:字节数能发现截断和少传,哈希能发现内容被改动。建议先对全部分片跑一次 sha256sum,把输出重定向到文件留档;如果权重包自带校验清单(常见是 SHA256SUMS 或类似文件),就用同一个命令对清单做校验。

cd weights/Naive-N0.5-Flash
sha256sum model-*.safetensors > sha256.local
wc -c model-*.safetensors

# 若权重包提供了校验清单
sha256sum -c SHA256SUMS

预期输出形式:sha256sum 每个文件一行,「哈希值 + 两个空格 + 文件名」,哈希是 64 位十六进制;wc -c 每行是「字节数 + 文件名」。sha256sum -c 在通过时逐行输出文件名加 OK,失败时输出 FAILED 并返回非零退出码。把这些输出和权重包提供的清单、或和同一份权重在另一台机器上的结果比对。

比对失败时的处理顺序建议是先重传、再查索引。理由很直接:哈希不一致里最常见的原因是下载或拷贝过程被中断,重传那一片的代价远小于去怀疑模型文件本身。重传完成后对单片重新跑 sha256sum,确认和清单一致。如果单片哈希反复不一致,但字节数正确,再去检查索引里的相对路径、分片总数是否写错、是否把两个不同版本的权重混在一个目录里。索引文件本身损坏的表现是加载器在解析 weight_map 阶段就报错,这时候重传分片没用,需要重新获取索引文件。

Naive-N0.5-Flash 准备本地跑,先把权重落到本地目录再验分片完整

在最小配置下加载模型,观察加载阶段报错位置

文件层确认之后再进加载,且先不要调并发、批大小、量化参数。最小配置的含义是:只指定权重目录、设备、以及必要的精度参数,其余用默认值。加载命令骨架按你所用框架的惯例写,例如命令行或 Python 入口形式:

# 通用骨架,参数名按实际框架替换
python -m <runtime> `--model-path` weights/Naive-N0.5-Flash \
  `--device` cuda:0 `--dtype` auto `--max-model-len` 2048

日志里要抓两类关键行,它们指向完全不同的方向。文件层问题的典型特征是路径和文件名出现在报错里,例如 FileNotFoundError、No such file or directory、OSError: Unable to load weights、以及 json 解析失败;这类报错在进程刚起来、还没明显占用显存时就出现。显存层问题的典型特征是 cuda out of memory、CUDA error: out of memory、或者先打印出各层参数加载进度再卡住,这类报错往往出现在部分权重已经读出之后。前者回去查目录结构和分片完整性,后者才需要调 max-model-len、dtype 或分批加载。

还有一个容易混的情况:分片字节数不对但没到解析失败的程度,加载器可能在读某一个张量时抛出 shape mismatch 或 size mismatch。这类报错看起来像模型结构问题,实际是文件层问题,处理方式回到上一节重传该分片。

Naive-N0.5-Flash 准备本地跑,先把权重落到本地目录再验分片完整

记录一次完整启动的耗时与显存峰值

最小配置能成功启动之后,先把这一次的基线记下来,后面调并发、调精度、换 dtype 才有对照。计时用 shell 的 time 或 date 打点都可以,建议前后各打一次,记录从进程启动到日志出现「就绪」信息的墙钟时间,不要只记模型下载或读取耗时。

/usr/bin/time -v python -m <runtime> `--model-path` weights/Naive-N0.5-Flash \
  `--device` cuda:0 `--dtype` auto `--max-model-len` 2048 2> startup.log

# 另开一个终端轮询显存,间隔 1 秒
while true; do nvidia-smi `--query-gpu`=timestamp,memory.used,memory.total \
  `--format`=csv,noheader; sleep 1; done

显存峰值从轮询输出里取最大值即可,注意区分「进程占用」和「整卡占用」,如果机器上还有别的进程,nvidia-smi 里按 PID 过滤更准。记录表格建议包含这些字段,一次启动一行:

  • 日期与权重版本标识(用目录名或索引文件里的字段,不要凭记忆写)
  • 启动方式与关键参数:device、dtype、max-model-len、是否分批加载
  • 加载耗时:从进程启动到日志出现就绪信息的墙钟秒数
  • 显存峰值:nvidia-smi 轮询到的最大 memory.used,注明是本进程还是整卡
  • 权重目录的 sha256sum 留档文件路径,便于确认这次基线对应的就是校验过的这批分片
  • 异常记录:是否出现警告、是否触发过重传或更换索引文件

这份基线只对应当前机器和当前权重版本,换卡、换 dtype、换权重版本都应该重新记录一次。它的用处不是给出一个「标准值」,而是让你在后续改动出问题时,能快速判断变化来自文件层、参数层还是硬件环境。