Search code examples
rcpparrayfire

random shuffle in RcppArrayFire


I am experiencing trouble getting this example to run correctly. Currently it produces the same random sample for every iteration and seed input, despite the seed changing as shown by af::getSeed().

#include "RcppArrayFire.h"
#include <random>

using namespace Rcpp;
using namespace RcppArrayFire;

// [[Rcpp::export]]
af::array random_test(RcppArrayFire::typed_array<f64> theta, int counts, int seed){

  const int theta_size = theta.dims()[0];

  af::array out(counts, theta_size, f64);

  for(int f = 0; f < counts; f++){

    af::randomEngine engine;
    af_set_seed(seed + f);
    //Rcpp::Rcout << af::getSeed();
    af::array out_temp = af::randu(theta_size, u8, engine);

    out(f, af::span) = out_temp;
    // out(f, af::span) = theta(out_temp);
  }
return out;
}


/*** R
theta <- 1:10
random_test(theta, 5, 1)
random_test(theta, 5, 2)
*/

Solution

  • The immediate problem is that you are creating a random engine within each iteration of the loop but set the seed of the global random engine. Either you set the seed of the local engine via engine.setSeed(seed), or you get rid of the local engine all together, letting af::randu default to using the global engine.

    However, it would still be "unusual" to change the seed during each step of the loop. Normally one sets the seed only once, e.g.:

    // [[Rcpp::depends(RcppArrayFire)]]
    #include "RcppArrayFire.h"
    
    // [[Rcpp::export]]
    af::array random_test(RcppArrayFire::typed_array<f64> theta, int counts, int seed){
    
        const int theta_size = theta.dims()[0];
    
        af::array out(counts, theta_size, f64);
        af::setSeed(seed);
    
        for(int f = 0; f < counts; f++){
    
            af::array out_temp = af::randu(theta_size, u8);
            out(f, af::span) = out_temp;
        }
        return out;
    }
    

    BTW, it makes sense to parallelize this as long as your device has enough memory. For example, you could generate a random counts x theta_size matrix in one go using af::randu(counts, theta_size, u8).