Hatena::ブログ(Diary)

My Life as a Mock Quant このページをアンテナに追加 RSSフィード Twitter

2012-02-01

Rcpp・inlineパッケージを使ってC++とRを連携させる

| 22:15 | Rcpp・inlineパッケージを使ってC++とRを連携させるを含むブックマーク

「R単体だと遅いので計算のボトルネックC++で書くようにすればいいんじゃないか、せっかくそのためのRcppなる便利パッケージもあるし」とずっと思っていたものの毎回インストール方法を調べることすら億劫がってやっていなかったのですが、前回の記事に書いたバイブル本にその辺りも書いてあったので、ここで一発奮起してやってみることにした。

まずは導入編ということでRcpp・inlineを使うための環境のインストールから。手元のOS等の環境は

とりあえずC++コンパイラ等を勝手に入れてくれるツール・Rtools.exeが必要なので最寄りのミラーである筑波のミラーサイトから自分のインストールしているRのバージョンに合わせたものをダウンロード*1&既定のフォルダにインストール、YES連打で無事に入る。

私と同じようにRをデフォルトインストール先に入れた状態だとこの先の作業で

以下にエラー compileCode(f, code, language = language, verbose = verbose) : 
  Compilation ERROR, function(s)/method(s) not created! cygwin warning:
  MS-DOS style path detected: C:/PROGRA~1/R/R-214~1.1/etc/i386/Makeconf
  Preferred POSIX equivalent is: /cygdrive/c/PROGRA~1/R/R-214~1.1/etc/i386/Makeconf
  CYGWIN environment variable option "nodosfilewarning" turns off this warning.
  Consult the user's guide for more details about POSIX paths:
    http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
g++.exe: C:/Program: No such file or directory
g++.exe: Files/R/R-2.14.1/library/Rcpp/lib/i386/libRcpp.a: No such file or directory

なるエラーにぶつかることになるのですが、「あぁこれは、Rのインストールフォルダにスペース文字があるのがよくないっぽいんだろうな」と思ってググったら皆さんやはり引っかかっていた。しょうがないので既存のRをアンインストールしてC直下にRフォルダを作って「C:\R\R-2.14.1\」フォルダに再インストール

〜追記〜

どうやらR本体というよりもパッケージのインストールフォルダの問題らしい。

情報ありがとうございます!


それから以下のディレクトリにパスを通しておく。これをやっておかないとコンパイルがうまく走らない。RtoolsやRのインストール先が違うなら以下のパスもちょっと違うので注意。特にMinGWは64bit版も同梱されているので64bitOSの方はそっちのほうがいいかも?

  • C:\Rtools\bin
  • C:\Rtools\MinGW\bin
  • C:\R\R-2.14.1\bin

次にRを起動して以下のパッケージをインストール

install.packages("Rcpp")
install.packages("inline")

これで動く状態まで持っていけたので、適当なサンプルコードを動かしてみる。

library(Rcpp)
library(inline)
src <- '
  Rcpp::NumericVector xa(a);
  Rcpp::NumericVector xb(b);
  int n_xa = xa.size(), n_xb = xb.size();
  Rcpp::NumericVector xab(n_xa + n_xb - 1);
  for (int i = 0; i < n_xa; i++){
    for (int j = 0; j < n_xb; j++){
      xab[i + j] += xa[i] * xb[j];
    }
  }
  return xab;
'
fun <- cxxfunction(signature(a = "numeric", b = "numeric"), src, plugin = "Rcpp")

これは

”R上にRcppパッケージを使ったC++のコードを文字列として書いておいて、それをinlineパッケージのcxxfunction関数に食わせることによってそのままDLLとしてコンパイル、更に自動でR上へロードしてそれをfun関数として割り当てる”までやってもらってるってことに該当する。すごい!!!

そして実行すると、なんか警告は出てるけど

> fun <- cxxfunction(signature(a = "numeric", b = "numeric"), src, plugin = "Rcpp")
cygwin warning:
  MS-DOS style path detected: C:/R/R-214~1.1/etc/i386/Makeconf
  Preferred POSIX equivalent is: /cygdrive/c/R/R-214~1.1/etc/i386/Makeconf
  CYGWIN environment variable option "nodosfilewarning" turns off this warning.
  Consult the user's guide for more details about POSIX paths:
    http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
> fun(1:3, 1:4)
[1]  1  4 10 16 17 12

と所望の結果となる。ここで出てきた警告を消すためには警告メッセージ本文中に

CYGWIN environment variable option "nodosfilewarning" turns off this warning.」

とあるように環境変数CYGWINに”nodosfilewarning”という値を設定すればOKだった。

f:id:teramonagi:20120207081231p:image

ここまでできれば後は以下のDirk氏の資料

を読んでおけばいいのかと。さらにちょっと調べたら上の資料も含めてvignetteとして大量に資料が配布されているのがわかった。以下がそのリストでR上で実行すると当該資料がPDFビューアーで起動します。「Rを使いつつもちょこっとC++で書こうかな?」くらいのライトユーザーならvignette("Rcpp-quickref")のクイックリファレンスを見るのが良さげです。

vignette("Rcpp-FAQ")
vignette("Rcpp-extending")
vignette("Rcpp-introduction")
vignette("Rcpp-modules")
vignette("Rcpp-package")
vignette("Rcpp-quickref")
vignette("Rcpp-sugar")

*1:私はRtools214.exeを落とした