2. mcFFT 使用方法
本章节提供了mcFFT库API的概览。
离散傅里叶变换(DFT)将一个复数向量 \(x_{k}\) (时域)映射到其频域表示,表示为:
\(X_{k}\) 是一个复数向量。时域映射到频域为正向DFT。如果指数中e的符号改为正号,该变换就是逆向变换。根据 \(N\) 的大小,会采用不同的算法来获得最佳性能。
mcFFT API 以 FFTW 为模型,后者是基于CPU,最流行、最高效的的FFT库之一。 mcFFT提供了一种简单的配置机制,称为计划(plan),该计划使用内部构建块来针对给定配置和选择的特定GPU硬件进行优化变换。 然后,当调用执行函数时,实际的变换按照计划的执行来进行。 这种方法的优势在于,一旦用户创建了一个计划,库将保留执行计划所需的状态,以便多次执行计划而无需重新计算配置。 对于mcFFT来说,这种模型非常有效,因为不同类型的FFT需要不同的线程配置和GPU资源,而计划接口提供了一种简单的方式来重用配置。
2.1. 傅里叶变换类型
除了一般的复数到复数(complex-to-complex,C2C)的变换,mcFFT还有效地实现了另外两种类型的变换:实数到复数(real-to-complex,R2C)的变换与复数到实数(complex-to-real,C2R)的变换。在许多实际应用中,输入向量是实数值的。可以很容易地证明,在这种情况下,输出满足厄米特矩阵对称(Hermitian symmetry)( \(X_{k} = X_{N - k}^{\ast}\) ,其中星号表示复数共轭)。反之也成立:对于复数域的共轭-厄米(complex-Hermitian)输入,逆向变换将是纯实数值。mcFFT利用了这种冗余,只对厄米特矩阵向量的前半部分起作用。单精度和双精度的变换执行函数被分别定义为:
mcfftExecC2C() / mcfftExecZ2Z()- 单/双精度复数到复数的变换。mcfftExecR2C() / mcfftExecD2Z()- 单/双精度实数到复数的正向变换。mcfftExecC2R() / mcfftExecZ2D()- 单/双精度复数到实数的逆向变换。
这些函数中的每一个都需要不同的输入数据布局。
备注
复数到实数(C2R)变换接受复数域的厄米特矩阵输入,这要求第0个元素(和第 \(\frac{N}{2}\) 个输入,如果N为偶数)为实数值,即其虚部应为零。否则,变换的行为是未定义的。
2.2. 数据布局
在mcFFT库中,数据布局严格依赖于配置和变换类型。在一般复数到复数变换的情况下,输入和输出数据应分别为单精度和双精度模式下的 mcfftComplex / mcfftDoubleComplex 数组。在C2R模式下,只需要包含非冗余复杂元素的输入数组 \((x_{1},x_{2},\ldots,x_{\lfloor\frac{N}{2}\rfloor + 1})\) 。输出数组 \((X_{1},X_{2},\ldots,X_{N})\) 由 mcfftReal / mcfftDoubleReal 元素组成。最后,R2C需要一个实数的输入数组 \((X_{1},X_{2},\ldots,X_{N})\) 并返回一个非冗余复数元素的数组 \((x_{1},x_{2},\ldots,x_{\lfloor\frac{N}{2}\rfloor + 1})\) 。在实数到复数和复数到实数的变换中,输入数据的大小和输出数据的大小是不同的。对于异地变换,将创建一个大小适当的单独数组。对于原地变换,用户应该使用 padded 数据布局。这种布局是FFTW兼容的。
在 padded 布局中,输出信号开始于与输入数据相同的内存地址。因此,必须对实数到复数的输入数据和复数到实数的输出数据进行填充。
一维变换的输入/输出数据的预期大小总结如下表:
FFT 类型 |
输入数据大小 |
输出数据大小 |
|---|---|---|
C2C |
\(x\) |
\(x\) |
C2R |
\(\lfloor\frac{x}{2}\rfloor + 1\) |
\(x\) |
R2C* |
\(x\) |
\(\lfloor\frac{x}{2}\rfloor + 1\) |
实数到复数的变换是一个正向变换。对于一个需要FFTW兼容输出的原地实数到复数变换,输入大小必须填充为 \(\left( {\lfloor\frac{N}{2}\rfloor + 1} \right)\) 复数。对于异地变换,输入和输出大小分别匹配逻辑变换大小 \(N\) 和非冗余大小 \(\lfloor\frac{N}{2}\rfloor + 1\) 。复数到实数变换是逆向变换。对于选择了FFTW兼容输出(默认填充模式)的原地复数到实数FFTs变换,假定输入大小为 \(\lfloor\frac{N}{2}\rfloor + 1\) mcfftComplex 元素。注意,当选择非单元输入和输出步幅时,原地复数到实数FFTs变换可能会 重写 任意虚输入点值。异地复数到实数FFT变换将总是 重写 输入缓冲区。对于异地变换,输入和输出大小分别匹配逻辑变换非冗余大小 \(\lfloor\frac{N}{2}\rfloor + 1\) 和大小 \(N\) 。
2.3. 多维变换
多维DFT将 \(d\) -维数组 \(x_{\mathbf{n}}\) 映射到其频域数组,其中 \(\mathbf{n} = (n_{1},n_{2},\ldots,n_{d})\) ,由以下公式给出:
其中 \(\frac{\mathbf{n}}{\mathbf{N}} = (\frac{n_{1}}{N_{1}},\frac{n_{2}}{N_{2}},\ldots,\frac{n_{d}}{N_{d}})\),求和表示嵌套求和的集合
mcFFT支持一维,二维和三维变换,它们都可以通过相同的 mcfftExec* 函数调用。
与一维情况类似,实数值输入数据的频域表示满足厄米特矩阵对称,定义为: \(x_{(n_{1},n_{2},\ldots,n_{d})} = x_{(N_{1} - n_{1},N_{2} - n_{2},\ldots,N_{d} - n_{d})}^{\ast}\) 。C2R和R2C算法利用该特性,只对信号数组的一半元素进行操作,即在: \(x_{\mathbf{n}}\) 因为 \(\mathbf{n} \in \{ 1,\ldots,N_{1}\} \times \ldots \times \{ 1,\ldots,N_{d - 1}\} \times \{ 1,\ldots,\lfloor\frac{N_{d}}{2}\rfloor + 1\}\) 。在 Data Layout 中描述的数据对齐的一般规则适用于高维变换。下表总结了多维DFTs的输入和输出数据大小:
维度 |
FFT类型 |
输入数据大小 |
输出数据大小 |
|---|---|---|---|
1D |
C2C |
\(\mathbf{N}_{1}\) |
\(\mathbf{N}_{1}\) |
1D |
C2R |
\(\lfloor\frac{\mathbf{N}_{1}}{2}\rfloor + 1\) |
\(\mathbf{N}_{1}\) |
1D |
R2C |
\(\mathbf{N}_{1}\) |
\(\lfloor\frac{\mathbf{N}_{1}}{2}\rfloor + 1\) |
2D |
C2C |
\(\mathbf{N}_{1}\mathbf{N}_{2}\) |
\(\mathbf{N}_{1}\mathbf{N}_{2}\) |
2D |
C2R |
\(\mathbf{N}_{1}(\lfloor\frac{\mathbf{N}_{2}}{2}\rfloor + 1)\)
|
\(\mathbf{N}_{1}\mathbf{N}_{2}\) |
2D |
R2C |
\(\mathbf{N}_{1}\mathbf{N}_{2}\) |
\(\mathbf{N}_{1}(\lfloor\frac{\mathbf{N}_{2}}{2}\rfloor + 1)\)
|
3D |
C2C |
\(\mathbf{N}_{1}\mathbf{N}_{2}\mathbf{N}_{3}\) |
\(\mathbf{N}_{1}\mathbf{N}_{2}\mathbf{N}_{3}\) |
3D |
C2R |
\(\mathbf{N}_{1}\mathbf{N}_{2}(\lfloor\frac{\mathbf{N}_{3}}{2}\rfloor + 1)\)
|
\(\mathbf{N}_{1}\mathbf{N}_{2}\mathbf{N}_{3}\) |
3D |
R2C |
\(\mathbf{N}_{1}\mathbf{N}_{2}\mathbf{N}_{3}\)
|
\(\mathbf{N}_{1}\mathbf{N}_{2}(\lfloor\frac{\mathbf{N}_{3}}{2}\rfloor + 1)\)
|
例如,对于一个异地变换的实数到复数变换输出的三维数组的静态声明如下所示:
mcfftComplex odata[N1][N2][N3/2+1];