我正在编写一个在傅立叶空间中及时集成 PDE 的代码,我正在 CUDA/C++ 中这样做。
我需要及时演化一个真正有价值的数组。
我用两种不同的方式编写代码,但遵循完全相同的逻辑。
在一个版本中,我简单地将所有数组定义为复数,并进行复数到复数的转换。我确保通过在每个时间步将它的虚部设置为 0(以考虑在其虚部中累积的小错误)来保留真正有价值的那个。
float *real;
cufftComplex *fourier;
...
for (int t = 0; t < totalTime; t++)
{
cufftEcexC2R(plan1, fourier, real);
// do some calculations
cufftExecR2C(plan2, real, fourier);
integrate<<<blocks, threads>>>(fourier, other parameters);
}
在另一个版本中,我有一个浮点数组用于实值数组,一个复数数组用于傅里叶变换,并进行复数到实数和实数到复数的转换。
cufftComplex *real;
cufftComplex *fourier;
...
for (int t = 0; t < totalTime; t++)
{
cufftEcexC2C(plan, fourier, real, CUFFT_INVERSE);
// do some calculations
cufftExecC2C(plan, real, fourier, CUFFT_FORWARD); // only need one plan in this case
integrate<<<blocks, threads>>>(fourier, other parameters);
}
我的印象是第二种选择会更快,内存效率更高。我知道它的内存效率更高,因为两个数组的大小都是一半,一个是实数而不是复数,而复数只存储 N/2+1 个值。然而,我观察到第一个选项始终如一,在我的情况下和我的硬件上,大约快 20%。
预计会是这样吗?复数到复数的转换在计算上是否比实数到复数或复数到实数更快?