R多线程并行计算 待我称王封你为后i 2021-12-03 16:45 323阅读 0赞 先上代码案例: ![1180731-20180830182124232-732349461.png][] 主要的操作: library(parallel);\#加载并行计算包 cl <- makeCluster(8);\# 初始化cpu集群 clusterEvalQ(cl,library(RODBC));\#添加并行计算中用到的包 clusterExport(cl,'variablename');\#添加并行计算中用到的环境变量(如当前上下文中定义的方法) dt <- parApply(cl,stasList, 1, stasPowerPre\_Time);\# apply的并行版本 all\_predata\_time <- do.call('rbind',dt);\# 整合结果 -------------------- **R并行计算相关** # `parallel`包 # <table> <tbody> <tr> <td> <div> 1 </div> </td> <td> <div> <div> <code>library</code> <code>(parallel)</code> </div> </div> </td> </tr> </tbody> </table> <table> <tbody> <tr> <td> <div> 1 </div> </td> <td> <div> <div> <code>#使用 <code>parallel</code>包,首先要初始化一个集群,这个集群的数量最好是你CPU核数-1。如果一台8核的电脑建立了数量为8的集群,那你的CPU就干不了其他事情了。所以可以这样启动一个集群:<br># Calculate the number of cores <br>no_cores <- detectCores() - 1<br># Initiate cluster<br>cl <- makeCluster(no_cores)</code> </div> </div> </td> </tr> </tbody> </table> <table> <tbody> <tr> <td> <div> 1 </div> </td> <td> <div> <div> <code>#现在只需要使用并行化版本的<code>lapply</code>,<code>parLapply</code>就可以了<br>parLapply(cl, 2:4,function(exponent) 2^exponent)</code> </div> </div> </td> </tr> </tbody> </table> <table> <tbody> <tr> <td> <div> 1 </div> </td> <td> <div> <div> <code>#结束后,要记得关闭集群,否则你电脑的内存会始终被R占用<br>stopCluster(cl)</code> </div> </div> </td> </tr> </tbody> </table> ## 变量作用域 ## 在Mac/[Linux][]中你可以使用 `makeCluster(no_core, type="FORK")`这一选项,从而使你并行运行的时候可以包含所有环境变量。 在Windows中由于使用的是Parallel Socket Cluster (PSOCK),所以每个集群只会加载base包,所以你运行时要指定加载特定的包或变量: `cl<-makeCluster(no_cores)` `base <-` `2` `clusterExport(cl,` `"base"` `)` `parLapply(cl,` `2` `:` `4` `,`function(exponent) base^exponent) `stopCluster(cl)` 注意:你需要用`clusterExport(cl, "base")`把base这一个变量加载到集群当中。 如果你在函数中使用了一些其他的包就要使用`clusterEvalQ`加载进去,比如说,使用rms包,那么就用`clusterEvalQ(cl, library(rms))`。 要注意的是,在clusterExport 加载某些变量后,这些变量的任何变化都会被忽略: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> <div> 16 </div> <div> 17 </div> </td> <td> <div> <div> <code>cl<-</code> <code>makeCluster</code> <code>(no_cores)</code> </div> <div> <code>clusterExport</code> <code>(cl, </code> <code>"base"</code> <code>)</code> </div> <div> <code>base <- 4</code> </div> <div> <code># Run</code> </div> <div> <code>parLapply</code> <code>(cl, 2:4, </code> <code>function</code> <code>(exponent) </code> </div> <div> <code> </code> <code>base^exponent) </code> </div> <div> <code># Finish</code> </div> <div> <code>stopCluster</code> <code>(cl)</code> </div> <div> </div> <div> <code>运行结果:</code> </div> <div> <code>[[1]]</code> </div> <div> <code>[1] 4</code> </div> <div> <code> </code> </div> <div> <code>[[2]]</code> </div> <div> <code>[1] 8</code> </div> <div> <code> </code> </div> <div> <code>[[3]]</code> </div> </div> </td> </tr> </tbody> </table> # 使用`parSapply` # 如果你想程序返回一个向量或者矩阵。而不是一个列表,那么就应该使用`sapply`,他同样也有并行版本`parSapply`: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> </td> <td> <div> <div> <code>parSapply</code> <code>(cl, 2:4, </code> </div> <div> <code> </code> <code>function</code> <code>(exponent) </code> </div> <div> <code> </code> <code>base^exponent)</code> </div> <div> </div> <div> <code>[1] 4 8 16</code> </div> </div> </td> </tr> </tbody> </table> 输出矩阵并显示行名和列名(因此才需要使用`as.character`): <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> </td> <td> <div> <div> <code>parSapply</code> <code>(cl, </code> <code>as.character</code> <code>(2:4), </code> </div> <div> <code> </code> <code>function</code> <code>(exponent){ </code> </div> <div> <code> </code> <code>x <- </code> <code>as.numeric</code> <code>(exponent)</code> </div> <div> <code> </code> <code>c</code> <code>(base = base^x, self = x^x)</code> </div> <div> <code> </code> <code>})</code> </div> <div> </div> <div> <code>2 3 4</code> </div> <div> <code>base 4 8 16</code> </div> <div> <code>self 4 27 256</code> </div> </div> </td> </tr> </tbody> </table> # `foreach`包 # 设计`foreach`包的思想可能想要创建一个lapply和for循环的标准,初始化的过程有些不同,你需要`register`注册集群: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> </td> <td> <div> <div> <code>library</code> <code>(foreach)</code> </div> <div> <code>library</code> <code>(doParallel)</code> </div> <div> <code>cl<-</code> <code>makeCluster</code> <code>(no_cores)</code> </div> <div> <code>registerDoParallel</code> <code>(cl)</code> </div> <div> </div> <div> <code>#要记得最后要结束集群(不是用stopCluster()):</code> </div> <div> <code>stopImplicitCluster</code> <code>()</code> </div> </div> </td> </tr> </tbody> </table> foreach函数可以使用参数`.combine`控制你汇总结果的方法: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> <div> 16 </div> <div> 17 </div> <div> 18 </div> <div> 19 </div> <div> 20 </div> <div> 21 </div> <div> 22 </div> <div> 23 </div> <div> 24 </div> <div> 25 </div> <div> 26 </div> <div> 27 </div> <div> 28 </div> <div> 29 </div> </td> <td> <div> <div> <code>foreach</code> <code>(exponent = 2:4, .combine = c) </code> </div> <div> <code> </code> <code>%dopar% </code> </div> <div> <code> </code> <code>base^exponent</code> </div> <div> <code> </code> </div> <div> <code> </code> <code>[1] 4 8 16</code> </code> </div> <div> </div> <div> <code>#-------------------------------------------------</code> </div> <div> <code> </code> <code>foreach</code> <code>(exponent = 2:4, .combine = rbind) </code> </div> <div> <code> </code> <code>%dopar% </code> </div> <div> <code> </code> <code>base^exponent</code> </div> <div> <code> </code> <code>[,1]</code> </div> <div> <code>result.1 4</code> </div> <div> <code>result.2 8</code> </div> <div> <code>result.3 16 </code> </div> <div> </div> <div> </div> <div> <code>#-------------------------------------------------</code> </div> <div> <code> </code> <code>foreach</code> <code>(exponent = 2:4, .combine = list, .multicombine = </code> <code>TRUE</code> <code>) </code> </div> <div> <code> </code> <code>%dopar% </code> </div> <div> <code> </code> <code>base^exponent</code> </div> <div> <code>[[1]]</code> </div> <div> <code>[1] 4</code> </div> <div> <code> </code> </div> <div> <code>[[2]]</code> </div> <div> <code>[1] 8</code> </div> <div> <code> </code> </div> <div> <code>[[3]]</code> </div> <div> <code>[1] 16</code> </div> <div> <code> </code> </div> </div> </td> </tr> </tbody> </table> 注意到最后list的combine方法是默认的。在这个例子中用到一个`.multicombine`参数,他可以帮助你避免嵌套列表。比如说`list(list(result.1, result.2), result.3)` : <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> </td> <td> <div> <div> <code>foreach</code> <code>(exponent = 2:4, .combine = list) </code> </div> <div> <code> </code> <code>%dopar% </code> </div> <div> <code> </code> <code>base^exponent</code> </div> <div> <code>[[1]]</code> </div> <div> <code>[[1]][[1]]</code> </div> <div> <code>[1] 4</code> </div> <div> <code> </code> </div> <div> <code>[[1]][[2]]</code> </div> <div> <code>[1] 8</code> </div> <div> <code> </code> </div> <div> <code> </code> </div> <div> <code>[[2]]</code> </div> <div> <code>[1] 16</code> </div> </div> </td> </tr> </tbody> </table> ## 变量作用域 ## 在foreach中,变量作用域有些不同,它会自动加载本地的环境到函数中: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> </td> <td> <div> <div> <code>base <- 2</code> </div> <div> <code>cl<-</code> <code>makeCluster</code> <code>(2)</code> </div> <div> <code>registerDoParallel</code> <code>(cl)</code> </div> <div> <code>foreach</code> <code>(exponent = 2:4, .combine = c) </code> </div> <div> <code> </code> <code>%dopar% </code> </div> <div> <code> </code> <code>base^exponent</code> </div> <div> <code>stopCluster</code> <code>(cl)</code> </div> <div> </div> <div> <code> </code> <code>[1] 4 8 16</code> </code> </div> </div> </td> </tr> </tbody> </table> 但是,对于父环境的变量则不会加载,以下这个例子就会抛出错误: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> </td> <td> <div> <div> <code>test <- </code> <code>function </code> <code>(exponent) { </code> </div> <div> <code> </code> <code>foreach</code> <code>(exponent = 2:4, </code> </div> <div> <code> </code> <code>.combine = c) %dopar% </code> </div> <div> <code> </code> <code>base^exponent</code> </div> <div> <code>}</code> </div> <div> <code>test</code> <code>()</code> </div> <div> <code> </code> </div> <div> <code> </code> <code>Error </code> <code>in</code> <code>base^exponent : task 1 failed - </code> <code>"object 'base' not found"</code> </div> </div> </td> </tr> </tbody> </table> 为解决这个问题你可以使用`.export`这个参数而不需要使用`clusterExport`。注意的是,他可以加载最终版本的变量,在函数运行前,变量都是可以改变的: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> <div> 16 </div> </td> <td> <div> <div> <code>base <- 2</code> </div> <div> <code>cl<-</code> <code>makeCluster</code> <code>(2)</code> </div> <div> <code>registerDoParallel</code> <code>(cl)</code> </div> <div> <code> </code> </div> <div> <code>base <- 4</code> </div> <div> <code>test <- </code> <code>function </code> <code>(exponent) { </code> </div> <div> <code> </code> <code>foreach</code> <code>(exponent = 2:4, </code> </div> <div> <code> </code> <code>.combine = c,</code> </div> <div> <code> </code> <code>.export = </code> <code>"base"</code> <code>) %dopar% </code> </div> <div> <code> </code> <code>base^exponent</code> </div> <div> <code>}</code> </div> <div> <code>test</code> <code>()</code> </div> <div> <code> </code> </div> <div> <code>stopCluster</code> <code>(cl)</code> </div> <div> <code> </code> </div> <div> <code> </code> <code>[1] 4 8 16</code> </div> </div> </td> </tr> </tbody> </table> 相似的你可以使用`.packages`参数来加载包,比如说:`.packages = c("rms", "mice")` # 使用Fork还是Psock? # 这两个的区别: **FORK**:”to pide in branches and go separate ways” 系统:Unix/Mac (not Windows) 环境: 所有 **PSOCK**:并行socket集群 系统: All (including Windows) 环境: 空 # 内存控制 # 如果你不打算使用windows的话,建议你尝试FORK模式,它可以实现内存共享,节省你的内存。 PSOCK: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> </td> <td> <div> <div> <code>library</code> <code>(pryr) </code> <code># Used for memory analyses</code> </div> <div> <code>cl<-</code> <code>makeCluster</code> <code>(no_cores)</code> </div> <div> <code>clusterExport</code> <code>(cl, </code> <code>"a"</code> <code>)</code> </div> <div> <code>clusterEvalQ</code> <code>(cl, </code> <code>library</code> <code>(pryr))</code> </div> <div> <code>parSapply</code> <code>(cl, X = 1:10, </code> <code>function</code> <code>(x) { </code> <code>address</code> <code>(a)}) == </code> <code>address</code> <code>(a)</code> </div> <div> </div> <div> <code>[1] </code> <code>FALSE</code> <code>FALSE</code> <code>FALSE</code> <code>FALSE</code> <code>FALSE</code> <code>FALSE</code> <code>FALSE</code> <code>FALSE</code> <code>FALSE</code> <code>FALSE</code> </div> </div> </td> </tr> </tbody> </table> FORK : <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> </td> <td> <div> <div> <code>cl<-</code> <code>makeCluster</code> <code>(no_cores, type=</code> <code>"FORK"</code> <code>)</code> </div> <div> <code>parSapply</code> <code>(cl, X = 1:10, </code> <code>function</code> <code>(x) </code> <code>address</code> <code>(a)) == </code> <code>address</code> <code>(a)</code> </div> <div> </div> <div> <code> </code> <code>[1] </code> <code>TRUE</code> <code>TRUE</code> <code>TRUE</code> <code>TRUE</code> <code>TRUE</code> <code>TRUE</code> <code>TRUE</code> <code>TRUE</code> <code>TRUE</code> <code>TRUE</code> </div> </div> </td> </tr> </tbody> </table> 你不需要花费太多时间去配置你的环境,有趣的是,你不需要担心变量冲突: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> </td> <td> <div> <div> <code>b <- 0</code> </div> <div> <code>parSapply</code> <code>(cl, X = 1:10, </code> <code>function</code> <code>(x) {b <- b + 1; b})</code> </div> <div> <code># [1] 1 1 1 1 1 1 1 1 1 1</code> </div> <div> <code>parSapply</code> <code>(cl, X = 1:10, </code> <code>function</code> <code>(x) {b <<- b + 1; b})</code> </div> <div> <code># [1] 1 2 3 4 5 1 2 3 4 5</code> </div> <div> <code>b</code> </div> <div> <code># [1] 0</code> </div> </div> </td> </tr> </tbody> </table> # 调试 # 当你在并行环境中工作是,debug是很困难的,你不能使用`browser`/`cat`/`print`等参数来发现你的问题。 ## `tryCatch`\-`list`方法 ## 使用`stop()`函数这不是一个好方法,因为当你收到一个错误信息时,很可能这个错误信息你在很久之前写的,都快忘掉了,但是当你的程序跑了1,2天后,突然弹出这个错误,就只因为这一个错误,你的程序终止了,并把你之前的做的计算全部扔掉了,这是很讨厌的。为此,你可以尝试使用`tryCatch`去捕捉那些错误,从而使得出现错误后程序还能继续执行: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> </td> <td> <div> <div> <code>foreach</code> <code>(x=</code> <code>list</code> <code>(1, 2, </code> <code>"a"</code> <code>)) %dopar% </code> </div> <div> <code>{ </code> </div> <div> <code> </code> <code>tryCatch</code> <code>({ </code> </div> <div> <code> </code> <code>c</code> <code>(1/x, x, 2^x)</code> </div> <div> <code> </code> <code>}, error = </code> <code>function</code> <code>(e) </code> <code>return</code> <code>(</code> <code>paste0</code> <code>(</code> <code>"The variable '"</code> <code>, x, </code> <code>"'"</code> <code>, </code> </div> <div> <code> </code> <code>" caused the error: '"</code> <code>, e, </code> <code>"'"</code> <code>)))</code> </div> <div> <code>}</code> </div> <div> <code>[[1]]</code> </div> <div> <code>[1] 1 1 2</code> </div> <div> <code> </code> </div> <div> <code>[[2]]</code> </div> <div> <code>[1] 0.5 2.0 4.0</code> </div> <div> <code> </code> </div> <div> <code>[[3]]</code> </div> <div> <code>[1] </code> <code>"The variable 'a' caused the error: 'Error in 1/x: non-numeric argument to binary operator\n'"</code> </div> </div> </td> </tr> </tbody> </table> 这也正是我喜欢list的原因,它可以方便的将所有相关的数据输出,而不是只输出一个错误信息。这里有一个使用`rbind`在`lapply`进行conbine的例子: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> </td> <td> <div> <div> <code>out <- </code> <code>lapply</code> <code>(1:3, </code> <code>function</code> <code>(x) </code> <code>c</code> <code>(x, 2^x, x^x))</code> </div> <div> <code>do.call</code> <code>(rbind, out)</code> </div> <div> <code> </code> <code>[,1] [,2] [,3]</code> </div> <div> <code>[1,] 1 2 1</code> </div> <div> <code>[2,] 2 4 4</code> </div> <div> <code>[3,] 3 8 27</code> </div> </div> </td> </tr> </tbody> </table> ## 创建一个文件输出 ## 当我们无法在控制台观测每个工作时,我们可以设置一个共享文件,让结果输出到文件当中,这是一个想当舒服的解决方案: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> </td> <td> <div> <div> <code>cl<-</code> <code>makeCluster</code> <code>(no_cores, outfile = </code> <code>"debug.txt"</code> <code>)</code> </div> <div> <code>registerDoParallel</code> <code>(cl)</code> </div> <div> <code>foreach</code> <code>(x=</code> <code>list</code> <code>(1, 2, </code> <code>"a"</code> <code>)) %dopar% </code> </div> <div> <code>{ </code> </div> <div> <code> </code> <code>print</code> <code>(x)</code> </div> <div> <code>}</code> </div> <div> <code>stopCluster</code> <code>(cl)</code> </div> <div> </div> <div> <code>starting worker pid=7392 on localhost:11411 at 00:11:21.077</code> </div> <div> <code>starting worker pid=7276 on localhost:11411 at 00:11:21.319</code> </div> <div> <code>starting worker pid=7576 on localhost:11411 at 00:11:21.762</code> </div> <div> <code>[1] 2]</code> </div> <div> <code> </code> </div> <div> <code>[1] </code> <code>"a"</code> </div> </div> </td> </tr> </tbody> </table> ## 创建一个结点专用文件 ## 一个或许更为有用的选择是创建一个结点专用的文件,如果你的数据集存在一些问题的时候,可以方便观测: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> </td> <td> <div> <div> <code>cl<-</code> <code>makeCluster</code> <code>(no_cores, outfile = </code> <code>"debug.txt"</code> <code>)</code> </div> <div> <code>registerDoParallel</code> <code>(cl)</code> </div> <div> <code>foreach</code> <code>(x=</code> <code>list</code> <code>(1, 2, </code> <code>"a"</code> <code>)) %dopar% </code> </div> <div> <code>{ </code> </div> <div> <code> </code> <code>cat</code> <code>(</code> <code>dput</code> <code>(x), file = </code> <code>paste0</code> <code>(</code> <code>"debug_file_"</code> <code>, x, </code> <code>".txt"</code> <code>))</code> </div> <div> <code>} </code> </div> <div> <code>stopCluster</code> <code>(cl)</code> </div> </div> </td> </tr> </tbody> </table> # `partools`包 # `partools`这个包有一个[dbs()][dbs]函数或许值得一看(使用非windows系统值得一看),他允许你联合多个终端给每个进程进行debug。 # Caching # 当做一个大型计算时,我强烈推荐使用一些缓存。这或许有多个原因你想要结束计算,但是要遗憾地浪费了计算的宝贵的时间。这里有一个包可以做缓存,[R.cache][],但是我发现自己写个函数来实现更加简单。你只需要嵌入`digest`包就可以。`digest()`函数是一个散列函数,把一个R对象输入进去可以输出一个md5值或sha1等从而得到一个唯一的key值,当你key匹配到你保存的cache中的key时,你就可以继续你的计算了,而不需要将算法重新运行,以下是一个使用例子: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> <div> 16 </div> <div> 17 </div> <div> 18 </div> <div> 19 </div> <div> 20 </div> <div> 21 </div> </td> <td> <div> <div> <code>cacheParallel <- </code> <code>function</code> <code>(){ </code> </div> <div> <code> </code> <code>vars <- 1:2</code> </div> <div> <code> </code> <code>tmp <- </code> <code>clusterEvalQ</code> <code>(cl, </code> </div> <div> <code> </code> <code>library</code> <code>(digest))</code> </div> <div> <code> </code> </div> <div> <code> </code> <code>parSapply</code> <code>(cl, vars, </code> <code>function</code> <code>(var){ </code> </div> <div> <code> </code> <code>fn <- </code> <code>function</code> <code>(a) a^2</code> </div> <div> <code> </code> <code>dg <- </code> <code>digest</code> <code>(</code> <code>list</code> <code>(fn, var))</code> </div> <div> <code> </code> <code>cache_fn <- </code> </div> <div> <code> </code> <code>sprintf</code> <code>(</code> <code>"Cache_%s.Rdata"</code> <code>, </code> </div> <div> <code> </code> <code>dg)</code> </div> <div> <code> </code> <code>if </code> <code>(</code> <code>file.exists</code> <code>(cache_fn)){ </code> </div> <div> <code> </code> <code>load</code> <code>(cache_fn)</code> </div> <div> <code> </code> <code>}</code> <code>else</code> <code>{ </code> </div> <div> <code> </code> <code>var <- </code> <code>fn</code> <code>(var); </code> </div> <div> <code> </code> <code>Sys.sleep</code> <code>(5)</code> </div> <div> <code> </code> <code>save</code> <code>(var, file = cache_fn)</code> </div> <div> <code> </code> <code>}</code> </div> <div> <code> </code> <code>return</code> <code>(var)</code> </div> <div> <code> </code> <code>})</code> </div> <div> <code>}</code> </div> </div> </td> </tr> </tbody> </table> 这个例子很显然在第二次运行的时候并没有启动Sys.sleep,而是检测到了你的cache文件,加载了上一次计算后的cache,你就不必再计算Sys.sleep了,因为在上一次已经计算过了。 <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> </td> <td> <div> <div> <code>system.time</code> <code>(out <- </code> <code>cacheParallel</code> <code>())</code> </div> <div> <code># user system elapsed</code> </div> <div> <code># 0.003 0.001 5.079</code> </div> <div> <code>out</code> </div> <div> <code># [1] 1 4</code> </div> <div> <code>system.time</code> <code>(out <- </code> <code>cacheParallel</code> <code>())</code> </div> <div> <code># user system elapsed</code> </div> <div> <code># 0.001 0.004 0.046</code> </div> <div> <code>out</code> </div> <div> <code># [1] 1 4</code> </div> <div> <code> </code> </div> <div> <code># To clean up the files just do:</code> </div> <div> <code>file.remove</code> <code>(</code> <code>list.files</code> <code>(pattern = </code> <code>"Cache.+\.Rdata"</code> <code>))</code> </div> </div> </td> </tr> </tbody> </table> # 载入平衡 # ## 任务载入 ## 需要注意的是,无论parLapply还是foreach都是一个包装(wrapper)的函数。这意味着他们不是直接执行并行计算的代码,而是依赖于其他函数实现的。在parLapply中的定义如下: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> </td> <td> <div> <div> <code>parLapply <- </code> <code>function </code> <code>(cl = </code> <code>NULL</code> <code>, X, fun, ...) </code> </div> <div> <code>{ </code> </div> <div> <code> </code> <code>cl <- </code> <code>defaultCluster</code> <code>(cl)</code> </div> <div> <code> </code> <code>do.call</code> <code>(c, </code> <code>clusterApply</code> <code>(cl, x = </code> <code>splitList</code> <code>(X, </code> <code>length</code> <code>(cl)), </code> </div> <div> <code> </code> <code>fun = lapply, fun, ...), quote = </code> <code>TRUE</code> <code>)</code> </div> <div> <code>}</code> </div> </div> </td> </tr> </tbody> </table> 注意到`splitList(X, length(cl))` ,他会将任务分割成多个部分,然后将他们发送到不同的集群中。如果你有很多cache或者存在一个任务比其他worker中的任务都大,那么在这个任务结束之前,其他提前结束的worker都会处于空闲状态。为了避免这一情况,你需要将你的任务尽量平均分配给每个worker。举个例子,你要计算优化神经网络的参数,这一过程你可以并行地以不同参数来训练神经网络,你应该将如下代码: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> </td> <td> <div> <div> <code># From the nnet example</code> </div> <div> <code>parLapply</code> <code>(cl, </code> <code>c</code> <code>(10, 20, 30, 40, 50), </code> <code>function</code> <code>(neurons) </code> </div> <div> <code> </code> <code>nnet</code> <code>(ir[samp,], targets[samp,],</code> </div> <div> <code> </code> <code>size = neurons))</code> </div> </div> </td> </tr> </tbody> </table> 改为: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> </td> <td> <div> <div> <code># From the nnet example</code> </div> <div> <code>parLapply</code> <code>(cl, </code> <code>c</code> <code>(10, 50, 30, 40, 20), </code> <code>function</code> <code>(neurons) </code> </div> <div> <code> </code> <code>nnet</code> <code>(ir[samp,], targets[samp,],</code> </div> <div> <code> </code> <code>size = neurons))</code> </div> </div> </td> </tr> </tbody> </table> ## 内存载入 ## 在大数据的情况下使用并行计算会很快的出现问题。因为使用并行计算会极大的消耗内存,你必须要注意不要让你的R运行内存到达内存的上限,否则这将会导致崩溃或非常缓慢。使用Forks是一个控制内存上限的一个重要方法。Fork是通过内存共享来实现,而不需要额外的内存空间,这对性能的影响是很显著的(我的系统时16G内存,8核心): <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> <div> 16 </div> <div> 17 </div> <div> 18 </div> <div> 19 </div> <div> 20 </div> <div> 21 </div> <div> 22 </div> <div> 23 </div> <div> 24 </div> <div> 25 </div> <div> 26 </div> <div> 27 </div> <div> 28 </div> </td> <td> <div> <div> <code>> </code> <code>rm</code> <code>(list=</code> <code>ls</code> <code>())</code> </div> <div> <code>> </code> <code>library</code> <code>(pryr)</code> </div> <div> <code>> </code> <code>library</code> <code>(magrittr)</code> </div> <div> <code>> a <- </code> <code>matrix</code> <code>(1, ncol=10^4*2, nrow=10^4)</code> </div> <div> <code>> </code> <code>object_size</code> <code>(a)</code> </div> <div> <code>1.6 GB</code> </div> <div> <code>> </code> <code>system.time</code> <code>(</code> <code>mean</code> <code>(a))</code> </div> <div> <code> </code> <code>user system elapsed </code> </div> <div> <code> </code> <code>0.338 0.000 0.337</code> </div> <div> <code>> </code> <code>system.time</code> <code>(</code> <code>mean</code> <code>(a + 1))</code> </div> <div> <code> </code> <code>user system elapsed </code> </div> <div> <code> </code> <code>0.490 0.084 0.574</code> </div> <div> <code>> </code> <code>library</code> <code>(parallel)</code> </div> <div> <code>> cl <- </code> <code>makeCluster</code> <code>(4, type = </code> <code>"PSOCK"</code> <code>)</code> </div> <div> <code>> </code> <code>system.time</code> <code>(</code> <code>clusterExport</code> <code>(cl, </code> <code>"a"</code> <code>))</code> </div> <div> <code> </code> <code>user system elapsed </code> </div> <div> <code> </code> <code>5.253 0.544 7.289</code> </div> <div> <code>> </code> <code>system.time</code> <code>(</code> <code>parSapply</code> <code>(cl, 1:8, </code> </div> <div> <code> </code> <code>function</code> <code>(x) </code> <code>mean</code> <code>(a + 1)))</code> </div> <div> <code> </code> <code>user system elapsed </code> </div> <div> <code> </code> <code>0.008 0.008 3.365</code> </div> <div> <code>> </code> <code>stopCluster</code> <code>(cl); </code> <code>gc</code> <code>();</code> </div> <div> <code>> cl <- </code> <code>makeCluster</code> <code>(4, type = </code> <code>"FORK"</code> <code>)</code> </div> <div> <code>> </code> <code>system.time</code> <code>(</code> <code>parSapply</code> <code>(cl, 1:8, </code> </div> <div> <code> </code> <code>function</code> <code>(x) </code> <code>mean</code> <code>(a + 1)))</code> </div> <div> <code> </code> <code>user system elapsed </code> </div> <div> <code> </code> <code>0.009 0.008 3.123</code> </div> <div> <code>> </code> <code>stopCluster</code> <code>(cl)</code> </div> </div> </td> </tr> </tbody> </table> FORKs可以让你并行化从而不用崩溃: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> </td> <td> <div> <div> <code>> cl <- </code> <code>makeCluster</code> <code>(8, type = </code> <code>"PSOCK"</code> <code>)</code> </div> <div> <code>> </code> <code>system.time</code> <code>(</code> <code>clusterExport</code> <code>(cl, </code> <code>"a"</code> <code>))</code> </div> <div> <code> </code> <code>user system elapsed </code> </div> <div> <code> </code> <code>10.576 1.263 15.877</code> </div> <div> <code>> </code> <code>system.time</code> <code>(</code> <code>parSapply</code> <code>(cl, 1:8, </code> <code>function</code> <code>(x) </code> <code>mean</code> <code>(a + 1)))</code> </div> <div> <code>Error </code> <code>in</code> <code>checkForRemoteErrors</code> <code>(val) : </code> </div> <div> <code> </code> <code>8 nodes produced errors; first error: cannot allocate vector of size 1.5 Gb</code> </div> <div> <code>Timing stopped at: 0.004 0 0.389</code> </div> <div> <code>> </code> <code>stopCluster</code> <code>(cl)</code> </div> <div> <code>> cl <- </code> <code>makeCluster</code> <code>(8, type = </code> <code>"FORK"</code> <code>)</code> </div> <div> <code>> </code> <code>system.time</code> <code>(</code> <code>parSapply</code> <code>(cl, 1:8, </code> <code>function</code> <code>(x) </code> <code>mean</code> <code>(a + 1)))</code> </div> <div> <code> </code> <code>user system elapsed </code> </div> <div> <code> </code> <code>0.014 0.016 3.735</code> </div> <div> <code>> </code> <code>stopCluster</code> <code>(cl)</code> </div> </div> </td> </tr> </tbody> </table> 当然,他并不能让你完全解放,如你所见,当我们创建一个中间变量时也是需要消耗内存的: <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> </td> <td> <div> <div> <code>> a <- </code> <code>matrix</code> <code>(1, ncol=10^4*2.1, nrow=10^4)</code> </div> <div> <code>> cl <- </code> <code>makeCluster</code> <code>(8, type = </code> <code>"FORK"</code> <code>)</code> </div> <div> <code>> </code> <code>parSapply</code> <code>(cl, 1:8, </code> <code>function</code> <code>(x) { </code> </div> <div> <code>+ b <- a + 1</code> </div> <div> <code>+ </code> <code>mean</code> <code>(b)</code> </div> <div> <code>+ })</code> </div> <div> <code>Error </code> <code>in</code> <code>unserialize</code> <code>(node$con) : error reading from connection</code></code> </div> </div> </td> </tr> </tbody> </table> # 内存建议 # 尽量使用rm()避免无用的变量 尽量使用gc()释放内存。即使这在R中是自动执行的,但是当它没有及时执行,在一个并行计算的情况下,如果没有及时释放内存,那么它将不会将内存返回给操作系统,从而影响了其他worker的执行。 通常并行化在大规模运算下很有用,但是,考虑到R中的并行化存在内存的初始化成本,所以考虑到内存的情况下,显然小规模的并行化可能会更有用。 有时候在并行计算时,不断做缓存,当达到上限时,换回串行计算。 你也可以手动的控制每个核所使用的内存数量,一个简单的方法就是:memory.limit()/memory.size() = max cores # 其他建议 # 一个常用的CPU核数检测函数:`max(``1``, detectCores() -``1``)` 永远不要使用`set.seed()`,使用clusterSetRNGStream()来代替设置种子,如果你想重现结果。 如果你有Nvidia 显卡,你可以尝试使用gputools 包进行GPU加速(警告:安装可能会很困难) 当使用[mice并行化][mice]时记得使用`ibind()`来合并项。 **转自:** https://www.2cto.com/kf/201606/517963.html -------------------- # [R中的apply族函数和多线程计算][R_apply] # **一.apply族函数** **1.apply 应用于矩阵和数组** <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> </td> <td> <div> <div> <code># apply</code> </div> <div> <code># 1代表行,2代表列</code> </div> <div> <code># create a matrix of 10 rows x 2 columns</code> </div> <div> <code>m <- </code> <code>matrix</code> <code>(</code> <code>c</code> <code>(1:10, 11:20), nrow = 10, ncol = 2)</code> </div> <div> <code># mean of the rows</code> </div> <div> <code>apply</code> <code>(m, 1, mean)</code> </div> <div> <code>[1] 6 7 8 9 10 11 12 13 14 15</code> </div> <div> <code># mean of the columns</code> </div> <div> <code>apply</code> <code>(m, 2, mean)</code> </div> <div> <code>[1] 5.5 15.5</code> </div> <div> <code># divide all values by 2</code> </div> <div> <code>apply</code> <code>(m, 1:2, </code> <code>function</code> <code>(x) x/2)</code> </div> </div> </td> </tr> </tbody> </table> **2.eapply 应用于环境中的变量** <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> </td> <td> <div> <div> <code># a new environment</code> </div> <div> <code>e <- </code> <code>new.env</code> <code>()</code> </div> <div> <code># two environment variables, a and b</code> </div> <div> <code>e$a <- 1:10</code> </div> <div> <code>e$b <- 11:20</code> </div> <div> <code># mean of the variables</code> </div> <div> <code>eapply</code> <code>(e, mean)</code> </div> <div> <code>$b</code> </div> <div> <code>[1] 15.5</code> </div> <div> <code> </code> </div> <div> <code>$a</code> </div> <div> <code>[1] 5.5</code> </div> </div> </td> </tr> </tbody> </table> **3.lapply应用于列表,返回列表,实际data.frame也是一种list,一种由多个长度相同的向量cbind一起的list:lapply(list, function)** <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> <div> 16 </div> </td> <td> <div> <div> <code>sapply</code> <code>(iris[,1:4],mean)</code> </div> <div> <code>Sepal.Length Sepal.Width Petal.Length Petal.Width</code> </div> <div> <code>5.843333 3.057333 3.758000 1.199333</code> </div> <div> <code> </code> </div> <div> <code>lapply</code> <code>(iris[,1:4],mean)</code> </div> <div> <code>$Sepal.Length</code> </div> <div> <code>[1] 5.843333</code> </div> <div> <code> </code> </div> <div> <code>$Sepal.Width</code> </div> <div> <code>[1] 3.057333</code> </div> <div> <code> </code> </div> <div> <code>$Petal.Length</code> </div> <div> <code>[1] 3.758</code> </div> <div> <code> </code> </div> <div> <code>$Petal.Width</code> </div> <div> <code>[1] 1.199333</code> </div> </div> </td> </tr> </tbody> </table> **4.sapply 是lapply的友好形式.lapply和sapply都可应用于list,data.frame。只是返回的对象类型不一样,前者是list,后者看情况,如果是每一个list下面的元素长度都一样,返回的结果就会被就会简化。举例说明。** <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> <div> 16 </div> <div> 17 </div> </td> <td> <div> <div> <code># 下面两个返回的结果是一样一样的,都是list</code> </div> <div> <code>sapply</code> <code>(iris,unique)</code> </div> <div> <code>lapply</code> <code>(iris,unique)</code> </div> <div> <code> </code> </div> <div> <code># 下面两个前者返回向量,后者返回list</code> </div> <div> <code>sapply</code> <code>(iris[,1:4],mean)</code> </div> <div> <code>lapply</code> <code>(iris[,1:4],mean)</code> </div> <div> <code> </code> </div> <div> <code>#下面两个前者返回data.frame,后者反回list</code> </div> <div> <code>sapply</code> <code>(iris[,1:4], </code> <code>function</code> <code>(x) x/2)</code> </div> <div> <code>lapply</code> <code>(iris[,1:4], </code> <code>function</code> <code>(x) x/2)</code> </div> <div> <code> </code> </div> <div> <code># sapply会根据返回结果,选最合适的对象类型来存放对象,而list反悔的统统都是list</code> </div> <div> <code># 以下两者返回结果一样</code> </div> <div> <code>library</code> <code>(magrittr)</code> </div> <div> <code>lapply</code> <code>(iris[,1:4],mean)%>%</code> <code>unlist</code> <code>()</code> </div> <div> <code>sapply</code> <code>(iris[,1:4],mean)</code> </div> </div> </td> </tr> </tbody> </table> ** 5.vapply要求提供第三个参数,即输出的格式** <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> </td> <td> <div> <div> <code>l <- </code> <code>list</code> <code>(a = 1:10, b = 11:20)</code> </div> <div> <code># fivenum of values using vapply</code> </div> <div> <code>l.fivenum <- </code> <code>vapply</code> <code>(l, fivenum, </code> <code>c</code> <code>(Min.=0, </code> <code>"1st Qu."</code> <code>=0, Median=0, </code> <code>"3rd Qu."</code> <code>=0, Max.=0))</code> </div> <div> <code>class</code> <code>(l.fivenum)</code> </div> <div> <code>[1] </code> <code>"matrix"</code> </div> <div> <code># let's see it</code> </div> <div> <code>l.fivenum</code> </div> <div> <code> </code> <code>a b</code> </div> <div> <code>Min. 1.0 11.0</code> </div> <div> <code>1st Qu. 3.0 13.0</code> </div> <div> <code>Median 5.5 15.5</code> </div> <div> <code>3rd Qu. 8.0 18.0</code> </div> <div> <code>Max. 10.0 20.0</code> </div> </div> </td> </tr> </tbody> </table> **6.replicate** ***Description: “replicate is a wrapper for the common use of sapply for repeated evaluation of an expression (which will usually involve random number generation).”*** <table> <tbody> <tr> <td> <div> 1 </div> </td> <td> <div> <div> <code>replicate</code> <code>(10, </code> <code>rnorm</code> <code>(10))</code> </div> </div> </td> </tr> </tbody> </table> **7.mapply可传递多个参数进去.** **mapply is a multivariate version of [sapply][]. mapply applies FUN to the first elements of each ... argument, the second elements, the third elements, and so on. Arguments are recycled if necessary.** <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> </td> <td> <div> <div> <code>l1 <- </code> <code>list</code> <code>(a = </code> <code>c</code> <code>(1:10), b = </code> <code>c</code> <code>(11:20))</code> </div> <div> <code>l2 <- </code> <code>list</code> <code>(c = </code> <code>c</code> <code>(21:30), d = </code> <code>c</code> <code>(31:40))</code> </div> <div> <code># sum the corresponding elements of l1 and l2</code> </div> <div> <code>mapply</code> <code>(sum, l1$a, l1$b, l2$c, l2$d)</code> </div> <div> <code>[1] 64 68 72 76 80 84 88 92 96 100</code> </div> <div> <code>#mapply像是可以传递多个参数的saply</code> </div> <div> <code>mapply</code> <code>(rep, 1:4, 5)</code> </div> <div> <code>[,1] [,2] [,3] [,4]</code> </div> <div> <code>[1,] 1 2 3 4</code> </div> <div> <code>[2,] 1 2 3 4</code> </div> <div> <code>[3,] 1 2 3 4</code> </div> <div> <code>[4,] 1 2 3 4</code> </div> <div> <code>[5,] 1 2 3 4</code> </div> </div> </td> </tr> </tbody> </table> **8.rapply** **Description: “rapply is a recursive version of lapply.”** <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> <div> 16 </div> <div> 17 </div> <div> 18 </div> <div> 19 </div> <div> 20 </div> <div> 21 </div> <div> 22 </div> <div> 23 </div> <div> 24 </div> <div> 25 </div> <div> 26 </div> <div> 27 </div> <div> 28 </div> <div> 29 </div> <div> 30 </div> <div> 31 </div> </td> <td> <div> <div> <code># let's start with our usual simple list example</code> </div> <div> <code>l <- </code> <code>list</code> <code>(a = 1:10, b = 11:20)</code> </div> <div> <code># log2 of each value in the list</code> </div> <div> <code>rapply</code> <code>(l, log2)</code> </div> <div> <code> </code> <code>a1 a2 a3 a4 a5 a6 a7 a8</code> </div> <div> <code>0.000000 1.000000 1.584963 2.000000 2.321928 2.584963 2.807355 3.000000</code> </div> <div> <code> </code> <code>a9 a10 b1 b2 b3 b4 b5 b6</code> </div> <div> <code>3.169925 3.321928 3.459432 3.584963 3.700440 3.807355 3.906891 4.000000</code> </div> <div> <code> </code> <code>b7 b8 b9 b10</code> </div> <div> <code>4.087463 4.169925 4.247928 4.321928</code> </div> <div> <code># log2 of each value in each list</code> </div> <div> <code>rapply</code> <code>(l, log2, how = </code> <code>"list"</code> <code>)</code> </div> <div> <code>$a</code> </div> <div> <code> </code> <code>[1] 0.000000 1.000000 1.584963 2.000000 2.321928 2.584963 2.807355 3.000000</code> </div> <div> <code> </code> <code>[9] 3.169925 3.321928</code> </div> <div> <code> </code> </div> <div> <code>$b</code> </div> <div> <code> </code> <code>[1] 3.459432 3.584963 3.700440 3.807355 3.906891 4.000000 4.087463 4.169925</code> </div> <div> <code> </code> <code>[9] 4.247928 4.321928</code> </div> <div> <code> </code> </div> <div> <code># what if the function is the mean?</code> </div> <div> <code>rapply</code> <code>(l, mean)</code> </div> <div> <code> </code> <code>a b</code> </div> <div> <code> </code> <code>5.5 15.5</code> </div> <div> <code> </code> </div> <div> <code>rapply</code> <code>(l, mean, how = </code> <code>"list"</code> <code>)</code> </div> <div> <code>$a</code> </div> <div> <code>[1] 5.5</code> </div> <div> <code> </code> </div> <div> <code>$b</code> </div> <div> <code>[1] 15.5</code> </div> </div> </td> </tr> </tbody> </table> **二.多线程计算** **下面用[欧拉问题14][14],来演示R中的向量化编程(利用apply组函数)和多线程** <table> <tbody> <tr> <td> <div> 1 </div> <div> 2 </div> <div> 3 </div> <div> 4 </div> <div> 5 </div> <div> 6 </div> <div> 7 </div> <div> 8 </div> <div> 9 </div> <div> 10 </div> <div> 11 </div> <div> 12 </div> <div> 13 </div> <div> 14 </div> <div> 15 </div> <div> 16 </div> <div> 17 </div> <div> 18 </div> <div> 19 </div> <div> 20 </div> <div> 21 </div> <div> 22 </div> <div> 23 </div> <div> 24 </div> <div> 25 </div> <div> 26 </div> <div> 27 </div> <div> 28 </div> <div> 29 </div> <div> 30 </div> <div> 31 </div> <div> 32 </div> <div> 33 </div> <div> 34 </div> <div> 35 </div> <div> 36 </div> <div> 37 </div> <div> 38 </div> <div> 39 </div> <div> 40 </div> <div> 41 </div> <div> 42 </div> <div> 43 </div> <div> 44 </div> <div> 45 </div> <div> 46 </div> <div> 47 </div> <div> 48 </div> <div> 49 </div> <div> 50 </div> <div> 51 </div> <div> 52 </div> <div> 53 </div> </td> <td> <div> <div> <code>#-----Longest Collatz sequence Problem 14</code> </div> <div> <code>func <- </code> <code>function</code> <code>(x) { </code> </div> <div> <code> </code> <code>n = 1</code> </div> <div> <code> </code> <code>raw <- x</code> </div> <div> <code> </code> <code>while </code> <code>(x > 1) { </code> </div> <div> <code> </code> <code>x <- </code> <code>ifelse</code> <code>(x%%2==0,x/2,3*x+1)</code> </div> <div> <code> </code> <code>n = n + 1</code> </div> <div> <code> </code> <code>}</code> </div> <div> <code> </code> <code>return</code> <code>(</code> <code>c</code> <code>(raw,n))</code> </div> <div> <code>}</code> </div> <div> <code> </code> </div> <div> <code>#方法1 向量化编程</code> </div> <div> <code>library</code> <code>(magrittr)</code> </div> <div> <code>system.time</code> <code>({ </code> </div> <div> <code> </code> <code>x <- 1:1e5</code> </div> <div> <code> </code> <code>res1 <- </code> <code>sapply</code> <code>(x, func)%>%</code> <code>t</code> <code>()</code> </div> <div> <code>})</code> </div> <div> <code> </code> </div> <div> <code>用户 系统 流逝</code> </div> <div> <code>37.960 0.360 41.315</code> </div> <div> <code> </code> </div> <div> <code>#方法2 向量化编程</code> </div> <div> <code>system.time</code> <code>({ </code> </div> <div> <code> </code> <code>x <- 1:1e5</code> </div> <div> <code> </code> <code>res2 <- </code> <code>do.call</code> <code>(</code> <code>'rbind'</code> <code>,</code> <code>lapply</code> <code>(x,func))</code> </div> <div> <code>})</code> </div> <div> <code> </code> </div> <div> <code>用户 系统 流逝</code> </div> <div> <code>36.031 0.181 36.769</code> </div> <div> <code> </code> </div> <div> <code>#方法3 多线程计算</code> </div> <div> <code>library</code> <code>(parallel)</code> </div> <div> <code># 用system.time来返回计算所需时间</code> </div> <div> <code>system.time</code> <code>({ </code> </div> <div> <code> </code> <code>x <- 1:1e5</code> </div> <div> <code> </code> <code>cl <- </code> <code>makeCluster</code> <code>(4) </code> <code># 初始化四核心集群</code> </div> <div> <code> </code> <code>results <- </code> <code>parLapply</code> <code>(cl,x,func) </code> <code># lapply的并行版本</code> </div> <div> <code> </code> <code>res.df <- </code> <code>do.call</code> <code>(</code> <code>'rbind'</code> <code>,results) </code> <code># 整合结果</code> </div> <div> <code> </code> <code>stopCluster</code> <code>(cl) </code> <code># 关闭集群</code> </div> <div> <code>})</code> </div> <div> <code> </code> </div> <div> <code>用户 系统 流逝</code> </div> <div> <code>0.199 0.064 20.038</code> </div> <div> <code> </code> </div> <div> <code># 方法4 for 循环</code> </div> <div> <code>system.time</code> <code>({ </code> </div> <div> <code> </code> <code>m <- </code> <code>matrix</code> <code>(nrow = 0,ncol = 2)</code> </div> <div> <code> </code> <code>for</code> <code>(i </code> <code>in</code> <code>1:1e5){ </code> </div> <div> <code> </code> <code>m <- </code> <code>rbind</code> <code>(m,</code> <code>func</code> <code>(i))</code> </div> <div> <code> </code> <code>}</code> </div> <div> <code>})</code> </div> <div> <code> </code> </div> <div> <code>#方法4用时太长</code> </div> </div> </td> </tr> </tbody> </table> 转载于:https://www.cnblogs.com/purple5252/p/11200729.html [1180731-20180830182124232-732349461.png]: /images/20211203/c6e56bc888f347e08d60d03ff92581e0.png [Linux]: https://www.2cto.com/os/linux/ [dbs]: https://matloff.wordpress.com/2015/01/03/debugging-parallel-code-with-dbs/ [R.cache]: http://cran.r-project.org/web/packages/R.cache/index.html [mice]: http://stackoverflow.com/questions/24040280/parallel-computation-of-multiple-imputation-by-using-mice-r-package/27087791 [R_apply]: https://www.cnblogs.com/litao1105/p/5573373.html [sapply]: http://127.0.0.1:11870/help/library/base/help/sapply [14]: https://projecteuler.net/problem=14
相关 多线程(2)并行和并发 并行(Parallelism)和并发(Concurrency)是计算机科学中两个重要概念,虽然它们在某些情况下可以互换使用,但本质上描述了两种不同的多任务处理方式。 太过爱你忘了你带给我的痛/ 2024年04月24日 23:04/ 0 赞/ 70 阅读
相关 mysql多线程并行查询_mysql并行查询问题 业务表数据量过大分表设计4张,然后需求是将4张表全量数据导出。 测试机器4核,做法是开启4个线程同时查询,最终结果汇总。 如果一个线程查询一张表耗时 2s,那么要实现的是 短命女/ 2023年01月11日 13:17/ 0 赞/ 122 阅读
相关 openmp超线程并行比串行慢_并行计算笔记(001) 并行计算笔记(001)-安装mpi,openmp 动力 需要用高性能计算求解微分方程,这也将是我这接下来三年的学习方向之一。目前以MPI为主,将来肯定会涉及到异构计算。希望 深藏阁楼爱情的钟/ 2023年01月10日 13:24/ 0 赞/ 142 阅读
相关 超线程对多线程并行化的影响 本篇基于 [C++性能优化系列——3D高斯核卷积计算(八)3D高斯卷积][C_3D_3D] 中的代码实现,测试超线程对多线程并行性的影响。 代码实现 测试平台支持8核1 Myth丶恋晨/ 2022年12月11日 12:16/ 0 赞/ 175 阅读
相关 多线程_多线程举例及并行和并发的区别 package cn.itcast_01; / 进程: 正在运行的程序,是系统进行资源分配和调用的独立单位。 雨点打透心脏的1/2处/ 2022年09月27日 06:33/ 0 赞/ 203 阅读
相关 完数的Java多线程并行程序设计-并行计算 目录 1.问题描述... 2 2.算法设计... 2 2.1 串行算法设计... 2 2.2 使用Runnable接口实现并行的算法设计... 3 2.3继承Thre 朴灿烈づ我的快乐病毒、/ 2022年07月16日 13:43/ 0 赞/ 205 阅读
相关 多进程、多线程、并行计算、并发计算、分布式计算的区别 多进程 进程就是正在进行的一个程序或者任务,而负责执行任务的是CPU,执行任务的地方是内存。与程序相比,程序只是一堆代码而已,而程序运行时的过程才是进程;另外同一个程序执 港控/mmm°/ 2022年01月07日 05:33/ 0 赞/ 330 阅读
相关 R多线程并行计算 先上代码案例: ![1180731-20180830182124232-732349461.png][] 主要的操作: library(parallel);\加载并行计算 待我称王封你为后i/ 2021年12月03日 16:45/ 0 赞/ 324 阅读
还没有评论,来说两句吧...