multicore パッケージを利用してマルチコア化してみます。とは言っても、sapply, lapply を mclapply にするだけの簡単なお仕事ですが、せっかくなので testthat を使ってマルチコア化する際にテスト駆動開発で実装していきます。
まずは、そのへんのアップルストアで購入可能な MacBook Air を購入しましょう。今回はこれでやります。Rも Mac 版の dmg を普通にインストールしましょう。次にパッケージをインストールします。
インストールが簡単なのがよいですね。MPIとかそういうものをごちゃごちゃ設定する必要なないです。
今回は非有界区間のモンテカルロ積分によって、標準正規分布の累積分布関数を計算します。まずは for で書きます。
とりあえず、マルチコア化は置いておいて、みんな大好き apply 系関数に書きかえてみましょう。もちろん、まずテストを書きます。set.seed で乱数をシードを固定して、testthat で単体テストします。
前置きが長いですが、いよいよ、multicore 化です。でも先にテスト書きます。 テストが通らないことを確認し、実装します。 テストが通ることを確認してください。では速度比較をしてみます。 4 cores なのですが2倍程度は速くなりました。おもったより unlist のコストがかかってないですね。ちなみにコア数は、
ちなみに 16 CPU cores のマシンで実行したら 6 倍程度の高速化でした。
foreach もありますが、multicore パッケージは、新しい文法を覚える必要がないので便利ですね。常に mclapply 使っておこうか、という気になります。
コードは以下にすべて置いてあります。
https://github.com/dritoshi/learning_multicore_pkg
参考:
CRAN: multicore
Rによる計算機統計学
まずは、そのへんのアップルストアで購入可能な MacBook Air を購入しましょう。今回はこれでやります。Rも Mac 版の dmg を普通にインストールしましょう。次にパッケージをインストールします。
sudo R install.packages(multicore) install.packages(testthat) q()
インストールが簡単なのがよいですね。MPIとかそういうものをごちゃごちゃ設定する必要なないです。
今回は非有界区間のモンテカルロ積分によって、標準正規分布の累積分布関数を計算します。まずは for で書きます。
とりあえず、マルチコア化は置いておいて、みんな大好き apply 系関数に書きかえてみましょう。もちろん、まずテストを書きます。set.seed で乱数をシードを固定して、testthat で単体テストします。
R library("testthat") test_file("test_mci.r")もちろん失敗します。 sapply 版を実装します。 テストが通りました。 リストで返ってくるので、unlist するバージョンも作ります。またテストを書きます。 失敗を確認してから、実装を開始します。 テストが通ります。
前置きが長いですが、いよいよ、multicore 化です。でも先にテスト書きます。 テストが通らないことを確認し、実装します。 テストが通ることを確認してください。では速度比較をしてみます。 4 cores なのですが2倍程度は速くなりました。おもったより unlist のコストがかかってないですね。ちなみにコア数は、
> library(multicore) > multicore:::detectCores()でわかります。
ちなみに 16 CPU cores のマシンで実行したら 6 倍程度の高速化でした。
for sapply sapply.unlist mclappy user.self 9.633 8.722 8.692 0.004 sys.self 0.111 0.300 0.223 0.014 elapsed 9.744 9.021 8.915 1.521 user.child 0.000 0.000 0.000 16.199 sys.child 0.000 0.000 0.000 0.949
foreach もありますが、multicore パッケージは、新しい文法を覚える必要がないので便利ですね。常に mclapply 使っておこうか、という気になります。
コードは以下にすべて置いてあります。
https://github.com/dritoshi/learning_multicore_pkg
参考:
CRAN: multicore
Rによる計算機統計学
foreachは並列計算のバックエンドを選べるのでマルチコア以外の状況(クラスタ化とか)が出てくるときには、バックエンドを変えるだけで対応できるので便利ですね。
返信削除plyr::llply(.parallel=TRUE)とかはforeachをラップしてるので、lapplyと同じ文法で、いろんな並列バックエンドに対応しようと思ったらplyr::llplyも選択肢に入ってきそうです。
ありがとうございます。foreach もいじってみようと思っています。今は core の数だけ R を起動して、GridEngine ようなジョブスケジューラに投げる、という力技をやっているので。
返信削除