![](/img/trans.png)
[英]How can I speed up my Rcpp code, which only carries out simple operations?
[英]How could I speed up this Rcpp code?
我已經在R中實現了一個需要長時間運行的函數。 我已經成功地在R中對其進行了改進,但是現在我想使用Rcpp軟件包來加快它的速度。
我創建了以下Rcpp代碼。 不幸的是,與R代碼運行大約需要相同的時間。 因此,我想對此進行改進。 有誰知道如何改進這段代碼?
非常感謝!
#include <math.h>
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double kernelcpp(NumericVector a, NumericVector b, int N){
int i;
double sum=0.0;
for (i=0;i<N;i++){
if (a[i] > b[i])
sum+= a[i] - b[i];
else
sum+= b[i] - a[i];
}
return(exp( - sum));
}
// [[Rcpp::export]]
NumericVector testFromontcpp(NumericMatrix z1, NumericMatrix z2, int Nbootstrap){
// first element of TKeps = TK
int i,j,k,t;
int dim1 = z1.nrow();
int dim2 = z2.nrow();
double n1 = (double) dim1;
double n2 = (double) dim2;
int dimension = z1.ncol();
int N = dim1 + dim2;
NumericVector TKeps(Nbootstrap+1);
Rcpp::NumericMatrix bb(N,N);
double cc = 1 / (n1*n2*(n1+n2-2));
double a = sqrt(1/(n1*n1-n1)-cc);
double b = - sqrt(1/(n2*n2-n2)-cc);
for (i=0 ; i<N ; i++){
for (j=0 ; j<N ; j++){
if (i != j){
if (i < dim1) {
if (j < dim1){
bb(i,j) = kernelcpp(z1(i,_),z1(j,_),dimension);
} else {
bb(i,j) = kernelcpp(z1(i,_),z2(j-dim1,_),dimension);
}
}
else{
if (j < dim1){
bb(i,j) = kernelcpp(z2(i-dim1,_),z1(j,_),dimension);
} else {
bb(i,j) = kernelcpp(z2(i-dim1,_),z2(j-dim1,_),dimension);
}
}
}
}
}
TKeps(0)=0.0;
for (i=0 ; i<N ; i++){
for (j=0 ; j<N ; j++){
if (i != j){
if (i < dim1) {
if (j < dim1){
TKeps(0) += bb(i,j)* (a*a + cc);
} else {
TKeps(0) += bb(i,j) * (a*b + cc);
}
}
else{
if (j < dim1){
TKeps(0) += bb(i,j) * (a*b + cc);
} else {
TKeps(0) += bb(i,j) * (b*b + cc);
}
}
}
}
}
for (k=1 ; k<=Nbootstrap ; k++){
TKeps(k)=0;
int R[N];
for (i = 0 ; i < N ; i++)
R[i] = i;
for (i = 0; i < N - 1 ; i++) {
int j = i + rand() / (RAND_MAX / (N - i) + 1);
t = R[j];
R[j] = R[i];
R[i] = t;
}
for (i=0 ; i<N ; i++){
for (j=0 ; j<N ; j++){
if (i != j){
if (R[i] < n1) {
if (R[j] < n1){
TKeps(k) += bb(i,j) * (a*a + cc);
} else {
TKeps(k) += bb(i,j) * (a*b + cc);
}
} else{
if (R[j] < n1){
TKeps(k) += bb(i,j) * (b*a + cc);
} else {
TKeps(k) += bb(i,j) * (b*b + cc);
}
}
}
}
}
}
return(TKeps);
}
由於我不完全了解您的代碼的功能,因此我可以從頭開始看到兩件事:
您從R環境調用的函數是testFromontcpp(...)。 我建議該函數應將SEXP值作為參數。 這些S表達式是指向R的內存的指針。如果您不使用SEXP,則兩個矩陣都將被復制:考慮一個1000x1000的矩陣,這意味着您有100萬個R中保存的條目,這些條目被復制到C ++。 為此,請寫:
testFromontcpp(SEXP x,SEXP y,SEXP z){
NumericMatrix z1(x),z2(y);
int * Nbootstrap = INTEGER(z);
...}
注意:在for循環中,您不能使用i<Nbootstrap
。 您必須寫i<*Nbootstrap
!!!
到最后一點:在大學里的一項工作中,我也遇到了遍歷矩陣的問題。 在我的情況下,轉置矩陣然后進行計算要便宜得多。
希望能對您有所幫助。
最好,邁克爾
PS:談到第1點...我只是通過實現和使用SEXP對您的代碼進行了基准測試。 使用SEXP時,對於100x100矩陣(隨機數介於1到10之間),速度會稍快一些。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.