在foreach %dopar%中调用Rcpp包函数遇并行错误求助
解决R包中并行调用Rcpp函数的问题
问题根源
你遇到的错误本质是:并行worker进程没有加载你的test包,无法访问Rcpp绑定的C++底层函数。rcpp_hello_world这类Rcpp生成的函数,实际是调用包动态链接库中的底层符号(比如_test_rcpp_hello_world),而跨进程传递这些符号指针是无效的——因为每个进程的内存空间独立,指针地址在worker进程中没有意义,所以会出现NULL value passed as symbol address错误。
可行解决方案
不要用clusterExport传递Rcpp函数,而是让每个worker进程加载你的包,这样包的命名空间和动态链接库会被正确加载,所有Rcpp函数自然可用。
方法1:用foreach的.packages参数
修改你的parallelize函数,利用foreach的.packages参数自动让worker加载包:
parallelize <- function() { cl <- parallel::makeCluster(parallel::detectCores() - 1) doParallel::registerDoParallel(cl) # 通过.packages让worker加载test包 res <- foreach::foreach(i = 1:5, .combine = c, .packages = "test") %dopar% { test_func() } parallel::stopCluster(cl) return(res) }
方法2:用clusterEvalQ预先让worker加载包
如果需要更明确控制worker的环境,也可以用parallel::clusterEvalQ让所有worker加载包:
parallelize <- function() { cl <- parallel::makeCluster(parallel::detectCores() - 1) # 让每个worker加载test包 parallel::clusterEvalQ(cl, library(test)) doParallel::registerDoParallel(cl) res <- foreach::foreach(i = 1:5, .combine = c) %dopar% { test_func() } parallel::stopCluster(cl) return(res) }
关键注意事项
- 如果是用
devtools::load_all()测试包,worker进程默认不会继承当前会话的包加载状态,此时需要让worker也执行devtools::load_all()(确保worker能找到包的路径),或者先通过devtools::install()把包安装到系统库,再用library(test)加载。 - 不需要再用
clusterExport导出test_func或rcpp_hello_world,因为包加载后这些函数会自动在worker的命名空间中可用。
内容的提问来源于stack exchange,提问作者shaelebrown
相关产品推荐
相关产品推荐

