c++ - 使用 CUDA 对相同数据进行 FFT 每次都会给出不同的结果?

标签 c++ cuda fft

为什么在使用 CUDA 时,如果我执行大小为 100 万的 FFT,每次得到的结果都会略有不同?

我的硬件采用费米架构。

最佳答案

这可能有一个简单的答案。 CUDA 程序经常使用 float 变量类型,因为它比 double 快得多。计算运算的顺序会显着影响浮点计算的最终值;这不是 CUDA 独有的,但您可能会特别敏锐地注意到这种影响,因为它是一个如此大规模的并行范例(并且并行性带来了不确定性,至少在进行全局归约之类的事情时是这样)。

编辑:需要说明的是,CUDA 不保证同一个内核将在多次执行中以相同的顺序执行,这是一个必要(但不充分)的条件。如果 CUDA 确实保证了这一点,那么执行算术运算的顺序就不可能在每次运行时发生变化,因此,人们不会期望看到相同浮点计算的不同值。

这是一个简单的 C 程序,证明了上述声明。试试代码

#include <stdio.h>

int main()
{
   float a = 100.0f, b = 0.00001f, c = 0.00001f;

   printf("a + b + c = %f\n", a + b + c);
   printf("b + c + a = %f\n", b + c + a);
   printf("a + b + c == b + c + a ? %d\n", (a + b + c) == (b + c + a));

   return 0;
}

在 Linux 上,看看你得到了什么(我使用的是 64 位 RHEL 6 和 gcc 版本 4.4.4-13)。我的输出如下:

[user@host directory]# gcc add.c -o add
[user@host directory]# ./add
a + b + c = 100.000015
b + c + a = 100.000023
a + b + c == b + c + a ? 0

编辑:请注意,虽然这个程序可能暗示潜在的问题是浮点加法是不可交换的,但实际上浮点加法是非关联的(因为 C 从左到是的,恰好第一次加法执行为 (a + b) + c,第二次加法执行为 (b + c) + a)。非关联性的原因是浮点表示法只能表示有限多个有效数字(以 2 为基数,但对以 10 为基数的系统的讨论本质上是等价的)。例如,如果只能表示三个有效数字,我们得到 (100 + 0.5) + 0.5 = 100 + 0.5 = 100,而 100 + (0.5 + 0.5) = 100 + 1 = 101。在第一种情况下,中间值结果 100 + 0.5 必须被截断(或可能向上舍入),因为不可能只用三个有效数字表示中间值 100.5。

这种现象有许多重要的含义;例如,通过按大小(指数)的递增顺序添加数字,您将获得更准确的答案。真正的收获是,除非以相同顺序执行计算,否则您不应期望结果相同,这可能很难保证在真实 GPU 上使用 CUDA。

关于c++ - 使用 CUDA 对相同数据进行 FFT 每次都会给出不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9283261/

相关文章:

javascript - 使用周期波作为逆变换 block

c++ - 逆 fft 产生接近但错误的输出

c++ - 从无序数据构建 QVariant 列表

c++ - VS Code 显示 clang 的编译错误消息

C++如何将结构化git日志的输出解析为对象

c++ - 编译共享库linux gcc/g++ cpp

CUDA 驱动程序版本不足以支持 CUDA 运行时版本

java - 枚举所有长度为 N 的 vector ,其中每个元素的值为 [0 ... K],所有元素的总和为 SUM

c++ - 如何在 CUDA 内核中使用 Eigen

matlab - 了解 Matlab FFT 示例