CUDA与OpenCL:浮点精度更改

CUDA与OpenCL:浮点精度更改,opencl,Opencl,我通过移植一些现有的CUDA函数来学习OpenCL。下面是我的CUDA和OpenCL内核。当向两个函数传递相同的输入参数时,输出的不同顺序为^-3到^-4。当我反复调用这些函数时,差异的顺序会显著增加(这对我的预期输出非常不利)。我的OpenCL移植有什么问题吗 注意:我已经在编译OpenCL内核时尝试了“-cl opt disable” CUDA内核: __global__ void normalize_kernel(int N, float *x, float *mean, float *v

我通过移植一些现有的CUDA函数来学习OpenCL。下面是我的CUDA和OpenCL内核。当向两个函数传递相同的输入参数时,输出的不同顺序为^-3到^-4。当我反复调用这些函数时,差异的顺序会显著增加(这对我的预期输出非常不利)。我的OpenCL移植有什么问题吗

注意:我已经在编译OpenCL内核时尝试了“-cl opt disable”

CUDA内核:

__global__ void normalize_kernel(int N, float *x, float *mean, float *variance, int batch, int filters, int spatial)
{
    int index = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x;
    if (index >= N) return;
    int f = (index/spatial)%filters;

    x[index] = (x[index] - mean[f])/(sqrt(variance[f] + .00001f));
}
OpenCL内核:

__kernel void normalize_kernel(int N, __global float *x, __global float *mean, __global float *variance, int filters, int spatial)
{
    int index =  get_group_id(1) * get_global_size(0) + get_global_id(0);
    if (index >= N) return;
    int f = (index/spatial)%filters;

    x[index] = (x[index] - mean[f])/(sqrt(variance[f] + .00001f));
}
输出:CUDA:OpenCL

{'1.293604': '1.293387',
 '0.727771': '0.727677',
 '0.868133': '0.867531',
 '2.195427': '2.195059'...

查看编译选项(OpenCL 1.2或更高版本)。在某些硬件上,这会稍微降低性能,但可能没什么大不了的


是什么让您认为CUDA的输出比OpenCL的“更正确”?除非两种实现都完全符合IEEE754(包括
sqrt
函数,通常不是),否则您不能期望100%相同的输出。如果您不能接受此精度级别,您可能希望在两种平台上切换到使用
double
s。(别忘了启用64位双支持。)@pmdj我不认为CUDA输出是正确的。OpenCL输出也因CPU输出而异。我想使用OpenCL复制CPU输出或CUDA输出。@pmdj精度差^-5或^-6是可以接受的。但是^-3会对输出产生很大影响。GPU通常没有符合IEEE754的FPU,因此无法获得一致的行为。我怀疑除法和
sqrt
可能是您的主要罪魁祸首,尤其是在方差值很小的情况下。您是否尝试过将计算替换为乘
rsqrt()
?这可能会减少分歧。(并且可能会提高性能,除非编译器已经应用了这种优化。)但是如果你关心精度,你需要使用真正的双精度来获得更大的安全缓冲。如果你想要100%的可预测性,你需要使用整数/定点数学。给出了定点数学的一个示例实现。我似乎还记得一本古老的“Graphics Gems”书,书中有一个平方根的定点实现,可能还有平方根的逆。不过,只有您知道您的数据,所以我不能说定点数学或双精度浮点更适合您的用例。谢谢,我会检查一下。在OpenCL 1.1中有类似的吗?