dqrng with Rcpp for drawing from a normal and a binomial distribution

前端 未结 1 421
暗喜
暗喜 2021-01-28 11:45

I\'m trying to learn how to draw random numbers from a normal and a binomial distribution from within a Rcpp OpenMP loop.

I wrote the following code using R::rnorm

相关标签:
1条回答
  • 2021-01-28 12:32

    A simple solution would be to create a new distribution object within the loop:

    // [[Rcpp::depends(dqrng, BH, RcppArmadillo)]]
    #include <RcppArmadillo.h>
    #include <boost/random/binomial_distribution.hpp>
    #include <xoshiro.h>
    #include <dqrng_distribution.h>
    // [[Rcpp::plugins(openmp)]]
    #include <omp.h>
    
    // [[Rcpp::plugins(cpp11)]]
    
    // [[Rcpp::export]]
    arma::mat parallel_random_matrix(int n, int m, int ncores, double p=0.5) {
      dqrng::xoshiro256plus rng(42);
      arma::mat out(n,m);
      // ok to use rng here
    
    #pragma omp parallel num_threads(ncores)
    {
      dqrng::xoshiro256plus lrng(rng);      // make thread local copy of rng 
      lrng.jump(omp_get_thread_num() + 1);  // advance rng by 1 ... ncores jumps 
    
    #pragma omp for
      for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
          // p can be a function of i and j
          boost::random::binomial_distribution<int> dist(1,p);
          auto gen = std::bind(dist, std::ref(lrng));
          out(j,i) = gen();
        }
      }
    }
      // ok to use rng here
      return out;
    }
    
    /*** R
    parallel_random_matrix(5, 5, 4, 0.75)
    */
    

    This way you can make p depend on i and j. It might be more efficient to keep one global dist object and reconfigure it within the loop, see here for a similar question.

    0 讨论(0)
提交回复
热议问题