On Sunday, 9 June 2013 at 12:09:03 UTC, bearophile wrote:
Time ago I tried simpledisplay (on 32 bit Windows) and I remember I had to make the class Image final to have some performance. I used it on Rosettacode too:

Hmm probably putPixel and impl.putPixel is too slow, it is called a lot. I made the class final now and got a about 8% improvement, using linux right now.

Eliminating those calls entirely, writing straight to the private rawData pointer, gives about 12% improvement, since this would get rid of calculating pixel offsets too (we can just do ptr++). Maybe I'll expose that and try to make it somehow cross platform.

I got as high as 45 fps using that trick plus the dmd -inline -release -O -noboundscheck flags. (The original code without flags and without final gave me only 30 fps).

I compiled and ran on wine too and it seems to have worked. Here's the nextState function using a pointer:


void nextState(ref World world, ref World nextWorld,
               ref Xorshift rnd, Image img) {
  auto pixelPointer = img.getDataPointer();
auto linePadding = img.bytesPerLine() - img.bytesPerPixel * img.width;
  auto pixelPadding = img.bytesPerPixel() - 3;
  enum double div = cast(double)typeof(rnd.front()).max;
  immutable nr = world.length;
  immutable nc = world[0].length;
  foreach (r, row; world) {
    foreach (c, elem; row) {
      final switch (elem) {
        case Cell.empty:
                *pixelPointer++ = 255;
                *pixelPointer++ = 255;
                *pixelPointer++ = 255;
          //img.putPixel(c, r, white);
nextWorld[r][c] = (rnd.front()/div)<P_PROB ? Cell.tree : Cell.empty;
          rnd.popFront();
          break;

        case Cell.tree:
          //img.putPixel(c, r, green);
                *pixelPointer++ = 0;
                *pixelPointer++ = 255;
                *pixelPointer++ = 0;

          foreach (rowShift; sp)
            foreach (colShift; sp)
              if ((r + rowShift) >= 0 && (r + rowShift) < nr &&
                  (c + colShift) >= 0 && (c + colShift) < nc &&
world[r + rowShift][c + colShift] == Cell.burning) {
                nextWorld[r][c] = Cell.burning;
                goto END;
              }

nextWorld[r][c]=(rnd.front()/div)<F_PROB ? Cell.burning : Cell.tree;
          rnd.popFront();
          END: break;

        case Cell.burning:
          //img.putPixel(c, r, red);
                *pixelPointer++ = 0;
                *pixelPointer++ = 0;
                *pixelPointer++ = 255;
          nextWorld[r][c] = Cell.empty;
          break;
      }

      pixelPointer += pixelPadding;
    }

    pixelPointer += linePadding;
  }

  swap(world, nextWorld);
}


I have tried that Forest fire code with your new version and it gives me a: simpledisplay.d(676): Error: undefined identifier i, did you mean variable s?

oops fixed. I added a new function but didn't even compile the Windows version of this change (only tried linux) and made a typo there.

Reply via email to