如何摆脱CUDA和CPU之间对数的不同结果?

oil*_*pig 2 c++ floating-point cuda

我想使用 CUDA 在 GPU 中实现一个算法。同时我用C++写了一个CPU版本来验证GPU版本的结果。但是我log()在 CPU 和 GPU 中使用时遇到了麻烦。一个非常简单的算法(在 CPU 和 GPU 上都使用)如下所示:

float U;
float R = U * log(U);
Run Code Online (Sandbox Code Playgroud)

但是,当我比较 CPU 端的结果时,我发现有很多结果(1843161 中的 459883)具有很小的差异(最大差异为 0.5)。部分结果如下所示:

U       -- R (CPU side)  -- R (GPU side)  -- R using Python (U * math.log(U))

86312.0 -- 980998.375000 -- 980998.3125   -- 980998.3627440572
67405.0 -- 749440.750000 -- 749440.812500 -- 749440.7721980268
49652.0 -- 536876.875000 -- 536876.812500 -- 536876.8452369706
32261.0 -- 334921.250000 -- 334921.281250 -- 334921.2605240216
24232.0 -- 244632.437500 -- 244632.453125 -- 244632.4440747978
Run Code Online (Sandbox Code Playgroud)

有人能给我一些建议吗?我应该相信哪一个?

Pas*_*uoq 5

我应该相信哪一个?

您应该相信 Python 计算的双精度结果,您也可以使用 CUDA 或 C++ 进行双精度计算以获得非常相似(尽管可能仍然不相同)的值。

重新表述 aland 的第一条评论,如果您关心 980998 中的 0.0625 错误,那么您首先不应该使用单精度。CPU 和 GPU 结果对于该级别的准确度来说都是“错误的”。在您的示例中,CPU 结果碰巧更准确,但您可以看到两个单精度结果与更准确的双精度 Python 结果相距甚远。这仅仅是使用允许 24 个有效二进制数字(大约 7 个十进制数字)的格式的结果,不仅用于输入和最终结果,还用于中间计算。

如果输入作为 提供float并且您想要最准确的float结果R,请计算U * log(U)usingdoublefloat最终只舍入到。那么 CPU 和 GPU 之间的结果几乎总是相同的。