使用furrr时多会话内存占用过高,如何最小化?
降低furrr多会话内存占用的优化方案
针对你遇到的furrr会话内存过高(尤其是Shiny环境中)的问题,即使设置globals=FALSE和指定包也无效,可尝试以下几个关键优化方向:
1. 改用cluster计划替代multisession
multisession会复制主进程的整个环境(包括Shiny加载的大量框架资源),而cluster计划可以更严格地控制worker的初始化环境,避免不必要的内存复制。
示例代码:
library(furrr) library(parallel) # 创建集群时指定仅加载必要包,且不继承主环境的冗余变量 cl <- makeCluster(10, outfile = "", rscript_args = c("--no-save", "--no-environ", "--no-site-file")) # 在每个worker中手动加载所需包 clusterEvalQ(cl, { library(paws) library(jsonlite) }) plan(cluster, workers = cl) results_calc_rds <- future_map(.x = tokens, .f = my_fun, .options = furrr_options(seed = NULL, globals = character(0))) # 用完集群后关闭释放资源 stopCluster(cl)
2. 严格排查函数的全局变量依赖
globals=FALSE可能并未真正生效,如果my_fun中隐式引用了主环境的变量(比如未作为参数传入的对象),future仍会自动传递这些变量到worker,导致内存飙升。用以下命令检查函数的全局依赖:
codetools::findGlobals(my_fun)
如果输出中包含除paws/jsonlite函数外的其他全局对象,需将这些对象改为函数参数传入,或在worker环境中重新定义,避免隐式传递。
3. 清理Shiny主环境的冗余资源
Shiny默认会在全局环境加载很多框架资源,multisession会复制这些资源到每个worker。优化点:
- 将非必要的包、数据移到
server()函数内部加载,而非全局环境 - 避免在全局环境存储大对象(如大数据集、缓存),仅在需要时创建
4. 精确控制全局变量传递
如果必须使用multisession,可放弃globals=FALSE,转而精确指定需要传递的变量(仅保留tokens和函数运行必需的对象),避免自动捕获冗余内容:
plan(multisession, workers = 10) results_calc_rds <- future_map(.x = tokens, .f = my_fun, .options = furrr_options(seed = NULL, globals = c("tokens"), packages = c("paws", "jsonlite")))
注意:如果tokens本身是大对象,考虑拆分后分批处理,减少单个worker的内存占用。
5. 限制worker的R启动参数
在创建worker时,禁止加载不必要的配置文件,减少初始化内存:
plan(multisession, workers = 10, gc = TRUE, # 自动触发垃圾回收 rscript_args = c("--no-save", "--no-environ", "--no-site-file", "--no-init-file"))
内容的提问来源于stack exchange,提问作者Arkadi w
相关产品推荐
相关产品推荐

