R︱并行计算以及提高运算效率的方式(parallel包、clusterExport函数、SupR包简介)

2023-11-11



终于开始攻克并行这一块了,有点小兴奋,来看看网络上R语言并行办法有哪些:

     赵鹏老师(R与并行计算)做的总结已经很到位。现在并行可以分为:


     隐式并行:隐式计算对用户隐藏了大部分细节,用户不需要知道具体数据分配方式 ,算法的实现或者底层的硬件资源分配。系统会根据当前的硬件资源来自动启动计算核心。显然,这种模式对于大多数用户来说是最喜闻乐见的。

    显性并行:显式计算则要求用户能够自己处理算例中数据划分,任务分配,计算以及最后的结果收集。因此,显式计算模式对用户的要求更高,用户不仅需要理解自己的算法,还需要对并行计算和硬件有一定的理解。值得庆幸的是,现有R中的并行计算框架,如parallel (snow,multicores),Rmpi和foreach等采用的是映射式并行模型(Mapping),使用方法简单清晰,极大地简化了编程复杂度。R用户只需要将现有程序转化为*apply或者for的循环形式之后,通过简单的API替换来实现并行计算。


简单总结就是:

    隐式并行:OpenBLAS,Intel MKL,NVIDIA cuBLAS,H2O(参考我的博客)等

    显性并行:parallel(主打lapply应用)、foreach(主打for循环)、SupR、还有利用GPU的办法(gpuR)


      同时并行时对内存的消耗极大,超级容易爆发内存问题,而且R的内存问题一直都是R很难解决的问题,这边笔者也把看到的一些方式列出来。

      当然在使用一些高大上的并行包以及框架之前,如果你能够从编码小细节优化,效率也能提高很多,譬如:

 

[html]  view plain  copy
  1. 方法:速度, nrow(df)/time_taken = n 行每秒  
  2. 原始方法:1X, 856.2255行每秒(正则化为1)  
  3. 向量化方法:738X, 631578行每秒  
  4. 只考虑真值情况:1002X,857142.9行每秒  
  5. ifelse:1752X,1500000行每秒  
  6. which:8806X,7540364行每秒  
  7. Rcpp:13476X,11538462行每秒  
  8. apply处理并行  



——————————————————————————————————————————————————————


在最后笔者在实践中遇到的问题,进行对应的解决:

应用一:使用parallel包时,能不能clusterExport整个函数呢?

应用二:在使用parallel包时,报错:Error in unserialize(node$con) : error reading from connection


——————————————————————————————————


一、parallel包的使用方法


多数内容参考:R语言并行化基础与提高

parallel是base包,所以不用install.packages就可以直接调用。

原理:是利用CPU的核心进行训练。

应用场景:跟apply族(lapply/sapply效果一致)( 

R语言︱数据分组统计函数族——apply族用法与心得


1、使用步骤

     设置核心数:no_cores <- detectCores() - 1

     步骤分群环境:cl <- makeCluster(no_cores)

     用到的变量与包复制给不同的核心:clusterEvalQ(包)、clusterExport(变量)

     运行算法:clusterApply(cl, c(9,5), get("+"), 3) 

     关闭集群:

stopCluster(cl)


     就OK啦。但是这里面很从前不一样的是,如果有环境里面的外置变量(自己定义)那么需要额外插入,复制到不同核上面,而且如果有不同包里面的函数,都要额外加载、复制多份给不同的电脑核心。


2、案例

[html]  view plain  copy
  1. library(parallel)  
  2. cl <- makeCluster(getOption("cl.cores", 2))  
  3. clusterApply(cl, c(9,5), get("+"), 3)   #加减乘除  
  4. parSapply(cl, c(9,5), get("+"), 3)     
       案例一:c1就是设置的核心数,此时是2核心,然后就可以利用clusterApply/parSapply等函数进行调用。
[html]  view plain  copy
  1. xx <- 1  
  2. clusterExport(cl, "xx")  
  3. clusterCall(cl, function(y) xx + y, 2)  
      案例二:这个里面有xx这个变量是额外定义的,所以需要额外加载,需要用clusterExport函数,导入到并行环境中。

3、parallel内存优化与管理

(1)注意数据容量的均匀分布

[html]  view plain  copy
  1. parLapply <- function (cl = NULL, X, fun, ...)   
  2. {  
  3.     cl <- defaultCluster(cl)  
  4.     do.call(c, clusterApply(cl, x = splitList(X, length(cl)),   
  5.         fun = lapply, fun, ...), quote = TRUE)  
  6. }  

    注意到splitList(X, length(cl)) ,他会将任务分割成多个部分,然后将他们发送到不同的集群中。这里一个问题就是,譬如假设有一个list,里面数据量分别是:

(99,99,99,2,5,2)

    如果是两个核数据分为了(99,99,99)、(2,5,2),第一个核分为到了那么多任务,第二个核很少,那么就会空闲,于是乎,效率还是不高,所以数据容量要尽量均匀分布。


(2)集群内存类型:FORK和PSOCK

FORK适用unix/max,实现内存共享以及节省内存,大数据环境下内存问题报错少

PSOCK适用所有(一般window都是这个)


parallel包中通过函数来设置:

[html]  view plain  copy
  1. makeCluster(4,type="FORK")  

FORK对性能提升很显著,但是window下不可适用。


4、parallel万一报错了咋办?

      lapply在使用的时候也会出现这样的问题,如果出现问题,那么就白跑了,而且也不可能给你停顿下来。那么如何让lapply运行中跳过报错的办法呢?

      R语言相关的报错处理函数可见:R语言-处理异常值或报错的三个示例

      用tryCatch跳过:

[html]  view plain  copy
  1. result = tryCatch(  
  2.         {expr},   
  3.         warning = function(w) {warning-handler-code},   
  4.         error = function(e) { error-handler-code},   
  5.         finally = {cleanup-code}  
  6.         )  
出现warning、error时候怎么处理,就可以跳过了。例子:

[html]  view plain  copy
  1. result = tryCatch(  
  2.         {segmentCN(txt)},   
  3.         warning = function(w) {"出警告啦"},   
  4.         error = function(e) { "出错啦"},   
  5.         )  

分词时候,容易因为Lapply中断之后,就不会运行了,这样功亏一篑所以可以用这个办法跳过。


5、parSapply/parLapply函数使用技巧

       函数的大体结构是:

[html]  view plain  copy
  1. parSapply(cl,x,fun)  

      其中cl是预先设定好的,x是需要循环的变量,而fun是函数。

      那么一般来说,fun之中要使用的任何内容都需要用clusterEvalQ(包)、clusterExport(变量)复制到不同的核心之中。

       而x则可以不用布置到全局,因为他是在源环境下调用出来,并拆分任务的。







——————————————————————————————————


二、foreach包的使用方法


1、简单使用案例

设计foreach包的思想可能想要创建一个lapply和for循环的标准,初始化的过程有些不同,你需要register注册集群:

library(foreach)
library(doParallel)

cl<-makeCluster(no_cores)
registerDoParallel(cl)

要记得最后要结束集群(不是用stopCluster()):

stopImplicitCluster()

foreach函数可以使用参数.combine控制你汇总结果的方法:

> foreach(exponent = 2:4, 
        .combine = c)  %dopar%  
  base^exponent
  [1]  4  8 16
> foreach(exponent = 2:4, .combine = rbind)  %dopar%   base^exponent
    [,1]
result.1 4 result.2 8 result.3 16
foreach(exponent = 2:4, .combine = list, .multicombine = TRUE)  %dopar%   base^exponent
[[1]]
[1] 4 [[2]]
[1] 8 [[3]]
[1] 16

注意到最后list的combine方法是默认的。在这个例子中用到一个.multicombine参数,他可以帮助你避免嵌套列表。比如说list(list(result.1, result.2), result.3) :

> foreach(exponent = 2:4, 
        .combine = list)  %dopar%  
  base^exponent
[[1]]
[[1]][[1]]
[1] 4

[[1]][[2]]
[1] 8


[[2]]
[1] 16


2、变量作用域

在foreach中,变量作用域有些不同,它会自动加载本地的环境到函数中:

> base <- 2
> cl<-makeCluster(2)
> registerDoParallel(cl)
> foreach(exponent = 2:4, 
        .combine = c)  %dopar%  
  base^exponent
stopCluster(cl)
 [1]  4  8 16

但是,对于父环境的变量则不会加载,以下这个例子就会抛出错误:

test <- function (exponent) {
  foreach(exponent = 2:4, 
          .combine = c)  %dopar%  
    base^exponent
}
test()

 Error in base^exponent : task 1 failed - "object 'base' not found" 

为解决这个问题你可以使用.export这个参数而不需要使用clusterExport。注意的是,他可以加载最终版本的变量,在函数运行前,变量都是可以改变的:

base <- 2
cl<-makeCluster(2)
registerDoParallel(cl)
 
base <- 4
test <- function (exponent) {
  foreach(exponent = 2:4, 
          .combine = c,
          .export = "base")  %dopar%  
    base^exponent
}
test()
 
stopCluster(cl)

 [1]  4  8 16

相似的你可以使用.packages参数来加载包,比如说:.packages = c("rms", "mice")


——————————————————————————————————


三、SupR

通过对现有R 内核的改进实现在单机上的多线程和在集群上的分布式计算功能。SupR目前仍处在内部试用和补充完善阶段。


       据说supR很好用,而且小象学院的讲师(游皓麟)已经开始教授这个系统的使用方法,挺好用的。


——————————————————————————————————


四、内存管理


方法有三:
      一、升级硬件
      二、改进算法
      三、修改操作系统分配给R的内存上限, memory.size(T)查看已分配内存 

[html]  view plain  copy
  1. memory.size(F)#查看已使用内存    
  2. memory.limit()#查看内存上限   
  3. object.size()#看每个变量占多大内存。  
  4. memory.size()#查看现在的work space的内存使用  
  5. memory.limit()#查看系统规定的内存使用上限。如果现在的内存上限不够用,可以通过memory.limit(newLimit)更改到一个新的上限。注意,在32位的R中,封顶上限为4G,无法在一个程序上使用超过4G (数位上限)。这种时候,可以考虑使用64位的版本。  

详情看: R语言︱大数据集下运行内存管理   以及   R语言之内存管理


——————————————————————————————————


应用一:使用parallel包时,能不能clusterExport整个函数呢?



      R语言在使用Parallel时候,会出现这样的疑问,一些东西都需要广播给不同的核心,那么在clusterExport步骤怎么办呢?能不能clusterExport一整个函数?然后直接parLapply呢?

      答案否定的。笔者在用的时候,怎么样都不能把整个函数加载进去,所以只能另想办法。

      既然不能clusterExport整个函数,那就只能改造我们的函数去适应parallel包了。

      来看几个函数“被”改造的例子,一般来说有两个办法:


1、方法一:通过.GlobalEnv广播成全局变量

[plain]  view plain  copy
  1. clusterExport(cl=cl, varlist=c("text.var", "ntv", "gc.rate", "pos"), envir=environment())  

      在函数导入的时候,加入envir变量让其广播给不同的核心,这个可以放在函数之中来使用。


2、方法二:把parLapply嵌套进函数之中

[plain]  view plain  copy
  1. par.test <- function(text.var, gc.rate=10){   
  2.     require(parallel)  
  3.     pos <-  function(i) {  
  4.         paste(sapply(strsplit(tolower(i), " "), nchar), collapse=" | ")  
  5.     }  
  6.     cl <- makeCluster(mc <- getOption("cl.cores", 4))  
  7.     parLapply(cl, text.var, function(text.vari, gc.rate, pos) {  
  8.         x <- pos(text.vari)  
  9.         if (i%%gc.rate==0) gc()  
  10.         x  
  11.     }, gc.rate, pos)  
  12. }  

       可以看到的这个 例子,就是把内容嵌套到parLapply之中了。同时也可以学习到,parLapply使用方法也很不错,也可以学习一下。

      再来看一个例子

[plain]  view plain  copy
  1. mainFunction <- function(cl) {  
  2.     fa <- function(x) fb(x)  
  3.     fb <- function(x) fc(x)  
  4.     fc <- function(x) x  
  5.     y <- 7  
  6.     workerFunction <- function(i) {  
  7.         do.call(functionNames[[i]], list(y))  
  8.     }  
  9.     environment(workerFunction) <- .GlobalEnv  
  10.     environment(fa) <- .GlobalEnv  
  11.     environment(fb) <- .GlobalEnv  
  12.     environment(fc) <- .GlobalEnv  
  13.     functionNames <- c("fa", "fb", "fc")  
  14.     clusterExport(cl, varlist=c("functionNames", functionNames, "y"),  
  15.                   envir=environment())  
  16.     parLapply(cl, seq_along(functionNames), workerFunction)  
  17. }  
  18.   
  19. library(parallel)  
  20. cl <- makeCluster(detectCores())  
  21. mainFunction(cl)  
  22. stopCluster(cl)  

——————————————————————————————————

应用二:在使用parallel包时,报错:Error in unserialize(node$con) : error reading from connection


      在R语言中使用并行算法的时候,会出现报错,无法连接到核心,即使在本来连接上的时候。通过查阅文献看到了,这是因为“调用核心数--计算机内存”的不匹配造成的。

      如果你的数据集很大,调用了很多核心,那么你的计算机内存如果不够匹配,就会出现连接不上的不错,甚至还出现卡机,一动不动的情况(当然,只要耐心等待,其实他还是会继续运行的...等待的时候会有点长)


解决办法一:调用FORK,window不能...

      FORK适用unix/max,实现内存共享以及节省内存,大数据环境下内存问题报错少

      PSOCK适用所有(一般window都是这个)

      不过调用FORK也还是治标不治本。


解决办法二:分开并行,小步迭代

      譬如10万数据,那么就“2万+2万+2万+2万+2万”的跑,如果还出现脱机,就用之前tryCatch跳过,让损失降低到最小。

      最好的办法了。



参考文献:How-to go parallel in R – basics + tips


——————————————————————————————————


参考文献


1、R语言并行化基础与提高

2、R与并行计算

3、sparklyr包:实现Spark与R的接口,会用dplyr就能玩Spark

4、Sparklyr与Docker的推荐系统实战

5、R语言︱H2o深度学习的一些R语言实践——H2o包

6、R用户的福音︱TensorFlow:TensorFlow的R接口

7、mxnet:结合R与GPU加速深度学习

8、碎片︱R语言与深度学习

版权声明:本文为博主原创文章,转载请注明来源“素质云博客”,谢谢合作!!微信公众号:素质云笔记 https://blog.csdn.net/sinat_26917383/article/details/52719232
终于开始攻克并行这一块了,有点小兴奋,来看看网络上R语言并行办法有哪些:

     赵鹏老师(R与并行计算)做的总结已经很到位。现在并行可以分为:


     隐式并行:隐式计算对用户隐藏了大部分细节,用户不需要知道具体数据分配方式 ,算法的实现或者底层的硬件资源分配。系统会根据当前的硬件资源来自动启动计算核心。显然,这种模式对于大多数用户来说是最喜闻乐见的。

    显性并行:显式计算则要求用户能够自己处理算例中数据划分,任务分配,计算以及最后的结果收集。因此,显式计算模式对用户的要求更高,用户不仅需要理解自己的算法,还需要对并行计算和硬件有一定的理解。值得庆幸的是,现有R中的并行计算框架,如parallel (snow,multicores),Rmpi和foreach等采用的是映射式并行模型(Mapping),使用方法简单清晰,极大地简化了编程复杂度。R用户只需要将现有程序转化为*apply或者for的循环形式之后,通过简单的API替换来实现并行计算。


简单总结就是:

    隐式并行:OpenBLAS,Intel MKL,NVIDIA cuBLAS,H2O(参考我的博客)等

    显性并行:parallel(主打lapply应用)、foreach(主打for循环)、SupR、还有利用GPU的办法(gpuR)


      同时并行时对内存的消耗极大,超级容易爆发内存问题,而且R的内存问题一直都是R很难解决的问题,这边笔者也把看到的一些方式列出来。

      当然在使用一些高大上的并行包以及框架之前,如果你能够从编码小细节优化,效率也能提高很多,譬如:

 

[html]  view plain  copy
  1. 方法:速度, nrow(df)/time_taken = n 行每秒  
  2. 原始方法:1X, 856.2255行每秒(正则化为1)  
  3. 向量化方法:738X, 631578行每秒  
  4. 只考虑真值情况:1002X,857142.9行每秒  
  5. ifelse:1752X,1500000行每秒  
  6. which:8806X,7540364行每秒  
  7. Rcpp:13476X,11538462行每秒  
  8. apply处理并行  



——————————————————————————————————————————————————————


在最后笔者在实践中遇到的问题,进行对应的解决:

应用一:使用parallel包时,能不能clusterExport整个函数呢?

应用二:在使用parallel包时,报错:Error in unserialize(node$con) : error reading from connection


——————————————————————————————————


一、parallel包的使用方法


多数内容参考:R语言并行化基础与提高

parallel是base包,所以不用install.packages就可以直接调用。

原理:是利用CPU的核心进行训练。

应用场景:跟apply族(lapply/sapply效果一致)( 

R语言︱数据分组统计函数族——apply族用法与心得


1、使用步骤

     设置核心数:no_cores <- detectCores() - 1

     步骤分群环境:cl <- makeCluster(no_cores)

     用到的变量与包复制给不同的核心:clusterEvalQ(包)、clusterExport(变量)

     运行算法:clusterApply(cl, c(9,5), get("+"), 3) 

     关闭集群:

stopCluster(cl)


     就OK啦。但是这里面很从前不一样的是,如果有环境里面的外置变量(自己定义)那么需要额外插入,复制到不同核上面,而且如果有不同包里面的函数,都要额外加载、复制多份给不同的电脑核心。


2、案例

[html]  view plain  copy
  1. library(parallel)  
  2. cl <- makeCluster(getOption("cl.cores", 2))  
  3. clusterApply(cl, c(9,5), get("+"), 3)   #加减乘除  
  4. parSapply(cl, c(9,5), get("+"), 3)     
       案例一:c1就是设置的核心数,此时是2核心,然后就可以利用clusterApply/parSapply等函数进行调用。
[html]  view plain  copy
  1. xx <- 1  
  2. clusterExport(cl, "xx")  
  3. clusterCall(cl, function(y) xx + y, 2)  
      案例二:这个里面有xx这个变量是额外定义的,所以需要额外加载,需要用clusterExport函数,导入到并行环境中。

3、parallel内存优化与管理

(1)注意数据容量的均匀分布

[html]  view plain  copy
  1. parLapply <- function (cl = NULL, X, fun, ...)   
  2. {  
  3.     cl <- defaultCluster(cl)  
  4.     do.call(c, clusterApply(cl, x = splitList(X, length(cl)),   
  5.         fun = lapply, fun, ...), quote = TRUE)  
  6. }  

    注意到splitList(X, length(cl)) ,他会将任务分割成多个部分,然后将他们发送到不同的集群中。这里一个问题就是,譬如假设有一个list,里面数据量分别是:

(99,99,99,2,5,2)

    如果是两个核数据分为了(99,99,99)、(2,5,2),第一个核分为到了那么多任务,第二个核很少,那么就会空闲,于是乎,效率还是不高,所以数据容量要尽量均匀分布。


(2)集群内存类型:FORK和PSOCK

FORK适用unix/max,实现内存共享以及节省内存,大数据环境下内存问题报错少

PSOCK适用所有(一般window都是这个)


parallel包中通过函数来设置:

[html]  view plain  copy
  1. makeCluster(4,type="FORK")  

FORK对性能提升很显著,但是window下不可适用。


4、parallel万一报错了咋办?

      lapply在使用的时候也会出现这样的问题,如果出现问题,那么就白跑了,而且也不可能给你停顿下来。那么如何让lapply运行中跳过报错的办法呢?

      R语言相关的报错处理函数可见:R语言-处理异常值或报错的三个示例

      用tryCatch跳过:

[html]  view plain  copy
  1. result = tryCatch(  
  2.         {expr},   
  3.         warning = function(w) {warning-handler-code},   
  4.         error = function(e) { error-handler-code},   
  5.         finally = {cleanup-code}  
  6.         )  
出现warning、error时候怎么处理,就可以跳过了。例子:

[html]  view plain  copy
  1. result = tryCatch(  
  2.         {segmentCN(txt)},   
  3.         warning = function(w) {"出警告啦"},   
  4.         error = function(e) { "出错啦"},   
  5.         )  

分词时候,容易因为Lapply中断之后,就不会运行了,这样功亏一篑所以可以用这个办法跳过。


5、parSapply/parLapply函数使用技巧

       函数的大体结构是:

[html]  view plain  copy
  1. parSapply(cl,x,fun)  

      其中cl是预先设定好的,x是需要循环的变量,而fun是函数。

      那么一般来说,fun之中要使用的任何内容都需要用clusterEvalQ(包)、clusterExport(变量)复制到不同的核心之中。

       而x则可以不用布置到全局,因为他是在源环境下调用出来,并拆分任务的。







——————————————————————————————————


二、foreach包的使用方法


1、简单使用案例

设计foreach包的思想可能想要创建一个lapply和for循环的标准,初始化的过程有些不同,你需要register注册集群:

library(foreach)
library(doParallel)

cl<-makeCluster(no_cores)
registerDoParallel(cl)

要记得最后要结束集群(不是用stopCluster()):

stopImplicitCluster()

foreach函数可以使用参数.combine控制你汇总结果的方法:

> foreach(exponent = 2:4, 
        .combine = c)  %dopar%  
  base^exponent
  [1]  4  8 16
> foreach(exponent = 2:4, .combine = rbind)  %dopar%   base^exponent
    [,1]
result.1 4 result.2 8 result.3 16
foreach(exponent = 2:4, .combine = list, .multicombine = TRUE)  %dopar%   base^exponent
[[1]]
[1] 4 [[2]]
[1] 8 [[3]]
[1] 16

注意到最后list的combine方法是默认的。在这个例子中用到一个.multicombine参数,他可以帮助你避免嵌套列表。比如说list(list(result.1, result.2), result.3) :

> foreach(exponent = 2:4, 
        .combine = list)  %dopar%  
  base^exponent
[[1]]
[[1]][[1]]
[1] 4

[[1]][[2]]
[1] 8


[[2]]
[1] 16


2、变量作用域

在foreach中,变量作用域有些不同,它会自动加载本地的环境到函数中:

> base <- 2
> cl<-makeCluster(2)
> registerDoParallel(cl)
> foreach(exponent = 2:4, 
        .combine = c)  %dopar%  
  base^exponent
stopCluster(cl)
 [1]  4  8 16

但是,对于父环境的变量则不会加载,以下这个例子就会抛出错误:

test <- function (exponent) {
  foreach(exponent = 2:4, 
          .combine = c)  %dopar%  
    base^exponent
}
test()

 Error in base^exponent : task 1 failed - "object 'base' not found" 

为解决这个问题你可以使用.export这个参数而不需要使用clusterExport。注意的是,他可以加载最终版本的变量,在函数运行前,变量都是可以改变的:

base <- 2
cl<-makeCluster(2)
registerDoParallel(cl)
 
base <- 4
test <- function (exponent) {
  foreach(exponent = 2:4, 
          .combine = c,
          .export = "base")  %dopar%  
    base^exponent
}
test()
 
stopCluster(cl)

 [1]  4  8 16

相似的你可以使用.packages参数来加载包,比如说:.packages = c("rms", "mice")


——————————————————————————————————


三、SupR

通过对现有R 内核的改进实现在单机上的多线程和在集群上的分布式计算功能。SupR目前仍处在内部试用和补充完善阶段。


       据说supR很好用,而且小象学院的讲师(游皓麟)已经开始教授这个系统的使用方法,挺好用的。


——————————————————————————————————


四、内存管理


方法有三:
      一、升级硬件
      二、改进算法
      三、修改操作系统分配给R的内存上限, memory.size(T)查看已分配内存 

[html]  view plain  copy
  1. memory.size(F)#查看已使用内存    
  2. memory.limit()#查看内存上限   
  3. object.size()#看每个变量占多大内存。  
  4. memory.size()#查看现在的work space的内存使用  
  5. memory.limit()#查看系统规定的内存使用上限。如果现在的内存上限不够用,可以通过memory.limit(newLimit)更改到一个新的上限。注意,在32位的R中,封顶上限为4G,无法在一个程序上使用超过4G (数位上限)。这种时候,可以考虑使用64位的版本。  

详情看: R语言︱大数据集下运行内存管理   以及   R语言之内存管理


——————————————————————————————————


应用一:使用parallel包时,能不能clusterExport整个函数呢?



      R语言在使用Parallel时候,会出现这样的疑问,一些东西都需要广播给不同的核心,那么在clusterExport步骤怎么办呢?能不能clusterExport一整个函数?然后直接parLapply呢?

      答案否定的。笔者在用的时候,怎么样都不能把整个函数加载进去,所以只能另想办法。

      既然不能clusterExport整个函数,那就只能改造我们的函数去适应parallel包了。

      来看几个函数“被”改造的例子,一般来说有两个办法:


1、方法一:通过.GlobalEnv广播成全局变量

[plain]  view plain  copy
  1. clusterExport(cl=cl, varlist=c("text.var", "ntv", "gc.rate", "pos"), envir=environment())  

      在函数导入的时候,加入envir变量让其广播给不同的核心,这个可以放在函数之中来使用。


2、方法二:把parLapply嵌套进函数之中

[plain]  view plain  copy
  1. par.test <- function(text.var, gc.rate=10){   
  2.     require(parallel)  
  3.     pos <-  function(i) {  
  4.         paste(sapply(strsplit(tolower(i), " "), nchar), collapse=" | ")  
  5.     }  
  6.     cl <- makeCluster(mc <- getOption("cl.cores", 4))  
  7.     parLapply(cl, text.var, function(text.vari, gc.rate, pos) {  
  8.         x <- pos(text.vari)  
  9.         if (i%%gc.rate==0) gc()  
  10.         x  
  11.     }, gc.rate, pos)  
  12. }  

       可以看到的这个 例子,就是把内容嵌套到parLapply之中了。同时也可以学习到,parLapply使用方法也很不错,也可以学习一下。

      再来看一个例子

[plain]  view plain  copy
  1. mainFunction <- function(cl) {  
  2.     fa <- function(x) fb(x)  
  3.     fb <- function(x) fc(x)  
  4.     fc <- function(x) x  
  5.     y <- 7  
  6.     workerFunction <- function(i) {  
  7.         do.call(functionNames[[i]], list(y))  
  8.     }  
  9.     environment(workerFunction) <- .GlobalEnv  
  10.     environment(fa) <- .GlobalEnv  
  11.     environment(fb) <- .GlobalEnv  
  12.     environment(fc) <- .GlobalEnv  
  13.     functionNames <- c("fa", "fb", "fc")  
  14.     clusterExport(cl, varlist=c("functionNames", functionNames, "y"),  
  15.                   envir=environment())  
  16.     parLapply(cl, seq_along(functionNames), workerFunction)  
  17. }  
  18.   
  19. library(parallel)  
  20. cl <- makeCluster(detectCores())  
  21. mainFunction(cl)  
  22. stopCluster(cl)  

——————————————————————————————————

应用二:在使用parallel包时,报错:Error in unserialize(node$con) : error reading from connection


      在R语言中使用并行算法的时候,会出现报错,无法连接到核心,即使在本来连接上的时候。通过查阅文献看到了,这是因为“调用核心数--计算机内存”的不匹配造成的。

      如果你的数据集很大,调用了很多核心,那么你的计算机内存如果不够匹配,就会出现连接不上的不错,甚至还出现卡机,一动不动的情况(当然,只要耐心等待,其实他还是会继续运行的...等待的时候会有点长)


解决办法一:调用FORK,window不能...

      FORK适用unix/max,实现内存共享以及节省内存,大数据环境下内存问题报错少

      PSOCK适用所有(一般window都是这个)

      不过调用FORK也还是治标不治本。


解决办法二:分开并行,小步迭代

      譬如10万数据,那么就“2万+2万+2万+2万+2万”的跑,如果还出现脱机,就用之前tryCatch跳过,让损失降低到最小。

      最好的办法了。



参考文献:How-to go parallel in R – basics + tips


——————————————————————————————————


参考文献


1、R语言并行化基础与提高

2、R与并行计算

3、sparklyr包:实现Spark与R的接口,会用dplyr就能玩Spark

4、Sparklyr与Docker的推荐系统实战

5、R语言︱H2o深度学习的一些R语言实践——H2o包

6、R用户的福音︱TensorFlow:TensorFlow的R接口

7、mxnet:结合R与GPU加速深度学习

8、碎片︱R语言与深度学习

版权声明:本文为博主原创文章,转载请注明来源“素质云博客”,谢谢合作!!微信公众号:素质云笔记 https://blog.csdn.net/sinat_26917383/article/details/52719232
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

R︱并行计算以及提高运算效率的方式(parallel包、clusterExport函数、SupR包简介) 的相关文章

  • 查找嵌套列表中元素的索引?

    我有一个类似的列表 mylist lt list a 1 b list A 1 B 2 c list C 1 D 3 是否有一种 无循环 方法来识别元素的位置 例如如果我想用 5 替换 C 的值 并且在哪里找到元素 C 并不重要 我可以这样
  • 简单的数据框重塑

    我刚刚从长时间的写作中断中回到 R 并且在记住如何重塑数据方面遇到了一些实际问题 我知道我想做的事情很容易 但出于某种原因 我今晚很愚蠢 并且将自己与融化和重塑混淆了 如果有人能快速指出我正确的方向 我将不胜感激 我有一个这样的数据框 pe
  • 在 Shiny 中设置一个绘图缩放以匹配另一个绘图缩放

    我正在尝试使用情节重排获取一个图的 x 轴缩放限制 并将它们应用到 Shiny 中的另一个图 到目前为止 我可以从 plot1 x轴限制 获取相关的plotly relayout数据 将其转换 从数字到日期 并在绘制 plot2 之前将其提
  • R - 正则表达式错误(PCRE 版本)

    我正在尝试使用koRpus在 R 中在运行 RHEL6 的 Linux 服务器上进行词形还原 上周 当我安装了 MRO Microsoft R Open 3 2 3 时 下面的代码效果很好 library koRpus lw c danci
  • R从列表中提取数据框,列名中没有前缀

    我在列表中放置了一个数据框 然后 当尝试将其提取回来时 我得到了该数据帧的所有以列表键为前缀的列名称 有没有办法完全按照最初传递的方式提取数据帧 cols lt c column1 Column2 Column3 df1 lt data f
  • 用于清除工作空间和转储存储的 R 全局函数

    我希望创建一个全局函数来清除我的工作区并转储我的内存 我将我的函数称为 cleaner 并希望它执行以下代码 remove list ls gc 我尝试在全局环境中创建该函数 但是当我运行它时 控制台仅打印该函数的文本 在我要获取的函数文件
  • 将值替换为其各自列的名称

    我有一个数据框 Code 401k CVS 101A true 231N true FD54 true 99JB 85F4 true 我试图用相应的列名称 例如 401k 替换 true 字符值 这是我想要的输出 Code 401k CVS
  • 如何在不循环的情况下添加组ID?

    我有数据框 例如 productid ordernum p1 10 p2 20 p3 30 p4 5 p5 20 p6 8 我想添加另一列 称为 groupid 它将产品按顺序分组在一起 一旦 sum ordernum 达到 30 分配一个
  • 如何更新条件公式?

    让我直接进入示例 考虑以下等式 frml lt formula y a b x z 使用这样的公式规范 例如和AER ivreg 我想更新这个公式 使其显示为 frml2 lt y a b c x z w 但是 我不确定如何更新条件标志之前
  • 错误:“rjags”的包或命名空间加载失败

    在终端的 conda 环境之一中 我能够成功安装包 rjags 但是 当我在该环境中运行 R 并运行库 rjags 时 出现以下错误 加载所需的包 coda 错误 rjags 的包或命名空间加载失败 rjags 的 loadNamespac
  • 从 R 中的 HTTPS 连接逐行读取

    当创建连接时open r 它允许逐行读取 这对于批量处理大数据流非常有用 例如这个脚本 https gist github com jeroenooms d33a24958d99bb969ac0通过一次读取 100 行来解析相当大的 gzi
  • 将 sf voronoi 多边形裁剪到边界框时出错

    我正在尝试将 voronoi polygons 使用 sf package 创建 剪辑 到边界框 但它引发了我无法定义的错误 我对 R 的空间世界不太有经验 感谢所有帮助 样本数据 stations lt structure list ST
  • fread 将空导入为 NA

    我正在尝试导入带有空白的 csv 读取为 不幸的是他们都读作 NA now 为了更好地演示问题 我还展示了如何NA NA and 都映射到同一事物 除了最底部的示例 这将妨碍简单的解决方法dt is na dt lt gt write cs
  • 如何将此“for”循环转换为向量解

    这个问题与 将嵌入其他文本的长州名称转换为两个字母的州缩写 https stackoverflow com questions 25582518 convert long state names embedded with other te
  • 如何匹配 R 中的所有匹配项?

    我有 1000 个名字的列表 说A 我还有另外 5 个名字的清单 说B 我想找出这5个名字出现在1000个号码列表中的第几行 例如 Amy 在 A 中可以出现 25 次 B 里有艾米 我想知道 Amy 出现在 A 中的哪些行 我以前使用过
  • ggplot2、R 中的单条形条形图

    我有以下数据和代码 gt ddf var1 var2 1 aa 73 2 bb 18 3 cc 9 gt gt dput ddf structure list var1 c aa bb cc var2 c 73L 18L 9L Names
  • 具有 dplyr、tidyverse 和 broom 的相关矩阵 - P 值矩阵

    全部 我想使用以下方法从相关矩阵中获取 p 值dplyr 和 或扫帚包 并同时测试多个变量 我知道其他方法 但 dplyr 对我来说似乎更简单 更直观 此外 dplyr 需要关联每个变量以获得特定的 p 值 这使得该过程更容易 更快 我检查
  • GGPLOT2:如何在 ggplot() 脚本中绘制特定选择

    这是一个名为的大型数据集的峰值P 其中有 10 个优惠 CS 有不同的商店 SHP 具有多个数值 数据集列出了按周排序的它们 WK 2 tm 52 它创建一个大文件 仅前 6 行出现峰值 WK MND CS SHP RevCY RevLY
  • 替换字符串/文本中“从第 n 次到最后一次”出现的单词

    这个问题以前曾被问过 但尚未得到令提问者满意的答案 https stackoverflow com questions 36368712 how to use stringrs replace all function to replace
  • 非闪亮上下文中的反应式对象绑定

    实际问题 你怎样才能近似反应性环境 行为 http shiny rstudio com tutorial lesson6 建立者shiny http shiny rstudio com函数 或者甚至可能在一个函数中使用这些函数无光泽上下文以

随机推荐

  • 判断玩家是否在敌人的可视范围的方法Physics.OverlapSphere

    Physics OverlapSphere Vector 3 position float radius 该方法判断以一个点为中心 半径为radius的球中的碰撞体集合 所以返回值可以用 var 如var colliders Physics
  • spring mvc 控制器返回 HTML 页面

    之前的页面都是 jsp的 后面需要改为html 如下代码 之前的Log 是 jsp 后面改为 html Log html 页面单独运行正常 但是在控制器跳转是出错 如下 RequestMapping value login out publ
  • HCIPR&S222-V2.5一些总结

    1 IP Precedence取值中 代表immediate的是2 2 VRRP中路由器已经为Master设备 不会被更高优先级的Backup设备抢占 如果出现故障的情况会被Backup设备抢占 故障恢复后重新抢占为Master设备 默认为
  • java jmf视频播放器无法播放视频问题

    初学java 谢了一个参照网上代码写了个java jmf视频播放器 运行调试代码没问题 可是被这个avi视频格式纠结的要死 换了n多个avi格式视频依然不行 经过查阅资料发现现在网上流行的avi格式并不是真正的avi格式 大都是其他格式转化
  • 原生AJAX 的基本使用

    1 准备工作 1 1 安装node js Node js 中文网 1 2 安装express 服务端框架 Express 基于 Node js 平台的 web 应用开发框架 Express 中文文档 Express 中文网 1 2 1 初始
  • MYSQL多表连查

    前言 多表查询 也称为关联查询 指两个或更多个表一起完成查询操作 前提条件 这些一起查询的表之间是有关系的 一对一 一对多 它们之间一定是有关联字段 这个关联字段可能建立了外键 也可能没有建立外键 比如 员工表和部门表 这两个表依靠 部门编
  • 诚邀您参加Go+1.0发布会!与大咖共同探索行业生态!

    你想参与iPhone13抽奖吗 你想和大咖面对面交流吗 你想收获最前沿的行业动态吗 10 月15 日 Go Together Go 1 0发布会暨Go 开发者基金会启动仪式重磅来袭 活动中除七牛云 CEO Go 语言发明人许式伟以及Go 开
  • 传奇私服游戏支付接口申请(已解决)

    传奇游戏是一款经典打怪升级 PK游戏 盛大游戏公司于2001年9月发布 随后出现了众多传奇私服游戏版本 到现在依然受很多人喜爱 经历了多次升级换代 现已转变为游戏体验更加细腻的页游和手游 成为了小成本高收益的热门游戏 受到各游戏服务商和玩家
  • IO流基础总结

    IO流 File 1 File类概述和构造方法 File 它是文件和目录路径名的抽象表示 文件和目录是可以通过File封装成对象的 对于File而言 其封装的并不是一个真正存在的文件 仅仅是一个路径名 而已 它可以是存在的 也可以是不存在的
  • Allegro PCB设计中:结构文件DXF导入、更新、PCB板框更改

    1 将结构工程师输出的DXF文件导入到Allegro PCB设计中 文章来源地址https www yii666 com blog 453846 html action onAll 2 结构文件DXF多次更改导致PCB板框尺寸涉及的修改 1
  • C++STL:vector

    C STL中的vector是一种动态分配的数组 可以在运行时动态增加和删除元素 它也是C 中最常用的容器之一 以下是vector的使用介绍 引入头文件 在使用vector之前 需要添加头文件 include
  • nrm 源管理

    什么是nrm nrm 是一个 npm 源管理器 你可以快速地在 npm源间切换 大家在开发中可能会经常切换 npm 源 我们会使用命令切换 如 npm set registry https registry npm taobao org 或
  • Vue style中的 scoped 属性

    Vue 中存在 scoped 属性 HTML5中也存在一个 scoped 属性 而且 这两者都是针对 css 样式处理的属性 所以很多文章在 解释 Vue scoped 的时候 都会把两者混为一谈 直接进把 HTML5 scoped 的定义
  • Login控件用法,用自己的数据库提供login控件的数据源

    一 在配置web config文件 web config 文件
  • 基于SuperSocket 1.6版本的自定义帧过滤的源码分析(实现MODBUS通信)

    一 SuperSocket 1 6 自定义帧过滤的官方文档地址 http docs supersocket net v1 6 zh CN Implement Your Own Communication Protocol with IReq
  • QT信号槽机制

    信号槽 信号槽是QT中用于对象间通信的一种机制 也是QT的核心机制 在GUI编程中 我们经常需要在改变一个组件的同时 通知另一个组件做出响应 例如 一开始我们的Find按钮是未激活的 用户输入要查找的内容后 查找按钮就被激活 这就是输入框与
  • 细线表格 border-collapse:collapse;/*细线表格,合并边框*/

  • vue3获取reactive代理的target原数组

    使用toRaw获取 可从vue引入toRaw const t3 reactive age name 3 console log toRaw t3 age 官方示例
  • MySQL-SQL全部锁详解(下)

    作者 小刘在C站 个人主页 小刘主页 努力不一定有回报 但一定会有收获加油 一起努力 共赴美好人生 学习两年总结出的运维经验 以及思科模拟器全套网络实验教程 专栏 云计算技术 小刘私信可以随便问 只要会绝不吝啬 感谢CSDN让你我相遇 前言
  • R︱并行计算以及提高运算效率的方式(parallel包、clusterExport函数、SupR包简介)

    终于开始攻克并行这一块了 有点小兴奋 来看看网络上R语言并行办法有哪些 赵鹏老师 R与并行计算 做的总结已经很到位 现在并行可以分为 隐式并行 隐式计算对用户隐藏了大部分细节 用户不需要知道具体数据分配方式 算法的实现或者底层的硬件资源分配