# FFTW scales pretty well (some @btime benchmarks)

**URL:** <https://discourse.julialang.org/t/fftw-scales-pretty-well-some-btime-benchmarks/28341>\
**Category:** Performance\
**Tags:** fftw, gpu, parallel, multithreading\
**Created:** [September 3, 2019, 6:27pm UTC](https://discourse.julialang.org/t/fftw-scales-pretty-well-some-btime-benchmarks/28341 "2019-09-03T18:27:41Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![xzackli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xzackli/32/38301_2.png) [@xzackli](https://discourse.julialang.org/u/xzackli)\
**Post date:** [September 3, 2019, 6:27pm UTC](https://discourse.julialang.org/t/fftw-scales-pretty-well-some-btime-benchmarks/28341/1 "2019-09-03T18:27:42Z")

</div>

I was misled into thinking that FFTW scales poorly in parallel after reading [this discourse thread](https://discourse.julialang.org/t/parallel-fft-not-that-much-faster/671/10), so I wanted to post some numbers for someone trying to do fast FFTs in the future. My use case requires repeatedly performing moderate-size 2D FFTs for what’s basically parameter estimation + image convolution. I run the benchmarks on a 40-core 2.4 GHz Skylake node.

For 1024x1024, here’s the output for 1/8/40 threads:

```julia-auto
  19.280 ms (0 allocations: 0 bytes)
  4.149 ms (0 allocations: 0 bytes)
  1.642 ms (0 allocations: 0 bytes)

```

For 2048x2048, the timings for 1/8/40 threads are

```julia-auto
  307.795 ms (0 allocations: 0 bytes)
  98.475 ms (0 allocations: 0 bytes)
  26.190 ms (0 allocations: 0 bytes)

```

Finally, Julia has the amazing `CuArrays`. We can compare to performance for double-precision operations on a Tesla P100. For 1024x1024 2D FFTs,

```julia-auto
  335.463 μs (6 allocations: 176 bytes)

```

For 2048x2048,

```julia-auto
  1.185 ms (6 allocations: 176 bytes)

```

GPU performance is pretty awe-inspiring, assuming I’ve done the benchmark correctly.

## Benchmark Code (CPU)

```Julia
using BenchmarkTools
using FFTW

const nx = 1024 # do 1024 x 1024 2D FFT

FFTW.set_num_threads(1)
p = plan_fft!( randn(Complex{Float64},nx,nx) )
@btime p*x setup=(x=randn(Complex{Float64},nx,nx));

FFTW.set_num_threads(8)
p = plan_fft!( randn(Complex{Float64},nx,nx) )
@btime p*x setup=(x=randn(Complex{Float64},nx,nx));

FFTW.set_num_threads(40)
p = plan_fft!( randn(Complex{Float64},nx,nx) )
@btime p*x setup=(x=randn(Complex{Float64},nx,nx));

```

## Benchmark Code (GPU)

```Julia
using BenchmarkTools
using FFTW
using CuArrays
using Random

const nx = 1024 # do 1024 x 1024 2D FFT
xc = CuArray{ComplexF64}(CuArrays.randn(Float64, nx, nx))
p = plan_fft!( xc )
@btime CuArrays.@sync(p * x) setup=(
    x=CuArray{ComplexF64}(CuArrays.randn(Float64, nx, nx)));

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 4, 2025, 2:30pm UTC](https://discourse.julialang.org/t/fftw-scales-pretty-well-some-btime-benchmarks/28341/4 "2025-02-04T14:30:43Z")

</div>

> [@xzackli](#):
>
> ```julia
> using FFTW
> using CuArrays
> 
> ```

`CuArrays` have their own FFT, they aren’t using FFTW. (So you only need `using AbstractFFTs`, maybe?)
