Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 7上内联函数的doParallel问题(适用于Linux)_R_Inline - Fatal编程技术网

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

Windows 7上内联函数的doParallel问题(适用于Linux),r,inline,R,Inline,我在Windows7和Linux(SUSE服务器11(x86_64))上都使用R3.0.1。下面的示例代码在Windows上生成错误,但在Linux上不生成错误。两台机器中列出的所有工具箱都是最新的。 Windows错误是: Error in { : task 1 failed - "NULL value passed as symbol address" 如果我将%dopar%更改为%do%,则Windows代码运行时不会出现任何错误。我最初的猜测是,这与Windows中的某些配置问题有关,

我在Windows7和Linux(SUSE服务器11(x86_64))上都使用R3.0.1。下面的示例代码在Windows上生成错误,但在Linux上不生成错误。两台机器中列出的所有工具箱都是最新的。 Windows错误是:

Error in { : task 1 failed - "NULL value passed as symbol address"
如果我将
%dopar%更改为%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()}
库(内联)

sigFunc我认为,最简单的“解决办法”是

1) 在单独的源文件中编写代码,例如
cFunc.c

2) 使用
R CMD SHLIB
编译它

3)
dyn.load
在您的
foreach
调用中加载该函数

比如说,

cFunc.c
=======

#include <R.h>
#include <Rinternals.h>

SEXP cFunc( SEXP x, SEXP size_x ) {

  double tot = 0;
  for (int k=0; k < INTEGER(size_x)[0]; ++k ) {
    tot += REAL(x)[k];
  }
  return ScalarReal(tot);

}
cFunc.c
=======
#包括
#包括
SEXP cFunc(SEXP x,SEXP size_x){
双tot=0;
对于(int k=0;k

库(foreach)
图书馆(双平行)
registerDoParallel()
x错误消息“作为符号地址传递的空值”是不寻常的,这不是因为函数没有导出到工作程序。
cFunc
函数在被序列化、发送到工作进程并取消序列化后就不起作用了。当从保存的工作区加载时,它也不工作,这会导致相同的错误消息。这并不让我感到惊讶,这可能是
inline
包的一种有文档记录的行为

正如您所演示的,您可以通过在workers上创建
cFunc
来解决问题。为了有效地完成这项工作,您只需要对每个员工执行一次。要使用
doParallel
后端实现这一点,我将定义一个worker初始化函数,并使用
clusterCall
函数在每个worker上执行它:

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()

worker.init+1导出函数的好方法。您是否可以使用
foreach
.export
参数?@SimonO101如果您使用
.verbose=TRUE
,您将看到
cFunc
是自动导出的,这解释了为什么您没有得到通常的“未找到对象”错误消息。我认为主机上的状态没有包含在序列化函数
cFunc
中,这需要更多的工作。我删除了Rcpp标记。这与Rcpp无关,您使用的是内联R C API codeRepeat。A.包装。这真的是组织代码的最明智的方法。我同意德克的观点。编写一个包可以解决与R中的并行计算相关的许多问题,以及许多其他好处。编写一个包听起来不错,但在多台机器上运行代码确实很痛苦。每次更改cpp代码时,您都必须更新所有计算机上的包。不太好。@Jfly:但是如果您编写一个脚本在所有机器上更新您的包,就不会有更多的麻烦了。
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()