Más contenido relacionado La actualidad más candente (20) Rの高速化2. 自己紹介
所属: 東京理科大学大学院
薬学研究科
修士課程2年 (来年からD進学予定)
専門: バイオインフォマティクス
twitterアカウント: @antiplastics
趣味: バイク、サーフィン、アニメ、読書など
研究内容: マイクロアレイデータからの
発現変動遺伝子の検出
3. 扱っているデータの構造
実験1 実験2 実験3 実験287 実験288 実験289
遺伝子1 1.7 3.9 4.8 4.4 2.5 4.8 実験特異的遺伝子
遺伝子2 -3.3 -0.2 0.2 -4.1 3.1 3.1 発現の検出 など
遺伝子5547 -1.2 4.6 -0.9 4.6 -4.4 1.5
遺伝子5548 1.3 2.7 1.6 6.1 -1.4 3.1
遺伝子5549 2.2 3.2 -1.4 1.3 -3.2 2.0
発現変動遺伝子の検出 など
行 (生物の遺伝子数) 列 (実験データの数)
*原核生物(大腸菌、緑膿菌など) *ますます増加するデータベースへの登録件数
6000gene
*真菌(カビ、酵母など) × *NGS(次世代シーケンサ)の登場
10000gene
*真核生物(ヒト、マウスなど)
20000gene
超多次元、多変量の大規模データ!!
7. 使用するマシン
iMac(21.5inch)
OS: MacOSⅩ10.6.8
SnowLeopard(64bit)
CPU: 2.8GHz
Intel Corei7(コア数:4)
メモリ: 8GB
HDD: 1TB
以下全てのプログラムはこのマシン上
で走らせる事とする。
9. Cのソースコード
#include<stdio.h>
#include<time.h>
#define num_steps 10000000 107という値をとる変数num_stepsを定義
int main(void){
clock_t t1, t2;
t1 = clock();
int i;
double x,pi,sum=0.0,step;
step = 1.0 / (double) num_steps; ステップ = 1/107を定義
for(i = 1;i <= num_steps; i++){
x = (i - 0.5) * step;
sum = sum + 4.0 / (1.0 + x * x);
各ステップ毎に長方形の面積を
} 計算し、最後に和を求める
pi = step * sum;
printf("%f¥n",pi);
t2 = clock();
printf("%f¥n", (double)(t2 - t1) / CLOCKS_PER_SEC);
return(0);
}
10. Perlのソースコード
$t1 = (times)[0];
$num_steps = 10000000;
$step = 1.0 / $num_steps;
for($i = 1;$i <= $num_steps; $i++){
$x = ($i - 0.5) * $step;
$sum = $sum + 4.0 / (1.0 + $x * $x);
}
$pi = $step * $sum;
print $pi;
print "¥n";
$t2 = (times)[0];
$t3 = $t2 - $t1;
print "$t3 秒¥n";
11. Pythonのソースコード
import sys
import time
before = time.time()
num_steps = 10000000
sum = 0
step = 1.0 / num_steps
for i in range(1,num_steps):
x = (i - 0.5) * step
sum = sum + 4.0 / (1.0 + x * x)
pi = step * sum
print pi
print "¥n"
after = time.time()
print "Running Time =", after - before, "s"
12. Rubyのソースコード
require "benchmark"
num_steps = 10000000
step = 1.0 / num_steps
sum = 0
puts Benchmark::CAPTION
puts Benchmark.measure{
for i in 1 .. num_steps
x = (i - 0.5) * step
sum = sum + 4.0 / (1.0 + x * x)
end
pi = step * sum
puts pi
}
13. 結果
ランク 言語 実行時間(s)
1 C 0.15
2 Python 5.19
3 Perl 5.59
4 Ruby 9.12
やはりCは最速。スクリプト言語とCの差は大きい。
14. R <R-2.12.1,64bit> のソースコード
*このくらいのステップ数だと32bitのRは使えなくなるので注意。
before <- proc.time()
num_steps <- 10000000
step <- 1.0 / num_steps
summ <- 0
for(i in 1:num_steps){
x <- (i - 0.5) * step
summ <- summ + 4.0 / (1.0 + x * x)
}
pi <- step * summ
print(pi)
after <- proc.time()
print(after – before)
15. 結果
ランク 言語 実行時間(s)
1 C 0.15
2 Python 5.19
3 Perl 5.59
4 Ruby 9.12
new 5 R 23.28
遅い…orz
16. Rの高速化手法① プログラム修正
before <- proc.time()
num_steps <- 1:10000000 num_stepsを変数からベクトルへ変更
step <- 1.0 / 10000000
x <- (num_steps - 0.5) * step for文をやめて、ベクトルに
pi <- sum((4.0 / (1.0 + x * x))*step) 一度にアクセスするような
書き方をする
print(pi)
after <- proc.time()
print(after - before)
17. 結果
ランク 言語 実行時間(s)
1 C 0.15
new 2 R(プログラム修正) 0.30
3 Python 5.19
4 Perl 5.59
5 Ruby 9.12
6 R 23.28
スクリプト言語をぶち抜きましたwww
19. Rの高速化手法② apply関数の使用
before <- proc.time()
num_steps <- 1:10000000
step <- 1.0 / 10000000
menseki <- function(A){
x <- (A - 0.5) * step
各ステップで長方形の面積を求める計算は、一
y <- 4.0 / (1.0 + x * x)
度関数として定義する
return(y*step)
}
pi <- sum(sapply(num_steps,menseki)) sapplyを使って、配列num_stepsの各要
print(pi) 素に関数mensekiを適用する。
after <- proc.time()
print(after - before)
20. 結果
ランク 言語 実行時間(s)
1 C 0.15
2 R(プログラム修正) 0.30
3 Python 5.19
4 Perl 5.59
5 Ruby 9.12
6 R 23.28
new 7 R(apply) 54.16
かえって遅くなった…。ただし、apply関数を覚
えておくといい事がある(後述)。
21. Rの高速化手法③ 並列化
snowパッケージを使えば、先程のapply関数が並列に計算できる!
applyファミリー snowのでのapplyファミリー
apply() parApply() #行列用
lapply() parLapply() #リスト用
sapply() parSapply() #ベクトル、行列用
mapply() × #グループ化されたデータ用
tapply() × #規則的なリストの作成
× parRapply() #行列の行に対して
× parCapply() #行列の列に対して
× parMM() #行列同士の掛け算
22. Rの高速化手法③ 並列化
before <- proc.time()
library("snow")
library(“Rmpi”) snowによりMPIクラスターを4個生成
cl <- makeCluster(4,type=“MPI")
num_steps <- 1:10000000
step <- 1.0 / 10000000
clusterExport(cl,”step”)
menseki <- function(A){
x <- (A - 0.5) * step
y <- 4.0 / (1.0 + x * x) 各ステップで長方形の面積を求める計算
return(y*step) は、一度関数として定義する
}
snow内で並列化対応したsapplyであ
pi <- sum(parSapply(cl,num_steps,menseki))
print(pi)
るparSapplyを使う
after <- proc.time()
print(after - before)
stopCluster(cl)
23. 結果
ランク 言語 実行時間(s)
1 C 0.15
2 R(プログラム修正) 0.30
3 Python 5.19
4 Perl 5.59
5 Ruby 9.12
new 6 R(snow) 17.35
7 R 23.28
8 R(apply) 54.16
24. Rの高速化手法④ ffパッケージ
Rはメモリを逼迫させる。
→データはハードディスクから、必要に応じてメモリに
ロードしたい。
*ベクトル、行列、因子などのデータ: ffパッケージ
*行列のデータ: bigmemoryパッケージ
しかも上記の2つは並列化まであわせてやってくれる!
25. Rの高速化手法④ ffパッケージ
before <- proc.time()
library(ff)
library(snowfall)
sfInit(parallel=TRUE, cpus=4,type=“MPI") 4つのクラスターを生成
num_steps <-ff(vmode="integer",1:10000000,length=10000000)
step <- 1.0 / 10000000 ff,stepを各クラス
sfLibrary(ff) ターにエクスポート
sfExport("step")
menseki <- function(A){
x <- (A - 0.5) * step
y <- 4.0 / (1.0 + x * x) snowfall内でのsapply()である、
return(y*step) sfSapply()を使う
}
pi <- sum(sfSapply(num_steps,menseki))
print(pi)
after <- proc.time()
print(after - before)
26. 結果
ランク 言語 実行時間(s)
1 C 0.15
2 R(プログラム修正) 0.30
3 Python 5.19
4 Perl 5.59
5 Ruby 9.12
new 6 R(ff) 17.00
7 R(snow) 17.35
8 R 23.28
9 R(apply) 54.16
snowより若干速いくらい
27. Rの高速化手法⑤ バイトコンパイラーの使用
あらかじめ構文解析後の関数にしておく。
人が見ても何しているのかわからない機械語に近い形式になる。
バイトコンパイル後
list(.Code, list(7L, GETVAR.OP, 1L,
LDCONST.OP, 2L, SUB.OP, 3L,
GETVAR.OP, 4L, MUL.OP, 5L,
①library(“compiler”) SETVAR.OP, 6L, POP.OP, LDCONST.OP,
②menseki2 <- cmpfun(menseki) 7L, LDCONST.OP, 8L, GETVAR.OP, 6L,
③disassemble(menseki2) GETVAR.OP, 6L, MUL.OP,
9L, ADD.OP, 10L, DIV.OP, 11L,
SETVAR.OP, 12L, POP.OP, GETVAR.OP,
バイトコンパイル前 12L, GETVAR.OP, 4L, MUL.OP, 13L,
RETURN.OP), list({
menseki <- function(A){ x <- (A - 0.5) * step
x <- (A - 0.5) * step y <- 4/(1 + x * x)
y <- 4.0 / (1.0 + x * x) return(y * step)
}, A, 0.5, A - 0.5, step, (A - 0.5) * step, x, 4, 1,
return(y*step) x * x, 1 +
} x * x, 4/(1 + x * x), y, y * step))
28. Rの高速化手法⑤ バイトコンパイラーの使用
before <- proc.time()
library("compiler")
num_steps <- 1:10000000
step <- 1.0 / 10000000
menseki <- function(A){
x <- (A - 0.5) * step
y <- 4.0 / (1.0 + x * x)
return(y*step)
}
menseki2 <- cmpfun(menseki) バイトコンパイル
pi <- sum(sapply(num_steps,menseki2))
print(pi)
after <- proc.time()
print(after - before)
29. 結果
ランク 言語 実行時間(s)
1 C 0.15
2 R(プログラム修正) 0.30
3 Python 5.19
4 Perl 5.59
5 Ruby 9.12
6 R(ff) 17.00
7 R(snow) 17.35
8 R 23.28
new 9 R(compiler + apply) 41.14
10 R(apply) 54.16
30. 並列化と組み合わせ
ランク 言語 実行時間(s)
1 C 0.15
2 R(プログラム修正) 0.30
3 Python 5.19
4 Perl 5.59
5 Ruby 9.12
new 6 R(compiler + ff) 14.41
new 7 R(compiler + snow) 15.11
8 R(ff) 17.00
9 R(snow) 17.35
10 R 23.28
11 R(compiler + apply) 41.14
12 R(apply) 54.16
32. 最終結果
ランク 言語 実行時間(s)
1 C 0.15
2 R(プログラム修正) 0.30
3 Python 5.19
4 Perl 5.59
5 Ruby 9.12
6 R(compiler + ff) 14.41
7 R(compiler + snow) 15.11
8 R(ff) 17.00
9 R(snow) 17.35
new 10 R(2.14.0) 22.01
11 R 23.28
12 R(compiler + apply) 41.14
13 R(apply) 54.16
33. 時間の関係でできなかった
高速化手法
• Revolution R
インストール時にコア数を勝手に調べて、マルチコア対応に計算を実行してくれる新型R
(Windows、Redhat用)。普通のRより2〜3倍速いという噂。
• RCCコンパイラー
R→C++に変換できます(Windows、Linux用)。
• RDBMSの利用
Rでリレーショナルデータベース(MySQL,PostgreSQL,RODBC,MiniSQL)がいじれます。
• Hadoop,Mapreduceの利用
http://www.slideshare.net/holidayworking/rmapreduce (以前のTokyo.Rのスライド)
• R+クラウドコンピューティング
segue: アマゾンがやっているlapply関数を並列に計算してくれるサービス(Mac,Linux用)。
http://code.google.com/p/segue/