我在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);
}
答案 0 :(得分:4)
由于我不确切知道你的代码是做什么的,所以我从头开始可以看到两件事:
您从R环境调用的函数是testFromontcpp(...)。我建议这个函数应该有SEXP值作为参数。那些S-Expressions指向R的内存。如果你不使用SEXP,那么两个矩阵都将被复制: 考虑1000x1000矩阵,这意味着您在R中保存了100万个条目,这些条目被复制到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之间会略快一些。