用拒绝方法用CUDA生成随机数。性能问题

时间:2014-03-10 09:50:57

标签: c++ optimization random cuda mathematical-optimization

我正在使用CUDA编写的蒙特卡罗代码进行粒子模拟。基本上,在每个步骤中,我计算每个粒子的速度并更新其位置。速度与路径长度成正比。对于给定的材料,路径长度具有一定的分布。我知道这个路径长度的概率密度函数。我现在尝试通过rejection method.根据此函数对随机数进行采样。我会将我的CUDA知识描述为有限的。我明白,最好一次创建大块的随机数而不是多个小块。但是,对于拒绝方法,我只生成两个随机数,检查一定条件并在失败的情况下重复此过程。因此我在内核上生成随机数。

使用profiler / nvvp我注意到,基本上50%的时间花在拒绝方法上。

以下是我的问题:有没有办法优化拒绝方法?

我很感激每一个答案。

CODE

这是拒绝方法。

__global__ void rejectSamplePathlength(float* P, curandState* globalState,
    int numParticles, float sigma, int timestep,curandState state) {
int i = blockDim.x * blockIdx.x + threadIdx.x;
if (i < numParticles) {
    bool success = false;
    float p;
    float rho1, rho2;
    float a, b;
    a = 0.0;
    b = 10.0;
    curand_init(i, 0, 0, &state);
    while (!success) {
        rho1 = curand_uniform(&globalState[i]);
        rho2 = curand_uniform(&globalState[i]);
        if (rho2 < pathlength(a, b, rho1, sigma)) {
            p = a + rho1 * (b - a);
            success = true;
        }
    }
    P[i] = abs(p);

}
}

if语句中的 pathlength 函数计算内核上的值y = f(x)。 我很确定, curand_init 在时间方面存在问题,但如果没有此声明,每个内核都会生成相同的数字?

1 个答案:

答案 0 :(得分:1)

也许您可以在之前的内核中创建一个随机生成的统一变量池,然后在该池中选择您的制服并在该池上循环。但它应该足够大以避免无限循环..