使用vdRngGaussian建议正态随机变量

时间:2015-11-06 17:20:26

标签: mex intel-mkl

我想使用函数 vdRngGaussian Normal(mean,sigma2)中绘制n个随机变量。 一种方法是使用命令

vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_ICDF, stream, n, x, mean, sqrt(sigma2) )

而不是这个,我想使用for循环。我写的mex代码是

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <mkl.h>
#include "mkl_vml.h"
#include "mex.h"
#include "matrix.h"
#include "mkl_vsl.h"
#include <time.h>
#define SEED  time(NULL)

double normal(double mean, double sigma2, VSLStreamStatePtr stream);

/* main fucntion */
void mexFunction(int nlhs,  mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double *x, mean, sigma2;

    VSLStreamStatePtr stream;
    vslNewStream( &stream, VSL_BRNG_MT19937, SEED );

    /* make pointers to input data */
    mean = (double)mxGetScalar(prhs[0]);
    sigma2= (double)mxGetScalar(prhs[1]);

    /* make pointers to output data */
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    x = mxGetPr(plhs[0]);


    x[0] = normal( mean, sigma2, stream);


    /* Deleting the stream */
    vslDeleteStream( &stream );

    return;
}

double normal(double mean, double sigma2, VSLStreamStatePtr stream)
{
    double x[1];

    vdRngGaussian(VSL_RNG_METHOD_GAUSSIAN_ICDF, stream, 1, x, mean, sqrt(sigma2) );

    return(x[0]);
}

当我使用命令

运行代码时
for i=1:5
out(i) = normalc(0.0, 1.0);
end

我得到以下结果:

-1.1739   -1.1739   -1.1739   -1.1739   -1.1739

如果我在没有for-loop的情况下调用我的函数5次,我会得到这些结果

-0.2720, 2.1457, -1.2397, 0.7501, 0.1490
你能帮我吗? 非常感谢你。

1 个答案:

答案 0 :(得分:1)

您使用vslNewStream创建的流将种子(随机数生成器的初始条件)作为参数,并且基于the outputtime function from the C time library。问题是它返回了一些。这是分辨率太粗糙,当你在for循环中调用它时,你最终得到相同的种子。 (假设for循环执行得很快,你的开始时间很幸运。)

也许使用不同的种子,例如high_resolution_clock from the C++11 <chrono> header。您仍然可以获得纪元时间,但是以不同的单位:

using namespace std::chrono;
system_clock::time_point now = high_resolution_clock::now();
system_clock::duration epoch = now.time_since_epoch();

long long ns = duration_cast<nanoseconds>(epoch).count();
long long mic = duration_cast<microseconds>(epoch).count();
long long ms = duration_cast<milliseconds>(epoch).count();

Demo (cpp.sh)

或者,您可以使用MKL's mkl_get_cpu_clocks function中已用的CPU时钟,但在关闭计算机时会回到零。 或只是time in seconds as a double with MKL's dsecnd