I like optimization challenges. This is an excellent test
program to check the effect of different floating point types
on intermediate values. Remember that when you store values in
a float variable, the FPU actually has to round it down to
that precision, store it in a 32-bit memory location, then
load it back in and expand it - you _asked_ for that.

I compiled with LDC2 and these are the results:

D code serial with dimension 32768 ...
  using floats  Total time: 13.399 [sec]
  using doubles Total time:  9.429 [sec]
  using reals   Total time:  8.909 [sec] // <- !!!

You get both, 50% more speed and more precision! It is a
win-win situation. Also take a look at Phobos' std.math that
returns real everywhere.

Modified code:
---8<-------------------------------

module main;

import std.datetime;
import std.metastrings;
import std.stdio;
import std.typetuple;


enum DIM = 32 * 1024;

int juliaValue;

template Julia(TReal)
{
        struct ComplexStruct
        {
                float r;
                float i;
        
                TReal squarePlusMag(const ComplexStruct another)
                {
                        TReal r1 = r*r - i*i + another.r;
                        TReal i1 = 2.0*i*r + another.i;
                        
                        r = r1;
                        i = i1;
                        
                        return (r1*r1 + i1*i1);
                }
        }

        int juliaFunction( int x, int y )
        {
                auto c = ComplexStruct(0.8, 0.156);
                auto a = ComplexStruct(x, y);
        
                foreach (i; 0 .. 200)
                        if (a.squarePlusMag(c) > 1000)
                                return 0;
                return 1;
        }
        
        void kernel()
        {
                foreach (x; 0 .. DIM) {
                        foreach (y; 0 .. DIM) {
                                juliaValue = juliaFunction( x, y );
                        }
                }
        }
}

void main()
{
        writeln("D code serial with dimension " ~ toStringNow!DIM ~ " ...");
        StopWatch sw;
        foreach (Math; TypeTuple!(float, double, real))
        {
                sw.start();
                Julia!(Math).kernel();
                sw.stop();
                writefln("  using %ss Total time: %s [sec]",
                         Math.stringof, (sw.peek().msecs * 0.001));
                sw.reset();
        }
}

------------------------------->8---

-- 
Marco

Reply via email to