FFT_Timings.mw

Timing the FFT Algorithm 

FFT Implementation via FFTeval 

 

We developed procedure FFTeval which is used for the forward FFT and the inverse FFT, as follows. 

 

> Typesetting:-mrow(Typesetting:-mi(
 

> Typesetting:-mrow(Typesetting:-mi(
 

>
 

> Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
 

>
 

> Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
 

>
 

 

where procedure FFTeval is as follows.
 

> Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
 

>
 

Timings using procedure FFTeval 

> Typesetting:-mrow(Typesetting:-mi(
 

15 (1)
 

 

Form random vectors Typesetting:-mrow(Typesetting:-mi( where Typesetting:-mrow(Typesetting:-mi( is a vector of length Typesetting:-mrow(Typesetting:-msup(Typesetting:-mn( containing floating point numbers in the following range. 

 

> Typesetting:-mrow(Typesetting:-mfenced(Typesetting:-mrow(Typesetting:-mi(
 

-100.0, 100.0 (2)
 

 

Choose Typesetting:-mrow(Typesetting:-mi( as follows for this set of timings. 

 

> Typesetting:-mrow(Typesetting:-mi(
 

15 (3)
 

> Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
 

>
 

 

Collect timings for forwardFFT on successive vectors. Set the frequency of gc (garbage collection) higher than normal so as to minimize the effect of gc cost on the timings being collected. 

 

> Typesetting:-mrow(Typesetting:-mi(
 

>
 

> Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

N = 2, runtime = 0.46e-1
N = 4, runtime = 0.
N = 8, runtime = 0.15e-1
N = 16, runtime = 0.16e-1
N = 32, runtime = 0.46e-1
N = 64, runtime = 0.46e-1
N = 128, runtime = 0.94e-1
N = 256, runtime = .187
N = 512, runtime = .405
N = 1024, runtime = .890
N = 2048, runtime = 1.952
N = 4096, runtime = 4.282
N = 8192, runtime = 9.312
N = 16384, runtime = 18.547
N = 32768, runtime = 38.375 (4)
 

> Typesetting:-mrow(Typesetting:-mi(
 

 

Calculate the successive ratios of runtimes. 

 

> Typesetting:-mrow(Typesetting:-mo(
 

 

 

 

 

 

 

 

 

 

 

 

 

 

0.
Float(infinity)
1.06666666666667
2.87500000000000
1.00000000000000
2.04347826086957
1.98936170212766
2.16577540106952
2.19753086419753
2.19325842696629
2.19364754098361
2.17468472676319
1.99173109965636
2.06906777376395 (5)
 

>
 

 

We see that when the size of the vector is multiplied by 2, the Typesetting:-mrow(Typesetting:-mi( increases by a factor only slightly larger than 2 (as Typesetting:-mrow(Typesetting:-mi( gets large), illustrating that the cost function is nearly linear. As we have analyzed, the cost function is Typesetting:-mrow(Typesetting:-mi( . 

 

>
 

 

DFT Implementation via GeneralPolyEval 

 

For comparison purposes, let us define procedure GeneralPolyEval which uses general polynomial evaluation, not exploiting the special properties of the roots of unity. We will see that the runtime cost for this algorithm is Typesetting:-mrow(Typesetting:-mi( . 

 

> Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
 

>
 

 

Just as we defined procedures forwardFFT and inverseFFT by invoking procedure FFTeval, let us now define procedures forwardDFT and inverseDFT by invoking procedure GeneralPolyEval. This time they won't be "Fast" Fourier Transform algorithms because the cost will be Typesetting:-mrow(Typesetting:-mi( 

 

> Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
 

>
 

> Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
Typesetting:-mrow(Typesetting:-mi(
 

>
 

 

Before calculating timings for these implementations, let us verify that procedures forwardDFT and inverseDFT compute the same results as procedures forwardFFT and inverseFFT, respectively. 

 

> Typesetting:-mrow(Typesetting:-mi(
 

> Typesetting:-mrow(Typesetting:-mi(
 

3 (6)
 

> Typesetting:-mrow(Typesetting:-mi(
 

Vector[column](%id = 150375364) (7)
 

> Typesetting:-mrow(Typesetting:-mi(
 

Typesetting:-mrow(Typesetting:-mverbatim( (8)
 

> Typesetting:-mrow(Typesetting:-mi(
 

Typesetting:-mrow(Typesetting:-mverbatim( (9)
 

> Typesetting:-mrow(Typesetting:-mi(
 

0.343656805548791e-11 (10)
 

> Typesetting:-mrow(Typesetting:-mi(
 

Typesetting:-mrow(Typesetting:-mverbatim( (11)
 

> Typesetting:-mrow(Typesetting:-mi(
 

0.178875655135068e-10 (12)
 

> Typesetting:-mrow(Typesetting:-mi(
 

Typesetting:-mrow(Typesetting:-mverbatim( (13)
 

> Typesetting:-mrow(Typesetting:-mi(
 

0.981537691825592e-11 (14)
 

>
 

 

Timings using procedure GeneralPolyEval 

 

Choose Typesetting:-mrow(Typesetting:-mi( not quite as large this time because the cost increases more quickly with this algorithm as Typesetting:-mrow(Typesetting:-mi( gets large. 

 

> Typesetting:-mrow(Typesetting:-mi(
 

10 (15)
 

> Typesetting:-mrow(Typesetting:-mi(
 

>
 

> Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
 

 

 

 

 

 

 

 

 

 

N = 2, runtime = 0.
N = 4, runtime = 0.
N = 8, runtime = 0.
N = 16, runtime = 0.32e-1
N = 32, runtime = 0.61e-1
N = 64, runtime = .155
N = 128, runtime = .579
N = 256, runtime = 2.593
N = 512, runtime = 9.985
N = 1024, runtime = 45.312 (16)
 

> Typesetting:-mrow(Typesetting:-mi(
 

 

Calculate the successive ratios of runtimes. 

 

> Typesetting:-mrow(Typesetting:-mo(
 

 

 

 

 

 

 

 

 

Float(undefined)
Float(undefined)
Float(infinity)
1.90625000000000
2.54098360655738
3.73548387096774
4.47841105354059
3.85075202468184
4.53800701051577 (17)
 

>
 

 

This time, when the size of the vector is multiplied by 2 the Typesetting:-mrow(Typesetting:-mi( increases by a factor of 4 (as Typesetting:-mrow(Typesetting:-mi( gets large), consistent with an Typesetting:-mrow(Typesetting:-mi( algorithm. 

 

>
 

Using DiscreteTransforms:-FourierTransform 

An efficient implementation of FFT is provided in the DiscreteTransforms package in Maple, namely the functions FourierTransform and InverseFourierTransform. These implementations carry out all of the computations in hardware floating point arithmetic. 

 

> Typesetting:-mrow(Typesetting:-mi(
 

 

We can choose Typesetting:-mrow(Typesetting:-mi( larger in this case because the computations are much more efficient. 

 

> Typesetting:-mrow(Typesetting:-mi(
 

22 (18)
 

> Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
 

 

Collect timings for FourierTransform on successive vectors. 

 

> Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
Typesetting:-mrow(Typesetting:-mo(
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

N = 2, runtime = 0.
N = 4, runtime = 0.
N = 8, runtime = 0.
N = 16, runtime = 0.
N = 32, runtime = 0.
N = 64, runtime = 0.
N = 128, runtime = 0.15e-1
N = 256, runtime = 0.
N = 512, runtime = 0.
N = 1024, runtime = 0.
N = 2048, runtime = 0.
N = 4096, runtime = 0.
N = 8192, runtime = 0.15e-1
N = 16384, runtime = 0.15e-1
N = 32768, runtime = 0.46e-1
N = 65536, runtime = 0.93e-1
N = 131072, runtime = .156
N = 262144, runtime = .453
N = 524288, runtime = .625
N = 1048576, runtime = .968
N = 2097152, runtime = 2.187
N = 4194304, runtime = 4.000 (19)
 

>
 

 

Calculate the successive ratios of runtimes, ignoring the first several values of Typesetting:-mrow(Typesetting:-mi( because the runtimes are essentially zero. 

 

> Typesetting:-mrow(Typesetting:-mo(
 

 

 

 

 

 

 

 

3.06666666666667
2.02173913043478
1.67741935483871
2.90384615384615
1.37969094922737
1.54880000000000
2.25929752066116
1.82898948331047 (20)
 

>
 

 

We see that when the size of the vector is multiplied by 2, the Typesetting:-mrow(Typesetting:-mi( increases by a factor close to 2 (as Typesetting:-mrow(Typesetting:-mi( gets large), illustrating that the cost function is nearly linear. As we know, the cost function is Typesetting:-mrow(Typesetting:-mi( . 

 

Note that the timings for this implementation of the FFT are about 1000 times faster than our previous implementation. This is due to code that has been optimized to exploit hardware floating point arithmetic whereas our previous timings were computing in Maple's default "software floating point arithmetic". 

 

>
 

 

Finally, let's verify that FourierTransform and InverseFourierTransform are computing correctly. 

 

> Typesetting:-mrow(Typesetting:-mi(
 

3 (21)
 

> Typesetting:-mrow(Typesetting:-mi(
 

Vector[column](%id = 150498140) (22)
 

> Typesetting:-mrow(Typesetting:-mi(
 

Typesetting:-mrow(Typesetting:-mverbatim( (23)
 

> Typesetting:-mrow(Typesetting:-mi(
 

Typesetting:-mrow(Typesetting:-mverbatim( (24)
 

> Typesetting:-mrow(Typesetting:-mi(
 

0. (25)
 

>