Two CTFE benchmarks
Don
nospam at nospam.com
Sun Mar 28 10:48:50 PDT 2010
bearophile wrote:
> It's a lot of time I don't show benchmarks here :-)
> I have taken the timings of run time or compile time of a integer-based function (nqueens) and a function that works with small arrays of integers (adapted from the Shootout).
>
> I have used dmd 2.042 with -O -release -inline
> The timings for the CFTE version don't include the printing on screen, I have just timed the compile time.
> The CPU is a Celeron at about 2.3 GHz. Code is shown below.
>
>
> Timings nqueens, seconds:
> N= 10 11 12 13 14 15
> ctfe: 0.43 1.83 23.40 - - -
> runtime: 0.04 0.04 0.05 0.13 0.55 3.21
>
>
> Timings fannkuch, seconds:
> N= 6 7 8 9 10 11
> ctfe: 0.22 0.51 17.50 - - -
> runtime: 0.03 0.03 0.04 0.07 0.43 4.63
>
>
> I have not timed ldc, but usually it's about 20-30% faster than dmd at CFTE (and often 100-300% faster than dmd at runtime).
>
> The CFTE is quite slower, but the main problem is that it uses a too much large amount of RAM. Reducing the RAM used can probably speed up too a little.
Memory reduction would speed it up enormously. Almost all CTFE issues
trace back to bug 1330. Thanks for the benchmarks, they're very helpful.
>
> ----------------------------
>
> // nqueens
>
> import std.c.stdio: printf;
>
> // the original code is not mine
> uint nqueens(uint c, uint ll=0, uint r=0, uint n=0) {
> uint b;
> if (~c)
> for (uint
> S = ll | c | r; ~0U != S;
> b = ~S & (S + 1), S |= b, n = nqueens(c | b, (ll | b) << 1, (r | b) >> 1, n)
> ) {}
> else
> n++;
> return n;
> }
>
> enum int n = 10;
> version(ctfe) enum uint result = nqueens(~0U >> n); // ctfe
> void main() {
> version(ctfe) {} else uint result = nqueens(~0U >> n); // runtime
> printf("nqueens(%d) = %u\n", n, result);
> }
>
> ----------------------------
>
> // fannkuch
>
> import std.c.stdio: printf;
>
> int fannkuch(int n) {
> int i, j, k, t, flips, maxFlipsCount, check;
> int r = n;
> auto perm = new int[n];
> auto perm1 = new int[n];
> auto count = new int[n];
>
> foreach (ist; 0 .. n)
> perm1[ist] = ist;
> for ( ; ; ) {
> if (check < 30) {
> //pragma(msg, permToString(perm1)); // not possible
> check++;
> }
>
> while (r != 1) {
> count[r - 1] = r;
> r--;
> }
>
> if (!(perm1[0] == 0 || perm1[n-1] == n-1)) {
> foreach (ist; 0 .. n)
> perm[ist] = perm1[ist];
>
> flips = 0;
> i = perm[0];
> do {
> for (j = 1, k = i - 1; j < k; j++, k--) {
> t = perm[j];
> perm[j] = perm[k];
> perm[k] = t;
> }
> flips++;
> t = perm[i];
> perm[i] = i;
> i = t;
> } while(i);
>
> if (flips > maxFlipsCount)
> maxFlipsCount = flips;
> }
>
> for ( ; ; ) {
> if (r == n)
> return maxFlipsCount;
> t = perm1[0];
> for (i = 0; i < r; ) {
> j = i + 1;
> perm1[i] = perm1[j];
> i = j;
> }
> perm1[r] = t;
>
> count[r]--;
> if (count[r] > 0)
> break;
> r++;
> }
> }
> }
>
>
> /*
> This is faster as run-time function:
>
> int fannkuch(int n)() {
> int i, j, k, t, flips, maxFlipsCount, check;
> int r = n;
> int[n] perm, perm1, count;
>
> foreach (ist; Range!(0, n))
> perm1[ist] = ist;
> for ( ; ; ) {
> if (check < 30) {
> //pragma(msg, permToString(perm1)); // not possible because of many D bugs
> check++;
> }
>
> while (r != 1) {
> count[r - 1] = r;
> r--;
> }
>
> if (!(perm1[0] == 0 || perm1[n-1] == n-1)) {
> foreach (ist; Range!(0, n))
> perm[ist] = perm1[ist];
> ...
> */
>
>
> enum int n = 11;
> version(ctfe) enum int result = fannkuch(n); // ctfe
> void main() {
> version(ctfe) {} else int result = fannkuch(n); // runtime
> printf("Pfannkuchen(%d) = %d\n", n, result);
> }
>
> ----------------------------
>
> Bye,
> bearophile
More information about the Digitalmars-d
mailing list