【发布时间】:2016-06-17 11:17:57
【问题描述】:
我正在考虑将我的计算卡从 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];
}
【问题讨论】:
-
我卡在第一句话这里。 Nvidia 至少支持双精度超过 5 年。你用哪张卡?真的有那么老吗?您可以添加一个 cuda 编译器标志来启用双精度支持。 - 除此之外,我欢迎您选择用您的软件支持除 nvidia 以外的供应商。 ;) 随机性通常由 noise 函数 完成,该函数采用种子和线程 ID 分别为每个线程获取随机数。请参阅this question 作为开始。
-
对不起,我的意思是快速双精度。
-
您可以使用 Boost.Compute 或 VexCL 库中的(基于计数器的)随机数生成器。
-
我使用this RNG named MWC64X 在我的 OpenCL Monte-Carlo 代码中替换 curand。它重量轻且非常有效。 IDK 如果它是最好的或任何东西,但它对我来说做得非常好