相当于 OpenCL 的 curand

Equivalent of curand for OpenCL

本文关键字:curand OpenCL 相当于      更新时间:2023-10-16

我正在考虑从 nvidia 切换到 amd 作为我的计算卡,因为我想要双精度支持。 在这样做之前,我决定在我的nvidia卡上学习opencl,看看我是否喜欢它。 我想将以下代码从 CUDA 转换为 OpenCL。 我正在使用curand库来生成均匀且正态分布的随机数。 每个线程需要能够创建不同的随机数序列,并为每个线程生成数百万个。 这是代码。 我将如何在 OpenCL 中做到这一点。 我在网上阅读的所有内容似乎都暗示我应该生成一个随机数缓冲区,然后在 GPU 上使用它,但这对我来说不切实际。

template<int NArgs, typename OptimizationFunctor>
__global__ 
void statistical_solver_kernel(float* args_lbounds, 
                    float* args_ubounds, 
                    int trials,
                    int initial_temp,
                    unsigned long long seed,
                    float* results,
                    OptimizationFunctor f)
{
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if(idx >= trials) 
        return;
    curandState rand;
    curand_init(seed, idx, 0, &rand);
    float x[NArgs];
    for(int i = 0; i < NArgs; i++)
    {
        x[i] = curand_uniform(&rand) * (args_ubounds[i]- args_lbounds[i]) + args_lbounds[i];
    }
    float y = f(x);
    for(int t = initial_temp - 1; t > 0; t--)
    {
        float t_percent = (float)t / initial_temp;
        float x_prime[NArgs];
        for(int i = 0; i < NArgs; i++)
        {
            x_prime[i] = curand_normal(&rand) * (args_ubounds[i] - args_lbounds[i]) * t_percent + x[i];
            x_prime[i] = fmaxf(args_lbounds[i], x_prime[i]);
            x_prime[i] = fminf(args_ubounds[i], x_prime[i]);
        }
        float y_prime = f(x_prime);
        if(y_prime < y || (y_prime - y) / y_prime < t_percent)
        {
            y = y_prime;
            for(int i = 0; i < NArgs; i++)
            {
                x[i] = x_prime[i];
            }
        }
    }   
    float* rptr = results + idx * (NArgs + 1);
    rptr[0] = y;
    for(int i = 1; i <= NArgs; i++)
        rptr[i] = x[i - 1];
}

VexCL 库提供了基于计数器的生成器的实现。您可以在较大的表达式中使用它们,有关示例,请参阅此幻灯片。

编辑:带着一点点,因为我是VexCL :)的作者。