SlideShare une entreprise Scribd logo
1  sur  22
Télécharger pour lire hors ligne
R と C/C++ の連携

     福島真太朗
 第 7 回 R 勉強会@東京
   2010 年 7 月 24 日



     Made with OpenOffice.org   1
自己紹介
 出身:埼玉県
 職業:コンサルタント
      主に金融工学のデータ解析・モデル構築等
 使用言語: R, C, C++, Java, Awk, Perl
 Twitter : @sfchaos




              Made with OpenOffice.org   2
発表の流れ

1.本発表の目標
2.R からの C/C++ の利用
3.C++ からの R の利用




              Made with OpenOffice.org   3
1. 本発表の目標
      将来こんな問題に直面するかも・・・

      蓄積してきた                        R では遅い処理を
  C/C++ のライブラリを                      C/C++ に任せて
       活用したい                          高速化したい



  R                                       C/C++




  R と C/C++ の連携させる基本的な方法を学ぶ
             Made with OpenOffice.org             4
2.R からの C/C++ の利用

R から C/C++ を利用する方法として,
主に2種類の方法が用いられる.
    .C() 関数を利用する方法
    .Call() 関数を利用する方法




           Made with OpenOffice.org   5
考える問題
2 つの多項式

                       かけあわせる




                                     この係数を求める
          Made with OpenOffice.org              6
2.1 .C() 関数を利用する方法
            R
         オブジェクト                                     共用
  R                                              オブジェクト        C/C++
                         .C() 関数                 ( または DLL )
            R
         オブジェクト




C/C++    SO(/DLL) の     SO(/DLL) の R の SO 呼び出し   R での
コードの作成      作成        R への読み込み       関数の作成     関数呼び出し




                      Made with OpenOffice.org                         7
Step1) C/C++ コードの作成
                                                       引数はポインタ渡し
   C++ コードでは                                           ( 最後の引数が R に渡す値を
“extern C” をつける                                        格納する配列の先頭ポインタ )
   1   extern "C" void convolve_c(double *a, int *na,
                  関数の返り値は double *b, int *nb, double *ab)
   2   {              void 型
   3       int nab = *na + *nb -1;
   4
   5       for (int i = 0; i < nab; ++i) ab[i] = .0;
   6       for (int i = 0; i < *na; ++i) {
   7           for (int j = 0; j < *nb; ++j) {
   8                 ab[i+j] += a[i] * b[j];
   9           }
  10       }
  11   }



                            Made with OpenOffice.org                 8
Step2) SO(/DLL) の作成
 [sfukushima@localhost test]$ R CMD SHLIB conv_c.cpp


Step3) SO(/DLL) の R への読み込み
 > dyn.load("conv_c.so")

                                                   ・第 1 引数は, C/C++ の関数名
Step4) R の SO(/DLL) 呼び出し関数の作成                      ・引数の型は厳密に指定
                                                   ・最後の引数に返り値の型と
                                                    サイズを指定
  conv.c <-
   function(a, b) .C("conv_c",
                      as.double(a), as.integer(length(a)),
                      as.double(b), as.integer(length(b)),
                      res = double(length(a)+length(b)-1))


                        Made with OpenOffice.org                    9
Step5) R での関数呼び出し

 > conv.c(1:10, 10:1)
 [[1]]
  [1] 1 2 3 4 5 6              7   8    9 10

 [[2]]
 [1] 10

 [[3]]
  [1] 10   9   8   7   6   5   4   3    2     1

 [[4]]
 [1] 10

 $result
  [1] 10 29 56         90 130 175 224 276 330 385 330 276 224 175 130
 90 56 29 10


                                   Made with OpenOffice.org             10
2.2 .Call() 関数を利用する方法
               R
            オブジェクト                                       共用
  R                                                   オブジェクト        C/C++
                         .Call() 関数                   ( または DLL )
                                            R
                                         オブジェクト




C/C++ コード   SO(/DLL) の       SO(/DLL) の R の SO 呼び出し   R での
   の作成         作成          R への読み込み       関数の作成     関数呼び出し




                           Made with OpenOffice.org                         11
Step1) C/C++ コードの作成
  1   #include <Rdefines.h>
  2                                                      引数,返り値ともに
  3   SEXP convolve_call(SEXP a, SEXP b)        型は” SEXP”
  4   {                                    (Symbolic EXPresion)
  5       PROTECT(a = AS_NUMERIC(a));
  6       PROTECT(b = AS_NUMERIC(b));
  7       int na = length(a), nb = length(b), nab = na + nb -1;
  8       SEXP ab;                          SEXP 型は R がメモリを
                                              開放しないように
  9       PROTECT(ab = NEW_NUMERIC(nab));
                                                           制御する
 10
 11       for (int i = 0; i < nab; ++i) REAL(ab)[i] = .0;
 12                                                      変数の型を陽に指定する
 13       for (int i = 0; i < na; ++i) {
 14           for (int j = 0; j < nb; ++j) {
 15               REAL(ab)[i+j] += REAL(a)[i] * REAL(b)[j];
 16           }
 17       }                 R がメモリを
 18       UNPROTECT(3); 開放できるようにする
 19       return(ab);
 20   }
                              Made with OpenOffice.org                 12
Step2) SO(/DLL) の作成
 [sfukushima@localhost test]$ R CMD SHLIB conv_call.cpp

Step3) SO(/DLL) の R への読み込み
 > dyn.load("conv_call.so")

Step4) R の SO(/DLL) 呼び出し関数の作成
  conv.call <-   function(a, b) .Call("conv_call", a, b)
                                           ・第 1 引数は, C/C++ の関数名
                                           ・引数の型はしてしなくて良い!


Step5) R での関数呼び出し
  > conv.call(1:10, 10:1)
   [1] 10 29 56 90 130 175 224 276 330 385 330 276 224
  175 130 90 56 29 10
                         Made with OpenOffice.org                 13
2.3 これまでのまとめ

                                                   考えられる
          C/C++ コードの作成          引数の渡し方
                                                   活用シーン
                                     △          既存のライブラリを
.C() 関数        ○
                                 ( 型を明示 )       用いるとき
                 △                              短い C/C++ のインタ
.Call() 関数 (R との連携専用に作                    ○     フェースを書いて呼
                 成)                             び出すとき



     .Call() 関数は R から呼び出すときに、引数の型を
     明示的に指定しなくても良い
     → 以降で述べる Rcpp パッケージは,この特徴をよ
     り良く活かしたパッケージ


                     Made with OpenOffice.org              14
2.4 Rcpp パッケージ
.Call() 関数を用いて, C/C++ を呼び出す場合
の C/C++ コードをもっと楽に書けないか?


               R
            オブジェクト                                       共用
  R                      .Call() 関数
                                                      オブジェクト            C/C++
                                                      ( または DLL )
                                            R
                                         オブジェクト



                                                                    Rcpp パッケージ




C/C++ コード   SO(/DLL) の       SO(/DLL) の R の SO 呼び出し   R での
   の作成         作成          R への読み込み       関数の作成     関数呼び出し


                           Made with OpenOffice.org                             15
Rcpp 使用                                                 Rcpp 不使用
 1   #include <R.h>                                        #include <Rdefines.h>
 2   #include <Rinternals.h>
 3   #include "Rcpp.h"                                     SEXP convolve_call(SEXP a, SEXP b) {
 4                                                           PROTECT(a = AS_NUMERIC(a));
 5   RcppExport SEXP conv_rcpp(SEXP a, SEXP b)               PROTECT(b = AS_NUMERIC(b));
 6   {                                                       int na = length(a),
 7     RcppVector<double> aa(a);                                 nb = length(b),
 8     RcppVector<double> bb(b);                                 nab = na + nb -1;
 9     int nab = aa.size() + bb.size() - 1;                  SEXP ab;
10                                                           PROTECT(ab = NEW_NUMERIC(nab));
11     Rcpp::NumericVector ab(nab);
12     for (int i = 0; i < nab; ++i) ab(i) = .0;                 for (int i = 0; i < nab; ++i)
13     for (int i = 0; i < aa.size(); ++i) {                       REAL(ab)[i] = .0;
14       for (int j = 0; j < bb.size(); ++j) {
15         ab(i + j) += aa(i) * bb(j);                           for (int i = 0; i < na; ++i) {
16       }                                                         for (int j = 0; j < nb; ++j) {
17     }                                                             REAL(ab)[i+j] +=
18    RcppResultSet rs;                                                REAL(a)[i] * REAL(b)[j];
19    rs.add("ab", ab);                                            }
20    return rs.getReturnList();                                 }
21   }                                                           UNPROTECT(3);
                                                                 return(ab);
                                                         }
                                      Made with OpenOffice.org                                   16
C++ 内部では STL の vector などを用いて最後に
Rcpp の wrap 関数で SEXP に変換することも可能
 1   #include   <R.h>
 2   #include   <Rinternals.h>
 3   #include   <Rdefines.h>
 4   #include   <Rcpp.h>
 5   #include   <vector>
 6
 7   extern "C" SEXP rcpp_test(SEXP x, SEXP y) {
 8       std::vector<double> xx(x), yy(y);
 9       int n = xx.size();
10       std::vector<double> res(n);
11
12        for (int i = 0; i < n; ++i) {
13            double x = xx[i], y = yy[i];
14            if (x < y) res[i] = x * x;
15            else res[i] = -y * y;
16        }
17       return Rcpp::wrap(res);
18   }
                                 Made with OpenOffice.org   17
3. C/C++ からの R の利用
 C/C++ コードで使用できる R の API がある
 (“R.h” 等を使用.
  “Writing R Extensions”Chapter.6 参照 ) .
 C++ からの R の利用方法として,今回は
 RInside パッケージを紹介する.
 RInside を用いると, C++ から R を呼び出し
 て処理を行わせ,その結果を C++ に戻すこと
 が楽になる.

                 処理の呼び出し

  R                                         C/C++
               RInside パッケージ


               計算結果の受け渡し
                 Made with OpenOffice.org           18
3 C/C++ からの R の利用
 1   #include <iostream>
 2   #include <algorithm>
 3   #include "Rinside.h"
 4
 5   int main(int argc, char *argv[])
 6   {
 7       const int dim = 10;
 8
 9       // 線形回帰分析に用いるデータの生成
10       std::vector<double> x, y;                          となる
11       for (int i = 0; i < dim;++i) {           ベクトル             を
12           x.push_back(i); y.push_back(2*i);    C++ で生成
13       }
14       // C++ 側でのデータの確認
15       std::cout << "In c++: x" << std::endl;
16       std::copy(x.begin(), x.end(),
17                  std::ostream_iterator<double>(std::cout, " "));
18       std::cout << std::endl;
19       std::cout << "In c++: v" << std::endl;
20       std::copy(y.begin(), y.end(),
21                  std::ostream_iterator<double>(std::cout, " "));
22       std::cout << std::endl;



                                Made with OpenOffice.org               19
23   // R 側の分析データオブジェクトの生成
24    RInside R(argc, argv);               R でも
25    R.assign(x, "x"); R.assign(y, "y"); ベクトル             を生成
26    // R のコマンドの生成,実行
27    std::string evalstr = "cat('In R: x n'); print(x); 
28                            cat('In R: y n'); print(y); 
29                            z <- lm(y~x); z <- z$fitted.values; 
30                            cat('In R: fitted.values n'); print(z); z";
31    SEXP ans;
32    R.parseEval(evalstr, ans);
33
                                                         R のコマンドの生成・
34   // C++ において R の返り値の格納
35   RcppVector<double> vec(ans);
                                                  受け渡し・実行
36   std::vector<double> v = vec.stlVector();
37   // 確認
38   std::cout << "In c++: v" << std::endl;
39   std::copy(v.begin(), v.end(),
40               std::ostream_iterator<double>(std::cout, " "));
41   std::cout << std::endl;




                              Made with OpenOffice.org                       20
[sfukushima@localhost test]$ ./rinside_test
In c++: x
0 1 2 3 4 5 6 7 8 9                  C++ での
In c++: v                            ベクトル       の中身の確認
0 2 4 6 8 10 12 14 16 18
In R: x
 [1] 0 1 2 3 4 5 6 7 8 9             R での
In R: y                              ベクトル       の中身の確認
 [1] 0 2 4 6 8 10 12 14 16 18
In R: fitted.values
 1 2 3 4 5 6 7 8 9 10                R の返り値の確認
 0 2 4 6 8 10 12 14 16 18
In c++: v
5.2423e-16 2 4 6 8 10 12 14 16 18
                                     C++ において R の返り値の確認




                         Made with OpenOffice.org         21
参考文献
 Dirk Eddelbuettel(2009):
 “Rcpp and Rinside: Easier R and C++
 integration”, UseR! 2009 Presentation.

 Dirk Eddelbuettel,Romain francois(2010):
 “Rcpp:Seamless R and C++”.

 R Development Core Team(2010):
 “Writing R Extensions(ver.2.11.0)”.

 John M.Chambers(2008):
 “Software for Data Analysis
 -Programming with R-”, Springer.
               Made with OpenOffice.org     22

Contenu connexe

Plus de Shintaro Fukushima

Why dont you_create_new_spark_jl
Why dont you_create_new_spark_jlWhy dont you_create_new_spark_jl
Why dont you_create_new_spark_jlShintaro Fukushima
 
Rユーザのためのspark入門
Rユーザのためのspark入門Rユーザのためのspark入門
Rユーザのためのspark入門Shintaro Fukushima
 
Juliaによる予測モデル構築・評価
Juliaによる予測モデル構築・評価Juliaによる予測モデル構築・評価
Juliaによる予測モデル構築・評価Shintaro Fukushima
 
機械学習を用いた予測モデル構築・評価
機械学習を用いた予測モデル構築・評価機械学習を用いた予測モデル構築・評価
機械学習を用いた予測モデル構築・評価Shintaro Fukushima
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるShintaro Fukushima
 
data.tableパッケージで大規模データをサクッと処理する
data.tableパッケージで大規模データをサクッと処理するdata.tableパッケージで大規模データをサクッと処理する
data.tableパッケージで大規模データをサクッと処理するShintaro Fukushima
 
アクションマイニングを用いた最適なアクションの導出
アクションマイニングを用いた最適なアクションの導出アクションマイニングを用いた最適なアクションの導出
アクションマイニングを用いた最適なアクションの導出Shintaro Fukushima
 
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用Shintaro Fukushima
 
不均衡データのクラス分類
不均衡データのクラス分類不均衡データのクラス分類
不均衡データのクラス分類Shintaro Fukushima
 
mmapパッケージを使ってお手軽オブジェクト管理
mmapパッケージを使ってお手軽オブジェクト管理mmapパッケージを使ってお手軽オブジェクト管理
mmapパッケージを使ってお手軽オブジェクト管理Shintaro Fukushima
 
Numpy scipyで独立成分分析
Numpy scipyで独立成分分析Numpy scipyで独立成分分析
Numpy scipyで独立成分分析Shintaro Fukushima
 
Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Shintaro Fukushima
 
Rにおける大規模データ解析(第10回TokyoWebMining)
Rにおける大規模データ解析(第10回TokyoWebMining)Rにおける大規模データ解析(第10回TokyoWebMining)
Rにおける大規模データ解析(第10回TokyoWebMining)Shintaro Fukushima
 

Plus de Shintaro Fukushima (19)

Why dont you_create_new_spark_jl
Why dont you_create_new_spark_jlWhy dont you_create_new_spark_jl
Why dont you_create_new_spark_jl
 
Rユーザのためのspark入門
Rユーザのためのspark入門Rユーザのためのspark入門
Rユーザのためのspark入門
 
Juliaによる予測モデル構築・評価
Juliaによる予測モデル構築・評価Juliaによる予測モデル構築・評価
Juliaによる予測モデル構築・評価
 
Juliaで並列計算
Juliaで並列計算Juliaで並列計算
Juliaで並列計算
 
機械学習を用いた予測モデル構築・評価
機械学習を用いた予測モデル構築・評価機械学習を用いた予測モデル構築・評価
機械学習を用いた予測モデル構築・評価
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみる
 
data.tableパッケージで大規模データをサクッと処理する
data.tableパッケージで大規模データをサクッと処理するdata.tableパッケージで大規模データをサクッと処理する
data.tableパッケージで大規模データをサクッと処理する
 
アクションマイニングを用いた最適なアクションの導出
アクションマイニングを用いた最適なアクションの導出アクションマイニングを用いた最適なアクションの導出
アクションマイニングを用いた最適なアクションの導出
 
R3.0.0 is relased
R3.0.0 is relasedR3.0.0 is relased
R3.0.0 is relased
 
外れ値
外れ値外れ値
外れ値
 
Rでreproducible research
Rでreproducible researchRでreproducible research
Rでreproducible research
 
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
 
不均衡データのクラス分類
不均衡データのクラス分類不均衡データのクラス分類
不均衡データのクラス分類
 
mmapパッケージを使ってお手軽オブジェクト管理
mmapパッケージを使ってお手軽オブジェクト管理mmapパッケージを使ってお手軽オブジェクト管理
mmapパッケージを使ってお手軽オブジェクト管理
 
Numpy scipyで独立成分分析
Numpy scipyで独立成分分析Numpy scipyで独立成分分析
Numpy scipyで独立成分分析
 
Rで学ぶロバスト推定
Rで学ぶロバスト推定Rで学ぶロバスト推定
Rで学ぶロバスト推定
 
Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)
 
Rにおける大規模データ解析(第10回TokyoWebMining)
Rにおける大規模データ解析(第10回TokyoWebMining)Rにおける大規模データ解析(第10回TokyoWebMining)
Rにおける大規模データ解析(第10回TokyoWebMining)
 
R-hpc-1 TokyoR#11
R-hpc-1 TokyoR#11R-hpc-1 TokyoR#11
R-hpc-1 TokyoR#11
 

Tokyo.R(#07)

  • 1. R と C/C++ の連携 福島真太朗 第 7 回 R 勉強会@東京 2010 年 7 月 24 日 Made with OpenOffice.org 1
  • 2. 自己紹介 出身:埼玉県 職業:コンサルタント 主に金融工学のデータ解析・モデル構築等 使用言語: R, C, C++, Java, Awk, Perl Twitter : @sfchaos Made with OpenOffice.org 2
  • 3. 発表の流れ 1.本発表の目標 2.R からの C/C++ の利用 3.C++ からの R の利用 Made with OpenOffice.org 3
  • 4. 1. 本発表の目標 将来こんな問題に直面するかも・・・ 蓄積してきた R では遅い処理を C/C++ のライブラリを C/C++ に任せて 活用したい 高速化したい R C/C++ R と C/C++ の連携させる基本的な方法を学ぶ Made with OpenOffice.org 4
  • 5. 2.R からの C/C++ の利用 R から C/C++ を利用する方法として, 主に2種類の方法が用いられる. .C() 関数を利用する方法 .Call() 関数を利用する方法 Made with OpenOffice.org 5
  • 6. 考える問題 2 つの多項式 かけあわせる この係数を求める Made with OpenOffice.org 6
  • 7. 2.1 .C() 関数を利用する方法 R オブジェクト 共用 R オブジェクト C/C++ .C() 関数 ( または DLL ) R オブジェクト C/C++ SO(/DLL) の SO(/DLL) の R の SO 呼び出し R での コードの作成 作成 R への読み込み 関数の作成 関数呼び出し Made with OpenOffice.org 7
  • 8. Step1) C/C++ コードの作成 引数はポインタ渡し C++ コードでは ( 最後の引数が R に渡す値を “extern C” をつける 格納する配列の先頭ポインタ ) 1 extern "C" void convolve_c(double *a, int *na, 関数の返り値は double *b, int *nb, double *ab) 2 { void 型 3 int nab = *na + *nb -1; 4 5 for (int i = 0; i < nab; ++i) ab[i] = .0; 6 for (int i = 0; i < *na; ++i) { 7 for (int j = 0; j < *nb; ++j) { 8 ab[i+j] += a[i] * b[j]; 9 } 10 } 11 } Made with OpenOffice.org 8
  • 9. Step2) SO(/DLL) の作成 [sfukushima@localhost test]$ R CMD SHLIB conv_c.cpp Step3) SO(/DLL) の R への読み込み > dyn.load("conv_c.so") ・第 1 引数は, C/C++ の関数名 Step4) R の SO(/DLL) 呼び出し関数の作成 ・引数の型は厳密に指定 ・最後の引数に返り値の型と サイズを指定 conv.c <- function(a, b) .C("conv_c", as.double(a), as.integer(length(a)), as.double(b), as.integer(length(b)), res = double(length(a)+length(b)-1)) Made with OpenOffice.org 9
  • 10. Step5) R での関数呼び出し > conv.c(1:10, 10:1) [[1]] [1] 1 2 3 4 5 6 7 8 9 10 [[2]] [1] 10 [[3]] [1] 10 9 8 7 6 5 4 3 2 1 [[4]] [1] 10 $result [1] 10 29 56 90 130 175 224 276 330 385 330 276 224 175 130 90 56 29 10 Made with OpenOffice.org 10
  • 11. 2.2 .Call() 関数を利用する方法 R オブジェクト 共用 R オブジェクト C/C++ .Call() 関数 ( または DLL ) R オブジェクト C/C++ コード SO(/DLL) の SO(/DLL) の R の SO 呼び出し R での の作成 作成 R への読み込み 関数の作成 関数呼び出し Made with OpenOffice.org 11
  • 12. Step1) C/C++ コードの作成 1 #include <Rdefines.h> 2 引数,返り値ともに 3 SEXP convolve_call(SEXP a, SEXP b) 型は” SEXP” 4 { (Symbolic EXPresion) 5 PROTECT(a = AS_NUMERIC(a)); 6 PROTECT(b = AS_NUMERIC(b)); 7 int na = length(a), nb = length(b), nab = na + nb -1; 8 SEXP ab; SEXP 型は R がメモリを 開放しないように 9 PROTECT(ab = NEW_NUMERIC(nab)); 制御する 10 11 for (int i = 0; i < nab; ++i) REAL(ab)[i] = .0; 12 変数の型を陽に指定する 13 for (int i = 0; i < na; ++i) { 14 for (int j = 0; j < nb; ++j) { 15 REAL(ab)[i+j] += REAL(a)[i] * REAL(b)[j]; 16 } 17 } R がメモリを 18 UNPROTECT(3); 開放できるようにする 19 return(ab); 20 } Made with OpenOffice.org 12
  • 13. Step2) SO(/DLL) の作成 [sfukushima@localhost test]$ R CMD SHLIB conv_call.cpp Step3) SO(/DLL) の R への読み込み > dyn.load("conv_call.so") Step4) R の SO(/DLL) 呼び出し関数の作成 conv.call <- function(a, b) .Call("conv_call", a, b) ・第 1 引数は, C/C++ の関数名 ・引数の型はしてしなくて良い! Step5) R での関数呼び出し > conv.call(1:10, 10:1) [1] 10 29 56 90 130 175 224 276 330 385 330 276 224 175 130 90 56 29 10 Made with OpenOffice.org 13
  • 14. 2.3 これまでのまとめ 考えられる C/C++ コードの作成 引数の渡し方 活用シーン △ 既存のライブラリを .C() 関数 ○ ( 型を明示 ) 用いるとき △ 短い C/C++ のインタ .Call() 関数 (R との連携専用に作 ○ フェースを書いて呼 成) び出すとき .Call() 関数は R から呼び出すときに、引数の型を 明示的に指定しなくても良い → 以降で述べる Rcpp パッケージは,この特徴をよ り良く活かしたパッケージ Made with OpenOffice.org 14
  • 15. 2.4 Rcpp パッケージ .Call() 関数を用いて, C/C++ を呼び出す場合 の C/C++ コードをもっと楽に書けないか? R オブジェクト 共用 R .Call() 関数 オブジェクト C/C++ ( または DLL ) R オブジェクト Rcpp パッケージ C/C++ コード SO(/DLL) の SO(/DLL) の R の SO 呼び出し R での の作成 作成 R への読み込み 関数の作成 関数呼び出し Made with OpenOffice.org 15
  • 16. Rcpp 使用 Rcpp 不使用 1 #include <R.h> #include <Rdefines.h> 2 #include <Rinternals.h> 3 #include "Rcpp.h" SEXP convolve_call(SEXP a, SEXP b) { 4 PROTECT(a = AS_NUMERIC(a)); 5 RcppExport SEXP conv_rcpp(SEXP a, SEXP b) PROTECT(b = AS_NUMERIC(b)); 6 { int na = length(a), 7 RcppVector<double> aa(a); nb = length(b), 8 RcppVector<double> bb(b); nab = na + nb -1; 9 int nab = aa.size() + bb.size() - 1; SEXP ab; 10 PROTECT(ab = NEW_NUMERIC(nab)); 11 Rcpp::NumericVector ab(nab); 12 for (int i = 0; i < nab; ++i) ab(i) = .0; for (int i = 0; i < nab; ++i) 13 for (int i = 0; i < aa.size(); ++i) { REAL(ab)[i] = .0; 14 for (int j = 0; j < bb.size(); ++j) { 15 ab(i + j) += aa(i) * bb(j); for (int i = 0; i < na; ++i) { 16 } for (int j = 0; j < nb; ++j) { 17 } REAL(ab)[i+j] += 18 RcppResultSet rs; REAL(a)[i] * REAL(b)[j]; 19 rs.add("ab", ab); } 20 return rs.getReturnList(); } 21 } UNPROTECT(3); return(ab); } Made with OpenOffice.org 16
  • 17. C++ 内部では STL の vector などを用いて最後に Rcpp の wrap 関数で SEXP に変換することも可能 1 #include <R.h> 2 #include <Rinternals.h> 3 #include <Rdefines.h> 4 #include <Rcpp.h> 5 #include <vector> 6 7 extern "C" SEXP rcpp_test(SEXP x, SEXP y) { 8 std::vector<double> xx(x), yy(y); 9 int n = xx.size(); 10 std::vector<double> res(n); 11 12 for (int i = 0; i < n; ++i) { 13 double x = xx[i], y = yy[i]; 14 if (x < y) res[i] = x * x; 15 else res[i] = -y * y; 16 } 17 return Rcpp::wrap(res); 18 } Made with OpenOffice.org 17
  • 18. 3. C/C++ からの R の利用 C/C++ コードで使用できる R の API がある (“R.h” 等を使用. “Writing R Extensions”Chapter.6 参照 ) . C++ からの R の利用方法として,今回は RInside パッケージを紹介する. RInside を用いると, C++ から R を呼び出し て処理を行わせ,その結果を C++ に戻すこと が楽になる. 処理の呼び出し R C/C++ RInside パッケージ 計算結果の受け渡し Made with OpenOffice.org 18
  • 19. 3 C/C++ からの R の利用 1 #include <iostream> 2 #include <algorithm> 3 #include "Rinside.h" 4 5 int main(int argc, char *argv[]) 6 { 7 const int dim = 10; 8 9 // 線形回帰分析に用いるデータの生成 10 std::vector<double> x, y; となる 11 for (int i = 0; i < dim;++i) { ベクトル を 12 x.push_back(i); y.push_back(2*i); C++ で生成 13 } 14 // C++ 側でのデータの確認 15 std::cout << "In c++: x" << std::endl; 16 std::copy(x.begin(), x.end(), 17 std::ostream_iterator<double>(std::cout, " ")); 18 std::cout << std::endl; 19 std::cout << "In c++: v" << std::endl; 20 std::copy(y.begin(), y.end(), 21 std::ostream_iterator<double>(std::cout, " ")); 22 std::cout << std::endl; Made with OpenOffice.org 19
  • 20. 23 // R 側の分析データオブジェクトの生成 24 RInside R(argc, argv); R でも 25 R.assign(x, "x"); R.assign(y, "y"); ベクトル を生成 26 // R のコマンドの生成,実行 27 std::string evalstr = "cat('In R: x n'); print(x); 28 cat('In R: y n'); print(y); 29 z <- lm(y~x); z <- z$fitted.values; 30 cat('In R: fitted.values n'); print(z); z"; 31 SEXP ans; 32 R.parseEval(evalstr, ans); 33 R のコマンドの生成・ 34 // C++ において R の返り値の格納 35 RcppVector<double> vec(ans); 受け渡し・実行 36 std::vector<double> v = vec.stlVector(); 37 // 確認 38 std::cout << "In c++: v" << std::endl; 39 std::copy(v.begin(), v.end(), 40 std::ostream_iterator<double>(std::cout, " ")); 41 std::cout << std::endl; Made with OpenOffice.org 20
  • 21. [sfukushima@localhost test]$ ./rinside_test In c++: x 0 1 2 3 4 5 6 7 8 9 C++ での In c++: v ベクトル の中身の確認 0 2 4 6 8 10 12 14 16 18 In R: x [1] 0 1 2 3 4 5 6 7 8 9 R での In R: y ベクトル の中身の確認 [1] 0 2 4 6 8 10 12 14 16 18 In R: fitted.values 1 2 3 4 5 6 7 8 9 10 R の返り値の確認 0 2 4 6 8 10 12 14 16 18 In c++: v 5.2423e-16 2 4 6 8 10 12 14 16 18 C++ において R の返り値の確認 Made with OpenOffice.org 21
  • 22. 参考文献 Dirk Eddelbuettel(2009): “Rcpp and Rinside: Easier R and C++ integration”, UseR! 2009 Presentation. Dirk Eddelbuettel,Romain francois(2010): “Rcpp:Seamless R and C++”. R Development Core Team(2010): “Writing R Extensions(ver.2.11.0)”. John M.Chambers(2008): “Software for Data Analysis -Programming with R-”, Springer. Made with OpenOffice.org 22