将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], nxny, 1, nx*ny,
&evg[0], nxny, 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上收到相同的结果呢?P.S.vector_double和vector_complex是特征向量,如果这有助于

我不能提供解决方案,但注释有大小限制,所以我把它放在这里:

  1. 使用FFTW可以使用在位变换,但不使用FFTW_IN_PLACE。我不知道这是否正确,我自己从未使用过原地变换。

  2. 事实上,cuFFT没有R2R,所以我们必须进行研究。根据fftw文件,fftw_RODFT00的意思是DST-I。根据维基百科的说法,DST-I是正弦变换,如果你制作一个大小为2*(N+1(的向量并反向复制值,它就具有等价的傅立叶变换,如右图中标记为DST-I的图片所示:https://en.wikipedia.org/wiki/Discrete_sine_transform。因此,如果你对"c"进行r2c(或c2c(变换;扩展向量";从变换向量中去掉一些值,就得到了R2R变换。看见https://en.wikipedia.org/wiki/Discrete_sine_transform#DST-I: ";DST-I精确地等效于实数序列的DFT,该实数序列在第0个点和中间点附近为奇数,按1/2〃缩放;。

不过有两个问题:

  1. 您必须自己推断哪些索引必须被删除(即,复制到结果向量(,现场处理有点复杂。

  2. 如果使用带有额外复制的c2r情况,GPU必须比r2r情况下的fftw进行更多的计算(2(N+1)-大小转换,而不仅仅是N(,并且必须进行更多的内存分配,因此它不会像r2c或c2c情况那样快。但根据我的经验,即使是旧的主流GPU也比使用FFT的CPU快得多(比如一个数量级(,所以你可能至少会得到一些加速。

最新更新