使用RcppEigen将随机状态传递给setRandom

时间:2014-05-23 13:18:37

标签: r eigen rcpp

有没有办法通过RcppEigen将随机状态传递给Eigen的setRandom,还是需要使用runif

以下是一个例子:

// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
using namespace Rcpp;
using  Eigen::MatrixXd;
using  Eigen::VectorXd;

// [[Rcpp::export]]
NumericVector fx() {
  RNGScope   scope;
  MatrixXd   x(3,2);
  x=x.setRandom();
  x.col(1)=as<VectorXd>(runif(3,0,1));

return wrap(x);
}

测试它:

set.seed(42); fx()
#           [,1]      [,2]
#[1,] -0.8105760 0.9148060
#[2,]  0.6498853 0.9370754
#[3,]  0.6221027 0.2861395

set.seed(42); fx()
#           [,1]      [,2]
#[1,] -0.9449154 0.9148060
#[2,]  0.8063267 0.9370754
#[3,] -0.0673205 0.2861395

请注意第2列(即runif)是如何重现的,但第1列(即setRandom)不是。

1 个答案:

答案 0 :(得分:3)

Eigen中的RNG与R的RNG正交。我们RNGScope处理R并允许您set.seed()如您所知;你对Eigen的RNG所做的是独立的。

特别是,您必须添加胶水以将Eigen的RNG注册为R的用户提供的RNG。默认情况下,R不知道Eigen,这在R用户期望R的RNG时是有意义的。

你的问题似乎是一个带有Eigen'问题的香草'编程,你无法初始化本征RNG。它与Rcpp无关。

编辑:以下是您的示例,已更正。结果是Eigen使用系统RNG,因此您需要srand()来播种它。

R> sourceCpp("/tmp/roland.cpp")
R> set.seed(42); fx(42)
          [,1]     [,2]
[1,] -0.933060 0.914806
[2,] -0.340072 0.937075
[3,]  0.381271 0.286140
R> set.seed(42); fx(42)
          [,1]     [,2]
[1,] -0.933060 0.914806
[2,] -0.340072 0.937075
[3,]  0.381271 0.286140
R>

它使用您修改后的代码版本:

// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
using namespace Rcpp;
using  Eigen::MatrixXd;
using  Eigen::VectorXd;

// [[Rcpp::export]]

  RNGScope   scope;
  MatrixXd   x(3,2);
  srand(seed);
  x=x.setRandom();
  x.col(1)=as<VectorXd>(runif(3,0,1));

  return wrap(x);
}

编辑2以回应OP的评论:

我不希望Eigen在Rcpp::runif()srand()调用之间产生太大的速度差异,所以你仍然会遇到srand()遇到问题的事实,以及可能在系统之间表现不同。

快速演示脚本:

#include <RcppEigen.h> 

// [[Rcpp::depends(RcppEigen)]]

// [[Rcpp::export]]
Rcpp::NumericVector v1(int n) {
  return Rcpp::runif(n);
}

// [[Rcpp::export]]
Rcpp::NumericVector v2(int n) {
  Eigen::VectorXd   x(n);
  x = x.setRandom();
  return Rcpp::wrap(x);
}

/*** R
library(rbenchmark)
N <- 1e7
benchmark(v1(N), v2(N))
*/

产生

R> sourceCpp("/tmp/roland.cpp")

R> library(rbenchmark)

R> N <- 1e7

R> benchmark(v1(N), v2(N))
   test replications elapsed relative user.self sys.self user.child sys.child
1 v1(N)          100  12.633    1.000    11.356    1.261          0         0
2 v2(N)          100  17.222    1.363    13.981    3.198          0         0
R> 

并注意,即使在仅创建向量的更简单设置中,RcppEigen也更慢。但我们在这里谈论微秒,这可能不是我在真正的应用程序中担心的问题,这很可能会产生其他瓶颈。