須通り
Sudo Masaaki official site
For the reinstatement of
population ecology.

ホーム | お問い合わせはこちらへ

「もっと先へ......《加速》したくはないか、少年」

ホーム | 統計 Top | C++は未経験だけどRcppで開発したい!(1) 環境構築編

(2015年5月20日執筆開始 2015年8月12日 初版 2016年1月26日 リンク追加)

目次

はじめに

このカテゴリで前回「複数の引数を取るRの関数を反復・並列化するmapplyとclusterMap」という記事を書いた。主にRでの並列計算について解説したものだったが、「ある計算の結果を次の計算に順次代入していく、純然たる繰り返し計算」ではR環境内での高速化に限界があるとともに、C++で実装したコードを呼び出すのが、その解決法の一つであることを最後に述べた。その公約どおり、本記事ではRcppの導入について、とりわけ初心者視点で引っかかった部分に着目しながら紹介してゆく。なお本ページは、それなりの制御構造を持つ関数を素のRで書いたことがあり、かつ汎用プログラミングは素人という超ニッチ層を対象としている。

筆者自身について少し述べておくと、元々は生態学の実験データを集計・解析するためにRを使い始めたクチであり、汎用プログラミングとしてはFLASHやperlを触ったことがある程度だ。つまりコンパイラ言語には馴染みがなく、C++を勉強し始めたのもつい先日、2015年2月中旬である。なんか色々ひどい。Rcppを使い始めた理由は、どうにかして高速なループ計算を行う必要が業務上生じ、かつプロトタイプを既にRで実装済みだったため。

こんな状態でRcppの解説文を物して、あまつさえ天下のインターネッツに公開しようと云うのだから呆れる。だがRcppやその他の並列・高速計算手法について、初学者向けの日本語情報が明らかに不足している現状、稚拙を承知で個人的な試行錯誤の過程を晒す意義は、決して小さくないはずだ。もちろん本記事をご笑覧いただき、私のようなペーペーが躓きがちなポイントを把握した上で、体系的な教科書を執筆してくれる玄人が現れるに越したことはない。

Rcpp関連リンク集

なのでこのページでは、汎用プログラミング初心者を意識した、くどい解説を進めてゆく。しゃらくせえと思う人は下記web情報で各自学習して、どうぞ。

とりあえず目を通しておきたい情報源

Rcpp 使い方 - Rcpp 入門 2015年5月現在、ネットで読める最も包括的な日本語情報。Rcpp環境の構築については同サイトのこちらのページを参照。

Introduction to Rcpp - GitBook 上記サイトの作者が満を持して公開したGitBookでの解説書。超強力。拙稿はもう用済みだなぁ。

Rcppのすゝめ 上記サイトの作者によるslideshareでの解説資料。

Rcpp 俺様備忘録 このページも、C++に馴れていないRユーザーが引っかかりそうな箇所を列挙してくれている。一度目を通しておけば、学習中の些細な知識不足で何日も足止めされるリスクを、多少なりとも低減できるだろう。

Rcpp・inlineパッケージを使ってC++とRを連携させる コンパイラ回りで引っかかったときのために。

{Rcpp}を入れる時はシステム内に既にあるgccに注意 こちらもコンパイラ回りで引っかかったときのために。

Rcpp使って統計処理言語Rのパッケージを楽々作成 Rcppで作った関数などを最終的にパッケージ化する方法。RのコードとCppのコードを両方含むパッケージの作成についてはこちらも参照。

以下は英語の情報で、公式ないし、ある程度包括的な解説を提供し、かつ汎用プログラミングの初心者でも理解可能なものを選んだ。個別のページを列挙はしないものの、stackoverflow.comには大量の質問がサンプルコードと一緒に記載されている。バグ取りで困った際は、出てきたエラーメッセージで検索すれば割となんとかなることが多い。

CRAN - package Rcpp CRANにあるRcppのパッケージ配布サイト。

Rcpp: Seamless R and C++ Integration Rcpp開発者による本家サイト。

Rcpp-introduction.pdf CRANの配布ページにあるVignetteの一つ。Rcppの歴史的経緯を知りたければどうぞ。

Rcpp Gallery: Articles and code examples for the Rcpp package Rcppでの開発事例集。素人目にコードの書き方が見当も付かないときは、まずここでサンプルを探すべし。

Rcpp citation info Rcppを論文に使う時の引用方法。

重要だが初心者向きではない情報源

dirk.eddelbuettel.com Rcpp開発の中心人物であるDirk Eddelbuettel氏のサイト。

Rcpp Class List 上記サイトにあるリファレンス。分かる人向け。

その他

Rcpp - RjpWiki みんな大好きRjpWikiのRcppコーナーだが、今のところはまだリンク集。解説ページとしての今後の充実に期待(だったら自分で編集しろよという突っ込みはさておき)。

準備 1:Rcppをインストールしよう

2015年5月現在、素のRにはRcppの機能は組み込まれていないため、まずはpackage Rcppを導入しよう。R GUIでCRANからバイナリを拾ってきて入れてもいいし、コンソールで

install.packages("Rcpp", dependencies=TRUE)

としてもよい。

このRcppパッケージが行う仕事は、C++で書かれた関数をR環境内から呼び出せるようにするための橋渡しである。とはいえ既存ライブラリを使うだけなら、手元のR環境にpackage Rcppが入っていなくても可能だ。たとえばあなたが、CRANにある適当なRパッケージのバイナリをインストールしたとする。そいつが高速化のため内部的にRcppを使っていたとしても、あなたがパッケージをRから使用する分には、素のRだけで事足りる(皆が何ら意識せずに普段やっていることだ)。

じゃあ、ユーザーが明示的にRcppをロードしなければならない局面とは何か?C++の関数がソースコード、たとえばCpp形式のテキストや、tar.gz形式のパッケージソースとして与えられた場合だ。自ら書いたC++のコードをR環境で実行する(=Rcppで開発を行う)ケースは、もちろんこれに当てはまる。

ネットにある情報を見ると "inline" というパッケージを入れろとも書いてある。これはRのコンソール上で、C++のソースコードをテキストとして記述し、その場でコンパイルして使いたいという人のためのツールである。しかし同等の機能が、既にRcpp内のsourceCpp()関数およびevalCpp()関数として統合されており、そっちを使うほうが便利らしい。どうせ上で dependencies=TRUE を指定しておけばinlineも自動で入るから、気にするこたぁないね(投げやり)。

準備 2:Rのパッケージソースをコンパイル・インストールできる環境を整えよう

パッケージ化するにせよsourceCppから呼び出すにせよ、C++で書いたコードをパソコンで走らせるにはコンパイルが必要だ。Rcppを学ぶには、何をおいてもコンパイラを導入すべし。もちろんR本体はインストール済みで、そのインストール場所を知っており、マシンの適切な管理者権限を持っていることを前提とする。

Windows 7 でのRtoolsを用いたコンパイラ導入

筆者の手元で使えるWindowsのバージョンが他にないので、特化した記述になるがご容赦。既に各種のコンパイラをバリバリ使っている人はお好きな環境でやればいいが、C++そのものが初心者であれば、Rtoolsを使う。これは要するに、Windows上でRの各種パッケージや、はたまたRそのものを、自力でソースからコンパイルするために必要なソフトウェアの集合である。なお細かく言うと、ここに収録されているGCC (the GNU Compiler Collection) というのがコンパイラの実体だ。

お使いのRのバージョンに対応する、最新版のRtoolsインストーラ(exeファイル)をダウンロード。インストール先はデフォルトの c:¥Rtools がいいだろう。「セットアップの種類」「追加タスクの選択」というのも出てくるが、分からなければデフォルトで構わない。大事なのは次の、システム環境変数「Path」を通す作業である。

WindowsでRtoolsとRにパスを通す

Pathの詳細説明は避けるが、早い話Windowsパソコンにおいて使用可能なプログラムが格納されている場所を、システムに教えてあげるための道標だ。ここに登録されているプログラムを呼び出したいとき、exeファイルの名前だけを指定すればシステムが自動的に探し回ってくれるので、カレントディレクトリがコンピュータ上のどの場所にあっても呼び出し可能である(さもないとフルパスで指定する必要がある)。

さて、Pathを変更するには

  1. Windowsスタートメニューの右側にある「ファイル名を指定して実行...」を開き、 SystemPropertiesAdvanced と打込んでOKを押す。
  2. 「詳細設定」タブの「環境変数(N)...」を開く。
  3. windows path edit

    Fig. 1 | Windowsの環境変数設定画面。

  4. 「システム環境変数(U)」という枠の中の変数「Path」をマウスクリックで選択して、直下にある「編集(I)...」ボタンを押す(Fig. 1)。
  5. 全容が見えにくいので、いったん手頃なテキストエディタを開いて、「変数値(V)」の中身を全てコピペしてみると良い。大ざっぱにいうと ; セミコロンで分かれている各部分が、システムに探してほしいディレクトリを表す。Rtools向けに要素を追加するには、

  6. 既存の変数値の末尾に ";C:\Rtools\bin;C:\Rtools\gcc-4.6.3\bin;C:\Program Files\R\R-3.1.1\bin" などと追記して、OKで確定。

追加したパスは3つあり、それぞれの意味は以下の通り。なおRtoolsインストール中の「追加タスクの選択」で "Edit the system PATH." にチェックを付けても編集画面が出るので、そちらで足しても良い。

  • C:\Rtools\bin あなたがインストールしたRtools本体の場所。
  • C:\Rtools\gcc-4.6.3\bin あなたがRtoolに使わせたいコンパイラ(gcc)の在処。具体的には"gcc.exe"のあるフォルダ。適宜読み替えること。
  • C:\Program Files\R\R-3.1.1\bin あなたがR本体をインストールした場所。具体的には"R.exe"のあるフォルダ。適宜読み替えること。

特に初心者が引っかかり易い点として、Rtoolsとgccにはインストール時に自動でパスが通るが、R.exeへのパス通しを失念していることがある。

なお他にも注意すべき点として、以前にgcc等のコンパイラを導入した経験があるコンピュータでは、その古いバージョンがパスの探索で先に引っかかる可能性があり、コンパイラが古くて対応できないヨとRcppに叱られるかもしれない。パスの探索は環境変数の先頭から順に実行されるので、Rtoolsのパスを末尾ではなく先頭に記入するのが一つの解決策である(逆に、他所での作業時にエラーが出る危険性もあるため万能ではないが)。

Windows環境でのRtools試運転

ここまでできたら、景気づけに何か適当なパッケージソースをcranからぶっこ抜いてきて、実際にコンパイルが通ることを確かめよう。とりあえずfortunes: R Fortunesなんぞが良いだろう。Downloads: Package source: fortunes_1.5-2.tar.gz (バージョンが更新されていれば適宜読み替える)というファイルをダウンロードして、適当な場所に配置(Rの作業ディレクトリである必要は全くない)。

次にコマンドプロンプトを開き、このファイルのある場所をカレントディレクトリに。ちなみに最も簡単な方法は、現在のフォルダ上で「Shiftキーを押しながらマウスを右クリック」して、コンテキストメニューから「コマンド ウィンドウをここで開く(W)」とすることだ。そして以下を打ち込む。

R CMD INSTALL --build fortunes_1.5-2.tar.gz

エンターキーを押すとずらずら途中経過が表示されて、
* DONE (fortunes)
という表示が最後に出ればコンパイルおよびインストール成功。
  

あとはR Consoleを普通に立ち上げて、「パッケージの読み込み...」にfortunesがあることを確かめる。まあ何ができるパッケージなのかは、ロードしてfortunes()と打ってみればわかるだろう。なおgzファイルを置いた場所には、fortunes_1.5-2.zipというファイルも作られているはずだ。これはCRAN掲載のWindows binariesデータと本質的には同じで、このzipファイルを保存しておけばコンパイラ環境のない別のWindowsパソコンでも、R GUIの操作で当該パッケージをインストールできる。

Mac OS X でのコンパイラ導入(とトラブルシューティング)

原則としてMac OS 10.9 Mavericksでの作業を想定している。一般には Xcode および、その追加機能である Xcode Command Line Tool なるものを使う。Xcode の入手先は、過去何度も変遷しているが、2015年5月現在はMacの App Store から無料で入手できる(有料だった時期もある)。Command Line Tool の導入方法もさらに迷走していて説明が難しいのだが、こちらのサイトこちらのサイトなどを参考に行っていただきたい。

問題は、ここまでのインストールを済ませたのに sourceCpp() などによるソースの評価時、以下のような警告が出てコンパイルに失敗する場合である。何を隠そう筆者自身もしばしば引っかかった。

        WARNING: The tools required to build C++ code for R were not found.

        Please install Command Line Tools for XCode (or equivalent).

ユーザー固有の環境問題や依存パッケージの有無など、背後に潜んでいる問題は千差万別なので、以下の手順を参考に試してみるとよい。

Command Line Toolsのライセンス条項に同意する

動かない原因としてまず考えられるのがこれ。ターミナルでライセンス条項を読んで同意しないと使えないらしい。そこで、

# 以下のコマンドを打つと、ログインパスワードの入力を求められる。その後ライセンス契約をターミナル上でスペースを押して読んでいき、最後にagreeと打込んでエンター。
sudo xcodebuild -license

必要なツールが本当にインストールされているか不安な場合は、以下の要領でコンパイラのバージョンを調べてみよう。

$ cc --version

#以下のように表示されればおk。
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

$ gcc -v

#以下のように表示されればおk。
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

Mac環境でのコンパイル:sourceCppの試運転

こちらのソースファイルをダウンロードして、Rのカレントディレクトリに配置。

library(Rcpp) # RcppパッッケージをRにロード
sourceCpp("minimum.cpp") # ローカルのC++ソースファイルを評価

この操作によってインストールされる testfunction(x) は、何か適当な整数xを1つだけ引数に取り、その二乗を計算するRの関数である。同等の機能はx^2とすれば演算子一発なので、まあ実用的な価値はないが、環境構築できているか否かの判断にはちょうど良い。

なお、この testfunction(x) は整数でない実数を読み込んでも何やら値を返すが、引数をゼロ方向へ丸めた整数(integer)を処理するので正確な答えにならないことに注意。

外部ライブラリに依存するパッケージをMac環境でコンパイルする

スタンドアロンの関数はコンパイルできるが、ちょっと複雑なコードはお手上げという場合がある。筆者が引っかかった例を挙げると、RcppArmadilloの機能を使う関数をコンパイル・インストールしようとした際、以下のエラーメッセージが出てリンクに失敗した。

ld: library not found for -lgfortran
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [sourceCpp_48342.so] Error 1

このようなケースにも2通りの問題があって、本当に gfortran が存在しない場合と、インストールされているがシンボリックリンクが無いためRcppから見つけられない場合とに大別される。

(たとえばgfortranが入っていない場合)
基本的に、手動で入れる必要がある。以下でバイナリを配布している。
https://gcc.gnu.org/wiki/GFortranBinariesMacOS

# インストール場所については以下の記載あり。
The gfortran package for MacOS X installs all files in the /usr/local/gfortran directory, and a single symbolic link (/usr/local/bin/gfortran).
(gfortranへのシンボリックリンクの張り方)
Rcppのコンパイルオプションの設定ファイルである Makevars に、手動で以下の行を追加する。
FLIBS=-L/usr/local/gfortran

# なお Makevars のファイル実体を見つけるのが一苦労なのだが、Mac OS X の場合は以下の手順となる。
(Finderから) まずメニューの「表示」>「不可視項目を表示」にチェック。この状態で
Macintosh HD > ユーザ > (あなたのユーザ名) >.R
というフォルダを探す。
あるいは (Finderから) メニューの「移動」>「フォルダへ移動...」と選んで、
~/.R
と打っても良い。蛇足だが「不可視項目」はシステムファイルを誤って消さないためにも、普段は非表示にしておくこと。

ここに拡張子なしの Makevars というファイルがあれば、手頃なテキストエディタで開いて編集。なければテキストエディタで新規作成。
# これらの処理が上手く行ったかどうかは、R環境からRcppArmadillo パッケージそのもののコンパイルが通るか否かで判定が可能。
install.packages(c("RcppArmadillo"), type = "source")

まとめ

ひとまず、既存のC++コードをRcpp環境でコンパイルして使えるようにするまでの環境構築を、駆け足で解説してきた。次のページでは、Rcppで自作関数を定義してみる。長くなってきたので一旦筆を置く。