提升Fortran伪谱DNS求解器FFTW性能的优化疑问
伪谱DNS代码FFTW优化求助
背景与现状
维护着一套继承而来的伪谱DNS流体模拟代码,已成功将旧FFT例程替换为FFTW例程,测试结果正确,但存在效率瓶颈,现寻求FFTW使用与数据排布的优化建议。
示例代码
! Complex array u of size (nyp,nz,nx/2) is stored in us and normalized before transform ! mx = (3/2)nx, mz = (3/2)nz for de-aliasing ... complex(C_DOUBLE_COMPLEX),dimension(nyp,mz,mx) :: us,aspec real(C_DOUBLE),dimension(nyp,mz,mx) :: up,aphys ... ! Plan FFTW transforms with dummy variables planZb = fftw_plan_dft_1d(mz,aspec,aspec,FFTW_BACKWARD,FFTW_PATIENT) planXb = fftw_plan_dft_c2r_1d(mx,aspec,aphys,FFTW_PATIENT) planY = fftw_plan_r2r_1d(nyp,aphys,aphys,FFTW_REDFT00,FFTW_PATIENT) ... ! Complex --> Complex z-transform do k = 1,nxh do i = 1,nyp call fftw_execute_dft(planZb,us(i,:,k),us(i,:,k)) . . . end do end do ! Complex --> Real x-transform do j = 1,mz do i = 1,nyp call fftw_execute_dft_c2r(planXb,us(i,j,:),up(i,j,:)) . . . end do end do ! Real --> Real y-transform (DCT-I) do k = 1,mx do j = 1,mz call fftw_execute_r2r(planY,up(:,j,k),up(:,j,k)) . . . end do end do ! Do stuff here ! Inverse transforms here, reverse process above + normalizations
相关观察
- 已启用OpenMP线程及编译器优化,当前聚焦FFTW使用与数据排布优化;
- 代码需对58个同尺寸变量执行变换,FFTW文档建议为每个变量单独规划,但不确定大量变量场景下的实用性;
- 尝试过用
fftw_plan_many_dft替代循环,但需将变换维度设为首位,测试显示该方法随网格增大速度显著变慢; - 目前采用x、z方向串行1D变换,尝试过2D变换但效率相近甚至略低。
核心疑问
是否值得使用FFTW的高级/专家接口替换现有FFT循环?该接口需数据重排,开销较高,不确定FFTW是否有对应优化方案。
优化建议
1. 批量变量处理优化
- 针对58个同尺寸变量,无需为每个变量单独创建plan。推荐使用
fftw_plan_many系列接口(对应dft/c2r/r2r版本),但需调整数据排布逻辑:将多个变量作为批次维度放在变换维度之后,而非之前。例如z方向1D复变换,可将数组组织为(mz, nyp, nxh, 58),然后调用fftw_plan_many_dft时设置rank=1、dims=[mz]、howmany=nyp*nxh*58、istride=1、ostride=1、idist=mz、odist=mz。这种方式让FFTW一次性处理所有变量的同一维度变换,减少循环开销与线程调度成本。 - 若调整数据排布存在困难,可利用FFTW 3.3+支持的
fftw_execute_batch接口,将多个变量的指针打包成数组,批量执行同一个plan,避免循环内重复调用fftw_execute_*的冗余开销。
2. 数据排布与缓存友好性
- 当前代码中,变换维度为数组中间维度(如z是
us(i,:,k)的第二维),会导致内存访问步长过大,缓存命中率低下。FFTW对连续内存的变换效率最高,建议将变换维度调整为数组的第一维。例如将us的维度改为(mz, nyp, mx),z方向变换时直接取us(:,i,k),内存连续,可大幅提升缓存利用率。 - 对于y方向的DCT变换(REDFT00),同样需保证变换维度为连续的第一维,避免跨内存块访问。
3. 高级接口的权衡策略
- FFTW的专家接口(
fftw_plan_guru)确实需要手动处理数据重排,但如果网格规模较大(百万级以上),重排的一次性开销会被后续反复变换(DNS时间步循环)的效率提升抵消。尤其是长期运行的模拟场景,重排成本可忽略不计。 - 专家接口的核心优势是支持自定义数据存储布局(如非连续stride),若无法调整原始数组维度,可通过它适配现有排布,同时用
FFTW_PATIENT或FFTW_EXHAUSTIVE模式生成最优变换计划,确保FFTW找到适配该布局的最佳算法。
4. 其他细节优化
- 所有plan均使用
FFTW_PATIENT(或FFTW_EXHAUSTIVE)模式生成,大网格下FFTW需要更多时间搜索最优变换路径,这对长期运行的DNS模拟来说是值得的投入。 - 确保OpenMP与FFTW线程兼容:避免FFTW线程池与OpenMP线程嵌套,建议通过
export OMP_NUM_THREADS=X和fftw_init_threads()+fftw_plan_with_nthreads(X)设置统一线程数,避免线程竞争。 - 逆变换尽量复用正向变换的plan(若为对称变换),或生成逆变换plan时共享优化信息,减少重复规划的时间开销。
内容的提问来源于stack exchange,提问作者Ryan Kelly
相关产品推荐
相关产品推荐

