Rの高速化

33
Rの高速化 Kashiwa.R#11 / 11 / 11 @antiplastics

Transcript of Rの高速化

Page 1: Rの高速化

Rの高速化

Kashiwa.R#1

11 / 11 / 11

@antiplastics

Page 2: Rの高速化

自己紹介

所属:

東京理科大学大学院

薬学研究科

修士課程2年

(来年からD進学予定)

専門: バイオインフォマティクス

twitterアカウント:

@antiplastics

趣味: バイク、サーフィン、アニメ、読書など

研究内容: マイクロアレイデータからの

発現変動遺伝子の検出

Page 3: Rの高速化

扱っているデータの構造

行 (生物の遺伝子数)*原核生物(大腸菌、緑膿菌など)

6000gene*真菌(カビ、酵母など)

10000gene

*真核生物(ヒト、マウスなど)

20000gene

列 (実験データの数)

*ますます増加するデータベースへの登録件数

*NGS(次世代シーケンサ)の登場

超多次元、多変量の大規模データ!!

×

実験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

実験特異的遺伝子

発現の検出

など

発現変動遺伝子の検出

など

Page 4: Rの高速化

データ解析の現場の実情

動画

Page 5: Rの高速化

遅い!!!

(ノ; _ ;)ノ ┫:・'.::結果待ちに数日かかる事もたびたび。

計算が速く終わるかどうかは死活問題。

Page 6: Rの高速化

Rはパッケージがとても豊富。

library(“hogehoge”)とか打ったら小難しい計算も、関数が勝 手にやってくれるからコード行数も少なくて済む。

めちゃくちゃ便利!

だが現実問題これだけ遅いと、やってられない時も。

→Rを高速化させて、サクサク研究を進めたい!!

→速くしようと思ったらどこまで速くなるかをみてみよう。

Page 7: Rの高速化

使用するマシン

iMac(21.5inch)OS:

MacOSⅩ10.6.8SnowLeopard(64bit)

CPU:

2.8GHz Intel Corei7(コア数:4)

メモリ:

8GBHDD:

1TB

以下全てのプログラムはこのマシン上 で走らせる事とする。

Page 8: Rの高速化

比較する計算

以下の数値積分(中点法)により近時的に円周率 πを求める。

N(ステップ数)が増すほど精度が上がる

今回は1千万(107)ステップで計算する

Page 9: Rの高速化

Cのソースコード#include<stdio.h>#include<time.h>#define num_steps 10000000

int main(void){clock_t t1, t2;

t1 = clock();int i;double x,pi,sum=0.0,step;step = 1.0 / (double) 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;printf("%f¥n",pi);t2 = clock();

printf("%f¥n", (double)(t2 - t1) / CLOCKS_PER_SEC);return(0);

}

107という値をとる変数num_stepsを定義

ステップ

= 1/107を定義

各ステップ毎に長方形の面積を

計算し、最後に和を求める

Page 10: Rの高速化

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";

Page 11: Rの高速化

Pythonのソースコードimport sysimport timebefore = time.time()num_steps = 10000000sum = 0step = 1.0 / num_steps

for i in range(1,num_steps):x = (i - 0.5) * stepsum = sum + 4.0 / (1.0 + x * x)

pi = step * sumprint piprint "¥n"

after = time.time()print "Running Time =", after - before, "s"

Page 12: Rの高速化

Rubyのソースコードrequire "benchmark"num_steps = 10000000step = 1.0 / num_stepssum = 0

puts Benchmark::CAPTIONputs Benchmark.measure{

for i in 1 .. num_stepsx = (i - 0.5) * stepsum = sum + 4.0 / (1.0 + x * x)

endpi = step * sumputs pi}

Page 13: Rの高速化

結果

ランク 言語 実行時間(s)1 C 0.152 Python 5.193 Perl 5.594 Ruby 9.12

やはりCは最速。スクリプト言語とCの差は大きい。

Page 14: Rの高速化

R <R-2.12.1,64bit> のソースコード

before <- proc.time()

num_steps <- 10000000step <- 1.0 / num_stepssumm <- 0for(i in 1:num_steps){

x <- (i - 0.5) * stepsumm <- summ + 4.0 / (1.0 + x * x)

}pi <- step * summprint(pi)

after <- proc.time()print(after – before)

*このくらいのステップ数だと32bitのRは使えなくなるので注意。

Page 15: Rの高速化

結果

ランク 言語 実行時間(s)1 C 0.152 Python 5.193 Perl 5.594 Ruby 9.125 R 23.28new

遅い…orz

Page 16: Rの高速化

Rの高速化手法① プログラム修正

before <- proc.time()

num_steps <- 1:10000000step <- 1.0 / 10000000

x <- (num_steps - 0.5) * steppi <- sum((4.0 / (1.0 + x * x))*step)

print(pi)

after <- proc.time()print(after - before)

num_stepsを変数からベクトルへ変更

for文をやめて、ベクトルに

一度にアクセスするような

書き方をする

Page 17: Rの高速化

結果

ランク 言語 実行時間(s)1 C 0.152 R(プログラム修正) 0.303 Python 5.194 Perl 5.595 Ruby 9.126 R 23.28

new

スクリプト言語をぶち抜きましたwww

Page 18: Rの高速化

Rの高速化手法②

apply関数の使用

apply関数ファミリー

①で行なったベクトル、行列に同時にアクセス

するような計算を、より明示的にできる関数。入

力データの型、出力データの型の違いなどで、

apply(),lapply(), sapply(), mapply(), tapply() がある。

Page 19: Rの高速化

Rの高速化手法②

apply関数の使用

before <- proc.time()

num_steps <- 1:10000000step <- 1.0 / 10000000

menseki <- function(A){x <- (A - 0.5) * stepy <- 4.0 / (1.0 + x * x)return(y*step)

}

pi <- sum(sapply(num_steps,menseki))print(pi)

after <- proc.time()print(after - before)

各ステップで長方形の面積を求める計算は、一

度関数として定義する

sapplyを使って、配列num_stepsの各要

素に関数mensekiを適用する。

Page 20: Rの高速化

結果ランク 言語 実行時間(s)

1 C 0.152 R(プログラム修正) 0.303 Python 5.194 Perl 5.595 Ruby 9.126 R 23.287 R(apply) 54.16new

かえって遅くなった…。ただし、apply関数を覚 えておくといい事がある(後述)。

Page 21: Rの高速化

Rの高速化手法③ 並列化snowパッケージを使えば、先程のapply関数が並列に計算できる!

applyファミリー

snowのでのapplyファミリー

apply() parApply() #行列用

lapply() parLapply() #リスト用

sapply() parSapply() #ベクトル、行列用

mapply() ×

#グループ化されたデータ用

tapply() ×

#規則的なリストの作成

×

parRapply() #行列の行に対して

×

parCapply() #行列の列に対して

×

parMM() #行列同士の掛け算

Page 22: Rの高速化

Rの高速化手法③ 並列化before <- proc.time()library("snow")library(“Rmpi”)cl <- makeCluster(4,type=“MPI")

num_steps <- 1:10000000step <- 1.0 / 10000000clusterExport(cl,”step”)

menseki <- function(A){x <- (A - 0.5) * stepy <- 4.0 / (1.0 + x * x)return(y*step)

}

pi <- sum(parSapply(cl,num_steps,menseki))print(pi)

after <- proc.time()print(after - before)stopCluster(cl)

snowによりMPIクラスターを4個生成

各ステップで長方形の面積を求める計算

は、一度関数として定義する

snow内で並列化対応したsapplyであ

るparSapplyを使う

Page 23: Rの高速化

結果

ランク 言語 実行時間(s)

1 C 0.152 R(プログラム修正) 0.303 Python 5.194 Perl 5.595 Ruby 9.126 R(snow) 17.357 R 23.288 R(apply) 54.16

new

Page 24: Rの高速化

Rの高速化手法④ ffパッケージ

Rはメモリを逼迫させる。

→データはハードディスクから、必要に応じてメモリに ロードしたい。

*ベクトル、行列、因子などのデータ:

ffパッケージ*行列のデータ:

bigmemoryパッケージ

しかも上記の2つは並列化まであわせてやってくれる!

Page 25: Rの高速化

Rの高速化手法④ ffパッケージ

before <- proc.time()library(ff)library(snowfall)sfInit(parallel=TRUE, cpus=4,type=“MPI")num_steps <-ff(vmode="integer",1:10000000,length=10000000)

step <- 1.0 / 10000000sfLibrary(ff)sfExport("step")

menseki <- function(A){x <- (A - 0.5) * stepy <- 4.0 / (1.0 + x * x)return(y*step)

}pi <- sum(sfSapply(num_steps,menseki))print(pi)

after <- proc.time()print(after - before)

4つのクラスターを生成

ff,stepを各クラス

ターにエクスポート

snowfall内でのsapply()である、

sfSapply()を使う

Page 26: Rの高速化

結果ランク 言語 実行時間(s)

1 C 0.152 R(プログラム修正) 0.303 Python 5.194 Perl 5.595 Ruby 9.126 R(ff) 17.007 R(snow) 17.358 R 23.289 R(apply) 54.16

new

snowより若干速いくらい

Page 27: Rの高速化

Rの高速化手法⑤

バイトコンパイラーの使用

menseki <- function(A){x <- (A - 0.5) * stepy <- 4.0 / (1.0 + x * x)return(y*step)

}

list(.Code, list(7L, GETVAR.OP, 1L, LDCONST.OP, 2L, SUB.OP, 3L,

GETVAR.OP, 4L, MUL.OP, 5L, SETVAR.OP, 6L, POP.OP, LDCONST.OP,

7L, LDCONST.OP, 8L, GETVAR.OP, 6L, 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({

x <- (A - 0.5) * stepy <- 4/(1 + x * x)return(y * step)

}, A, 0.5, A - 0.5, step, (A - 0.5) * step, x, 4, 1, x * x, 1 +

x * x, 4/(1 + x * x), y, y * step))

①library(“compiler”)②menseki2 <- cmpfun(menseki)③disassemble(menseki2)

バイトコンパイル前

バイトコンパイル後

あらかじめ構文解析後の関数にしておく。

人が見ても何しているのかわからない機械語に近い形式になる。

Page 28: Rの高速化

Rの高速化手法⑤

バイトコンパイラーの使用

before <- proc.time()library("compiler")

num_steps <- 1:10000000step <- 1.0 / 10000000

menseki <- function(A){x <- (A - 0.5) * stepy <- 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)

バイトコンパイル

Page 29: Rの高速化

結果

ランク 言語 実行時間(s)

1 C 0.152 R(プログラム修正) 0.303 Python 5.194 Perl 5.595 Ruby 9.126 R(ff) 17.007 R(snow) 17.358 R 23.289 R(compiler + apply) 41.1410 R(apply) 54.16

new

Page 30: Rの高速化

並列化と組み合わせランク 言語 実行時間(s)

1 C 0.152 R(プログラム修正) 0.303 Python 5.194 Perl 5.595 Ruby 9.126 R(compiler + ff) 14.417 R(compiler + snow) 15.118 R(ff) 17.009 R(snow) 17.3510 R 23.2811 R(compiler + apply) 41.1412 R(apply) 54.16

new

new

Page 31: Rの高速化

Rの高速化手法⑥

R-2.14.0最新VerのR-2.14.0はかなり速い。

*全ての基本パッケージの関数があらかじめ、バ イトコンパイルされているとか

R-2.4.0 30.1s

R-2.8.0 30.8s

R-2.9.10 31.7s

R-2.10.0 31.7s

R-2.11.0 24.2s

R-2.12.1 23.28s

R-2.13.2 24.4s

R-2.14.0 ?

の順

64bit化

バイトコンパイル化

Page 32: Rの高速化

最終結果ランク 言語 実行時間(s)

1 C 0.152 R(プログラム修正) 0.303 Python 5.194 Perl 5.595 Ruby 9.126 R(compiler + ff) 14.417 R(compiler + snow) 15.118 R(ff) 17.009 R(snow) 17.3510 R(2.14.0) 22.0111 R 23.2812 R(compiler + apply) 41.1413 R(apply) 54.16

new

Page 33: Rの高速化

時間の関係でできなかった 高速化手法

• 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/