如何解决将 R2R FFT 从 FFTW 移植到 cuFFT
我正在尝试将一些代码从 cpu 移植到 GPU,其中包括一些 FFT。因此,在 cpu 代码中,一些复杂的数组使用 fftw_plan_many_r2r
分别对其实部和图像部分进行转换。函数 foo 代表 R2R 变换例程,并为复数数组的每一部分调用两次。
void foo(vector_double &evg) {
int nx = Dims[0],ny = Dims[1],nz = Dims[2];
const int nxny[] = {ny,nx};
const int n = nx*ny*nz;
const fftw_r2r_kind kinds[] = {FFTW_RODFT00,FFTW_RODFT00};
if (evg.size() != n)
throw std::runtime_error ("*** weird size of evg");
fftw_plan p;
p = fftw_plan_many_r2r(2,nxny,nz,&evg[0],1,nx*ny,kinds,FFTW_ESTIMATE);
// actual FFT
fftw_execute(p);
}
void bar(vector_complex &evg) {
vector_double tmp;
tmp = evg.real();
foo(tmp);
evg.real() = tmp;
tmp = evg.imag();
foo(tmp);
evg.imag() = tmp;
}
那么,由于没有从 FFTW R2R 到 cuFFT 的直接转换,我如何在 CUDA 上获得相同的结果? 附注如果有帮助,vector_double 和 vector_complex 是特征向量
解决方法
我无法提供解决方案,但评论有大小限制,所以我把它放在这里:
-
在 FFTW 中,您使用原位变换,但您没有使用 FFTW_IN_PLACE。我不知道这是否正确,我自己从未使用过原位变换。
-
确实 cuFFT 没有 R2R,因此我们必须进行调查。根据 fftw 文档,FFTW_RODFT00 表示 DST-I。根据维基百科,DST-I 是正弦变换,如果你制作一个大小为 2*(N+1) 的向量并反向复制值,它具有等效的傅立叶变换,如右图标记为 DST-I:{ {3}}。因此,如果您对该“扩展向量”进行 r2c(或 c2c)变换并从变换向量中删除一些值,则您将完全进行 R2R 变换。请参阅 https://en.wikipedia.org/wiki/Discrete_sine_transform:“DST-I 完全等同于实数序列的 DFT,它在第零点和中间点周围是奇数,按 1/2 缩放”。
不过有两个问题:
-
你必须自己推导出哪些索引必须被删除(即复制到结果向量),当场接近它有点复杂。
-
如果你在 c2r 的情况下使用额外的复制,GPU 必须比 fftw 在 r2r 的情况下进行更多的计算(
2(N+1)
-size 变换而不是仅仅N
),并且必须完成更多的内存分配,因此它不会像 r2c 或 c2c 情况一样快。但根据我的经验,即使是较旧的主流 GPU 也比带 FFT 的 CPU 快很多(比如一个数量级),因此您至少可以获得一些加速。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。