我在 R 中运行 rstan 贝叶斯预测模型,需要大约 60 小时才能确定结果。我目前正在我的本地桌面上执行此操作,所以我只是让它一直运行直到它完成,但我们计划将它放在可能会受到不可预测的停机时间影响的服务器上。有没有办法,比如说,部分保存二进制文件,以便程序从服务器关闭之前停止的地方恢复?
我不确定这个问题是否遵循 SO 的所有规则,或者它是否已经被回答过——在任何一种情况下,如果你能在标记它之前指出一个替代资源,那就太好了:)
谢谢
如果可以的话,最好的办法是在 R 代码中使用save
,save.image
或saveRDS
酌情构建一些检查点。如果你不能(因为例如时间都花在 C 代码上),那么你可以看看更通用的东西。
适用于最新版本 Linux 上任何正在运行的任务的通用解决方案是使用criu。这种方法有几个注意事项。首先,criu
必须以 root 身份运行,通常使用sudo
. 如果您在运行代码的服务器上没有 root 权限,这可能会破坏交易。您(或管理员)可以添加criu
到 /etc/suoders,但显然这具有安全隐患,特别是因为criu
可以运行任意操作脚本,该脚本也将以 root 权限运行。
如果您确实能够以 root 身份运行进程,并且对潜在的安全问题感到满意,那么这里有一个解决方案。我假设您有一个名为“long-running-script.r”的 R 脚本。
这是所需的文件:
运行-long-run.sh:
#!/bin/bash
set -e
if [ -d "r-criu-current" ]
then
RPID=$(ls r-criu-current/core*.img |perl -pe's/.*?(\d+)\.img/\1/')
if (ps -p$RPID >/dev/null) then
ps -p$RPID
echo "A process is already running with the PID $RPID; perhaps the old process hasn't exited."
exit 1
fi
bash r-criu-pre-restore.sh
criu restore -D r-criu-current &
else
setsid Rscript "long-running-script.r" </dev/null &>r-criu.log &
RPID=$!
fi
echo $RPID
mkdir -p r-criu-current
while :; do
sleep 5m # Change if needed
if kill -0 "$RPID" 2>/dev/null
then
mkdir -p r-criu-temp
criu dump -t $RPID --leave-running -D r-criu-temp --action-script ../r-criu-post-dump.sh
rm -rf r-criu-old || true
mv r-criu-current r-criu-old
mv r-criu-temp r-criu-current
echo "Snapshot saved at "$(date)
else
echo "R finished"
exit
fi
done
r-criu-pre-restore.sh:
#!/bin/bash
cp r-criu-current/r-criu.log .
r-criu-post-dump.sh:(请注意,这将在 r-criu-temp 中有一个工作目录,因此需要使用 引用文件..
)
#!/bin/bash
[ "$CRTOOLS_SCRIPT_ACTION" = post-dump ] || exit 0
cp ../r-criu.log .
长时间运行的.script.r:
i <- 0
while(TRUE) {
i <- i + 1
cat(i, "\n")
Sys.sleep(10)
}
主脚本的作用是检查以前的检查点。如果它存在,并且该进程未仍在运行,它将从该检查点恢复该进程。如果没有,它将在新会话中从头开始启动脚本,并将输出重定向到日志文件。然后,每 5 分钟(虽然这可以改变)脚本调用一次criu
检查点正在运行的 R 进程,同时仍然保持它运行。该r-criu-post-dump.sh
脚本用于确保所有文件都保留在转储时的状态。在这种情况下,仅更改日志文件,但可以根据需要复制其他文件。然后在恢复检查点之前恢复这些文件。
在每个时间点,应该保留两个检查点,当前一个和最近的前一个。这是为了防止在创建/移动检查点时出现崩溃/电源故障。
你确定你需要跑60小时吗?您需要多大的有效样本量?链条收敛需要多长时间?此外,还有多种方法可以通过向量化、使用足够的统计数据、在早期块中重新定义变量、重用重复的子表达式、用向量化的单变量法线用对角协方差矩阵替换多元法线、根据数据大小重新参数化等来加速 Stan 程序。感觉费在 Stan 用户组上给我们留言——那里有更多的 Stan 用户和开发人员在听(尽管你可以从我和 Ben 看到,我们现在也在监视 stackoverflow)。
您可以使用 CmdStan 输出平局。在预热结束之前无法保存适应状态,即使那样,也无法以该状态重新启动,因此它不会解决您的问题。
我们正在重构 Stan 3 的底层 C++ 命令结构,这将使保存状态和重新启动成为可能。