2017-09-13 21 views
0

我已经成功地并行化的功能 - 我们称之为AddOne - 通过doParallel包,foreach%dopar%和我很熟悉.packages.export自变量为foreach的foreach%dopar%屈服“找不到函数”的错误时要并行化的功能列表元素

我的问题是,我想AddOne,而不是一个“独立”功能,是一个列表的元素,在这种情况下,我不能让事情工作。具体而言,如果AddOne调用子程序AddOneSubroutine,则AddOneSubroutine在“工作”环境中找不到,即使它是“导出”。

我使用的是Windows 10和R.version产量:

platform  x86_64-w64-mingw32   
arch   x86_64      
os    mingw32      
system   x86_64, mingw32    
status          
major   3       
minor   4.1       
year   2017       
month   06       
day   30       
svn rev  72865      
language  R       
version.string R version 3.4.1 (2017-06-30) 
nickname  Single Candle 

的doParallel版本我是1.0.10。 下面是一些能够尽可能简洁地展示问题的代码。

library(doParallel) 
if(!exists("Registered")){ 
    registerDoParallel(cores = detectCores(logical = TRUE)) 
    Registered = TRUE 
} 

AddOne<-function(x){AddOneSubroutine(x)} 
AddOneSubroutine <-function(x){x+1} 

MyList<-list() 
MyList$f<-AddOne 

# Not using parallel environments, works correctly when calling AddOne 3 times 
Result1 = foreach(i = 1:3) %do% AddOne(i) 
Result1 

# Not using parallel environments, works correctly when calling MyList$f 3 times 
Result2 = foreach(i = 1:3) %do% MyList$f(i) 
Result2 

# Using parallel environments, works correctly when calling AddOne 3 times, 
# despite not explicitly using the .export argument to export AddOneSubroutine 
Result3 = foreach(i = 1:3) %dopar% AddOne(i) 
Result3 

# Using parallel environments, fails when calling MyList$f with error 
# "could not find function "AddOneSubroutine"", even though that function is "exported" 
Result4 = foreach(i = 1:3,.export = "AddOneSubroutine") %dopar% MyList$f(i) 
Result4 

我什么都不明白?

回答

1

对于完全重现无处不在,让我们确保我们使用工人背景的R会话:

library("doParallel") 
cl <- parallel::makeCluster(detectCores(logical = TRUE)) 
registerDoParallel(cl) 

现在,我还没有挖成在很多细节的doParallel后端代码,所以我不是100肯定是什么原因导致了这个问题但我们知道,AddOneSubroutine的确是出口,你可以看到,如果你使用​​,或者干脆:

AddOneSubroutine <- function(x) { x + 1 } 
y <- foreach(i = 1L, .export = "AddOneSubroutine") %dopar% { 
    get("AddOneSubroutine") 
} 
str(y) 
## List of 1 
## $ :function (x) 
## ..- attr(*, "srcref")=Class 'srcref' atomic [1:8] 1 20 1 40 20 40 1 1 
## .. .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x2e475a0> 

但是,调用该函数MyList$f()它是找不到的,可以通过使用而确认:

AddOne <- function(x) exists("AddOneSubroutine") 
MyList <- list() 
MyList$f <- AddOne 
y <- foreach(i = 1L, .export = "AddOneSubroutine") %dopar% { 
    MyList$f(i) 
} 
str(y) 
## List of 1 
## $ : logi FALSE 

那么,为什么AddOneSubroutine不在从MyList$f内搜索的帧中?这可能是因为doParallel不能正确获取MyList$f的环境。似乎工作的解决方法是,以下攻击:

AddOne <- function(x) { AddOneSubroutine(x) } 
y <- foreach(i = 1L) %dopar% { 
    environment(MyList$f) <- environment(AddOneSubroutine) 
    MyList$f(i) 
} 
str(y) 
## List of 1 
## $ : num 2 

不幸的是,它不是很整洁,也不是很方便。

作为替代方案,doFuture后端(我是作者)似乎稍微好一点的工作:

library("doFuture") 
registerDoFuture() 
plan(multisession) 

AddOneSubroutine <- function(x) { x + 1 } 
AddOne <- function(x) { AddOneSubroutine(x) } 
MyList <- list() 
MyList$f <- AddOne 

y <- foreach(i = 1L) %dopar% { 
    AddOneSubroutine ## dummy guiding auto-export 
    MyList$f(i) 
} 
str(y) 
## List of 1 
## $ : num 2 

PS。您对我的使用感兴趣,因为理想的AddOneSubroutine应该在使用doFuture时自动导出,但它没有。我在底层globals包(我是作者)中发现了一个修复程序,但在发布它之前我需要更多地考虑它。

我的详细信息:

> sessionInfo() 
R version 3.4.1 (2017-06-30) 
Platform: x86_64-pc-linux-gnu (64-bit) 
Running under: Ubuntu 16.04.3 LTS 

Matrix products: default 
BLAS: /usr/lib/atlas-base/atlas/libblas.so.3.0 
LAPACK: /usr/lib/atlas-base/atlas/liblapack.so.3.0 

locale: 
[1] LC_CTYPE=en_US.UTF-8  LC_NUMERIC=C    
[3] LC_TIME=en_US.UTF-8  LC_COLLATE=en_US.UTF-8  
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 
[7] LC_PAPER=en_US.UTF-8  LC_NAME=C     
[9] LC_ADDRESS=C    LC_TELEPHONE=C    
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C  

attached base packages: 
[1] parallel stats  graphics grDevices utils  datasets methods 
[8] base  

other attached packages: 
[1] doFuture_0.5.1 iterators_1.0.8 foreach_1.4.3 future_1.6.1 

loaded via a namespace (and not attached): 
[1] compiler_3.4.1 tools_3.4.1  listenv_0.6.0 codetools_0.2-15 
[5] digest_0.6.12 globals_0.10.2 
相关问题