Closed. This question needs to be more focused。它当前不接受答案。
想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
3年前关闭。
我想使用
现在,让我们生成一些数据:
接下来,我们计算并检查每个对象的总和,以确保它们都相等:
最后,我们在每个函数上运行一个微基准测试:
从微基准测试中,我们有:
因此,通过
Q.E.D?
想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
3年前关闭。
我想使用
Rcpp::NumericMatrix
作为将遍历它的C ++函数的参数类型。我现在是否应该将Rcpp::NumericMatrix
的全部内容复制到C样式的数组中以具有良好的性能,还是在C ++循环中多次使用Rcpp::NumericMatrix
的[]运算符还快吗?是否有比使用随机访问遍历Rcpp::NumericMatrix
实例更快的方法? 最佳答案
由于这是一个悠闲的日子,因此我无法快速找到基准(Rcpp Sugar第4节是TBD,第6节是TBD)...我的好奇心...让我们一起去吧!
首先,要访问NumericMatrix
的c样式数组,我们首先需要将NumericMatrix
转换为std::vector
。从std::vector
,我们可以提取一个由指针控制的c样式数组。在这种结构下,我们将完全复制数据。尽管如此,我们可以调查提出的问题,然后再调查一些。
以下是针对四个不同组件的功能快速测试套件:
c样式数组std::accumulate
循环std::vector
使用NumericMatrix
进行元素访问
现在,我在纯c样式函数中进行了“欺骗”操作,因为我没有尝试通过sizeof()
计算从自身计算数组的大小。 (这可能会引起一些问题,因为应该指定指针大小...)
让我们检查一下功能测试套件。
#include <Rcpp.h>
// [[Rcpp::export]]
double c_for_access(const Rcpp::NumericMatrix& x){
// Cast to std vector
std::vector<double> v = Rcpp::as<std::vector<double> >(x);
// Convert to c-style pointer
double* pv = &v[0];
// Sum using a pointer
double sum = 0;
for(unsigned int i = 0; i < v.size(); i++){
sum += *(pv+i);
}
return sum;
}
// [[Rcpp::export]]
double stl_for_access(const Rcpp::NumericMatrix& x){
// Cast to std vector
std::vector<double> v = Rcpp::as<std::vector<double> >(x);
// Summing Operation
double sum = 0;
for(unsigned int i = 0; i < v.size(); i++){
sum += v[i];
}
return sum;
}
// [[Rcpp::export]]
double stl_access(const Rcpp::NumericMatrix& x){
// Cast to STL Vector
std::vector<double> v = Rcpp::as<std::vector<double> >(x);
// Use STL to return sum
return std::accumulate(v.begin(), v.end(), 0.0); // Important to specify 0.0 instead of 0.
}
// [[Rcpp::export]]
double matrix_access(const Rcpp::NumericMatrix& x) {
// Define matrix information and looping variables.
unsigned int r = x.nrow(), c = x.ncol(), i, j;
// Sum elements
double sum = 0;
for(i = 0; i < r; i++){
for(j = 0; j < c; j++){
sum += x(i,j);
}
}
return sum;
}
现在,让我们生成一些数据:
# Set seed for reproducibility
set.seed(1337)
# Create a 100x100 matrix
x = matrix(rnorm(10000),nrow=100,ncol=100)
接下来,我们计算并检查每个对象的总和,以确保它们都相等:
# Calculate each object
oracle = sum(x) # Oracle is the correct answer given by R
c.out = c_for_access(x)
stl.loop = stl_for_access(x)
stl.lib = stl_access(x)
rcpp.pure = matrix_access(x)
# Check all equal
all.equal(oracle, c.out)
all.equal(oracle, stl.loop)
all.equal(oracle, stl.lib)
all.equal(oracle, rcpp.pure)
最后,我们在每个函数上运行一个微基准测试:
# install.packages("microbenchmark")
microbenchmark::microbenchmark(oracle = sum(x),
c.out = c_for_access(x),
stl.loop = stl_for_access(x),
stl.lib = stl_access(x),
rcpp.pure = matrix_access(x)
)
从微基准测试中,我们有:
Unit: microseconds
expr min lq mean median uq max neval
oracle 8.105 8.705 9.11406 8.7060 9.0060 24.016 100
c.out 30.319 31.220 31.75767 31.2210 31.5210 54.636 100
stl.loop 30.320 30.921 32.56819 31.2210 31.5210 55.836 100
stl.lib 30.319 30.920 31.64063 31.2205 31.6705 50.133 100
rcpp.pure 9.907 10.807 10.95122 10.8070 11.1070 12.909 100
因此,通过
Rcpp
进行的矩阵求和比R慢约2微秒,但比std::vector
和c样式的数组设置要快得多。Q.E.D?
10-06 05:18