AWSに36コア環境作ってR言語プログラミング

この記事はR Advent Calendar 2015, HashiCorp Advent Calendar 2015, AWS Advent Calendar 2015の19日目です。

ある日のこと

  • ボス: 「オレの書いたR言語スクリプトの実行に時間がかかってしょうがないんだ…」
  • 僕: 「それならAWSできっと解決できますよ!」

僕の考えた最強のR言語プログラミング環境

bigpicture

そこで上図のような環境を作ってみました。R言語プログラミングでのユースケースはスクリプトのバッチ実行とEmacs上でのインタラクティブなプログラミングが挙げられるでしょう。そこでこれらのユースケースをローカルPCで実行するRプログラムではなく、AWS上でリモートに実行できるようにしました。今日ではローカルPCはノートパソコンのような非力な計算資源しか使えないことが多いですが、AWS上であれば最大36コア(c4.8xlarge)までスケールアップすることができます。この環境を”Kick-R”と呼ぶことにします。Kick-RのソースコードはGitHubで公開しています。

Kick-Rのやることは単純です。VMインスタンスの種であるUbuntuのAMIをPackerを使って開いて、R言語関連の環境をインストールし、新たなAMIとしてAWS上に保存します。このR言語環境が追加されたUbuntuAMIをここでは”R AMI”と呼ぶことにします。さらにR AMIをTerraformを使って起動し、ssh接続可能にします。これでどこからでもR環境入りのVMインスタンスにsshログインできるようになりました。このAWS上で起動したR言語実行環境を含むVMインスタンスを”Rインスタンス”と呼ぶことにします。このR環境が不要になったら、R AMIとRインスタンスをいつでもAWS上から削除することができます。使わない時はRインスタンスを削除することでAWSの課金を最小限にすることができます。R AMIは残したままでも課金されることはありません。

一度AWS上にRインスタンスが立ち上がってしまえば、sshを使ってローカルPCからRインスタンスにバッチジョブを投げることもできますし、EmacsのESSモードを使ってEmacsを使ったインタラクティブプログラミングをもAWS上でssh経由のリモート実行することができます。その使い方は後の章で説明します。

ベンチマーク

よくある以下のようなRプログラムを考えましょう。

library(foreach)
library(doParallel)
library(randomForest)
library(kernlab)

data(spam)
cores <- detectCores()
cl <- makeCluster(cores)
registerDoParallel(cl)

system.time(fit.rf <- foreach(ntree = rep(40, 36), .combine = combine,
.export = “spam”, .packages = “randomForest”) %dopar% {
randomForest(type ~ ., data = spam, ntree = ntree)
})

stopCluster(cl)

このスクリプトを:

  • ThinkPad X220で実行すると25.0秒かかるところ…
  • AWS上で実行すると10.5秒で済みます

より実践的なRプログラム(すいません、そのソースコードは社外秘です…)を実行させると以下のようなベンチマーク結果になります。

  • ThinkPad X220上: 555秒
  • AWS上: 84秒

利用シーンと使い方

セットアップ

この作業はKick-Rを使う前に一度だけ実行すれば済みます。まずKick-Rのために必要なパッケージをインストールしてください。

$ sudo apt-get install git make bundler unzip

次にPackerとTerraformをインストールしましょう。

$ cd /usr/local/bin
$ wget https://releases.hashicorp.com/packer/0.8.6/packer_0.8.6_linux_amd64.zip
$ wget https://releases.hashicorp.com/terraform/0.6.7/terraform_0.6.7_linux_amd64.zip
$ sudo unzip -x packer_0.8.6_linux_amd64.zip
$ sudo unzip -x terraform_0.6.7_linux_amd64.zip

AWS鍵を環境変数で指定します。${HOME}/.bashrc などに書いておくと良いでしょう。

$ export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX
$ export AWS_SECRET_ACCESS_KEY=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY

Kick-RのソースコードをGitHubから入手します。

$ git clone https://github.com/centillion-tech/kick-r.git
$ cd kick-r

最後に自分の.emacsファイルでtrampを有効にしておきます。

$ vi ${HOME}/.emacs
(require 'tramp)

これで準備が整いました。以後はこの”kick-r”ディレクトリで作業することにします。

出社

朝会社に出社しました。今日も元気にRプログラミングをはじめましょう。プログラミングの前に重い計算をするためにRインスタンスをAWS上に起動しておきます。チェックアウトした”kick-r”ディレクトリで単にmakeコマンドを実行すればRインスタンスは起動します。ログインに必要なsshの設定はmake ssh-configコマンドで設定します。

$ make
$ make ssh-config > ~/.ssh/config
$ ssh kick-r
ubuntu@ip-10-189-135-202:~$ R --version | head -1
R version 3.0.2 (2013-09-25) -- "Frisbee Sailing"

ちゃんとRインスタンスはAWS上で起動して、少し古いですがR環境も使えるようですね。

インタラクティブプログラミング

Emacs ESSモードを使ってインタラクティブにRスクリプトをデザインしましょう。まずはEmacs上でRを起動します。

emacs-r-1

次にAWS上のRインスタンスへのsshセッションを開始します。”/ssh:kick-r:”と入力しましょう。

emacs-r-2

はじめてsshセッションを作るときには下図のように聞かれるかもしれませんが、yesと答えれば大丈夫です。人生はyesマンでだいたい問題ありません。

emacs-r-3

これでRのプロンプトがEmacs上で表示されました。Emacs上で起動したRはAWS上のRインスタンスで起動していて、ローカルPCとリモートで接続されています。

emacs-r-4

それではこのRプロンプトからグラフを描画してみましょう。

> x <- 1:10
> y <- 1:10
> plot(x, y)

emacs-r-graph

sshを経由してAWS上でRが実行されているにもかかわらず、plot関数はグラフをローカルのPCに表示することができました。これは ${HOME}/.ssh/config にXを転送するように設定されているためです。

バッチ実行

Rスクリプトが完成したら、Emacsで実行するよりRコマンドを直接たたいてバッチ実行した方が便利かもしれません。以下のようにCSVの内容をグラフ描画するようなプログラムをAWS上のRインスタンスで実行してみましょう。makeコマンドのjobターゲットのR変数にはRスクリプトの在処を絶対パスで指定してください。

$ ls examples/batch_job/
plot.R  plot_tfidf.csv
$ cat examples/batch_job/plot.R
data <- read.csv('plot_tfidf.csv', header=T, sep=",")
pdf("plot_result.pdf")
plot(data)
dev.off()
$ cat examples/batch_job/plot_tfidf.csv
  "a",    "b"
0.688, 0.1930
0.701, 0.7370
0.705, 0.6860
0.732, 0.0174
0.341, 0.1390
$ make job R=`pwd`/examples/batch_job/plot.R
$ ls examples/batch_job/
plot.R  plot_result.pdf  plot_tfidf.csv

plot.Rスクリプトはplot_tfidf.csvファイルを読み込んで、その内容をplot_result.pdfに描画します。このとき、このplot.RスクリプトはAWS上のRインスタンスで実行されいるにもかかわらず、plot_tfidf.csvとplot_result.pdfファイルをRインスタンスへ送受信する手間は不要でした。これはKick-Rが裏でこれらのファイルの送受信を自動的に行なってくれるためです。このおかげでRスクリプトをAWS上でバッチ実行する使い勝手はローカルPCでバッチ実行するのと同様にスムーズです。

退社

今日はがんばりました。もう帰ってもよいでしょう。帰る前に余計な課金を避けるためにRインスタンスを落としてしまいましょう。

$ make distclean

これでR AMIとRインスタンスはきれいさっぱりAWS上から削除されました。寝ている間の課金を防止できて、お財布にやさしい生活がおくれます。

もし、R AMIファイルだけは削除せず残しておきたい場合にはdistcleanのかわりにcleanターゲットを使うこともできます。R AMIを作るのには時間がかかるので、この方が明日の朝にすぐRインスタンスを起動できるでしょう。

$ make clean

蛇足

Japan.R 2015で発表するはずだったスライドもあります。将来的にはスケールアップだけでなくクラスタを使ったスケールアウトも検討したいところですが、そのニーズがまだないために対応していません。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中