문제
R에서 C ++ 라이브러리를 사용하여 C ++ 데이터 구조를 보존하는 가장 좋은 방법은 무엇입니까? 나는 전혀 C ++ 사용자가 아니므로 사용 가능한 접근법의 상대적인 장점에 대해서는 명확하지 않습니다. R-ext 매뉴얼은 C로 모든 C ++ 함수를 포장하는 것을 제안하는 것으로 보이지만, C ++를 통합하는 다른 4 개 또는 5 개 이상의 다른 수단이 존재합니다.
두 가지 방법은 유사한 계보가있는 패키지, RCPP (다량의 오버 플라워 Dirk Eddelbuettel에 의해 유지됨) 및 RCPPTemplate 패키지 (CRAN 모두)입니다. 둘 사이의 차이점은 무엇입니까?
C ++ 및 R의 바인딩에 대한 다른 접근법을 취한다고 주장하는 R Forge에서 사용 가능한 다른 패키지 인 RCPPBind (알 수 없음).
CRAN에서 사용할 수있는 패키지 인라인은 인라인 C/C ++를 허용한다고 주장합니다.이 기능이 내장 기능과 다르다고 확신하지 못하고 코드가 w/r로 인라인이 될 수 있습니다.
그리고 마지막으로 RSWIG가 나타납니다 야생에서 그러나 그것이 얼마나지지되었는지는 확실하지 않습니다. 저자의 페이지 몇 년 동안 업데이트되지 않았습니다.
내 질문은, 이러한 다른 접근법의 상대적인 장점은 무엇입니까? 가장 휴대하고 강력하며 구현하기가 가장 쉬운 것입니다. CRAN에 패키지를 배포 할 계획이라면 어떤 방법을 사용 하시겠습니까?
해결책
우선, 면책 조항 : 나는 사용합니다 RCPP 항상. 실제로 (RCPP의 시간에 이름이 바뀌었을 때) rcpptemplate이 이미 고아가되었고 2 년 동안 업데이트되지 않았을 때, 나는 RCPP의 초기 이름으로 그것을 유지하기 시작했습니다 (그 아래에서 기여한 것입니다. rquantlib). 그것은 약 1 년 전이었고, 나는 당신이 Changelog에서 문서화 할 수있는 몇 가지 점진적인 변화를 만들었습니다.
이제 rcpptemplate은 최근에 35 개월 만에 업데이트 나 수정없이 돌아 왔습니다. 흥미로운 새 코드가 포함되어 있지만 거꾸로 호환되지 않으므로 이미 RCPP를 사용한 곳에서는 사용하지 않을 것 같습니다.
rcppbind 내가 확인할 때마다 적극적으로 유지되지 않았습니다. Whit Armstrong에는 또한 템플릿 인터페이스 패키지가 있습니다 Rabstraction.
인라인 완전히 다른 것 : 프로그램을 R 캐릭터 문자열로 '내부'하여 컴파일 / 링크 사이클을 완화시켜 컴파일, 링크 및로드됩니다. 나는 Oleg에게 좋은 RCPP를 지원하는 것에 대해 이야기했습니다.
통음 흥미 롭습니다. Joe Wang은 그곳에서 큰 일을했고 R을 위해 모든 Quantlib를 포장했습니다. 그러나 마지막으로 시도했을 때 R 인테일의 일부 변화로 인해 더 이상 작동하지 않았습니다. SWIG 팀의 누군가에 따르면 Joe는 여전히 작업 할 수 있습니다. SWIG의 목표는 어쨌든 더 큰 라이브러리입니다. 이 프로젝트는 아마도 부흥과 관련이있을 수 있지만 기술적 인 도전이없는 것은 아닙니다.
또 다른 언급은 가야합니다 rinside RCPP와 함께 작동하며 C ++ 응용 프로그램 내부에 R을 포함시킬 수 있습니다.
요약하려면 : RCPP 특히 함수를 추가하려는 소규모 탐색 프로젝트에서는 나에게 잘 작동합니다. 초점은 사용이 용이하며, 항상 함께 일하기에 항상 재미 있지 않은 r 내부를 '숨길'할 수 있습니다. 나는 이메일을 통해 내가 도와 준 다른 많은 사용자들을 알고 있습니다. 그래서 나는 이것을 위해 가고 싶다.
RCPP, Rinside 및 Inline의 몇 가지 예가 있습니다.
편집하다: 따라서 구체적인 예를 살펴 보겠습니다 ( 'r intro'슬라이드가있는 'HPC에서 가져와 Venables와 Ripley에서 가져온 Stephen Milborrow에서 빌린). 작업은 각 위치에 단일 자릿수 만 포함하는 2x2 행렬의 결정 인자의 가능한 모든 조합을 열거하는 것입니다. 이것은 튜토리얼 슬라이드에서 논의하는 것처럼 영리한 벡터화 된 방법 또는 다음과 같이 잔인한 힘으로 수행 할 수 있습니다.
#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;
}
이것을 저장하면 dd.rcpp.cpp
그리고 가지고 있습니다 RCPP 설치 한 다음 간단히 사용하십시오
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 및 C ++ 데이터 유형의 벡터, 행렬 등을 쉽게 보낼 수 있습니다. 이것이 다소 도움이되기를 바랍니다.
편집 2 (약 5 년 후) :
그래서이 대답은 방금 뿌리를 내렸고 따라서 내 줄에 거품이 생겼습니다. ㅏ 많은 내가 쓴 이후로 시간이 지났고 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()
그것; 마지막에 R 테스트 코드를 실행합니다 - 본격적인
IntegerVector
유형 - 예외 처리 래퍼가 자동으로 추가됩니다
sourceCpp()
코드 생성기