That's odd, I'm getting opposite results: iota = 78ms baseline = 187ms
Andreas' old code gives: 421ms This is over multiple runs so I'm getting the average out of about 20 runs. On 12/23/10, Andrei Alexandrescu <[email protected]> wrote: > On 12/22/10 4:04 PM, Andreas Mayer wrote: >> To see what performance advantage D would give me over using a scripting >> language, I made a small benchmark. It consists of this code: >> >>> auto L = iota(0.0, 10000000.0); >>> auto L2 = map!"a / 2"(L); >>> auto L3 = map!"a + 2"(L2); >>> auto V = reduce!"a + b"(L3); >> >> It runs in 281 ms on my computer. >> >> The same code in Lua (using LuaJIT) runs in 23 ms. >> >> That's about 10 times faster. I would have expected D to be faster. Did I >> do something wrong? >> >> The first Lua version uses a simplified design. I thought maybe that is >> unfair to ranges, which are more complicated. You could argue ranges have >> more features and do more work. To make it fair, I made a second Lua >> version of the above benchmark that emulates ranges. It is still 29 ms >> fast. >> >> The full D version is here: http://pastebin.com/R5AGHyPx >> The Lua version: http://pastebin.com/Sa7rp6uz >> Lua version that emulates ranges: http://pastebin.com/eAKMSWyr >> >> Could someone help me solving this mystery? >> >> Or is D, unlike I thought, not suitable for high performance computing? >> What should I do? > > I reproduced the problem with a test program as shown below. On my > machine the D iota runs in 108ms, whereas a baseline using a handwritten > loop runs in 43 ms. > > I then replaced iota's implementation with a simpler one that's a > forward range. Then the performance became exactly the same as for the > simple loop. > > Andreas, any chance you could run this on your machine and compare it > with Lua? (I don't have Lua installed.) Thanks! > > > Andrei > > // D version, with std.algorithm > // ~ 281 ms, using dmd 2.051 (dmd -O -release -inline) > > import std.algorithm; > import std.stdio; > import std.range; > import std.traits; > > struct Iota2(N, S) if (isFloatingPoint!N && isNumeric!S) { > private N start, end, current; > private S step; > this(N start, N end, S step) > { > this.start = start; > this.end = end; > this.step = step; > current = start; > } > /// Range primitives > @property bool empty() const { return current >= end; } > /// Ditto > @property N front() { return current; } > /// Ditto > alias front moveFront; > /// Ditto > void popFront() > { > assert(!empty); > current += step; > } > @property Iota2 save() { return this; } > } > > auto iota2(B, E, S)(B begin, E end, S step) > if (is(typeof((E.init - B.init) + 1 * S.init))) > { > return Iota2!(CommonType!(Unqual!B, Unqual!E), S)(begin, end, step); > } > > void main(string args[]) { > double result; > auto limit = 10_000_000.0; > if (args.length > 1) { > writeln("iota"); > auto L = iota2(0.0, limit, 1.0); > result = reduce!"a + b"(L); > } else { > writeln("baseline"); > result = 0.0; > for (double i = 0; i != limit; ++i) { > result += i; > } > } > writefln("%f", result); > } >
