C++ rcpp功能中的长清理时间
观察到,在下面的rcpp函数中,当它以type==0运行时(使用std::unordered_map而不是std::map),运行时间会非线性增加C++ rcpp功能中的长清理时间,c++,r,rcpp,C++,R,Rcpp,观察到,在下面的rcpp函数中,当它以type==0运行时(使用std::unordered_map而不是std::map),运行时间会非线性增加 // [[Rcpp::export]] void cpp_test1(int a, int b, int type) { if (type==0) { std::unordered_map<int, std::unordered_map<int, NumericVector>> exposu
// [[Rcpp::export]]
void cpp_test1(int a, int b, int type)
{
if (type==0)
{
std::unordered_map<int, std::unordered_map<int, NumericVector>> exposure_by_date_name;
for (int i=0; i < a; ++i)
{
for (int j=0; j < b; ++j)
{
exposure_by_date_name[i][j] = NumericVector(68);
}
}
Rcpp::Rcout << "done work " << std::endl;
} else {
std::map<int, std::map<int, NumericVector>> exposure_by_date_name;
for (int i=0; i < a; ++i)
{
for (int j=0; j < b; ++j)
{
exposure_by_date_name[i][j] = NumericVector(68);
}
}
Rcpp::Rcout << "done work " << std::endl;
}
return;
}
我还注意到,这些时间似乎并没有花在填充地图结构上,“完成的工作”打印出来会很快打印出来,而且大部分时间都花在可能的某种清理上
有人了解到在使用无序地图的情况下,清理过程中等待的时间很长吗?部分答案记录了我的发现:
- 我可以在g++版本6.2和clang++版本3.8中重现这个问题,在这两种情况下都使用
-O2
- 它仅适用于
和std::unordered_map
或Rcpp::NumericVector
的组合Rcpp::IntegerVector
- 使用
或std::map
而不是boost::unordered_map
可以消除该问题。使用std::unordered_map
而不是std::vector
也是如此Rcpp::NumericVector
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::depends(BH)]]
#include <boost/unordered_map.hpp>
template<typename T, typename V>
void map_test(int a, int b) {
T exposure_by_date_name;
for (int i=0; i < a; ++i)
{
for (int j=0; j < b; ++j)
{
exposure_by_date_name[i][j] = V(68);
}
}
Rcpp::Rcout << "done work" << std::endl;
}
// [[Rcpp::export]]
void cpp_test2(int a, int b, int type) {
if (type == 0) {
map_test<std::unordered_map<int, std::unordered_map<int, Rcpp::NumericVector>>, Rcpp::NumericVector>(a, b);
} else if (type == 1) {
map_test<std::map<int, std::map<int, Rcpp::NumericVector>>, Rcpp::NumericVector>(a, b);
} else if (type == 2) {
map_test<std::unordered_map<int, std::unordered_map<int, std::vector<double>>>, std::vector<double>>(a, b);
} else if (type == 3) {
map_test<boost::unordered_map<int, boost::unordered_map<int, Rcpp::NumericVector>>, Rcpp::NumericVector>(a, b);
} else if (type == 4) {
map_test<std::unordered_map<int, std::unordered_map<int, Rcpp::IntegerVector>>, Rcpp::IntegerVector>(a, b);
}
Rcpp::Rcout << "function done" << std::endl;
}
/*** R
result = vector(mode = "list")
for (type in c(0, 1, 2, 3, 4))
{
for (n in c(10, 50, 100, 200, 500))
{
this_result = system.time(cpp_test2(100, n, type))
this_result$type = type
this_result$n = n
result = rbind(result, this_result)
print(result)
}
}
print(result)
*/
你在测试优化版还是未优化版?好问题。。。我对rcpp比较陌生,我甚至不知道如何控制它来构建优化或不优化的cpp代码。。。我如何判断/控制这一点以及默认值是什么?如果你在寻找性能,我想我在某个地方读到过,最好使用
boost::unordered\u map
而不是std::unordered\u map
。您可以通过包{BH}获得boost头文件。我可以通过优化的构建(通过调用Rcpp::sourceCpp
,使用选项verbose=TRUE
)重现问题。如果我使用std::vector
而不是Rcpp::NumericVector
),它就会消失。疯狂。在您的系统上,什么是sizeof(std::vector)
vssizeof(Rcpp::NumericVector)
?这会导致不同的分配/负载因子策略吗?@KonradRudolph,sizeof(std::vector)
为24,sizeof(Rcpp::NumericVector)
为16。
#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::depends(BH)]]
#include <boost/unordered_map.hpp>
template<typename T, typename V>
void map_test(int a, int b) {
T exposure_by_date_name;
for (int i=0; i < a; ++i)
{
for (int j=0; j < b; ++j)
{
exposure_by_date_name[i][j] = V(68);
}
}
Rcpp::Rcout << "done work" << std::endl;
}
// [[Rcpp::export]]
void cpp_test2(int a, int b, int type) {
if (type == 0) {
map_test<std::unordered_map<int, std::unordered_map<int, Rcpp::NumericVector>>, Rcpp::NumericVector>(a, b);
} else if (type == 1) {
map_test<std::map<int, std::map<int, Rcpp::NumericVector>>, Rcpp::NumericVector>(a, b);
} else if (type == 2) {
map_test<std::unordered_map<int, std::unordered_map<int, std::vector<double>>>, std::vector<double>>(a, b);
} else if (type == 3) {
map_test<boost::unordered_map<int, boost::unordered_map<int, Rcpp::NumericVector>>, Rcpp::NumericVector>(a, b);
} else if (type == 4) {
map_test<std::unordered_map<int, std::unordered_map<int, Rcpp::IntegerVector>>, Rcpp::IntegerVector>(a, b);
}
Rcpp::Rcout << "function done" << std::endl;
}
/*** R
result = vector(mode = "list")
for (type in c(0, 1, 2, 3, 4))
{
for (n in c(10, 50, 100, 200, 500))
{
this_result = system.time(cpp_test2(100, n, type))
this_result$type = type
this_result$n = n
result = rbind(result, this_result)
print(result)
}
}
print(result)
*/
user.self sys.self elapsed user.child sys.child type n
this_result 0.004 0 0.003 0 0 0 10
this_result 0.096 0 0.097 0 0 0 50
this_result 0.444 0 0.443 0 0 0 100
this_result 1.572 0.004 1.574 0 0 0 200
this_result 18.9 0 18.899 0 0 0 500
this_result 0.004 0 0.002 0 0 1 10
this_result 0.004 0 0.004 0 0 1 50
this_result 0.004 0 0.006 0 0 1 100
this_result 0.008 0 0.009 0 0 1 200
this_result 0.028 0 0.026 0 0 1 500
this_result 0.004 0 0.001 0 0 2 10
this_result 0.004 0 0.002 0 0 2 50
this_result 0.004 0 0.004 0 0 2 100
this_result 0.008 0 0.007 0 0 2 200
this_result 0.02 0 0.018 0 0 2 500
this_result 0.004 0 0.001 0 0 3 10
this_result 0 0 0.002 0 0 3 50
this_result 0.004 0 0.004 0 0 3 100
this_result 0.008 0 0.008 0 0 3 200
this_result 0.02 0 0.022 0 0 3 500
this_result 0.004 0 0.003 0 0 4 10
this_result 0.096 0 0.093 0 0 4 50
this_result 0.376 0 0.376 0 0 4 100
this_result 1.508 0 1.508 0 0 4 200
this_result 18.896 0.024 18.916 0 0 4 500