18
Rmpi snow 並列処理 2011227岡田 昌史(@mokjpn) 1 2011227日日曜日

Rmpiとsnowで 並列処理

Embed Size (px)

DESCRIPTION

Tokyo Web Mining #10での発表資料です

Citation preview

Page 1: Rmpiとsnowで 並列処理

Rmpiとsnowで並列処理

2011年2月27日岡田 昌史(@mokjpn)

12011年2月27日日曜日

Page 2: Rmpiとsnowで 並列処理

本日の内容

自己紹介

使用したデータとツール

並列化の効果

snowパッケージの具体的な使い方

22011年2月27日日曜日

Page 3: Rmpiとsnowで 並列処理

自己紹介

フリーソフトウェアの統計解析環境 “R”に関する日本語Wikiである、RjpWikiの管理人です

仕事は大学で医学の一分野である「疫学」の講師をしています。

ガジェットマニアです。

32011年2月27日日曜日

Page 4: Rmpiとsnowで 並列処理

データマイニングとの関わり

医学研究で扱うデータは、数十例~せいぜい数百例が中心。そこから古典的な検定をしたり回帰モデルをあてはめて係数の議論をします。

バイオインフォマティクスの人たちは違うけど.....

マイニングは言葉としては知っているけど、遠い世界の話です。

42011年2月27日日曜日

Page 5: Rmpiとsnowで 並列処理

でも....

医学研究に病院のデータを使用するには患者さんの同意が必要ですが、最近大学病院などで、匿名化したデータを研究に利用するための同意を受診者全員にお願いするところが出てきました

一気に数十万件のデータを利用した研究が始まりつつあります

52011年2月27日日曜日

Page 6: Rmpiとsnowで 並列処理

そんなわけで初めて数十万件のデータを扱ってみたところ、いつものコー

ドの書き方じゃ遅い!仕事にならない!

でもこのMac, 8コアじゃん....今度新しく買う予定のなんか、

12コアじゃん....なのにアクティビティモニタでRのCPU使用

率100%で打ち止めってなんか許せん

それじゃ、並列処理っていうのをやってみよう!という

のが、今日のお話です。

62011年2月27日日曜日

Page 7: Rmpiとsnowで 並列処理

使用したデータある病院で, 数年間にわたって蓄積された検査データ, 約50万件(患者数としては5万人強)

各行に, 検査日, 検査結果, 患者ID, 年齢, 性別等が入っています

同じ患者さんのデータが、日付が変わって繰り返し出てきますが、規則性はありません

72011年2月27日日曜日

Page 8: Rmpiとsnowで 並列処理

解析の目的

ある検査値について、2日間以内に0.3以上上昇していた人を抽出する(ある病気の診断)

その日から1年±90日以内にその人のデータがまだあれば、それを抽出する(前記の病気が他の病気の発症につながったかどうかをみる)

82011年2月27日日曜日

Page 9: Rmpiとsnowで 並列処理

難しい点

多くのデータをまず患者(5万人)ごとの時系列データに直さなくては...50万件のデータからの検索、抽出を5万回繰り返す。

患者単位になった表(5万枚)それぞれをなめて、診断をつけて1年後の状態を計算する必要がある。

92011年2月27日日曜日

Page 10: Rmpiとsnowで 並列処理

使用したツール(R使わなきゃよい, というツッコミは無しの方向で...)

患者間のデータは関係しないので、患者ごとの処理は並列化できる

Simple Network of Workstations: snowパッケージのparLapply関数

102011年2月27日日曜日

Page 11: Rmpiとsnowで 並列処理

並列処理のパッケージ

snowは、”SOCK”, “MPI”, “PVM” の並列化方式をサポートしますが, 使っていたのがMac

だったから Leopard以降 OpenMPIがデフォルトで入っている(/usr/bin/mpirunとか) ため、MPIにしてみました。

RではRmpiパッケージを介して使用します。

112011年2月27日日曜日

Page 12: Rmpiとsnowで 並列処理

並列化の効果50万件からsample関数で5万件ランダムサンプリング(患者数は約2万人)した縮小データセットでのsystem.time関数による実測値(Mac Pro,

2.66GHz Quad-Core Xeon), 4コアユーザ システム 経過

並列化しない 35.815 6.944 42.481

4クラスタ 5.226 21.670 26.806

8クラスタ 5.169 28.009 34.398

2クラスタ 7.339 23.668 30.854

122011年2月27日日曜日

Page 13: Rmpiとsnowで 並列処理

snowの使い方> # Rmpiおよびsnowパッケージのインストールは済んでいる前提で

> library(Rmpi)

> library(snow)

> cl <- makeCluster(4, “MPI”)

> # (実際の処理: 後述).....

> stopCluster(cl)

132011年2月27日日曜日

Page 14: Rmpiとsnowで 並列処理

並列処理の書き方all2list <- function(cl, all=fakeall, columns=c("OrderAcceptDate.D","Sex", "Age", "XFT4000", "XQM9800")) { clusterExport(cl,c("all","columns")) # 引数のall, columnsの値を各クラスタで利用可能に

id <- paste("P",unique(all$PatientID),sep="") # 患者ID(数値)をリストのラベルに使いたいので, 先頭に”P”をつける

idlist <- as.list(unique(all$PatientID)) # 生のID値のリストをつくって...

names(idlist) <- id # そのラベル(names)に、”P”をつけた文字列を設定

# 検査データ全体(all)から, 該当する患者(x)のデータのcolumnで指定された列だけを抽出して, 検査日(OrderAcceptDate.D)でソートしたデータフレームを返す無名関数を、患者IDごとにクラスターでまわす parLapply(cl, idlist, function(x) { ctable <- all[which(all$PatientID == x), columns] return(ctable.sorted <- ctable[order(ctable$OrderAcceptDate.D),]) } )}

※ ここで使っている clusterExport関数は、グローバル環境のオブジェクト以外も

exportできるように若干修正しています。(RjpWiki “Rで並列計算”を参照)

142011年2月27日日曜日

Page 15: Rmpiとsnowで 並列処理

データの動き OrderAcceptDate.D XFT4000 XQM9800 Admission Age Sex PatientID1 2008-11-11 NA 1.13 入院 55 F 56642972 2009-09-11 0.95 0.27 入院 61 M 29892333 2010-05-28 0.82 0.92 外来 70 F 32049644 2007-08-27 0.21 1.01 入院 38 F 75037795 2010-02-18 7.26 0.88 入院 73 M 30901356 2010-02-04 0.50 3.30 入院 63 M 7271333

$P2989233

OrderAcceptDate.D Sex Age XFT4000 Admission XQM98002009-01-20 M 60 1.09 外来 0.072009-02-13 M 60 1.06 外来 0.632009-03-03 M 60 0.91 外来 0.272009-09-11 M 61 0.95 入院 0.272010-05-28 M 61 0.92 外来 0.822010-06-25 M 62 1.17 外来 0.332010-06-29 M 62 1.10 外来 6.94

※ID, 値はすべて架空のものに置き換えています152011年2月27日日曜日

Page 16: Rmpiとsnowで 並列処理

難しいところparLapply関数の処理結果は lapply関数と同様にリストで帰ってきます。たとえばfunction(x)の戻り値をデータフレームにすると、前スライドのようなデータフレームのリストです

戻り値が単一の値であれば、unlist関数で素直にvectorに変換できます

連結して1つのデータフレームにしたい場合は、下記のようにrbindで連結するのが便利そうです

クラスター内の処理のデバッグは非常にやりにくいので、parLapplyの代わりにlapplyを使った非クラスターでの処理でデバッグを済ませておくとよいです

# parLapplyの戻り値: result, 連結済みのデータフレームを入れる変数: d d <- data.frame()for(n in names(result)) { if(!is.null(a <- result[[n]] )) { d <<- rbind(d,data.frame(name=n, Sex=a$Sex,Age=a$Age, XFT4000=a$XFT4000)) }}

162011年2月27日日曜日

Page 17: Rmpiとsnowで 並列処理

まとめMacでRな人は, Rmpiとsnowパッケージをインストールすると、今すぐにでも並列化処理を体験できます。

parLapply関数を使えば、lapply関数で行っていた処理をそのまま並列で実行でき、速くなります。

listの操作が多くなるので、リストをベクタに展開するunlist関数, リストの内部要素を$を使わずに取り出す[[ ]] 構文について復習しておくとよいです

172011年2月27日日曜日

Page 18: Rmpiとsnowで 並列処理

宣伝Rmpiとか, snowとか, Rの「パッケージ」50個を各々のヘビーユーザーが紹介+動かせるコードを収録した本を出します

『Rパッケージガイドブック』

著者代表 岡田昌史,B5変形判,並製本,約500ページ, ISBN 978-4-489-02097-1

4月中には書店に並ぶスケジュールで進行中182011年2月27日日曜日