FFTW 单精度库在使用 SIMD 优化时输出不正确的 DFT

FFTW single-precision library outputs incorrect DFT when using SIMD optimizations

我正在测试用于一维离散傅里叶变换 (DFT) 计算的 FFTW 3.3.8 C 库。当我使用 float(单精度)版本的库时,我得到的结果通常是不正确的,配置了 --enable-generic-simd128--enable-generic-simd256 选项(和 --enable-float for float支持)。我已经在 MinGW-w64 以及 Windows 子系统 Linux 中测试过它,使用 gcc 作为编译器。当我使用 MinGW-w64 的预构建 FFTW 包时,我也会遇到相同的错误,该包是通过 pacman 在 MSYS2 中下载的。

作为一个简单的测试,我使用的是 1 的输入向量。预期 DFT 的第一个元素应等于输入向量的长度,所有其他元素为零。

有没有人运行以前处理过这个问题,或者有人愿意尝试重现它吗?我是否认为使用 float 版本的库时不支持 --enable-generic-simd128--enable-generic-simd256 优化?我的 CPU 是英特尔 i7-4720HQ。

这里有一个简单的测试程序来演示这个问题:

main.c

#include <stdio.h>
#include <fftw3.h>

int main()
{
    fftwf_complex *in, *out;
    fftwf_plan p;
    int N = 21;
    int i;

    in = fftwf_malloc(sizeof(fftwf_complex) * N);
    out = fftwf_malloc(sizeof(fftwf_complex) * N);
    p = fftwf_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);

    for (i = 0; i < N; i++) {
        in[i][0] = 1.0f;
        in[i][1] = 0.0f;
    }
    fftwf_execute(p);

    for (i = 0; i < N; i++) 
        printf("%d: %8.5g\t + j %8.5g\n", i, out[i][0], out[i][1]);

    fftwf_destroy_plan(p);
    fftwf_free(in);
    fftwf_free(out);
}

我用 gcc -o main main.c -lfftw3f -lm 构建它。输出结果如下:

0:       21      + j    -7.87
1:        0      + j        0
2:        0      + j        0
3:  -5.2972      + j      1.9
4:        0      + j        0
5:        0      + j        0
6:   -1.862      + j     1.08
7:        0      + j        0
8:        0      + j        0
9: -0.52584      + j    0.956
10:        0     + j        0
11:        0     + j        0
12:  0.52584     + j    0.956
13:        0     + j        0
14:        0     + j        0
15:    1.862     + j     1.08
16:        0     + j        0
17:        0     + j        0
18:   5.2972     + j      1.9
19:        0     + j        0
20:        0     + j        0

这似乎是 FFTW 3.3.8 中的错误。

我在 2016 15 英寸 MacBook Pro 运行 macOS 10.14.6 和 Clang 11.0.0 和 Xcode 11.3.1 上用 --enable-float 构建了 FFTW 3.3.8 并构建了并执行问题中的代码。它为元素 0 显示输出 21,为其他元素显示接近 0 的值(例如“6.6324e-07 + j -2.0458e-07”)。在我添加 --enable-generic-simd128 重建 FFTW 后,程序给出了问题中显示的输出。

这确实是 FFTW 3.3.8 中的错误。我在几个平台上重现了这个问题,并且有几个人证实了这一点,包括 Eric Postpischil。我已将此问题报告给 FFTW 开发人员,并已在 recent commit.

中修复