Future包中断、崩溃与重试机制详解

Future包:中断、崩溃与重试机制

future包于2025年6月19日在CRAN上庆祝了十周年纪念。本文将重点介绍futureverse生态系统最近改进的第四篇博客文章,特别关注future包如何处理中断和崩溃情况。

主要改进

在过去,被中断或突然终止的future可能会使future生态系统处于损坏状态,需要手动重启future后端。现在不再需要这样:

  • Future现在能够处理计算中断
  • Future现在能够处理并行工作进程突然终止(“崩溃”)
  • 崩溃的工作进程会自动重启

中断处理

以下是一个模拟R表达式在计算过程中被中断的future:

library(future)
f <- future({ a <- 42; rlang::interrupt(); 2 * a })

当我们尝试获取这个future的值时:

v <- value(f)
#> Error: A future (<unnamed-1>) of class SequentialFuture was interrupted
#> at 2025-10-15T15:37:09, while running on 'localhost' (pid 530375)

这在所有future后端中的工作方式相同,例如:

plan(future.mirai::mirai_multisession)
f <- future({ a <- 42; rlang::interrupt(); 2 * a })
v <- value(f)
#> Error: A future (<unnamed-2>) of class MiraiMultisessionFuture was
#> interrupted at 2025-10-15T15:39:17, while running on 'localhost' (pid 531734)

工作进程崩溃

以下是一个模拟并行工作进程在计算过程中突然终止(“崩溃”)的future:

library(future)
plan(multisession)
f <- future({ a <- 42; tools::pskill(Sys.getpid()); 2 * a })

这里的tools::pskill(Sys.getpid())会杀死评估调用的R工作进程。在实践中,工作进程可能因各种原因崩溃:

  • R进程可能耗尽内存并被操作系统杀死(“OOM杀手”)
  • 在HPC环境中,作业调度程序可能会在工作进程超过内存或运行时间限制时终止它
  • 用户可能手动杀死工作进程

无论并行工作进程如何终止,请求值都会产生:

v <- value(f)
#> Error: Future (<unnamed-4>) of class MultisessionFuture interrupted,
#> while running on 'localhost' (pid 538181)

从技术上讲,此错误也继承FutureInterruptError,就像用户中断时一样。future后端会自动重启崩溃的工作进程,这意味着不再需要手动重启后端来实现相同的效果。

重试被中断的future

无论future为何被中断,都可以首先调用reset(),然后通过resolved()value()触发重新计算。

例如,考虑一个有问题的函数,大约有50%的时间会使工作进程崩溃:

problematic_fcn <- function(x) {
  if (proc.time()[3] %% 1 < 0.5)
    tools::pskill(Sys.getpid())
  sqrt(x)
}

如果在并行工作进程中调用,我们可以重试最多十次,然后放弃:

library(future)
plan(multisession)

f <- future({ problematic_fcn(9) })

for (kk in 10:1) 
  tryCatch({
    v <- value(f)
    break
  }, FutureInterruptError = function(e) {
    if (kk == 1) stop(e)
    message("future interrupted, retrying ...") 
    f <- reset(f)
  })
}

message("value: ", v)

这可能会产生:

future interrupted, retrying ...
future interrupted, retrying ...
future interrupted, retrying ...
value: 3

编写一个辅助函数future_retry()来简化这个过程是一个有趣的练习:

f <- future_retry({ problematic_fcn(9) }, times = 10)
message("value: ", v)

更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)或者 我的个人博客 https://blog.qife122.com/
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值