我设置了以下的
struct
,试图准确地表示您的情况并促进基准测试:
#include <Rcpp.h>
struct runif_test {
size_t runs;
size_t each;
runif_test(size_t runs, size_t each)
: runs(runs), each(each)
{}
void pre_init() {
Rcpp::NumericVector v = no_init();
for (size_t i = 0; i < runs; i++) {
v = Rcpp::runif(each);
}
}
void post_init() {
for (size_t i = 0; i < runs; i++) {
Rcpp::NumericVector v = Rcpp::runif(each);
}
}
void gen_runif() {
Rcpp::NumericVector v = no_init();
for (size_t i = 0; i < runs; i++) {
std::generate_n(v.begin(), each, []() -> double {
return Rcpp::as<double>(Rcpp::runif(1));
});
}
}
inline Rcpp::NumericVector no_init() {
return Rcpp::NumericVector(Rcpp::no_init_vector(each));
}
};
我对以下导出函数进行了基准测试:
void do_pre(size_t runs, size_t each) {
runif_test obj(runs, each);
obj.pre_init();
}
void do_post(size_t runs, size_t each) {
runif_test obj(runs, each);
obj.post_init();
}
void do_gen(size_t runs, size_t each) {
runif_test obj(runs, each);
obj.gen_runif();
}
这是我得到的结果:
R> microbenchmark::microbenchmark(
do_pre(100, 10e4)
,do_post(100, 10e4)
,do_gen(100, 10e4)
,times=100L)
Unit: milliseconds
expr min lq mean median uq max neval
do_pre(100, 100000) 109.9187 125.0477 145.9918 136.3749 152.9609 337.6143 100
do_post(100, 100000) 103.1705 117.1109 132.9389 130.4482 142.7319 204.0951 100
do_gen(100, 100000) 810.5234 911.3586 1005.9438 986.8348 1062.7715 1501.2933 100
R> microbenchmark::microbenchmark(
do_pre(100, 10e5)
,do_post(100, 10e5)
,times=100L)
Unit: seconds
expr min lq mean median uq max neval
do_pre(100, 1000000) 1.355160 1.614972 1.740807 1.723704 1.815953 2.408465 100
do_post(100, 1000000) 1.198667 1.342794 1.443391 1.429150 1.519976 2.042511 100
所以,假设我正确理解并准确表达了你的第二个问题,
如果两个版本都分配一个新向量,我能否通过在标量模式下逐个生成随机数来改进呢?
使用我的gen_runif()
成员函数,我认为我们可以自信地说,这不是最佳方法 - 比另外两个函数慢约7.5倍。
更重要的是,回答您的第一个问题,似乎直接将新的
NumericVector
初始化并赋值给
Rcpp::runif(n)
的输出速度要快一些。我并不是C++专家,但我认为第二种方法(将其分配给新的本地对象)比第一种方法更快,因为采用了
复制省略。在第二种情况下,看起来好像创建了两个对象-位于
=
左侧的对象
v
和位于
=
右侧的(临时?rvalue?)对象,它是
Rcpp::runif()
结果。但实际上,编译器很可能会优化掉这个不必要的步骤-我认为这在我链接的文章中有所解释:
这至少是我对结果的解释。希望更熟练该语言的人能够确认/否定/纠正这个结论。