R:foreach不能用于导出数字输出,例如png或ggsave

R:foreach不能用于导出数字输出,例如png或ggsave,r,ggplot2,foreach,parallel-processing,R,Ggplot2,Foreach,Parallel Processing,我正在本地机器上运行foreach和doParallel(Mac Pro 2009 12核或Macbook Pro 2017)。一旦出现绘图或设备输出,如png或ggsave,foreach就会死锁 2019年8月29日更新:我做了一个简单的测试: library(foreach) library(doParallel) library(ggplot2) registerDoParallel(cores = 4) ret.plot=foreach(i = 1:4) %dopar% { wri

我正在本地机器上运行
foreach
doParallel
(Mac Pro 2009 12核或Macbook Pro 2017)。一旦出现绘图或设备输出,如png或ggsave,foreach就会死锁

2019年8月29日更新:我做了一个简单的测试:

library(foreach)
library(doParallel)
library(ggplot2)
registerDoParallel(cores = 4)
ret.plot=foreach(i = 1:4) %dopar% {
  write(1:1, paste0(i, '_p.txt'))
  md=data.frame(x=1:10, y=1:10); 
  p=ggplot(md, aes(x=x, y=y))+geom_point();
}

# for(i in 1:4){
ret.save1=foreach(i = 1:4) %do% {
  ggsave(filename = paste0(i, '_do.png'), ret.plot[[i]])
}

ret.save2=foreach(i = 1:4) %dopar% {
  ggsave(filename = paste0(i, '_dopar.png'), ret.plot[[i]])
}

# ret.save2=foreach(i = 1:4, .packages = c("ggplot2")) %dopar% {
#   ggsave(filename = paste0(i, '_dopar.png'), ret.plot[[i]])
# }
第一个并行循环
ret.plot=…
工作,它导出四个.txt文件,并返回
ggplot
结果列表。 第二个循环,
for(1:4中的i)
foreach
%do%
都能很好地工作。 但是,第三个循环,
foreach
%dopar%
再次阻塞

因此它表明1)并行在我的机器中正常工作,2)绘图函数(
base::plot
ggsave
)和并行之间可能存在兼容问题

Mac上的活动监视器显示四个会话运行在后台,CPU风扇工作更努力。终端或RStudio中的R没有差异


原始问题说明:

Session information:

> sessionInfo() R version 3.6.1 (2019-07-05) Platform:
> x86_64-apple-darwin17.7.0 (64-bit) Running under: macOS High Sierra
> 10.13.6
> 
> Matrix products: default BLAS:  
> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
> LAPACK: /usr/local/Cellar/openblas/0.3.7/lib/libopenblasp-r0.3.7.dylib
> 
> locale: [1]
> en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
> 
> attached base packages: [1] parallel  stats     graphics  grDevices
> utils     datasets  methods   base     
> 
> other attached packages: [1] ggplot2_3.2.1     doParallel_1.0.15
> iterators_1.0.12  foreach_1.4.7    
> 
> loaded via a namespace (and not attached):  [1] Rcpp_1.0.1      
> codetools_0.2-16 withr_2.1.2      assertthat_0.2.1  [5] dplyr_0.8.3   
> crayon_1.3.4     R6_2.4.0         grid_3.6.1        [9] gtable_0.3.0  
> magrittr_1.5     scales_1.0.0     pillar_1.4.2     [13] rlang_0.4.0   
> lazyeval_0.2.2   rstudioapi_0.10  tools_3.6.1      [17] glue_1.3.1    
> purrr_0.3.2      munsell_0.5.0    compiler_3.6.1   [21]
> pkgconfig_2.0.2  colorspace_1.4-1 tidyselect_0.2.5 tibble_2.1.3



library(foreach)
library(doParallel)
library(ggplot2)
fxp<- function(x){
  png(paste0(x, '_p.png')) ;
  plot(1:10);
  dev.off()
}
fxg <-function(x){ 
  md=data.frame(x=1:10, y=1:10); 
  p=ggplot(md, aes(x=x, y=y))+geom_point();
  ggsave(filename = paste0(x, '_g.png'), p)
}
fxp(0);fxg(0)

cl <- 4
registerDoParallel(cl)
x=foreach(i =1:4) %dopar% {
  # for( i in 1:2){
  fxp(i);
  fxg(i)
}
会话信息:
>sessionInfo()R版本3.6.1(2019-07-05)平台:
>x86_64-apple-darwin17.7.0(64位)运行于:macOS High Sierra
> 10.13.6
> 
>矩阵乘积:默认BLAS:
>/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
>LAPACK:/usr/local/ceral/openblas/0.3.7/lib/libopenblasp-r0.3.7.dylib
> 
>地点:[1]
>en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
> 
>附加的基本包:[1]并行设备
>utils数据集方法库
> 
>其他随附文件包:[1]ggplot2_3.2.1 doParallel_1.0.15
>迭代器1.0.12 foreach_1.4.7
> 
>通过命名空间加载(未附加):[1]Rcpp_1.0.1
>代码工具\u 0.2-16,其R\u 2.1.2资产为\u 0.2.1[5]dplyr\u 0.8.3
>蜡笔1.3.4 R6 2.4.0网格3.6.1[9]表格0.3.0
>magrittr_1.5比例尺_1.0.0支柱_1.4.2[13]rlang_0.4.0
>lazyeval_0.2.2 rstudioapi_0.10工具_3.6.1[17]胶水_1.3.1
>purrr_0.3.2蒙塞尔_0.5.0编译器_3.6.1[21]
>pkgconfig_2.0.2颜色空间_1.4-1 TIDY选择_0.2.5 TIBLE_2.1.3
图书馆(foreach)
图书馆(双平行)
图书馆(GG2)

fxp在Mac OS上使用%dopar%中的png()时,我预期会出现同样的问题(linux和Windows工作正常)

这是由于Mac Os上的分叉机制和图形设备(以及可能的png()实现)。
如果您这样做,您将看到png不会创建新的图形设备:

fxp<- function(x){
    print(dev.cur())
    png(paste0(x, '_p.png')) ;
    print(dev.cur())
    plot(1:10);
    dev.off()
}

## quartz_off_screen
##               2

fxp谢谢@jfrey,你说得对。我必须使用开罗。而且,它需要X11

这是我发现并解决我的问题的东西。 1.从R-project而不是自制程序安装R。 2.type='cairo',正如jfrey所建议的那样

我的Mac电脑上的R是从自制软件安装的,因此
capabilities()
返回X11=FALSE。 然后我从自制中卸载了R,然后从下载并安装R for Mac。然后
capabilities()
返回
X11=TRUE

然后,带有type='cairo'的并行代码在我的Mac上完美地工作

 capabilities()



     jpeg         png        tiff       tcltk         X11        aqua 
       TRUE        TRUE        TRUE        TRUE        TRUE        TRUE 
   http/ftp     sockets      libxml        fifo      cledit       iconv 
       TRUE        TRUE        TRUE        TRUE        TRUE        TRUE 
        NLS     profmem       cairo         ICU long.double     libcurl 
       TRUE        TRUE        TRUE        TRUE        TRUE        TRUE 
线程可能很有用:

我用代码blow确认:

library(foreach)
library(doParallel)
library(ggplot2)
fxp<- function(x){
  png(paste0(x, '_p.png'), type = "cairo") ;
  plot(1:10);
  dev.off()
}
fxg <-function(x){ 
  md=data.frame(x=1:10, y=1:10); 
  p=ggplot(md, aes(x=x, y=y))+geom_point();
  ggsave(filename = paste0(x, '_g.png'), p, type = "cairo")
}
fxp(0);fxg(0)

cl <- 4
registerDoParallel(cl)
x=foreach(i =1:4) %dopar% {
  fxp(i);
  fxg(i)
}
库(foreach)
图书馆(双平行)
图书馆(GG2)

fxpTry改为使用cl=detectCores()-1运行,并查看是否复制错误。如果您的机器在MAC中只有4核,您可能会耗尽所有资源。谢谢您的建议。这没什么区别。如果我使用一个核心(仅此一个),它就可以工作。如果我将%dopar%更改为%do%,它就可以工作。好的。我们消除了这一点。我认为另一个关键步骤是在每个集群内本地加载包。因此,请在foreach.x=foreach(I=1:4,.packages=c(“ggplot2”)中添加库(ggplot2)。x=foreach(I=1:4,.packages=c(“ggplot2”))%dopar%等。在此之后,请按原样运行代码。如果不成功,请按顺序重复测试1-3,以了解此更改的响应方式。由于您使用的是
registerDoParallel(4)
,并且在macOS上(在Linux上也是如此),因此您将得到类似于
parallel::McLappy()的分叉并行处理
。如果您可以单独使用
parallel::mclappy()
来重现这一点,您可以排除foreach/doParallel是问题所在。谢谢。@HenrikB。经过更多测试,我知道并行代码在没有任何绘图函数的情况下运行良好。一旦有了plot()或ggsave(),并行永远不会结束。谢谢你,jfrey。是的,我应该使用type='cairo'。除了你的建议,我必须使用R-project.org上的R,而不是自制的。
 capabilities()



     jpeg         png        tiff       tcltk         X11        aqua 
       TRUE        TRUE        TRUE        TRUE        TRUE        TRUE 
   http/ftp     sockets      libxml        fifo      cledit       iconv 
       TRUE        TRUE        TRUE        TRUE        TRUE        TRUE 
        NLS     profmem       cairo         ICU long.double     libcurl 
       TRUE        TRUE        TRUE        TRUE        TRUE        TRUE 
library(foreach)
library(doParallel)
library(ggplot2)
fxp<- function(x){
  png(paste0(x, '_p.png'), type = "cairo") ;
  plot(1:10);
  dev.off()
}
fxg <-function(x){ 
  md=data.frame(x=1:10, y=1:10); 
  p=ggplot(md, aes(x=x, y=y))+geom_point();
  ggsave(filename = paste0(x, '_g.png'), p, type = "cairo")
}
fxp(0);fxg(0)

cl <- 4
registerDoParallel(cl)
x=foreach(i =1:4) %dopar% {
  fxp(i);
  fxg(i)
}