Parallel processing Rcpp导致SEGFULT RcppArmadillo不存在

Parallel processing Rcpp导致SEGFULT RcppArmadillo不存在,parallel-processing,openmp,rcpp,armadillo,Parallel Processing,Openmp,Rcpp,Armadillo,我目前正在尝试并行化现有的分层MCMC采样方案。我的大部分(现在是顺序的)源代码都是用RcppArmadillo编写的,所以我也希望使用这个并行化框架 在开始并行化我的代码之前,我读了几篇关于Rcpp/Openmp的博客文章。在大多数博客文章(例如)中,作者警告线程安全、R/Rcpp数据结构和Openmp的问题。到目前为止,我读过的所有帖子的底线是,R和Rcpp不是线程安全的,不要从omp并行pragma中调用它们 因此,当从R调用时,以下Rcpp示例会导致segfault: #include

我目前正在尝试并行化现有的分层MCMC采样方案。我的大部分(现在是顺序的)源代码都是用RcppArmadillo编写的,所以我也希望使用这个并行化框架

在开始并行化我的代码之前,我读了几篇关于Rcpp/Openmp的博客文章。在大多数博客文章(例如)中,作者警告线程安全、R/Rcpp数据结构和Openmp的问题。到目前为止,我读过的所有帖子的底线是,R和Rcpp不是线程安全的,不要从omp并行pragma中调用它们

因此,当从R调用时,以下Rcpp示例会导致segfault:

#include <Rcpp.h>
#include <omp.h>

using namespace Rcpp; 

double rcpp_rootsum_j(Rcpp::NumericVector x)
{
  Rcpp::NumericVector ret = sqrt(x);
  return sum(ret);
}

// [[Rcpp::export]]
Rcpp::NumericVector rcpp_rootsum(Rcpp::NumericMatrix x, int cores = 2)
{
  omp_set_num_threads(cores);
  const int nr = x.nrow();
  const int nc = x.ncol();
  Rcpp::NumericVector ret(nc);

  #pragma omp parallel for shared(x, ret)
  for (int j=0; j<nc; j++)
    ret[j] = rcpp_rootsum_j(x.column(j));

  return ret;
}
有趣的是,语义等价的代码不会导致segfault

在研究过程中我注意到的第二件事是,前面提到的语句(R和Rcpp不是线程安全的,不要从omp并行pragma中调用它们)似乎并不总是正确的。例如,下一个示例中的调用不会导致segfault,尽管我们正在读取和写入Rcpp数据结构

#include <Rcpp.h>
#include <omp.h>

// [[Rcpp::export]]
Rcpp::NumericMatrix rcpp_sweep_(Rcpp::NumericMatrix x, Rcpp::NumericVector vec)
{
  Rcpp::NumericMatrix ret(x.nrow(), x.ncol());

  #pragma omp parallel for default(shared)
  for (int j=0; j<x.ncol(); j++)
  {
    #pragma omp simd
    for (int i=0; i<x.nrow(); i++)
      ret(i, j) = x(i, j) - vec(i);
  }

  return ret;
}

在我看来,第一个和第二个例子显然干扰了我在第一点和第二点所作的假设。例三也让我头疼,因为对我来说,这就像是一个打电话给R

我的最新问题

  • 示例1/2和我的第一个代码示例之间的区别在哪里
  • 我在哪里迷失在我的假设中 除了RcppGallery和GitHub之外,对于如何更好地了解Rcpp和OpenMP的交互有什么建议吗

    在开始并行化我的代码之前,我读了几篇关于Rcpp/Openmp的博客文章。在大多数博客文章(如Drew Schmidt、wrathematics)中,作者警告线程安全、R/Rcpp数据结构和Openmp的问题。到目前为止,我读过的所有帖子的底线是,R和Rcpp不是线程安全的,不要从omp并行pragma中调用它们

    这是R本身不具有线程安全性的一个众所周知的限制。这意味着您无法回调或触发R事件,除非您非常小心,否则Rcpp可能会发生这种情况。更简单地说:约束与Rcpp无关,它只是意味着您不能通过Rcpp盲目地进入OpenMP。但是如果你小心的话,你可以

    我们有无数的OpenMP和相关工具成功的例子,它们在CRAN、Rcpp Gallery和RcppParallel等扩展包中都有

    你在这个话题上的选择似乎很有选择性,你最终的结果是在错误和误导之间。我建议您在处理OpenMP/RcppParallel的问题时,参考上面的几个例子。或者如果您赶时间:在RcppParallel文档中查找
    RVector
    RMatrix

    资源:

    <> P>和您最大的资源可能是GITHUB的一些有针对性的搜索,包括R、C++和OpenMP的代码。它将引导您找到许多工作示例

    在开始并行化我的代码之前,我读了几篇关于Rcpp/Openmp的博客文章。在大多数博客文章(如Drew Schmidt、wrathematics)中,作者警告线程安全、R/Rcpp数据结构和Openmp的问题。到目前为止,我读过的所有帖子的底线是,R和Rcpp不是线程安全的,不要从omp并行pragma中调用它们

    这是R本身不具有线程安全性的一个众所周知的限制。这意味着您无法回调或触发R事件,除非您非常小心,否则Rcpp可能会发生这种情况。更简单地说:约束与Rcpp无关,它只是意味着您不能通过Rcpp盲目地进入OpenMP。但是如果你小心的话,你可以

    我们有无数的OpenMP和相关工具成功的例子,它们在CRAN、Rcpp Gallery和RcppParallel等扩展包中都有

    你在这个话题上的选择似乎很有选择性,你最终的结果是在错误和误导之间。我建议您在处理OpenMP/RcppParallel的问题时,参考上面的几个例子。或者如果您赶时间:在RcppParallel文档中查找
    RVector
    RMatrix

    资源:


    <> P>和您最大的资源可能是GITHUB的一些有针对性的搜索,包括R、C++和OpenMP的代码。它将引导您找到许多工作示例。

    感谢您的快速回复!也许我的问题措辞含糊不清:我不想把这种行为归咎于Rcpp,而且我知道有很多R-packages可以使用openmp代码。我的问题很简单:我只是不明白为什么称arma::col(I)或Rcpp::(I,j)而不是Rcpp::.colm(I)是安全的。不幸的是,引用的资料中没有一个明确提到这个问题;GitHub上的评论也是如此[search:Rcpp&Openmp]。错误的假设:仅仅因为第二种方法没有立即失效并不能证明它是合理的或推荐的。通过我们选择的(有效的)方法,RcppArmadillo对象仍然使用R内存。所以,请去阅读我提供的参考资料。再次感谢您的时间!周末,我更仔细地研究了您向我指出的Rcpp图库中的OpenMP示例。由于一些例子让我更加困惑,我已经编辑了我的原始问题。如果你有一个新问题,最好用一个简短的可复制的例子提出一个新的、有重点的问题。这不是一个按需教程网站。我已经给你们指出了很多工作示例。好的,明白了。我将创建一个新问题@德克:我知道你的例子是有效的(!)我只是不知道为什么,我不能
    #include <Rcpp.h>
    #include <omp.h>
    
    // [[Rcpp::export]]
    Rcpp::NumericMatrix rcpp_sweep_(Rcpp::NumericMatrix x, Rcpp::NumericVector vec)
    {
      Rcpp::NumericMatrix ret(x.nrow(), x.ncol());
    
      #pragma omp parallel for default(shared)
      for (int j=0; j<x.ncol(); j++)
      {
        #pragma omp simd
        for (int i=0; i<x.nrow(); i++)
          ret(i, j) = x(i, j) - vec(i);
      }
    
      return ret;
    }
    
    arma::mat temp_row_sub = temp_mat.rows(x-2, x+2);
    
    interMatrix(_, i) = MAT_COV(_, index_asset); // 3rd code example 3rd method
    
    thread_sum += R::dlnorm(i+j, 0.0, 1.0, 0); // subsection OpenMP support