SCCAS FFTW使用说明 王 武 中科院超级计算中心 Email: wangwu@sccas.cn 2010 年 5月 1 SCCAS 内容提要 一. 快速傅立叶变换 二. FFTW 的使用指南 三. FFTW 的技术特点 四. FFTW 的调用算例 五. FFTW在Unix上的安装 2 一. 快速傅立叶变换 SCCAS 1.1.1 Fourier Transform (FT) F (k ) f ( x)e2 kx dx (Forward FT) f ( x) F (k )e 2 kx dk (Inverse FT) 1.1.2 Discrete Fourier Transform (DFT) One-dimension: n 1 y Fn ( x) , yr xk wn rk , wn e-2 i / n , r 0,1, , n -1. k 0 Multi-dimension: n1 1 n2 1 y(i1 , , id ) nd 1 k1 0 k2 0 kd 0 -2 i / ni with wni e x(k1, , ri 0,1, , kd )wnr11k1 wnr22k2 , ni -1, i 1, wnr11k1 , , d. 3 一. 快速傅立叶变换 SCCAS 1.1.3 DFT in Matrix-vector Form Eg: DFT in 1D y Fx , x,y R F is a matrix as in right: Complexity: 2 O(n ) It’s applied in DSP ( Digital Signal Processing ): analyse and manipulate real-world signals by computer – Toys and consumer electronics (Spectrogram ) – Speech recognition – Audio/video compression – Medical imaging – Communications – Radar 4 一. 快速傅立叶变换 1.2.1 Fast Fourier Transform (FFT) Cooley & Tukey , 1965 FFT is a divide-and-conquer algorithm using binary reversal sort Eg: FFT in 1D SCCAS 0 1 2 3 4 5 6 7 0 4 2 6 1 5 3 7 Order: even, odd Complexity: O( N log2 N ) 5 一. 快速傅立叶变换 SCCAS 1.2.3 Parallel FFT in 1D Combine: using butterfly computation 1.2.4 FFT in Multi-dimension 2 Eg: DFT in 2D, Complexity : (n1n2 ) n1 1 n2 1 y (i1 , i2 ) x(k1 , k2 ) w w r1k1 n1 k1 0 k2 0 n1 1 w k1 0 r1k1 n1 n2 1 r2 k2 n2 x( k , k ) w k2 0 1 2 [0, 4] [2, 6] [1, 5] [3, 7] r2 k2 Log28 transform steps n2 reduced to 2 steps of DFT in 1D Computed by FFT,Complexity : O(n1n2 log n1n2 ) 6 一. 快速傅立叶变换 SCCAS 1.3 Example: FFT for Convolution Form N 1 y(k ) x(k )* h(k ) x( j )h(k j ), k 0,..., N 1 j 0 Step 1: FFT for x(N) and h(N) N 1 N 1 X (n) x(k )e 2 ikn / N Step 2: Vec-Vec Mult: Y(n)=X(n)H(n) k 0 k 0 Step 3: IFFT for Y(N): Complexity: , H (n) h(k )e 2 ikn / N O( N log N ) N 1 1 2 ikn / N y ( k ) Y ( n) e N n 0 7 二. FFTW的使用指南 SCCAS 2.1 FFTW简单概述 FFTW ( the Faster Fourier Transform in the West) 是一个快速计算离散傅里叶变换的标准C语言程序集 FFTW 由MIT的 M. Frigo 和 S. Johnson 开发, 可计算一维或多维, 实和复数据以及任意规模的DFT. FFTW 还包含对共享和分布式存储系统的并行变换, 它可自动适应你的机器, 缓存, 存储器大小, 寄存器个数 . FFTW 通常比目前其它开源Fourier变换程序都要快 ! FFTW 最新版本为fftw-3.2.2 FFTW下载及相关资料提供 http:// www.fftw.org 8 二. FFTW的使用指南 SCCAS 2.2. FFTW 计算: 1) 复(实)一维变换及其逆变换: n 1 Yi X j e n 1 Yi X j e j 0 2 ij 1/ n 由于没有正规化: F j 0 2) 复(实)多维变换及其逆变换: n1 1 n2 1 nd 1 j1 0 j2 0 n1 1 n2 1 jd 0 nd 1 Y [i1 , i2 , , id ] Y [i1 , i2 , , id ] j1 0 j2 0 2 ij 1/ n X [ j1, j2 , X[ j , j , jd 0 1 2 计算一个向前变换随后一个向后变换将用 1 || F F ( A) A || 变换的正确性检验: 1 F ( X ) nX , jd ]1i1 j12i2 j2 , jd ] i1 j1 1 d s 1 i2 j2 2 di d jd id jd d ns 乘以输入(正规化). 3) 以上变换的并行实现 共享和分布式存储系统,一维和多维DFT, 实变换和复变换,多线程和MPI. 9 二. FFTW的使用指南 SCCAS 2.3.1 复一维变换 #include <fftw.h> … { fftw_complex in[N], out[N]; //定义数据类型:复数组 fftw_plan p; //定义计划 … //创建计划 ,向前变换 p = fftw_create_plan(N, FFTW_FORWARD, FFTW_ESTIMATE); … // ESTIMATE表示不运行任何计算 //而只是建立一个合理的计划 fftw_one(p, in, out); … //一维变换的输入(出)数组 fftw_destroy_plan(p); //用完后,取消计划 } // 在Unix上,一个使用FFTW的程序应该与-lfftw –lm相连接 10 二. FFTW的使用指南 SCCAS 2.3.2 复多维变换 #include <fftw.h> … //对于FFTW3.0以上版本则采用fftw3.h { fftw_complex in[L][M][N]; //数据类型 fftwnd_plan p; … // fftwnd代表N维fftw p = fftwnd_create_plan(L, M, N, FFTW_FORWARD, FFTW_MEASURE | FFTW_IN_PLACE); … //在位(in-place)变换 用输出数组覆盖组 //MEASURE即FFTW实际执行和测量几个FFT的执行时间 以发现计算规模为N的变换的最好方式 ; fftwnd_one(p, &in[0][0][0], NULL); … fftwnd_destroy_plan(p); } //程序编译时需与-lfftwnd –lfftw –lm相连接 11 二. FFTW的使用指南 SCCAS 2.3.3 实一维变换 #include <rfftw.h> … //专门针对实型数据的rfftw变换 { // 数据类型 fftw_real in[N], out[N]; rfftw_plan p; //计划 int k … //创建计划 ,实到复的变换,复到实则为逆变换 p = rfftw_create_plan(N, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); … rfftw_one(p, in, out); rfftw_destroy_plan(p); } //程序编译时需与-lrfftw –lfftw –lm相连接 12 二. FFTW的使用指南 SCCAS 2.3.4 实多维变换 #include <rfftw.h> … //专门针对实型数据的rfftw变换 { // 数据类型 fftw_real in[M, N], out[M, N]; rfftw_plan p; //计划 int k … //创建计划 ,实到复的变换,复到实则为逆变换 p = rfftwnd_create_plan(M, N, FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE); … rfftwnd_one(p, in, out); rfftwnd_destroy_plan(p); } //程序编译时需与-lrfftwnd –lfftw –lm相连接 13 二. FFTW的使用指南 SCCAS 2.4.1. FFTW的多线程并行 1.头文件: <fftw_threads.h>或<rfftw_theads.h> 2.线程初始化: int fftw_threads_init(void); 3.用到的函数 fftw_threads_one(nthreads, plan, in, out); //一维复变换 fftwnd_threads_one(nthreads, plan, in, out); //n维复变换 rfftw_threads_one(nthreads, plan, in, out); //一维实变换 rfftwnd_threads_one(nthreads, plan, in, out); //n维实变换 以一维复变换为例 用 fftw_threads_one (nthreads, plan, in, out) 代替调用单机 fftw_one (plan, in, out) 在Unix上,使用并行复变换的程序应该与 -lfftw_threads - lfftw - lm相连接, 使用并行实变换的程序应与 -lrfftw_threads -lfftw_threads -lrfftw -lfftw –lm 相连接 14 二. FFTW的使用指南 SCCAS 2.4.2. FFTW的MPI并行 1. 调用头文件<fftw_mpi.h> 2. 创建计划: fftw_mpi_plan fftw_mpi_create_plan(MPI_Comm comm, int n FFTW_FORWARD, FFTW_ESTIMATE ); 用完后通过fftw_mpi_destroy_plan(plan)来取消. 3. 变换函数为: void fftw_mpi(fftw_mpi_plan p, int n_fields, fftw_complex *local_data, fftw_complex *work); 返回时, local_data包含局限于当前进程的输出部分, 可调用: void fftw_mpi_local_sizes(fftw_mpi_plan p, int *local_n, int *local_start,int *local_n_after_transform, int *local_start_after_transform,int *total_local_size); 在Unix上, FFTW MPI的程序应与MPI库和-lfftw_mpi -lfftw -lm连接. 15 三 FFTW的技术特点 SCCAS 3.1 The Planner • For a given N, there are many factorizations – – • not clear a priori which is best Eg: 32768 =16x8x8x32=64x16x32 The planner tries them “all” and picks the best one – – • uses actual runtime timing measurements result is encoded in a “plan” Uses dynamic programming to reduce no. of possible plans – • remembers optimal sub-plans for small sizes The Runtime Planner – • optimizes FFTW for your CPU, your cache size, etc. Ideas – – – Modern architectures are invalidating conventional wisdom about what is fast no new wisdom is emerging In the name of performance, designers have sacrificed: predictability, repeatability, composability Hand-optimization of programs is becoming impractical 16 三 FFTW的技术特点 SCCAS 3.2 The Codelet Generator • Generates highly-optimized transforms of small sizes form the base cases of the FFT recursion • Manipulates abstract syntax tree which is unparsed to C knows about complex arithmetic, etc. • The codelets – composable blocks of optimized code computer generated Advantages • Long, unrolled code takes advantage of: optimizing compilers (instruction scheduling, etc.), large register sets • Applies tedious optimizations • Easy to experiment with different algorithms – – prime factor, split-radix (transform sizes not a power of 2) various optimization schemes 17 三 FFTW的技术特点 SCCAS 3.3 The Executor • • Executes the plan by composing codelets Explicit recursion divide-and-conquer uses all levels of the memory hierarchy fit in cache • Novel storage for the twiddle factors store them in the order they are used 3.4 FFTW is Easy to Use COMPLEX A[n], B[n]; fftw_plan plan; plan = fftw_create_plan(n); /* create the plan */ fftw(plan, A); /* use the plan */ fftw(plan, B); /* re-use the plan */ fftw_destroy_plan(plan) /* destroy the plan*/ 18 四 FFTW 的调用算例 SCCAS 4.1 调用说明 1. 2. 3. • • • FFTW 的C函数允许Fortran程序调用 . fftw/fftwnd/rfftw/rfftwnd 由 fftw_f77/fftwnd_f77/rfftw_f77/rfftwnd_f77所替代 函数的大多数参数相同, 少数例外: plan变量在C中为fftw_plan, rfftw_plan等类型, Fortran上对64位机器用integer*8 类型 Fortran数组列存储,C为行存储, integer对应于int, real对应于float fortran/fftw_f77.i中已将选项参数化 integer FFTW_FORWARD, FFTW_BACKWARD parameter(FFTW_FORWARD=-1, FFTW_BACKWARD=1 integer FFTW_OUT_OF_PLACE, FFTW_IN_PLACE parameter(FFTW_OUT_OF_PLACE=0) parameter(FFTW_IN_PLACE=8) integer FFTW_ESTIMATE, FFTW_MEASURE parameter (FFTW_ESTIMATE=0, FFTW_MEASURE=1) 19 四 FFTW 的调用算例 SCCAS 4.2 串行一维复变换的例子 //C编译环境 fftw_complex in[N], *out[N]; fftw_plan plan; plan = fftw_create_plan(N, FFTW_FORWARD, FFTW_ESTIMATE); fftw_one(plan, in, out); fftw_destroy_plan(plan); // Fortran编译环境 double complex in, out dimension in(N), out(N) integer plan call fftw_f77_create_plan(plan, N, FFTW_FORWARD, FFTW_ESTIMATE) call fftw_f77_one(plan, in, out) call fftw_f77_destroy_plan(plan) 20 四 FFTW 的调用算例 SCCAS 4.3. 并行一维复变换的例子 #include <fttw_mpi.h> int main(int argc, char **argv) { const int N = 128; fftwnd_mpi_plan plan; fftw_complex *data; MPI_Comm comm=MPI_COMM_WORLD; MPI_Init(&argc, &argv); MPI_Comm_rank(comm,&rank);MPI_Comm_size(comm,&np); plan = fftwnd_mpi_creat_plan(comm, N, -1, 8); fftw_mpi_local_sizes(plan,&local_n,&nx_out, &start_x,&start_x_out, &size); …allocate and initialize data . . . //分配并初始化数据 data= (fftw_complex*) fftw_malloc(sizeof(fftw_complex)* size); preal=(fftw_real *)in;;srand(rank*100); for(i=0;i<2*local_n;i++) preal[i]=(fftw_real)rand()/RAND_MAX; fftwnd_mpi(p, 1, data, NULL, FFTW_NORMAL_ORDER); fftw_mpi_destroy_plan(plan); MPI_Finalize( ); 21 } 四 FFTW 的调用算例 SCCAS 4.4. FFTW的数值测试 [scwang@LB]$ locate fftw /soft/fftw-215 fftw_test fftw_mpi_test [scydf@LB270108 ~/fftw/fftw-f90/2ds_test]$ %Demo 计算时间:T(Forward_plan)+T(Forward_FFT)+T(Inverse_plan)+T(Inverse_FFT) 表1:串行性能(深腾7000, x86_64, 时间: 秒, 浮点性能: Mflops) 问题规模 1024x 1024 2048 x 2048 5120 x 5120 10240 x 10240 计算时间 0.16 5.40039 35.06543 浮点性能 1 310 695 788 670 646 024 表2:并行效率(深腾7000, x86_64, 4096 x 4096 ) 146.90234 647 917 处理机数 1 2 4 8 16 32 时间 6.7383 4.8354 3.2163 3.1541 1.5784 0.7881 效率 1 0.6967 0.5238 0..2670 0.2668 0.2672 22 五. FFTW在Unix上的安装 SCCAS 1) FFTW带有一个GNU形式的configure程序,安装很简单: tar –xvfz fftw-3.0.1.tar.gz ./configure make make install 这将建立单机形式的复和实变换库以及测试程序 2) 对于某些系统, configure脚本知道好的CFLAG. 如果你的系统不知道, 可用如下命令编译 FFTW: ./ configure CC=“<Compiler>”, CFLAGS=”<Compiler CFLAGS >” configure 也可接受一些FFTW说明的标志 : --enable-float 生成一个单精度版的FFTW --enable-threads 使能够编译和安装FFTW线程库 --enable-mpi 使能够编译和安装FFTW的MPI库 --disable-fortran 禁止FFTW库中包含Fortran可调用程序 3) 比如调用 dfftw_one或 sfftw_one 之前的安装选项为: ./configure --prefix=/home_soft/soft/ia64/lib/Mathlib/fftw-2.1.5 CC=icc MPICC=icc CFLAGS=-O3 F77=ifort FFLAGS=-O3 --enable-double --enable-type-prefix --enable-mpi --enable-fortran --enable-shared (double/float对应于双精度或单精度) make make install 23 SCCAS 24