[phobos] FFT

David Simcha dsimcha at gmail.com
Tue Aug 3 21:01:49 PDT 2010


Ok, I've got some more optimizations.  I figured out that it's worth 
trading off some space to make the sin/cos lookup tables be in 
contiguous memory blocks for all sub-FFTs.  I'm now down to ~340 ms on 
my benchmark, but fresh out of optimization ideas.  Here are the 
performance characteristics of the code in case anyone has any clever ideas:

1.  Skipping the slowFourier2 base case and simply returning (Yes, this 
produces incorrect results, but it's just to see the cost of it) shaves 
off a surprising ~110 milliseconds or roughly 30%.  This is probably 
because slowFourier2 always accesses two memory positions that are 
virtually guaranteed to be cache misses.

2.  Switching from doubles to floats for both input and output gains ~60 
milliseconds, probably due to better cache performance.

3.  Skipping the entire twiddle factor loop by sticking a return 
statement before it saves about 190 milliseconds, or only a little over 
half of the total execution time.  This is surprising because a naive 
reader of the code would probably think that almost all execution time 
is being spent in this loop.

4.  I didn't bother (at least, not yet) with a breadth first base case 
because recursion overhead seems fairly negligible.  The code with the 
return statement before the twiddle factor loop and with the 
slowFourier2 call commented out executes in about 40 ms; this is only 
~12%, the recursive implementation is more cache efficient up to a 
point, and the breadth-first impl wouldn't be entirely overhead-free.

I've attached the latest code for review.  If everyone's happy with it 
and noone has any more clever optimization ideas, I'd like to include it 
in the next release.  If I do, I guess std.numerics would be the place 
for it?


On 8/2/2010 10:23 AM, Don Clugston wrote:
> On 2 August 2010 15:41, David Simcha<dsimcha at gmail.com>  wrote:
>    
>> Unfortunately I just downloaded the benchmark program for FFTW and my FFT is
>> a ton slower, depending on how you look at it.  Using size 2^20 as my
>> benchmark, FFTW takes about 131 seconds to create its plan, even using
>> -oestimate, the fastest planner.  However, the plan can be reused if
>> performing multiple FFTs of the same size, and once the plan is created, it
>> can do an FFT of size 2^20 in about 53 milliseconds (which I find almost
>> unbelievable because even sorting an array of size 2^20 using a
>> well-optimized quick sort takes almost that long, and FFT seems like it
>> should should have a much larger constant than quick sort), compared to my
>> latest improvements to around 730 on the hardware I'm benchmarking on.
>>
>> On the other hand, for one-off use cases, the lack of needing to create a
>> plan is a big win, both from a speed and a simplicity of API point of view.
>>   Benchmarking against R, which doesn't appear to use plans, making the
>> comparison somewhat more relevant, things look better for my FFT:  R takes
>> about 610 milliseconds for a size 2^20 pure real FFT.
>>      
> All you're seeing is the L2 cache. Did you see the link I posted to
> the NG about the internals of FFTW? The graph at the top shows FFTW is
> 40 times faster than the 'numerical recipes' code for 2^^20. So your
> factor of 13 isn't so bad. Based on that graph, if you reduce it to
> say 2^^15, the factor should drop significantly. Adding a little bit
> of cache awareness (using core.cpuid) should be able to avoid the
> performance cliff.
> Also, DMD's floating point optimiser is so primitive, you lose up to a
> factor of two immediately.
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos
>
>    

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: fft3.d
URL: <http://lists.puremagic.com/pipermail/phobos/attachments/20100804/20487348/attachment.ksh>


More information about the phobos mailing list