yum/gpu_fft
A GPU-friendly FFT
git clone https://git.yummers.dev/yum/gpu_fft
d144a07
master
1use criterion::{ BatchSize , Criterion , black_box, criterion_group, criterion_main}; 2use gpu_fft:: cpu::{ 3 fft_v1_hoist, fft_v2_double_buffer, fft_v3_iterative, fft_v4_radix_4, fft_v5_s0_opt, 4 fft_v6_unsafe, fft_v7_radix_8, naive_dft, naive_fft, precompute_twiddles, 5}; 6use num:: complex:: Complex ; 7use num:: traits:: Float ; 8 9// Cast one float type to another, truncating if needed. 10fn t0_to_t1 < T0 : Float , T1 : Float >( val : T0 ) ->T1 { 11return num:: cast ( val). unwrap (); 12} 13 14// Casts one Complex<T> to another. 15fn complex_to_t < T0 : Float , T1 : Float >( data : & [ Complex < T0 >]) ->Vec < Complex < T1 >> { 16 data. iter () 17. map ( |c|Complex :: new ( t0_to_t1 ( c. re ), t0_to_t1 ( c. im ))) 18. collect () 19} 20 21fn get_data < const N : usize >() ->Vec < Complex < f32 >> { 22let mut data: Vec < Complex < f32 >> =Vec :: new (); 23 data. resize ( N , Complex :: ZERO ); 24// Randomize data. 25for iin 0 ..data. len () { 26 data[ i] =Complex :: new ( rand:: random (), rand:: random ()); 27} 28 data 29} 30 31fn do_dft_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 32let data =get_data ::< N >(); 33 34let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 35 36 c. bench_function ( format! ( "size {}, dft" , N ). as_str (), |b|{ 37 b. iter_batched_ref ( 38 || result_ref. clone (), 39 |result_ref|{ 40naive_dft ::< f32 >( result_ref); 41black_box ( result_ref); 42}, 43BatchSize :: PerIteration , 44); 45}); 46} 47 48fn do_naive_fft_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 49let data =get_data ::< N >(); 50 51let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 52 53 c. bench_function ( format! ( "size {}, naive fft" , N ). as_str (), |b|{ 54 b. iter_batched_ref ( 55 || result_ref. clone (), 56 |result_ref|{ 57naive_fft ::< f32 >( result_ref); 58black_box ( result_ref); 59}, 60BatchSize :: PerIteration , 61); 62}); 63} 64 65fn do_fft_v1_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 66let data =get_data ::< N >(); 67 68let twiddles =precompute_twiddles ( N ); 69let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 70 71 c. bench_function ( format! ( "size {}, fft v1" , N ). as_str (), |b|{ 72 b. iter_batched_ref ( 73 || result_ref. clone (), 74 |result_ref|{ 75fft_v1_hoist ::< f32 >( result_ref, & twiddles); 76black_box ( result_ref); 77}, 78BatchSize :: PerIteration , 79); 80}); 81} 82 83fn do_fft_v2_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 84let data =get_data ::< N >(); 85 86let twiddles =precompute_twiddles ( N ); 87let mut scratch =vec! [ Complex :: new ( 0.0 , 0.0 ); N ]; 88let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 89 90 c. bench_function ( format! ( "size {}, fft v2" , N ). as_str (), |b|{ 91 b. iter_batched_ref ( 92 || result_ref. clone (), 93 |result_ref|{ 94fft_v2_double_buffer ::< f32 >( result_ref, & mut scratch, & twiddles); 95black_box ( result_ref); 96}, 97BatchSize :: PerIteration , 98); 99}); 100} 101 102fn do_fft_v3_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 103let data =get_data ::< N >(); 104 105let twiddles =precompute_twiddles ( N ); 106let mut scratch =vec! [ Complex :: new ( 0.0 , 0.0 ); N ]; 107let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 108 109 c. bench_function ( format! ( "size {}, fft v3" , N ). as_str (), |b|{ 110 b. iter_batched_ref ( 111 || result_ref. clone (), 112 |result_ref|{ 113fft_v3_iterative ::< f32 >( result_ref, & mut scratch, & twiddles); 114black_box ( result_ref); 115}, 116BatchSize :: PerIteration , 117); 118}); 119} 120 121fn do_fft_v4_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 122let data =get_data ::< N >(); 123 124let twiddles =precompute_twiddles ( N ); 125let mut scratch =vec! [ Complex :: new ( 0.0 , 0.0 ); N ]; 126let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 127 128 c. bench_function ( format! ( "size {}, fft v4" , N ). as_str (), |b|{ 129 b. iter_batched_ref ( 130 || result_ref. clone (), 131 |result_ref|{ 132fft_v4_radix_4 ::< f32 >( result_ref, & mut scratch, & twiddles); 133black_box ( result_ref); 134}, 135BatchSize :: PerIteration , 136); 137}); 138} 139 140fn do_fft_v5_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 141let data =get_data ::< N >(); 142 143let twiddles =precompute_twiddles ( N ); 144let mut scratch =vec! [ Complex :: new ( 0.0 , 0.0 ); N ]; 145let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 146 147 c. bench_function ( format! ( "size {}, fft v5" , N ). as_str (), |b|{ 148 b. iter_batched_ref ( 149 || result_ref. clone (), 150 |result_ref|{ 151fft_v5_s0_opt ::< f32 >( result_ref, & mut scratch, & twiddles); 152black_box ( result_ref); 153}, 154BatchSize :: PerIteration , 155); 156}); 157} 158 159fn do_fft_v6_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 160let data =get_data ::< N >(); 161 162let twiddles =precompute_twiddles ( N ); 163let mut scratch =vec! [ Complex :: new ( 0.0 , 0.0 ); N ]; 164let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 165 166 c. bench_function ( format! ( "size {}, fft v6" , N ). as_str (), |b|{ 167 b. iter_batched_ref ( 168 || result_ref. clone (), 169 |result_ref|{ 170fft_v6_unsafe ::< f32 >( result_ref, & mut scratch, & twiddles); 171black_box ( result_ref); 172}, 173BatchSize :: PerIteration , 174); 175}); 176} 177 178fn do_fft_v7_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 179let data =get_data ::< N >(); 180 181let twiddles =precompute_twiddles ( N ); 182let mut scratch =vec! [ Complex :: new ( 0.0 , 0.0 ); N ]; 183let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 184 185 c. bench_function ( format! ( "size {}, fft v7" , N ). as_str (), |b|{ 186 b. iter_batched_ref ( 187 || result_ref. clone (), 188 |result_ref|{ 189fft_v7_radix_8 ::< f32 >( result_ref, & mut scratch, & twiddles); 190black_box ( result_ref); 191}, 192BatchSize :: PerIteration , 193); 194}); 195} 196 197fn do_ref_benchmark_for_n < const N : usize >( c : & mut Criterion ) { 198let data =get_data ::< N >(); 199 200let result_ref: Vec < rustfft:: num_complex:: Complex < f32 >> =complex_to_t ( & data); 201let mut ref_planner = rustfft:: FftPlanner ::< f32 >:: new (); 202let mut scratch: Vec < rustfft:: num_complex:: Complex < f32 >> = 203vec! [ Complex ::< f32 >:: new ( 0.0 , 0.0 ); N ]; 204let ref_fft = ref_planner. plan_fft_forward ( result_ref. len ()); 205 206 c. bench_function ( format! ( "size {}, reference" , N ). as_str (), |b|{ 207 b. iter_batched_ref ( 208 || result_ref. clone (), 209 |result_ref|{ 210 ref_fft. process_with_scratch ( result_ref, & mut scratch); 211black_box ( result_ref); 212}, 213BatchSize :: PerIteration , 214); 215}); 216} 217 218pub fn criterion_benchmark ( c : & mut Criterion ) { 219do_dft_benchmark_for_n ::< 4096 >( c); 220 221do_fft_v6_benchmark_for_n ::< 256 >( c); 222do_ref_benchmark_for_n ::< 256 >( c); 223 224do_fft_v7_benchmark_for_n ::< 512 >( c); 225do_ref_benchmark_for_n ::< 512 >( c); 226 227do_fft_v6_benchmark_for_n ::< 1024 >( c); 228do_ref_benchmark_for_n ::< 1024 >( c); 229 230do_dft_benchmark_for_n ::< 4096 >( c); 231do_naive_fft_benchmark_for_n ::< 4096 >( c); 232do_fft_v1_benchmark_for_n ::< 4096 >( c); 233do_fft_v2_benchmark_for_n ::< 4096 >( c); 234do_fft_v3_benchmark_for_n ::< 4096 >( c); 235do_fft_v4_benchmark_for_n ::< 4096 >( c); 236do_fft_v5_benchmark_for_n ::< 4096 >( c); 237do_fft_v6_benchmark_for_n ::< 4096 >( c); 238do_fft_v7_benchmark_for_n ::< 4096 >( c); 239do_ref_benchmark_for_n ::< 4096 >( c); 240} 241 242criterion_group! ( benches, criterion_benchmark); 243criterion_main! ( benches);