多会话模式下future_map无法识别字符向量引用的全局变量问题
解决future_map无法识别字符串引用全局变量的问题
问题场景
尝试在future_map的.x参数传入字符向量列表bestVars,让自定义函数run_sim_in_par通过mget(.x)从全局环境获取对应变量并处理。但多会话模式下持续报错:
Error in (function (.x, .f, ..., .progress = FALSE) :
ℹ In index: 1.
Caused by error: ! value for 'a1' not found
原因是future框架的静态分析无法自动识别通过字符串指定的全局变量,导致子会话无法获取这些变量。
解决方案
针对furrr的future_map场景,有两种适配现有需求的可行方案:
方案1:显式注入全局变量
在调用run_sim_in_par前,显式引用需要的变量,让future的静态分析能捕捉到这些全局变量,同时提前用mget获取变量列表传入函数:
simulated_res <- future_map_dfr( .x = bestVars, .f = { ~{ # 显式引用value,让future识别到该全局变量 value # 提前获取当前任务需要的变量列表 vars_list <- mget(.x) run_sim_in_par(vars_to_sim = vars_list) } } )
方案2:动态指定globals参数
利用future的globals参数,为每个映射任务动态添加需要的变量,确保子会话能获取到字符串对应的全局变量:
simulated_res <- future_map_dfr( .x = bestVars, .f = ~run_sim_in_par(vars_to_sim = mget(.x)), .options = furrr_options( globals = function(x) { # 为当前任务添加对应的变量,加上固定依赖的value和函数 structure(TRUE, add = c(x, "value", "run_sim_in_par")) } ) )
修改后的完整可运行代码
library(future) library(furrr) library(kit) library(tidyverse) ## 模拟数据 vars <- paste0(letters,1:10) bestVars <- combn(vars, 5, simplify = F) df <- data.frame( matrix(data = rnorm(50000*length(vars),200,500), nrow = 50000, ncol = length(vars)) ) names(df) <- vars df$value <- rnorm(n = nrow(df), 350, 300) df <- df %>% dplyr::select(value,everything(.)) df <- lapply(split.default(x = df, names(df)), function(x) x[[1]]) list2env(df, globalenv()) rm(df) run_sim_in_par <- function(vars_to_sim) { sampled_rows <- sample(x = 1:length(value), size = 50, replace = F) varname <- paste(names(vars_to_sim), collapse = "*") best <- Reduce(vars_to_sim, f = '*')[sampled_rows] row_idx <- kit::topn(best, n = 5, decreasing = T, hasna = FALSE, index = TRUE) best_row_value <- value[sampled_rows][row_idx] sim <- data.frame(var = varname, mean_value = mean(best_row_value)) return(sim) } plan(multisession) # 启用多会话模式 ## 方案1运行示例 simulated_res1 <- future_map_dfr( .x = bestVars, .f = { ~{ value vars_list <- mget(.x) run_sim_in_par(vars_to_sim = vars_list) } } ) ## 方案2运行示例 simulated_res2 <- future_map_dfr( .x = bestVars, .f = ~run_sim_in_par(vars_to_sim = mget(.x)), .options = furrr_options( globals = function(x) { structure(TRUE, add = c(x, "value", "run_sim_in_par")) } ) )
内容的提问来源于stack exchange,提问作者On_an_island
相关产品推荐
相关产品推荐

