作者gsuper (Logit(odds))
看板R_Language
标题Fw: [笔记] R 的设定-平行运算 (CPU)
时间Sat Mar 30 20:32:45 2013
※ [本文转录自 Statistics 看板 #1D-QxyXv ]
作者: gsuper (统计的巴比伦塔) 看板: Statistics
标题: [问题] R 的设定 (CPU)
时间: Thu Jun 16 15:21:29 2011
请问一下
再 linux 下有没有办法把 CPU 的多个核心分配给 R?
因为我的电脑有8核
可是每次都只有一个 core 跑 100%
是否有办法设定成多核运算?
---------------------------------------
我有查到一个 "multicore" 的 package
可是看起来好难...
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.113.239.247
※ 编辑: gsuper 来自: 140.113.239.247 (06/16 15:27)
1F:推 Wush978:我之前是用Rmpi和snow来跑 06/16 18:56
本篇的 reference
3F:→ gsuper:太好了 sapply 可以这样做应该可以快超多的 谢谢 06/16 19:06
4F:→ gsuper:你说得"乱数相依"是指 seed default 一开始都相同 06/16 19:13
5F:→ gsuper:所以分配给4核的4次随机样本会完全相同的状况吗? 06/16 19:13
6F:推 Wush978:ya, 我记得平行运算在这方面是有问题的 06/16 19:49
7F:→ gsuper:OK~~~ 3Q 06/16 20:06
8F:→ clickhere:no,即便是用不同的seed,还是有乱数相依的问题. 06/16 21:27
9F:→ clickhere:除非是独立的模拟, 否则一般MCMC可能要用parallel的乱数 06/16 21:28
10F:→ clickhere:生成器 SPRNG. google: rsprng 06/16 21:29
11F:→ clickhere:Wush的网志写得很好. 可以改用lam/mpi效能会比mpich2好 06/16 21:31
12F:→ clickhere:很多, 但不确定有windows版. 06/16 21:31
13F:→ clickhere:mpi得注意资料在cpu间的传递,否则有可能会比开4个R慢的. 06/16 21:33
14F:→ clickhere:multicore用得是process的观念,就像是linux多工. 06/16 21:40
15F:→ clickhere:内部用fork产生子程序. windows版要自己编. 06/16 21:41
※ 编辑: gsuper 来自: 140.113.239.247 (06/16 23:21)
16F:→ gsuper:之後玩一玩再整理成笔记 06/17 13:35
笔记开始
-------------------------------------------------------------
先安装 snow 与 Rmpi
在 ubontu 图形介面下 , 直接在
"管理" -> "Synnaptic 安装套件"
分别搜寻
r-cran-Rmpi
r-cran-snow
进行安装
------------------------------------------------------------
http://www.sfu.ca/~sblay/R/snow.html#clusterCall
这是一些 snow 的函式教学
很容易学
主要分成
三个步骤
下面有操作简介
---------------------------------------------------
StepA
cl <- makeCluster(4,type="MPI")
4为想要用的核的数目
type 有很多种
"SOCK","PVM","MPI","NWS" (有空再来学这些东西的意义)
一旦做了以下的指令
library(snow)
cl <- makeCluster(4,type="MPI")
就可以在 top 看到 (linux 的工作管理员)
R 变成 4 组 (平行CPU分配 , 连结成功)
-------------------------------------------------
再来是
StepB
parApply (相同於 apply 的用法 , 但速度比 parCapply 和 parRapply 慢)
parCapply (Column apply , 不需要下 MARGIN=2 的参数)
parRapply ( Row apply , 不需要下 MARGIN=1 的参数)
parSapply
parLapply
这些升级过的函式
重点只有一个
就是在原本的应用方式上
加上一个 cl 变数
比方说
apply ( x,1,paste,collapse="")
parApply (
cl,x,1,paste,collapse="")
parRapply(cl,x, paste,collapse="")
------------------------------------------------
StepC
最後一定要记得下一个指令
stopCluster(cl)
把多核的分配结束掉 (资源吃很大)
若 [R] 不正常中止
也需要去 top 自己把程序 kill 掉
不然会变成殭屍程式
------------------------------------------------
以下是我比较速度的程式
我有8核 , 所以开 2~7核 , 测50次
library(snow)
SPEED <- matrix(0,3,8)
rownames(SPEED) <- c("parRapply","parApply","apply")
colnames(SPEED) <- c(paste(1:8,"CORE",sep="_"))
SPEED_MULTI <- list(NULL)
x <- matrix(sample(c("A","T","C","G"),100000,T),50000,2)
for(k in 1:50)
{
for(g in 2:7)
{
cl <- makeCluster(g,type="MPI")
SPEED[1,g] <- system.time(parRapply(cl,x, paste,collapse=""))[3] #平行
SPEED[2,g] <- system.time(parApply (cl,x,1,paste,collapse=""))[3] #平行
SPEED[3,g] <- system.time( apply ( x,1,paste,collapse=""))[3] #非平行
stopCluster(cl)
print(g)
}
SPEED_MULTI[[k]] <- SPEED
}
PAR_RAPPLY <- t(sapply(SPEED_MULTI,function(tmp){tmp[1,c(-1,-8)]}))
PAR_APPLY <- t(sapply(SPEED_MULTI,function(tmp){tmp[2,c(-1,-8)]}))
---------------------------------------------------------
先从单一次的时间测试可看到
在
速度上 parRapply > parApply > apply
> SPEED
1_CORE 2_CORE 3_CORE 4_CORE 5_CORE 6_CORE 7_CORE 8_CORE
parRapply 0 0.288 0.226 0.277 0.260 0.235 0.311 0
parApply 0 0.353 0.309 0.451 0.444 0.438 0.434 0
apply 0 0.439 0.464 0.709 0.716 0.742 0.706 0
----------------------------------------------------------
从50次的平均速度来看
开3核似乎是最快的
> colMeans(PAR_RAPPLY)
2_CORE 3_CORE 4_CORE 5_CORE 6_CORE 7_CORE
0.31814
0.24738 0.27184 0.26138
0.25736 0.27146
> colMeans(PAR_APPLY)
2_CORE 3_CORE 4_CORE 5_CORE 6_CORE 7_CORE
0.35836 0.31936 0.36772 0.40882 0.42408 0.43074
------------------------------------------------
从 50 次的标准差来看
有时 4核5核 比较稳定
有时 3核7核 比较稳定
没有明显的赢家
> apply(PAR_RAPPLY,2,sd)
2_CORE 3_CORE 4_CORE 5_CORE 6_CORE 7_CORE
0.05133762 0.04803141
0.01216613 0.02597243 0.04290034 0.04530721
> apply(PAR_APPLY,2,sd)
2_CORE 3_CORE 4_CORE 5_CORE 6_CORE 7_CORE
0.04761742
0.04154111 0.05557053 0.05804034 0.04591911
0.02569746
-------------------------------------------------
结论 :
1. 平行运算在速度上
至少可加速一倍
2. 在 Ram 够用的情况下
开3核或6核较好
但推测每台电脑可能会不一样
3. 平均效能
6核 > 5核 > 4核 > 7核的原因可能是
我的8核中 , 1个分配给虚拟机
所以实质上是 7 核
由於 linux 也要1核
所以当我开 7 核平行时
抢占 linux 的资源
因此反而速度下降
4. 依旧不能理解的问题
是为什麽 3核 会比 6核 还快
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 15:59)
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 16:01)
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 16:09)
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 16:09)
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 16:10)
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 16:10)
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 16:10)
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 16:15)
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 16:24)
※ 编辑: gsuper 来自: 140.113.239.247 (06/23 16:26)
17F:→ clickhere:good job 06/24 00:58
18F:→ clickhere:copy x到各别的cpu上需要耗时的. 8不一定快. 06/24 00:58
19F:→ clickhere:paste太简单是另一个原因.再apply中多repeat个几次,3就 06/24 00:59
20F:→ clickhere:不一定比较快了. Memory也是个问题, 8 可能需要swap. 06/24 01:00
21F:→ clickhere:你用mpich or lam/mpi也有影响. mpich要求8个需要同步. 06/24 01:01
22F:→ clickhere:lam/mpi内定是先到先做,做完可以休息,资源可以暂时丢回 06/24 01:02
23F:→ clickhere:给系统(memory release) 06/24 01:02
24F:→ clickhere:另外apply函数可能测不出真正的差异(它内定做太多杂事) 06/24 01:06
25F:推 ADORIAN:这篇要不要考虑收入? 06/24 09:30
※ 编辑: gsuper 来自: 218.160.244.59 (06/25 04:17)
26F:推 ADORIAN:我有寄信给板主请他考虑收录此篇, 但没有任何回应. 06/28 16:25
27F:→ ADORIAN: 尚未得到回应 06/28 16:32
※ 发信站: 批踢踢实业坊(ptt.cc)
※ 转录者: gsuper (140.113.239.247), 时间: 03/30/2013 20:32:45
28F:推 Wush978:已收录至 03/30 23:33
范例 : 计算相关系数
当矩阵极大时 (480000 x 800), 48万 rows, 800 samples (file size = 3.64Gb)
计算相关系数或 distance matrix
将 800 samples 切分
假设 split = 10
切分成 10 个 480000 x 80 小矩阵
where S = S1, S2, ...., S80
彼此两两计算相关系数
where cor(S1,S2)
再合并为1个大相关系数矩阵
则平行运算要开多少核?
split 要下多少才合适?
Ans :
当 split = 5, 需要进行 C5取2 + 5 = 15 次比较
当 split = 10, 需要进行 C10取2 + 10 = 55 次比较
经验法则, 开平行运算时
核心重复使用会拖慢速度 (若核心数低於计算次数, 也等於核心重复使用)
因此, 上述状况,
当 split = 5 时, 给 15 核
当 split = 10 时, 开 55 核
core <- ncol(combn(split,2)) + split
以下为实测结果
######################################################
### spearman (samples = 791)
### Row Core Split Time
### 10w 1 1 160s
### 10w 10 5 81s (insufficient core)
### 10w 10 10 114s (insufficient core)
### 10w 10 15 skip (insufficient core)
### 10w 10 20 skip (insufficient core)
### 10w 20 5 48s (1.x times)
### 10w 20 10 68s (insufficient core)
### 10w 20 15 91s (insufficient core)
### 10w 20 20 116s (insufficient core)
### 10w 40 5 50s (2.x times)
### 10w 40 10 57s (insufficient core)
### 10w 40 15 72s (insufficient core)
### 10w 40 20 88s (insufficient core)
### 10w 60 5 50s (4 times)
### 10w 60 10 47s (1.x times)
### 10w 60 15 68s (insufficient core)
### 10w 60 20 91s (insufficient core)
### 10w 15 5 48s * [best match]
### 10w 21 6 46s * [best match]
### 10w 28 7 39s * [best match]
### 10w 36 8 40s * [best match]
### 10w 45 9 40s * [best match]
### 10w 55 10 43s * [best match]
################################################
实测结果显示
1. 用刚刚好的 cores 数量, 速度最佳, 甚至优於多给 cores
2. split 过大, 对速度没帮助, 吃的核心变多, 浪费资源
3. 当 split 不足时, 切分的小矩阵过大, 仍会有运算压力
4. 承3, 可事前测试各个 function 的最大记忆体耐受值, 即可决定 split number
Note :
我是 AMD64核, 记忆体接近无限
由於 speed of Intel CPU >> AMD CPU , 因此本文不适用於 intel CPU
※ 编辑: gsuper (114.32.201.238), 05/04/2015 16:24:55
############################################################
############################################################
############################################################
# foreach 的用法
# 注意存变数会出问题, 要用 res 这个变数来解决
# 直接用於作图或存出实体档案都相当不错
# 尽量让 loop number %% cores number 能整除
require(doMC)
library(parallel)
registerDoMC(cores = 4)
library(foreach)
res <- foreach(g = 1:ncol(DATA)) %dopar%
{ exprs() }
※ 编辑: gsuper (114.32.201.238), 05/26/2015 14:32:26
※ 编辑: gsuper (114.32.201.238), 05/26/2015 14:33:00
[快速读档]
library(data.table)
fread("./table.txt")
※ 编辑: gsuper (114.32.201.238), 06/05/2015 13:57:07
※ 编辑: gsuper (114.32.201.238), 06/05/2015 13:58:54