C ++ 및 특히 Rcpp 패키지가 내 코드 속도를 높이는 데 매우 도움이되었지만 목록 또는 데이터 프레임 입력 인수 (Rcpp :: DataFrame 및 Rcpp :: List 형식의 인수)가있는 C ++ 함수가 내 다른 C ++ 함수에 비해 매우 느립니다. 샘플 코드를 작성했고 코드를 더 빠르게 만들 수있는 트릭을 요청하고 싶었습니다.
먼저, 내부에 두 개의 List가 포함 된 R의 List를 시뮬레이션 해 보겠습니다. 고려 으로 myList를 measure1 및 measure2 - 두 개의 목록을 포함하는 목록으로. measure1 및 measure2는 각각 대상에 대한 측정 벡터를 포함하는 목록입니다. 다음은 R 코드입니다.
lappend <- function(lst, ...){
lst <- c(lst, list(...))
return(lst)
}
nSub <- 30
meas1 <- list()
meas2 <- list()
for (i in 1:nSub){
meas1 <- lappend(meas1, rnorm(10))
meas2 <- lappend(meas2, rnorm(10))
}
myList <- list(meas1 = meas1, meas2 = meas2)
이제 각 주제에 대해 측정 값 1의 합계와 측정 값 2의 합계를 찾은 다음이 두 합계를 기반으로 두 개의 새 측정 값을 생성하는 C ++ 함수가 필요하다고 가정합니다. 마지막으로 함수는 이러한 새 측정 값을 목록으로 반환해야합니다.
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::List mySlowListFn(Rcpp::List myList, int nSub){
arma::vec myMult(nSub);
arma::vec myDiv(nSub);
for (int i = 0; i < nSub; i++){
arma::vec meas1_i = Rcpp::as<arma::vec>(Rcpp::as<Rcpp::List>(myList["meas1"])[i]);
arma::vec meas2_i = Rcpp::as<arma::vec>(Rcpp::as<Rcpp::List>(myList["meas2"])[i]);
myMult[i] = arma::sum(meas1_i)*arma::sum(meas2_i);
myDiv[i] = arma::sum(meas1_i)/arma::sum(meas2_i);
}
return Rcpp::List::create(Rcpp::Named("myMult") = myMult,
Rcpp::Named("myDiv") = myDiv);
}
위의 기능을 더 빠르게 만들 수있는 방법은 무엇입니까? 나는 특히 코드에 입력 및 출력 목록을 유지하는 아이디어를 찾고 있지만 (목록을 다루는 내 프로그램에서는 불가피하기 때문에) 약간의 오버 헤드 시간을 줄이기위한 몇 가지 트릭이 있습니다. 내가 생각한 한 가지는 :
Rcpp::List mySlowListFn(const Rcpp::List& myList, int nSub)
도와 주셔서 대단히 감사합니다.
첫째, 목록에 대한 복사 의미는 R의 최신 버전에서 변경되었습니다 (확실히 최신 R-devel에서는 R 3.1.0으로 만들 었는지 확실하지 않음). 이로 인해 목록의 얕은 복사본 이 만들어지고 내부 요소가 나중에 복사됩니다. 수정 된 경우. 이전 버전의 R을 실행하는 경우 더 비싼 목록 복사 의미 체계가 방해받을 가능성이 큽니다.
즉, 벤치 마크를 사용하여 추가 속도를 위해 함수를 다시 작성하는 방법은 다음과 같습니다. sourceCpp
자신의 컴퓨터에서 비교할 수 있습니다.
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::List mySlowListFn(Rcpp::List myList, int nSub){
arma::vec myMult(nSub);
arma::vec myDiv(nSub);
for (int i = 0; i < nSub; i++){
arma::vec meas1_i = Rcpp::as<arma::vec>(Rcpp::as<Rcpp::List>(myList["meas1"])[i]);
arma::vec meas2_i = Rcpp::as<arma::vec>(Rcpp::as<Rcpp::List>(myList["meas2"])[i]);
myMult[i] = arma::sum(meas1_i)*arma::sum(meas2_i);
myDiv[i] = arma::sum(meas1_i)/arma::sum(meas2_i);
}
return Rcpp::List::create(Rcpp::Named("myMult") = myMult,
Rcpp::Named("myDiv") = myDiv);
}
// [[Rcpp::export]]
Rcpp::List myFasterListFn(Rcpp::List myList, int nSub) {
Rcpp::NumericVector myMult = Rcpp::no_init(nSub);
Rcpp::NumericVector myDiv = Rcpp::no_init(nSub);
Rcpp::List meas1 = myList["meas1"];
Rcpp::List meas2 = myList["meas2"];
for (int i = 0; i < nSub; i++) {
arma::vec meas1_i(
REAL(VECTOR_ELT(meas1, i)), Rf_length(VECTOR_ELT(meas1, i)), false, true
);
arma::vec meas2_i(
REAL(VECTOR_ELT(meas2, i)), Rf_length(VECTOR_ELT(meas2, i)), false, true
);
myMult[i] = arma::sum(meas1_i) * arma::sum(meas2_i);
myDiv[i] = arma::sum(meas1_i) / arma::sum(meas2_i);
}
return Rcpp::List::create(
Rcpp::Named("myMult") = myMult,
Rcpp::Named("myDiv") = myDiv
);
}
/*** R
library(microbenchmark)
lappend <- function(lst, ...){
lst <- c(lst, list(...))
return(lst)
}
nSub <- 30
n <- 10
meas1 <- list()
meas2 <- list()
for (i in 1:nSub){
meas1 <- lappend(meas1, rnorm(n))
meas2 <- lappend(meas2, rnorm(n))
}
myList <- list(meas1 = meas1, meas2 = meas2)
x1 <- mySlowListFn(myList, nSub)
x2 <- myFasterListFn(myList, nSub)
microbenchmark(
mySlowListFn(myList, nSub),
myFasterListFn(myList, nSub)
)
*/
나에게 준다
> library(microbenchmark)
> lappend <- function(lst, ...){
+ lst <- c(lst, list(...))
+ return(lst)
+ }
> nSub <- 30
> n <- 10
> meas1 <- list()
> meas2 <- list()
> for (i in 1:nSub){
+ meas1 <- lappend(meas1, rnorm(n))
+ meas2 <- lappend(meas2, rnorm(n))
+ }
> myList <- list(meas1 = meas1, meas2 = meas2)
> x1 <- mySlowListFn(myList, nSub)
> x2 <- myFasterListFn(myList, nSub)
> microbenchmark(
+ mySlowListFn(myList, nSub),
+ myFasterListFn(myList, nSub)
+ )
Unit: microseconds
expr min lq median uq max neval
mySlowListFn(myList, nSub) 14.772 15.4570 16.0715 16.7520 42.628 100
myFasterListFn(myList, nSub) 4.502 5.0675 5.2470 5.8515 18.561 100
미래 버전 Rcpp
과 Rcpp11
것이다 ListOf<T>
적절한 의미가 밖으로 다림질 한 후 훨씬 쉽게, 우리가 사전에 내부 유형을 알고 목록과 상호 작용을 할 것이다 클래스를.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다