gpt4 book ai didi

r - Windows 7 上内联函数的 doParallel 问题(适用于 Linux)

转载 作者:行者123 更新时间:2023-12-04 09:54:52 27 4
gpt4 key购买 nike

我在 Windows 7 和 Linux (SUSE Server 11 (x86_64)) 上都使用 R 3.0.1。以下示例代码在 Windows 上产生错误,但在 Linux 上没有。列出的所有工具箱在两台机器中都是最新的。
Windows 错误是:

Error in { : task 1 failed - "NULL value passed as symbol address"

如果我改变 %dopar% to %do% ,Windows 代码运行时没有任何错误。我最初的猜测是这与 Windows 中的某些配置问题有关,我尝试重新安装 Rcpp 和 R,但这没有帮助。该错误似乎与范围有关 - 如果我在 f1 中定义并编译函数 cFunc,则 %dopar%可以工作,但正如预期的那样,它非常慢,因为我们为每个任务调用一次编译器。

有没有人对错误发生的原因有一些见解或有关如何修复它的建议?
library(inline)
sigFunc <- signature(x="numeric", size_x="numeric")
code <- ' double tot =0;
for(int k = 0; k < INTEGER(size_x)[0]; k++){
tot += REAL(x)[k];
};
return ScalarReal(tot);
'
cFunc <- cxxfunction(sigFunc, code)

f1 <- function(){
x <- rnorm(100)
a <- cFunc(x=x, size_x=as.integer(length(x)))
return(a)
}

library(foreach)
library(doParallel)
registerDoParallel()
# this produces an error in Windows but not in Linux
res <- foreach(counter=(1:100)) %dopar% {f1()}
# this works for both Windows and Linux
res <- foreach(counter=(1:100)) %do% {f1()}

# The following is not a practical solution, but I can compile cFunc inside f1 and then this works in Windows but it is very slow
f1 <- function(){
library(inline)
sigFunc <- signature(x="numeric", size_x="numeric")

code <- ' double tot =0;
for(int k = 0; k < INTEGER(size_x)[0]; k++){
tot += REAL(x)[k];
};
return ScalarReal(tot);
'
cFunc <- cxxfunction(sigFunc, code)
x <- rnorm(100)
a <- cFunc(x=x, size_x=as.integer(length(x)))
return(a)
}
# this now works in Windows but is very slow
res <- foreach(counter=(1:100)) %dopar% {f1()}

谢谢!
古斯塔沃

最佳答案

错误消息“NULL 值作为符号地址传递”是不寻常的,并不是由于函数没有导出到工作线程。 cFunc函数在被序列化、发送给工作人员和反序列化后不起作用。当它从保存的工作区加载时,它也不起作用,这会导致相同的错误消息。这并不让我感到惊讶,这可能是 inline 的记录行为。包裹。

正如您所展示的,您可以通过创建 cFunc 来解决该问题。在 worker 身上。要有效地做到这一点,您只需对每个工作人员执行一次。使用 doParallel 来做到这一点后端,我将定义一个工作器初始化函数,并使用 clusterCall 在每个工作器上执行它。功能:

worker.init <- function() {
library(inline)
sigFunc <- signature(x="numeric", size_x="numeric")
code <- ' double tot =0;
for(int k = 0; k < INTEGER(size_x)[0]; k++){
tot += REAL(x)[k];
};
return ScalarReal(tot);
'
assign('cFunc', cxxfunction(sigFunc, code), .GlobalEnv)
NULL
}

f1 <- function(){
x <- rnorm(100)
a <- cFunc(x=x, size_x=as.integer(length(x)))
return(a)
}

library(foreach)
library(doParallel)
cl <- makePSOCKcluster(3)
clusterCall(cl, worker.init)
registerDoParallel(cl)
res <- foreach(counter=1:100) %dopar% f1()

请注意,您必须显式创建 PSOCK 集群对象才能调用 clusterCall .

您的示例在 Linux 上运行的原因是 mclapply调用 registerDoParallel 时使用函数没有参数,而在 Windows 上创建一个集群对象和 clusterApplyLB函数被使用。使用 mclapply 时,函数和变量不会序列化并发送给工作人员,所以没有错误。

如果 doParallel 就好了包括对初始化 worker 的支持,而无需使用 clusterCall ,但还没有。

关于r - Windows 7 上内联函数的 doParallel 问题(适用于 Linux),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18245193/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com