VASP 算一半停了:先分清是被杀还是自己崩
「算到一半没了」是云上跑 VASP 最高频的事故,也是最容易误判的一类:有一半的人直接换机器,结果换完还是照停;另一半人反复重跑,白烧了几百元机时。判断只需要三条命令,顺序不能反。
第一步:看进程是怎么死的
先拿到退出码。这是唯一能直接区分「被外部杀」和「自己崩」的证据:
# 用了任务队列
sacct -j <jobid> --format=JobID,State,ExitCode,MaxRSS,Elapsed
# 直接跑的
echo $? # 前台
grep -i "exit" slurm-*.out # Slurm 的 .out 文件里也有
| 退出码 | 含义 | 性质 |
|---|---|---|
| 137 | 128+9,SIGKILL | 被外部杀掉:OOM killer、实例回收、平台强制停止、ulimit 限制 |
| 139 | 128+11,SIGSEGV | 程序自身崩:段错误,多为编译与指令集不匹配、MPI 库混搭、输入文件损坏 |
| 1 / 2 | 正常退出但报错 | 程序主动退出,去看 OUTCAR 末尾几行 |
| 无退出码、进程凭空消失 | — | 多半是 137 的变体(SSH 断开后进程随会话被清掉) |
第二步:如果是 137,找谁杀的
按概率从高到低查四件事。注意 dmesg 的环形缓冲区会被冲掉,越早查越好;被冲掉就看 journald:
dmesg -T | grep -iE "killed process|out of memory|oom"
journalctl -k --since "2 hours ago" | grep -i oom
free -g ; vmstat 1 5 # si/so 长期不为 0 = 一直在 swap
看到 Out of memory: Killed process … (vasp_std) 并且 total-vm 接近你的物理内存,就是内存不足,与算力无关,加核只会更糟。
没有 OOM 记录、但机器在半夜"消失"过几分钟、SSH 断线、监控里有缺口——那是实例层面被回收或重启,见下一节。
云上特有的五个「杀手」
本地超算上不存在的死法,云上全都有。这五种占了云上 VASP 中断的一大半:
1. 抢占式实例被回收
抢占式(Spot)价格便宜一半以上,但市场价高于你的出价时会被回收,只给约 5 分钟预警。预警信息在实例元数据里:
curl -s http://100.100.100.200/latest/meta-data/spot/termination-time
返回一个时间戳就说明正在被回收。长任务不要放抢占式;要放就放能随时重来的短任务,并把中间结果每 10 分钟同步到对象存储或另一台机器上。
2. 突发性能实例的 CPU 积分耗尽
共享型 / 突发性能实例(如 t 系列)靠 CPU 积分换性能。积分耗尽后 CPU 被限制在基准性能的百分之几,VASP 不是"停了"而是"慢到看起来停了"——一小时只走一步。判断方法:
top -bn1 | head -5 # 看 %Cpu 是否被限在个位数
# 或看云监控里的 CPU 积分余额
这类实例适合网站,不适合任何长时间满核计算。看到 VASP 慢得离谱先确认实例类型,别急着优化参数。
3. 按量付费欠费停机
按量实例欠费后会进入"停机保号"状态,进程全部被杀,磁盘保留但有保留期。科研场景里"跑一晚上"最容易碰上:账户余额不够覆盖整晚的费用。
预防办法很土但有效:跑长任务前先算这笔账——机时估算器会给出一整段任务的费用,账户里至少留两倍。
4. 系统盘或数据盘写满
VASP 的输出体积容易被低估:WAVECAR、CHGCAR、vasprun.xml 三者加起来,128 原子体系跑 100 个离子步可以轻松吃掉几十 GB。盘满之后的表现是程序报错退出,退出码可能是 1 也可能是 137(写失败后被信号杀掉),很容易误判成内存问题。
df -h ; du -sh * | sort -h | tail
体积估算见内存与 WAVECAR 估算器。
5. ulimit / cgroup 限制
有些云镜像默认 stack size 只有 8 MB、open files 只有 1024。VASP 在某些体系上需要更大的栈,撞上限制会直接段错误(139),看起来像编译问题其实是系统限制。
ulimit -s # 栈,建议 unlimited
ulimit -n # 文件句柄,建议 65536
cat /sys/fs/cgroup/memory.max # cgroup v2 的内存上限
第三步:续算,而不是重算
VASP 的价值在于它把中间状态全写在了文件里。中断后不要清目录重跑,按这个顺序续:
cp CONTCAR POSCAR # 用最后一步的结构
# 保留 WAVECAR、CHGCAR,不要删
# INCAR 里改两行
ISTART = 1
ICHARG = 1
然后从 OSZICAR 数一下已经完成的离子步,确认续算从正确的位置接上。几个要点:
- 结构弛豫:续算几乎无损,能省下已完成的全部机时。
- 静态计算(单点):本身不可中断续算,只能重跑;但保留
WAVECAR可以让 SCF 更快收敛(ISTART=1)。 - 分子动力学:只能从最后一个完整的
XDATCAR步重建结构再跑,损失的步数取决于你多久存一次。 - 被 OOM 杀掉的任务:先降内存需求再续算,否则同样的死法会再来一次。
中断的真实成本:算成钱
假设你的任务总共约 4850 核时(64 核跑 100 个离子步,见估算器默认算例),跑到 60% 被中断:
| 情形 | 损失 | 折成钱(0.06 元/核时) |
|---|---|---|
| 不能续算,全部重跑 | 2910 核时 | 约 175 元 |
| 能续算,但配置没改 | 可能再中断一次 | 再 175 元 |
| 续算 + 修好内存 | 接近 0 | — |
所以「中断」这件事的正确反应顺序永远是:先看退出码 → 再定性质 → 再决定续算还是换机器。换机器是最后一步,不是第一步。
预防清单
- 内存按估算值的 1.5 倍选规格,别贴着上限买。
- 长任务用
nohup/systemd-run/tmux起,不要挂在 SSH 会话上。 - 抢占式只放能重来的短任务,中间结果每 10 分钟外传一次。
- 满核长跑用计算型实例(c/g 系列、非共享型),不要用突发性能实例。
- 开跑前
df -h看一眼剩余空间,并按输出体积留 3 倍余量。 - 把
LWAVE=.FALSE.之外的非必要写入关掉,减少 IO 与占地。
如果排查完发现确实是机器规格不对(内存不够、CPU 被限流、盘太小),那就是该换规格的时候了:先看实例族怎么选,再算按量和包月哪个便宜。
先算清楚,再决定换不换
中断一次的成本可以算出来:用机时估算器把总核时和费用算明白,再判断是该续算、该改配置,还是该换实例。
打开 core-hour 估算器 查看计算型实例要买的话:先点上面的推广链接登录或注册,再回到本页点一次同一条链接——阿里云按「两次点击」建立推广关联(关联期 90 天),你的价格不受任何影响。