在 V100 上用 Slurm 跑通 MiniMax H3

目标是让 33B 的视频生成模型在 112 张 V100 上产出 30 秒成片。为此要先修共享存储、统一 GPU 基线、自建调度器、把节点从 K3s 手里接过来。含每一次失败的根因。

目标

在自有的 V100 机队上跑通 MiniMax-H3 FL2VA,产出一段 30 秒、1080p、24 fps、带连续音频的视频。

H3 是 33B 的视频生成模型,同时产出画面和声音,checkpoint 144 GB,需要多卡张量并行。把它放到这批硬件上,硬约束有四条:

约束后果
V100 是 SM70,无 BF16H3 的发布路径偏向 BF16,精度策略和 attention kernel 都得换
单卡 16 GB33B 权重必须 TP8 切分,activation 稍大就八卡同时 OOM
12/14 台节点归 K3s没有能做多节点多卡分配的调度器
共享存储的 /data 挂不上144 GB checkpoint 没有分发路径,模型服务 CrashLoop

所以在碰模型之前要先补四层:一个真的能挂的共享存储、一致的 GPU 运行时、一个能做设备隔离和多卡分配的调度器,以及把节点从 K3s 手里接过来。

完成的定义

sinfo 能看到节点、srun hostname 能返回,这两条不足以支撑上面的目标。这次的标准定在七条:

  1. 14 台节点、112 张 V100 全部被调度器正确识别
  2. GPU、CPU、内存和设备访问受 cgroup 约束
  3. 模型只读、任务数据可写,失败任务不污染共享目录
  4. Accounting 记录 generic 和 typed GPU TRES
  5. Web 页面从 Tailnet 可访问,管理面不直接暴露
  6. K3s 的 12 个可达节点、workload intent、hostPath 与 PostgreSQL 数据都有实际恢复证明
  7. H3 作业跑通,并且产出的成片通过语义验收

机队现状

项目状态
在线计算节点14 台,每台 80 CPU、8×Tesla V100-SXM2-16GB
不可达节点1 台,网络原因,保持 pending
节点归属12 台跑 K3s,1 台 Slurm canary,1 台空闲
GPU 基线有漂移:3 台内核模块与用户态 NVML 版本不匹配,1 台仍在 570 驱动分支
共享存储/data 路径存在,客户端挂载失败
故障域模型、运行时、输出、数据库、控制面全部落在同一台存储服务器

最终生产分区是 14 节点、1120 CPU 线程、2,576,000 MiB 调度内存、112 张 V100。

本文数字取自实际验收记录。主机名、地址、账户和变更 ID 用占位符替代。

数据面

H3 的 checkpoint 有 144 GB,要对 14 个节点只读可见,任务输出又要可写且互不污染。这两件事都落在共享存储上,而它当时是坏的。

这台存储原本有一个 ZFS 池,/data 是池上某个数据集的挂载点,NFS 从这里导出给计算节点。池后来不可导入,预期的 8 个成员只匹配到 4 个,超出 RAIDZ1 的冗余能力。池没挂上来,/data 就退回成根盘上的一个空目录,而目录本身还在。

NFS export 那一侧设了 mountpoint 条件,rpc.mountd 因此拒绝导出这个未挂载的目录。showmount 读的是配置视图,仍然列得出这一项。当时的维护探针只做 timeout 10 stat /data,目录存在就判定 responsive。

于是三个信号都是绿的:目录能 stat、export 配置在、showmount 有输出。客户端日志一直是 No such file or directory。

目录存在、export 配置存在、内核实际提供导出,探针要分别验:

# 服务端:路径必须真的是预期文件系统的挂载点
findmnt -T /path/to/export -o SOURCE,TARGET,FSTYPE,OPTIONS

# 服务端:配置视图与内核有效导出交叉检查
exportfs -v
cat /proc/fs/nfsd/exports

# 客户端:验证来源、文件系统类型和挂载参数
findmnt -M /mnt/data -o SOURCE,TARGET,FSTYPE,OPTIONS

# 业务层:验证 manifest 与权重可读
test -r /mnt/models/MODEL_ID/model_index.json

成员不完整时没有强行导入旧池,也没有为了让 NFS 看起来能挂而去掉 mountpoint 条件。去掉之后会把一个空的底层目录导出给客户端,故障从明确失败变成静默读空。

在健康池上重建了两个职责分离的数据集:

数据集客户端权限用途
ai/models只读canonical checkpoint、manifest
ai/data读写jobs/、inputs/、outputs/

单节点 canary 的 1 GiB 顺序 I/O 实测 803 MB/s 写、1.5 GB/s 读。这个数字的作用是证明读写路径和权限合同成立。

GPU 基线

TP8 要求同一节点内的 8 张卡在驱动、CUDA runtime 和设备枚举上行为一致,跨节点的三段并行还要求 3 台机器之间也一致。

节点间驱动、CUDA、时钟和 cgroup 状态不一致的话,Slurm 会把这些差异包装成更难追踪的随机失败。所以先对 14 台统一并逐台复验:

  • 8/8 GPU 可枚举,112 个 UUID 全集无重复
  • 驱动统一到 580.173.02,CUDA toolkit 12.9.1 走共享只读路径
  • 每台实际编译并运行 CUDA runtime probe,报告 runtime=12090、devices=8、sm70=yes
  • cgroup v2 的 cpuset、cpu、memory、io、pids 控制器就位
  • NTP 已同步,uncorrected ECC 为 0
  • 不可达节点留在 pending,不用陈旧 inventory 强行入池

自建 Slurm 包

H3 用 TP8,需要 PMIx runtime;GPU 分配需要 NVML GRES;accounting 需要数据库插件。这几项的组合要能确定复现。

版本固定在 26.05.4(Debian 版本号 26.05.4-1+v1001),从固定源码哈希在 digest-pinned 的 Ubuntu 22.04 容器里构建 17 个 DEB,发布到 storage 上的版本化本地仓库。

自建包是为了同时控制这几项:Slurm 与 PMIx、NVML、JWT、数据库插件的构建组合;包名、版本号和依赖关系;所有节点安装同一批二进制;升级时先发布新版本目录再对 canary 滚动测试;已部署包可以 hold,避免系统更新混入另一套 Slurm。

构建产物带源码哈希、包清单、Packages.gz 和整棵 artifact tree 的校验记录。

Canary

Controller 放在 storage,slurmd 只装到那台没有 K3s 的 8 卡节点。仍受 K3s 管理的节点这时不交给 Slurm。

核心配置压成四类合同:

# 资源选择
SelectType=select/cons_tres
SelectTypeParameters=CR_Core_Memory
GresTypes=gpu

# 进程与设备隔离
ProctrackType=proctrack/cgroup
TaskPlugin=task/cgroup,task/affinity

# 身份认证
AuthType=auth/munge
CredType=cred/munge

# 调度
SchedulerType=sched/backfill
ReturnToService=1
DisableRootJobs=YES
# cgroup.conf
CgroupPlugin=autodetect
ConstrainCores=yes
ConstrainRAMSpace=yes
ConstrainSwapSpace=yes
ConstrainDevices=yes
AllowedSwapSpace=0

# gres.conf
AutoDetect=nvml
Name=gpu Type=v100 File=/dev/nvidia[0-7]

MUNGE 与 UID/GID 要在第一步固定

MUNGE key 一致只是第一层。跨主机运行时,slurm、munge 和业务账户的数值 UID/GID 也必须相容,否则会出现四类问题:controller 与 compute 对 spool/config 的所有权解释不同;NFS 上同一文件在不同节点解析成不同用户;重装后账户 ID 漂移导致旧状态读不出;回滚时删错或保留错误的账户目录。

所以部署前先冻结身份元数据,apply 和 rollback 都校验进入状态。

Canary 的验收内容

第一个真实作业要同时证明分配到的 GPU、可见设备数、cgroup 路径、只读模型可读、共享结果可写、退出码,以及任务结束后的显存释放:

srun -p "$CANARY" --nodes=1 --ntasks=1 \
  --gres=gpu:v100:1 --cpus-per-task=8 --mem=20G \
  bash -lc '
    set -euo pipefail
    [[ "$CUDA_VISIBLE_DEVICES" =~ ^[0-7]$ ]]
    grep -Eq "/job_[0-9]+/" /proc/self/cgroup
    test -r "$MODEL_MARKER"
    probe="$JOB_ROOT/.probe-${SLURM_JOB_ID}"
    trap "rm -f \"$probe\"" EXIT
    printf verified > "$probe"
    test "$(cat "$probe")" = verified
    nvidia-smi -i "$CUDA_VISIBLE_DEVICES" \
      --query-gpu=index,name --format=csv,noheader
  '

这一步先后暴露出六个问题:

  1. NVML 的 per-device 信息写在 stderr,健康脚本只解析 stdout,形成假失败
  2. 构建时启用了 PMIx 插件,运行节点缺少对应 runtime,daemon 启动报插件错误
  3. systemd delegation 要同时校验 package unit 里有 Delegate=yes,以及 systemctl show 返回 live 的 Delegate=yes
  4. Ubuntu 上 MUNGE 的卸载后状态与预期不同,回滚逻辑不能假设 purge 等于完全消失
  5. 重新配置 controller 时缺少 staged config 和隔离验证,坏配置会直接打到生产 daemon
  6. 同一个变更 ID 重入时,不能重新生成 MUNGE key 或覆盖首次基线

这六项都写进了幂等和回滚合同。

Accounting

Canary 通过之后才加 accounting 层:

  • MariaDB 11.4.13 跑在 storage,主机只绑定 loopback,数据放独立 ZFS dataset
  • slurmdbd 只允许 loopback 和计算网段,继续用 MUNGE
  • slurmrestd 只监听 Unix socket,不开默认 TCP 端口
  • JWT signing key 只存在远端受限目录,短效 token 不进仓库和日志
JobAcctGatherType=jobacct_gather/cgroup
JobAcctGatherFrequency=30
AccountingStorageType=accounting_storage/slurmdbd
AccountingStorageTRES=gres/gpu,gres/gpu:v100
AuthAltTypes=auth/jwt

备份要证明能恢复

数据库备份最危险的状态是文件存在、哈希也对,但从未 restore 过。回滚顺序固定成七步:停止新的 accounting writer;生成带时间戳的 SQL dump;校验压缩流和 SHA-256;导入 scratch database;验证 schema、34 张表和历史 job row;restore proof 成功之后才移除 active dataset;reapply 先验 dump 哈希再恢复历史。

多次 rollback / reapply 之后旧作业记录仍在,新作业继续追加。

首次从无 accounting 的 controller state 接入新数据库时遇到 CLUSTER ID MISMATCH。这是 Slurm 对共享状态损坏的主动保护,删 state 文件绕过就失去了保护意义。处理方式是停掉 writer、保存原 clustername、以 DBD 注册项作为本次迁移的 authoritative ID,走受控流程让 controller 采用;rollback 恢复原 ClusterID,reapply 从已验证的数据库历史继续。

Web 与 Tailnet

Slurm-web 7.0.0 作为独立层部署,agent 通过 Unix socket 连 slurmrestd,gateway 才对外提供页面。容器用固定镜像 digest、非 root UID/GID、read-only rootfs、drop all capabilities、no-new-privileges、CPU/内存/PID 限制、secret 只读挂载,anonymous policy 只保留观察动作。

初次部署撞到两个陷阱:

  1. 镜像内 /var/lib/slurm-web 的父目录属于镜像自带 UID,而容器跑在另一个固定非 root UID 上,读取单文件 secret 路径时出现确定性 PermissionError。改成每组件只读目录挂载后父目录可遍历,secret 仍保持最小暴露
  2. Docker 的 solely-internal network 不发布 gateway 端口,需要单独的 ingress bridge,宿主端口仍绑在 loopback

Tailnet 暴露做成独立变更层:保留 SSH tunnel,只在指定 Tailnet 地址监听,LAN、agent 和 REST 端口继续关闭。一次 reapply 中 systemd watchdog 与 Compose recreate 发生竞争,用「暂停 timer → 等 watchdog 退出 → 共享锁 → 强制恢复 handler」解决。

这一层有自己的 marker、baseline 和 rollback,与 Web 安装分开。

K3s 迁移

H3 的三段并行要 3 个节点、24 张卡,而当时只有 2 台不属于 K3s。要凑够就得把节点接过来。

Canary、accounting 和观察面都稳定之后,才动那 12 台 K3s 节点。

硬件与所有权审计

扩容前对每台在线主机采集 CPU topology、内存、GPU UUID/型号/驱动、K3s/Slurm/MUNGE service、NFS、NTP、cgroup v2、根盘空间和 slurmd -C。

结果确认 14 台的调度关键资源一致:2×20×2 CPU topology、8 张同型号 V100、统一驱动,scheduler memory 取 184000 MiB。kernel 与根盘容量并不完全一致,但不影响调度。

这一步也把「当前谁拥有 GPU」记录清楚了。

保留式退役

K3s 的处理是退役并保留,二进制、datastore、hostPath 和恢复包都不删。停服务之前先保存 SQLite 在线备份和 API object export、Deployment/DaemonSet/CronJob 的 intent、hostPath 数据、PostgreSQL custom-format dump、服务与文件基线,以及一个带 SHA-256 的 recovery bundle。然后按 agent batches、server-last 的顺序停止并禁用服务,用 systemd condition 防意外重启。

第一次退役在 API state / SQLite 备份阶段中断,而该任务用了 no_log,记录不足以证明具体根因。处理方式是用同一变更 ID 续做:核对已有 marker、immutable baseline 和完成 seal,只补未完成的步骤。根因保持未知,没有补一个说得通的解释上去。

fail-closed 扩容

全量加入分三层验收。每节点注册并进入 IDLE 之前,验证 controller 签发的 MUNGE credential 能在 compute 端 unmunge、复制同一份冻结配置、8 个 NVML GRES、cgroup 配置与 live Delegate、mount source、K3s GPU 进程为空、已安装 package 版本。随后一个 all-node / all-GPU 作业实测 CUDA_VISIBLE_DEVICES、Slurm cgroup 路径、模型读取与任务目录写入。该作业连同 accounting / Web 验收通过之后,才 hold 精确包集合并记录各节点最终 config hash。

任意 all-node acceptance 失败,生产分区回到 INACTIVE,不带着部分成功的节点继续服务。

两次验收器自己的 bug

  • apt simulation 生成的包名与 dpkg-query 对 Multi-Arch 后缀的表示不同,原比较器又漏了两个传递依赖,形成 22 对 24 的假差异。修复是对架构后缀做 canonicalize,并冻结完整 transaction plan
  • 第一次 112-GPU 验收把 CUDA_VISIBLE_DEVICES 里的七个逗号当成七张 GPU,14 个 task 全部退出 1。诊断表当时已经显示每台物理机都有 8 张卡、NFS 和 cgroup 也正常。修复 oracle 后按字段数计数;失败 rescue 仍取消残留 step 并把两个分区置为 INACTIVE

最终一个作业同时拿到 14 个节点、每节点 8 张 GPU:

nodes=14
generic GPU TRES=112
typed v100 GPU TRES=112
visible_gpus_per_task=8
job_state=COMPLETED
exit_code=0:0

全链回滚实际执行过

  1. Slurm fleet 从 14 节点退回单节点 canary
  2. 单卡 canary 作业再次成功
  3. K3s 恢复 12 个可达 Ready 节点
  4. Deployment / DaemonSet / CronJob intent 恢复
  5. PostgreSQL:退役前 custom dump 已在 scratch database 证明 source 与 restored 都是 58 张用户表;K3s 回滚后恢复运行的实例同样回报 58 张
  6. 再用新的变更 ID 重做最终迁移

跑 MiniMax H3

下文用别名代替真实 scheduler Job ID:P0 是运行时打包,G* 是 GPU 推理尝试,C* 是清理恢复,R* 是 CPU 后处理。

模型只下载一次

快照固定到一个 revision,84 个文件合计 144,051,241,571 字节,含 29 个 Safetensors。下载器支持并发、续传和重试;84/84 manifest size 通过之后才原子发布,发布后再独立解析 model_index.json 和全部 29 个 Safetensors header。

14 个节点从只读 NFS 看到同一快照,写探针按预期失败。回滚下载器只移除 service 和 script,模型与 partial data 保留。

V100 兼容层

H3 的发布路径偏向 BF16,V100 是 SM70。canary runtime 的构成:

  • FP16 主计算,sensitive 部分 FP32 累加
  • original-format 权重的 streaming name mapping
  • TP8 分片前完成 QKV 拆分和 gate/value 重排
  • native / PyTorch attention,不复制 SM80+ 的 kernel 配置
  • conditioner block offload
  • DiT 完成后、VAE decode 前释放大模型阶段
  • 每个 rank 输出 generated / release receipt

一个 5.167 秒的早期 canary 生成了 124 帧、960×544、24 FPS、AAC 双声道;每 rank 峰值 reserved 12,557,746,176 字节。这证明兼容层可用,没有证明 30 秒连续 FL2VA 的目标形状可用。

OOM 揭出的 geometry 缺陷

30 秒视频规划成三个 10 秒 FL2VA 段。每段用两张冻结锚点图,前一段末锚点和后一段首锚点是同一个文件同一个哈希,所以三段能在三个节点上并行。

第一个声明为 640×384×243 的 canary(G1)在八张卡上同时 OOM:

requested allocation: 1.49 GiB
GPU capacity:         15.77 GiB
in use:               15.43 GiB
free:                  336.50 MiB

直觉是继续降分辨率。声明 512×320 的 G2/G3 提交上去,日志里的 packed layout 却完全不符合这个画布——从 packed layout 可以直接反推出实际用的是 1216×768。

根因在 launcher:构造 FL2VA input 对象时没有把 target_shape 放进去。JSON 里的目标尺寸是对的,真正进入 runner 的对象没有这个字段。G1 用的是同一个缺陷 launcher 并在同一 DiT 路径 OOM,但本地摘要没保留它的 resolved canvas,所以精确的 1216×768 只归于 G2/G3。

修复是给 launcher 加显式参数,并让每个 rank 在进入 DiT 前打印:

{
  "stage": "request_geometry",
  "task": "fl2av",
  "target_shape": [384, 640],
  "target_video_length": 243
}

G4 因为用了带同一缺陷的冻结资产被主动取消,不作为放行证据。修正后的 canary G5 在单节点 TP8 上通过:

shape=640x384
frames=243
text/audio/video/total rows=699/810/17760/19269
8/8 generated receipts
8/8 release receipts
peak reserved=13.086 GiB per GPU
state=COMPLETED
exit=0:0

这时才放行三节点 full render。

作业生命周期

推理跑成 Slurm 作业。canary 之前先由 P0 把已验证 runtime 打包成带哈希的 runtime.tar.zst,G1 通过 afterok:<P0> 启动并再次验证 archive hash。

三段 full render 的资源拓扑:

#SBATCH --partition=v100
#SBATCH --nodes=3
#SBATCH --ntasks=3
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=80
#SBATCH --mem=176G
#SBATCH --gres=gpu:v100:8
#SBATCH --time=01:30:00

每个 outer task 占一个节点,节点内启一个 TP8 group。共享锚点预先冻结所以三段能并行;锚点如果来自上一段的真实输出,工作流就得改成 afterok 串行依赖。

生命周期拆三步:stage-runtime 验证共享 tar 和 hash、解到 node-local 路径;render 按 SLURM_PROCID 唯一映射 segment、运行 TP8;cleanup 由 node-local EXIT trap 清理当前 job 的 runtime 并确认 8 卡显存回落。

scancel 之后再创建 cleanup srun 并不可靠,事后用 SSH 清理也分不清哪些进程属于哪个作业,所以清理步骤跟着作业一起进节点。

正式生成 G6:3 个节点、24 张 V100、528 GiB 调度内存,13 分钟完成,三段媒体、done receipt 和 verification JSON 全部通过。

成片交付

模型跑通只解决了第七条标准的前半句。三段素材生成出来之后,问题转到成片本身。

接点连续性

最早的分段提示词保证不了场景连续。改成 first/last-frame conditioned FL2VA,让相邻段共享完全相同的 anchor 之后,10 秒和 20 秒接点的画面变化指标下降约 95%,狐狸姿态、楼梯、栏杆、天际线和船位在接点保持连续。

分段提示词能约束语义,接点的连续性靠的是冻结锚点这个共享输入。

音频接点

旧组装只在每段边缘做很短的 fade,形成明显的中心掉音。改成两次 0.75 秒 equal-power qsin crossfade,再整体 retime、pad/trim 到 960,000 个 32 kHz 时间样本。

接点旧版 RMS 差新版改善
10 s3.394 dB0.112 dB96.7%
20 s5.288 dB3.455 dB34.7%

最终音频 -18.6 LUFS、true peak -4.3 dBFS,无削波、无 100 ms 以上静音,packet timeline 精确结束在 30.000 秒。

帧数:717 和 720 都可能不合格

每个模型段原生 243 帧,三段 30.375 秒。旧方案每段删三个内部帧凑到 720,在九个固定位置制造了运动跳步。改用轻微整体 retime 加 MCI/AOBMC 双向运动补偿之后,九个位置的三帧窗口变化指标平均下降 36.192%。

CPU 后处理阶段(R0–R6,都是 Slurm 调度的 CPU 作业,不重跑 GPU 推理)暴露了一串朴素问题:

  1. R0 立即失败——compute batch 的 PATH 里没有 FFmpeg。SSH 登录后能运行,不代表 batch 环境能运行
  2. R1 改为引用 frozen runtime 里带哈希的 static FFmpeg 7,预检 minterpolate、acrossfade、PyAV 和三段输入
  3. R2 在 set -o pipefail 下把长输出直接送给 grep -q;grep 匹配到就提前退出,生产端收到 SIGPIPE,整个 capability check 被判失败。改成先捕获完整输出再匹配
  4. R3 的 MP4 已改用 $MEDIA_DIR,.done 校验仍读默认目录,路径合同不统一

然后是版本行为差异:本机 FFmpeg 8 每段输出 240 帧,集群固定的 FFmpeg 7 在相同 minterpolate 链末尾只 flush 239 帧。R4 因此产出 717 帧,被结构 validator 拦下。

R5 用 tpad=clone 补三帧,形式上 720 帧、24 FPS、30 秒,validator 全过。但逐帧 QA 发现 frame 239/479/719 成了全片运动最低的三帧,10 秒前出现「停一帧再跳一步」的微顿挫。它通过了容器合同,破坏了动作语义,所以内部 HOLD 未发布。

R6 用确定性方案:

每段 = 前 239 个 MCI 输出 + 显式追加原始源 frame 242
[src] split [motion_input][endpoint_input]

[motion_input]
  -> setpts(239/242)
  -> minterpolate(24fps, MCI/AOBMC/BIDIR)
  -> trim(239 frames)

[endpoint_input]
  -> select(source frame 242)

[motion_239][source_endpoint]
  -> concat(240 frames)

这样不依赖 FFmpeg 版本的 EOF flush 行为,同时保留了模型被锚点约束的真实末帧。

语义 gate

R6 在 720 帧和连续 PTS 之外加了一组语义门槛:6 个 remaster 段首尾对冻结 G6 源视频端点的 SSIM ≥ 0.996;10 秒 join SSIM ≥ 0.980;20 秒 join SSIM ≥ 0.970;完整音视频严格解码;黑帧、冻结、非静音、AAC packet end 检查;光流敏感区域的人工抽样(雨线、围巾、栏杆、快速腿部、遮挡、背景)。

6 endpoint SSIM: 0.996787 .. 0.998840
10 s join SSIM:  0.983828
20 s join SSIM:  0.976954
video:            1920x1080 / 24 fps / 720 frames / 30.000 s
audio:            AAC / 32 kHz / stereo / 960000 ticks
state:            COMPLETED / 0:0

发布与回滚

R6 用独立 attempt 目录,结构与语义 gate 全部通过后才原子改名,发布目录按 job ID 隔离。G6 源段同样按 attempt 隔离,但它的 wrapper 是先把 MP4 从 temp 改名、再做 post-generation 验证,验证成功才写 done receipt——这两条路径的顺序不同。

一个发布包含最终媒体、verification JSON、final.done、release.sha256。

回滚脚本只允许把当前 job 的发布目录原子移动到固定归档名,执行前断言:job 的 Slurm 状态和 exit code;发布目录 realpath、非 symlink、精确 allowlist;成片字节数与 SHA-256;原始 source segments 的哈希;前一版成片和被拒候选仍保持原哈希。回滚后再验 attempt、source、旧片的 hash 和 stat 均未改变。

对真实发布目录跑过 preview,在同构 fixture 上实际执行过 rollback,唯一变化是目标发布目录的 rename。

失败时间线

阶段症状根因修复
存储/data 存在但客户端挂载失败旧池不可用;普通目录不满足 NFS mountpoint 条件在健康池上重建 models/data 合同
CanaryGRES/daemon 假失败NVML per-device 记录写 stderr;PMIx 插件已构建但目标机缺 runtime合并 stdout/stderr;装 PMIx runtime;Delegate=yes 作独立门槛
配置验证slurmctld -t 只返回 usage,重入抢占 live 端口production-state isolation 不足隔离端口/状态目录前台启动;live daemon 走 reconfigure/ping
Accounting首次接入后 controller 起不来验证器先误判 slurmdbd wildcard listener;随后查出 controller state 与 DBD 的 ClusterID 真的对不上systemd policy 加正负连通性验证;受控采用 DBD ClusterID
Web页面端口不通solely-internal Docker 网络不发布端口独立 ingress bridge,仅绑 loopback
Web reapplyCompose 临时容器竞争watchdog timer 与 recreate 并发pause/drain timer,共享锁,forced handler
112-GPU 验收每台 8 卡被判成 7 卡七个逗号当成七个字段修正计数 oracle,保留 fail-closed rescue
G1声明 640×384 仍八卡 OOMgeometry 未进入 runtime request,自动大画布令 activation 超限显式传 geometry,保留 TP8 与 sensitive FP32
G2/G3声明低分辨率仍 OOMtarget_shape 没传入 runner,实际是默认大画布input object 显式传 geometry,并打印 packed layout
G4试验无效使用带 geometry 缺陷的冻结资产主动取消,不包装成证据
C1取消后原 cleanup step 不可复用G4 已离开可创建 step 的状态独立 cleanup recovery,只清该 job runtime
G5Canary 成功真实 640×384×243 生效8/8 receipts 与 13.086 GiB 峰值放行 full
G6三段生成成功—三节点 TP8 并行,job-local cleanup
R0preflight 立即失败batch PATH 没有 FFmpeg固定 static binary 的绝对路径与哈希
R2capability grep 失败pipefail + grep -q 触发上游 SIGPIPE先捕获完整输出再匹配
R3输入文件校验失败MP4 与 .done 用不同目录变量统一 $MEDIA_DIR 合同
R4只有 717 帧FFmpeg 7 minterpolate EOF 行为不同不依赖隐式 flush
R5720 帧仍有微顿挫clone 尾帧掩盖缺帧内部 HOLD,新增语义 gate
R6PASS239 MCI + 明确源末帧endpoint/join SSIM 与视听 QA 后发布

缺口

  • 单故障域。 storage、controller、accounting 和 Web 仍集中在一台,没有 backup controller 和 backup DBD
  • 备份代次不够。 MariaDB 只有本机和同一 storage 池内的恢复代次,需要异机、加密、定期演练
  • Web 无身份。 Slurm-web 是 Tailnet 内 anonymous read-only 观察界面,没有 OIDC/LDAP 和逐用户审计
  • 没开 association/limit enforcement。 QoS、多租户配额和公平分享都未完成
  • pending 节点。 需要恢复网络并重新验证身份、GPU、NFS、时钟后才能加入
  • Tailnet 提交作业只完成设计。 边界应该是 Tailnet ACL/身份校验 → loopback job broker → 固定 workflow allowlist → sbatch,直接开放 slurmrestd 写接口或 anonymous Web 权限都不合适
  • 快速腿部仍有轻微软化,末段角色风格漂移来自源生成内容,本轮没有重新推理消除

Slurm 基础设施验收通过、H3 runtime 跑通、媒体质量 PASS 是三个不同层次的结论。184000 MiB 是每节点 scheduler memory,与物理 RAM 是两个数。