rcpp函数中的清理时间长

时间:2018-10-30 19:23:25

标签: 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>> 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;
}

这是我捕获system.time捕获的运行时间以及计时结果的方法:

for (type in c(0, 1))
{
  for (n in c(10, 50, 100, 200, 500, 1000))
  {
    this_result = system.time(cpp_test1(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   
0.004     0        0.006   0          0         0    10  
0.152     0        0.151   0          0         0    50  
0.616     0        0.617   0          0         0    100 
2.624     0.008    2.631   0          0         0    200 
17.828    0.004    17.836  0          0         0    500 
58.844    0.06     58.907  0          0         0    1000
0.008     0        0.009   0          0         1    10  
0.004     0        0.003   0          0         1    50  
0.008     0        0.006   0          0         1    100 
0.012     0        0.013   0          0         1    200 
0.024     0        0.024   0          0         1    500 
0.052     0        0.049   0          0         1    1000   

我还注意到,似乎没有花费很多时间来填充地图结构,“完成的工作”打印输出很快就会被打印出,并且大部分时间都花在了某种清理上

是否有人对使用unordered_map时清理工作的漫长等待时间有所了解?

1 个答案:

答案 0 :(得分:1)

记录我的发现的部分答案:

  • 在两种情况下,我都可以使用-O2重现g ++ 6.2版和clang ++ 3.8版的问题。
  • 仅在std::unordered_mapRcpp::NumericVectorRcpp::IntegerVector的组合中发生。
  • 使用std::mapboost::unordered_map代替std::unordered_map消除了此问题。就像使用std::vector<double>而不是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)
*/

结果:

            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