Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何正确使用RcppThread并行化for循环_C++_R_Rcpp - Fatal编程技术网

C++ 如何正确使用RcppThread并行化for循环

C++ 如何正确使用RcppThread并行化for循环,c++,r,rcpp,C++,R,Rcpp,我正在尝试将for循环与RcppThread并行化。未配置的版本如下所示: IntegerVector simulate_pos(NumericVector x_pop, NumericVector y_pop, int n_studies, int sample_size_min,

我正在尝试将for循环与RcppThread并行化。未配置的版本如下所示:

IntegerVector simulate_pos(NumericVector x_pop,
                           NumericVector y_pop,
                           int n_studies,
                           int sample_size_min,
                           int sample_size_max,
                           bool replace,
                           float lower_limit,
                           float upper_limit){
  IntegerVector pos(n_studies);
  int npop = x_pop.size();
  NumericVector index_pop(npop);
  for (int i = 0; i < npop; i++){
    index_pop[i] = i;
  }

  // HERE IS THE LOOP-------------------------------------------------
  for (int k = 0; k < n_studies; k++){
    pos[k] = simulate_one_pos(x_pop, y_pop, index_pop, sample_size_min,
                              sample_size_max, replace, lower_limit,
                              upper_limit);
  }
  // ------------------------------------------------------------------

  return(pos);
}
PS:也尝试使用
pool.pushReturn
,但结果相同

编辑:问题确实是使用Rcpp数据结构(
NumericVector
)。当用
std::vector
替换所有这些变量时,运行良好。现在,如果没有Rcpp糖,我必须找到一种方法,如何从
std::vector
(在我在循环中调用的函数中)进行采样,但这显然是值得的

问题是多个线程同时读取相同的内存地址吗?或者,Rcpp数据结构(例如NumericVector)是否导致问题

我倾向于说“可能”。请参阅包RcppParallel中的优秀文档,以及它是如何通过小示例构建的

我知道这听起来很不吸引人,但我真的建议从一个非常小的函数开始构建,可能会慢慢添加零个或一个参数,并确保当您跨越添加任何R-可访问或创建的内存的桥梁时,事情仍能按预期工作

可悲的是,我们不能在内部R代码和“希望最好”之间打一个并行的外循环。OpenMP和friends的要求更高,而R的单线程特性施加了更多的限制

(您可能知道,当然可以通过R over R函数运行更高级别的并行性,但这是一个不同的主题和方法。)

您这样写吗

问题是多个线程同时读取相同的内存地址吗?或者,Rcpp数据结构(例如NumericVector)是否导致问题

我倾向于说“可能”。请参阅包RcppParallel中的优秀文档,以及它是如何通过小示例构建的

我知道这听起来很不吸引人,但我真的建议从一个非常小的函数开始构建,可能会慢慢添加零个或一个参数,并确保当您跨越添加任何R-可访问或创建的内存的桥梁时,事情仍能按预期工作

可悲的是,我们不能在内部R代码和“希望最好”之间打一个并行的外循环。OpenMP和friends的要求更高,而R的单线程特性施加了更多的限制


(您可能知道,当然可以通过R over R函数运行更高级别的并行性,但这是一个不同的主题和方法。)

您没有展示的一个关键部分是
simulate\u-one\u-pos
的定义。此外,正如@Dirk所指出的,从一个较小的例子开始可以带来很大的好处。您没有展示的一个关键部分是
simulate\u one\u pos
的定义。此外,正如@Dirk所指出的,从一个较小的例子开始可以获得巨大的回报。非常感谢!我不使用更高级别的并行性,因为我需要某种进度指示器(模拟运行相当长)。添加一个较小的函数是有意义的,但对我来说,问题在于如何正确地测试它。有时代码只会运行十几次而没有错误,然后再次中断,尽管我没有做任何更改。这对我来说有点不可预测。我想在我的经验水平上最好不要弄乱它,但我至少会尝试摆脱Rcpp数据结构。再次感谢是的,这是一种“额外的兴奋”:错误并不总是表现出来。最安全的方法是显式使用非R/非Rcpp数据结构。。。我喜欢这种态度(“额外的兴奋”),看到激情是件好事。问题确实是使用Rcpp数据结构,我替换了它们,现在它运行得很好。耶!有没有预感到复制的成本是多少?“可忽略的”?(请随意投票和/或接受,让业力四处传播……)我可以不用Rcpp数据结构就可以做到。但不幸的是,总的来说,似乎有太多的开销,单线程实际上更快。☉_☉ 我找到了一个可以更好控制的更简单的解决方案,我使用R中的futures在后台运行几个模拟,同时主R进程使用cpp中的ProgesBar启动另一个模拟。显然,所有模拟都在相似的时间结束。我获得了速度优势和进度条,没有“额外的刺激”。非常感谢!我不使用更高级别的并行性,因为我需要某种进度指示器(模拟运行相当长)。添加一个较小的函数是有意义的,但对我来说,问题在于如何正确地测试它。有时代码只会运行十几次而没有错误,然后再次中断,尽管我没有做任何更改。这对我来说有点不可预测。我想在我的经验水平上最好不要弄乱它,但我至少会尝试摆脱Rcpp数据结构。再次感谢是的,这是一种“额外的兴奋”:错误并不总是表现出来。最安全的方法是显式使用非R/非Rcpp数据结构。。。我喜欢这种态度(“额外的兴奋”),看到激情是件好事。问题确实是使用Rcpp数据结构,我替换了它们,现在它运行得很好。耶!有没有预感到复制的成本是多少?“可忽略的”?(请随意投票和/或接受,让业力四处传播……)我可以不用Rcpp数据结构就可以做到。但不幸的是,总的来说,似乎有太多的开销,单线程实际上更快。☉_☉ 我找到了一个可以更好控制的更简单的解决方案,我使用R中的futures在后台运行几个模拟,同时主R进程使用cpp中的ProgesBar启动另一个模拟。显然,所有模拟都在相似的时间结束。我获得了速度优势和进度条,没有“额外的刺激”。
std::vector<int> simulate_pos(NumericVector x_pop,
                              NumericVector y_pop,
                              int n_studies,
                              int sample_size_min,
                              int sample_size_max,
                              bool replace,
                              float lower_limit,
                              float upper_limit,
                              int n_threads){
  std::vector<int> pos(n_studies);
  int npop = x_pop.size();
  NumericVector index_pop(npop);
  for (int i = 0; i < npop; i++){
    index_pop[i] = i;
  }
  
  // HERE IS THE LOOP-------------------------------------------------
  RcppThread::parallelFor(0, pos.size(), [&] (int i){
    pos[i] = simulate_one_pos(x_pop, y_pop, index_pop, sample_size_min,
                              sample_size_max, replace, lower_limit,
                              upper_limit);
  });
  // -----------------------------------------------------------------

  return(pos);
}
devtools::install_github("johannes-titz/fastpos@rcppthread")

pop <- fastpos::create_pop(0.5, 1e5)
x <- pop[,1]
y <- pop[,2]
lower_limit <- 0.4
upper_limit <- 0.6
n_studies <- 50
sample_size_min <- 20
sample_size_max <- 1000

res <- fastpos::simulate_pos(x, y, n_studies, sample_size_min, sample_size_max, TRUE, lower_limit,
                             upper_limit, 4)