Image processing 使用atomicAdd平均CUDA上的图像会产生不一致的结果
我将平均图像的强度作为一个更大问题的简单测试用例。但每次运行时,得到的结果都略有不同。相反,如果我在CPU上连续运行相同的算法,结果是静态的。让我们看看GPU上的代码Image processing 使用atomicAdd平均CUDA上的图像会产生不一致的结果,image-processing,graphics,parallel-processing,cuda,computer-vision,Image Processing,Graphics,Parallel Processing,Cuda,Computer Vision,我将平均图像的强度作为一个更大问题的简单测试用例。但每次运行时,得到的结果都略有不同。相反,如果我在CPU上连续运行相同的算法,结果是静态的。让我们看看GPU上的代码 //util.cu __global__ void avgImageDevice(float3 *avg, float3 *d_colorImageRGB, unsigned int width, unsigned int height) { const unsigned int x = blockIdx.x*blockD
//util.cu
__global__ void avgImageDevice(float3 *avg, float3 *d_colorImageRGB, unsigned int width, unsigned int height)
{
const unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
const unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
if (x >= width || y >= height) return;
atomicAdd(&avg->x, d_colorImageRGB[y*width + x].x);
atomicAdd(&avg->y, d_colorImageRGB[y*width + x].y);
atomicAdd(&avg->z, d_colorImageRGB[y*width + x].z);
}
extern "C" void avgImage(float3 *avg, float3 *d_colorImageRGB, unsigned int width, unsigned int height)
{
const int T_PER_BLOCK = 16;
const dim3 blockSize((width + T_PER_BLOCK - 1) / T_PER_BLOCK, (height + T_PER_BLOCK - 1) / T_PER_BLOCK);
const dim3 gridSize(T_PER_BLOCK, T_PER_BLOCK);
avgImageDevice << <blockSize, gridSize >> >(avg, d_colorImageRGB, width, height);
}
我有GTX960、CUDA6.5和Windows7。这是一个数据竞争问题吗?据我所知,
atomicAdd
没有报告全局内存有任何问题。结果可能取决于线程的调度顺序。实际上,根据图像大小、组件中的值,结果平均值可能会因运行而略有不同,尽管所有值都是正确的。如果num不同于一个运行到另一个运行,则代码的其他部分很可能存在问题。如果num相同,则所有结果都符合IEEE-754标准 结果可能取决于线程的调度顺序。实际上,根据图像大小、组件中的值,结果平均值可能会因运行而略有不同,尽管所有值都是正确的。如果num不同于一个运行到另一个运行,则代码的其他部分很可能存在问题。如果num相同,则所有结果都符合IEEE-754标准 这不是一场数据竞赛
浮点加法是可交换的:
a + b == b + a
但它是非关联的;有a、b、c,以便:
(a + b) + c != a + (b + c)
单个添加的不同顺序(特别是它们的关联方式)将产生不同的结果。这不是数据竞争
浮点加法是可交换的:
a + b == b + a
但它是非关联的;有a、b、c,以便:
(a + b) + c != a + (b + c)
单个加法的不同顺序(特别是它们的关联方式)将产生不同的结果。您是否确实初始化了传递的值并以原子方式递增?是的。我确保了我正在初始化所有的东西。那么,当你还没有发布一个?我只是想猜测一下?相应地修改了。您是否验证了程序集以确保您的cpu操作在fp32而不是fp64中?您是否确实初始化了您传递的值并以原子方式递增?是的。我确保了我正在初始化所有的东西。那么,当你还没有发布一个?我只是猜一下?相应地修改了。你们验证了程序集以确保你们的cpu操作在fp32而不是fp64中吗?这实际上是有道理的。将平均强度视为一棵树从下到上的节点总和,然后在GPU中,这棵树在每次迭代中看起来都不同。因为每个线程都在不同的时间范围内运行。这实际上是有意义的。将平均强度视为一棵树从下到上的节点总和,然后在GPU中,这棵树在每次迭代中看起来都不同。因为每个线程都在不同的时间范围内运行。