2009-11-12 10 views
14

R에서 C++ 라이브러리를 사용하고 C++ 데이터 구조를 보존하는 가장 좋은 방법은 무엇입니까? 나는 C++ 사용자가 아니기 때문에 가능한 접근법의 상대적 장점에 대해서는 분명하지 않다. R-ext 매뉴얼은 C에서 모든 C++ 함수를 래핑하는 것을 제안하는 것으로 보입니다. 그러나 C++를 통합하는 데 최소한 4 ~ 5 개의 다른 방법이 존재합니다.R 패키지에서 C++ 라이브러리 사용

두 가지 방법은 유사한 혈통, Rcpp (Dick Eddelbuettel에 의해 유지 관리 됨) 및 RcppTemplate 패키지 (CRAN에서 모두)의 패키지이며, 둘 사이의 차이점은 무엇입니까?

또 다른 패키지는 C 바인딩 ++ 및 R (내가 말할 지식이 아니에요)에 다른 접근 방식을 주장 R 단조에 사용할 수 rcppbind. CRAN 볼 수

패키지 인라인 허용 주장 인라인 C/C++ 나는이 코드/R w 인라인 될 수 있도록 따로, 기능 내장 다릅니다 모르겠어요.

그리고 마지막으로 in the wild 인 것으로 보이는 RSwig이지만 지원되는 방법은 확실하지 않습니다. author's page은 수년간 업데이트되지 않았습니다.

내 질문은 이러한 다양한 접근 방식의 상대적인 장점은 무엇입니까? 가장 휴대하고 견고하며 구현하기가 가장 쉽습니다. CRAN에 패키지를 배포 할 계획이라면 어떤 방법을 쓰겠습니까?

답변

15

첫째, 면책 조항 : 나는 Rcpp 모든 시간을 사용합니다. 사실, (Rcpp에서 시간에 의해 이름이 바뀌었을 때) RcppTemplate은 이미 고아가되었고 2 년 동안 업데이트가 없었기 때문에 초기 이름 인 Rcpp (RQuantLib에 기부 됨) 아래서 유지하기 시작했습니다. 이는 약 1 년 전의 일이며 변경 로그에 문서화 된 몇 가지 점진적인 변경 사항을 만들었습니다.

지금 RcppTemplate 아주 최근에 갱신없이 전체 삼십오개월 후 돌아올 또는 수정했다. 흥미로운 새로운 코드가 포함되어 있지만 역 호환이되지 않아서 이미 Rcpp를 사용했던 곳에서는 사용하지 않을 것입니다. 나는 검사 할 때마다

Rcppbind 매우 적극적으로 유지되지 않았습니다. Whit Armstrong은 rabstraction이라는 템플릿 기반 인터페이스 패키지도 제공합니다.

Inline은 완전히 다른 것입니다. 프로그램을 R 문자열로 '포함'하여 컴파일/링크주기를 단축하고 컴파일하고 링크하고로드합니다. 나는 올레그에게 Rcpp를 인라인으로 지원하는 것에 대해 이야기했다.

Swig도 흥미 롭습니다. Joe Wang은 그곳에서 큰 성과를 거두었으며 QuantLib for R을 모두 감쌌습니다.하지만 마지막으로 시도해 보았을 때 R 내부의 일부 변경으로 인해 더 이상 작동하지 않았습니다. Swig 팀의 누군가에 따르면, Joe는 여전히 그것을 연구 할 것입니다. 어쨌든 Swig의 목표는 더 큰 도서관입니다. 이 프로젝트는 아마도 부흥으로 할 수 있지만 기술적 인 어려움이있는 것은 아닙니다.

또 다른 언급은 Rcpp와 함께 작동하며 C++ 응용 프로그램의 내부 R을 삽입 할 수 있습니다 RInside로 이동합니다.

따라서 요약하면 Rcpp이 나를 위해 잘 작동합니다. 특히 기능을 추가하려는 소규모 프로젝트의 경우에 적합합니다. 초점은 사용하기 쉽고 항상 작업하기에 즐겁지 않은 R 내부를 '숨길'수 있습니다. 나는 이메일을 통해 도움을주고받는 다른 많은 사용자를 알고있다. 그래서 나는 이것에 대해 말할 것이다.

내 'Intro to HPC with R'자습서에는 Rcpp, RInside 및 인라인의 몇 가지 예가 있습니다.

편집 : 그럼 구체적인 예를 들어 봅시다. 작업은 각 위치에서 한 자리 만 포함하는 2x2 행렬의 행렬식의 가능한 모든 조합을 열거하는 것입니다. 또는 무력에 의해 (우리는 튜토리얼 슬라이드 논의로) 이것은 다음과 같이 영리한 벡터화 방법으로 수행 할 수 있습니다 : 당신이 dd.rcpp.cpp, 말,로 이것을 저장하고 간단하게

를 사용 Rcpp가 설치되어있는 경우

#include <Rcpp.h> 

RcppExport SEXP dd_rcpp(SEXP v) { 
    SEXP rl = R_NilValue;  // Use this when there is nothing to be returned. 
    char* exceptionMesg = NULL; // msg var in case of error 

    try { 
    RcppVector<int> vec(v);  // vec parameter viewed as vector of ints 
    int n = vec.size(), i = 0; 
    if (n != 10000) 
     throw std::length_error("Wrong vector size"); 
    for (int a = 0; a < 9; a++) 
     for (int b = 0; b < 9; b++) 
     for (int c = 0; c < 9; c++) 
      for (int d = 0; d < 9; d++) 
      vec(i++) = a*b - c*d; 

    RcppResultSet rs;   // Build result set to be returned as list to R 
    rs.add("vec", vec);   // vec as named element with name 'vec' 
    rl = rs.getReturnList(); // Get the list to be returned to R. 
    } catch(std::exception& ex) { 
    exceptionMesg = copyMessageToR(ex.what()); 
    } catch(...) { 
    exceptionMesg = copyMessageToR("unknown reason"); 
    } 

    if (exceptionMesg != NULL) 
    Rf_error(exceptionMesg); 

    return rl; 
} 

PKG_CPPFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'` \ 
    PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'` \ 
    R CMD SHLIB dd.rcpp.cpp 

공유 라이브러리를 작성하는 중입니다. Rscript (또는 r)을 사용하여 Rcpp에 헤더 및 라이브러리 위치를 문의하십시오. 일단 내장, 우리는로드하고 다음과 같이 R에서이를 사용할 수 있습니다

같은 방법으로
dyn.load("dd.rcpp.so") 

dd.rcpp <- function() { 
    x <- integer(10000) 
    res <- .Call("dd_rcpp", x) 
    tabulate(res$vec) 
} 

, 다양한 R의 ... 벡터, MATRICS을 보낼 수 및 C++ 데이터 유형이 다시 쉽게 앞으로 끝. 희망이 다소 도움이됩니다.

편집 2 (일부 오 + 년 이상) :

그래서이 답변이 그냥 upvote에있어 따라서 내 대기열에 버블. A 이 내가 작성한 이래로 시간이 지났으며 Rcpp이의 기능이 풍부한 을 많이 받았습니다. 그래서 매우 빠르게 쓴이 파일의 코드를 다음과 같이 사용할 수 있습니다

#include <Rcpp.h> // [[Rcpp::export]] Rcpp::IntegerVector dd2(Rcpp::IntegerVector vec) { int n = vec.size(), i = 0; if (n != 10000) throw std::length_error("Wrong vector size"); for (int a = 0; a < 9; a++) for (int b = 0; b < 9; b++) for (int c = 0; c < 9; c++) for (int d = 0; d < 9; d++) vec(i++) = a*b - c*d; return vec; } /*** R x <- integer(10000) tabulate(dd2(x)) */ 

/tmp/dd.cpp

R> Rcpp::sourceCpp("/tmp/dd.cpp") # on from any other file and path 

R> x <- integer(10000) 

R> tabulate(dd2(x)) 
[1] 87 132 105 155 93 158 91 161 72 104 45 147 41 96 
[15] 72 120 36 90 32 87 67 42 26 120 41 36 27 75 
[29] 20 62 16 69 19 28 49 45 12 18 11 57 14 48 
[43] 10 18 7 12 6 46 23 10 4 10 4 6 3 38 
[57] 2 4 2 3 2 2 1 17 
R> 

주요 차이점 중 일부는

:

  • 간단하게 빌드 : 단지 sourceCpp() it; 심지어 끝에 답변
  • 본격적인 IntegerVector
  • 예외 처리 sourceCpp() 자동 코드 생성기로 추가 래퍼
+0

감사 R 테스트 코드를 실행한다! RcppTemplate에서 "흥미로운 새 코드"가 의미하는 바를 명확히 할 수 있습니까? 패키지는 Rcpp와 어떻게 다릅니 까? C++에 대해서는 거의 알지 못합니다.이 패키지는 어떻게 작동합니까? – Peter

+2

더크, 어쩌면 C++이 R과 함께 작동하도록하는 데에 대해 이야기 할 때가왔다. (! – knguyen

+0

그들이 C++에서 어떻게 다른지 설명하는 것은 쉽지 않다. . –

관련 문제