Close

Handling data

A project log for Game of Life bit-parallel algorithm

A different kind of computation for Conway's most famous puzzle, borrowing from my algorithmics and computer design experiences

yann-guidon-ygdesYann Guidon / YGDES 11/29/2016 at 03:590 Comments

I've just uploaded a C file that works with 64 bits (though it can be anything) and provides a skeleton for the data shuffling that reduces memory usage.

There is no double-buffering, the cells are computated "in place". To prevent time-distorsions (the result being directly used for the next iteration), the current result is written to the WriteBuffer variable. This variable is then written back to memory after the past value is read (again).

    L1=world[i-1];          // make sure we read
    world[i-1]=WriteBuffer; // the value of t-1, not the
                            // result computed in the last iteration
    L2=world[i  ];   // I know, a rotating register barrel
    L3=world[i+1];   // would work better but not for AMBAP
To emulate "some sort of expanding computation", I have used the following simple formula :
WriteBuffer = L1+L2+L3;

This helps me check that the ranges of indices can be dynamically adjusted. For example, with the following initial configuration:

start: 13

                         #
                       # ##
             ##      ## ## #       ##
            # ###    # #  ##       #  #
 ##        #  # # #   # #  #       ####
 #  #      #   # ### # ####        ####
 ####       ## #### # # #  #       #  #
 ####      ## ### #### #  ##       ##
 #  #       ## #### ### ## #
 ##        #   # ###   # ##
           #  # # #      #
            # ###
             ##
               ##
              # # #
             #  # ##
            #    # ##
            #  # # # #
            #### ## ##
            #### ## ##
            #  # # # #
            #    # ##
             #  # ##
              # # #
               ##
max=40

After a few cycles, the range has grown :

start: 10

                         #
                       #  ##
             ##      ### # # #     ##
            #### #    ####   ##     #  #
 ##        #####  ## ###  ## # #     ####
  #  #       ##### # ##### # ###   ###    #
   ####    # ####   ##   # #    #  #    ###
 ###    #   #   # ## #    ##    #       #  #
 #    ###   #  # # # ##    #    #       #  #
      #  #  # # ### # # # ##    #  #    ###
      #  # # ### ###      ##    #  ###    #
 #    ###   # # ### # ### ## ###     ####
 ###    #   #  # # # ##  ### # #    #  #
   ####     #  # ### # #  #  ##    ##
  #  #     # # ### ## # ## # #
 ##           ###   # ##  ##
           # ##    ####  #
            ##     #####
              # ##  # ###
            #  ##   #### #
            ###### #      #
             # # ##### #  #
             # # ##### #  #
            ###### #      #
            #  ##   #### #
             ### #  # ###
              # # # ####
            ### ## # ##
             #### #  #
              ###  #
               ##
max=43
It is important to keep an empty line before first line and after the last line, so more cells can grow there.

The adjustment of the last line is done with the variable run: it is first cleared to 0 then set to the line number where the line is not empty. This value is then assigned at the end of the scan:

  MaxLine=run;

MaxLine will be the upper limit for the next time step, but it should preserve the previously mentioned "margin" for the growth of new cells beyond the last line. That's why run is set with a little offset, inside the loop:

    if (WriteBuffer)
      run=i+2;  // push the end of the work range

Dealing with the start index is a bit more tricky but run provides us with a way to handle it nicely. It remains stuck to 0 while empty lines are found so we can increase MinLine as long as run is cleared. The complete code is simply:

    if (WriteBuffer)
      run=i+2;  // push the end of the work range
    else
      if (run==0) // no life found yet
        MinLine=i-1; // push the start of the work range
Overall, it's a bit delicate but not totally arcane, since it's only a 1D array. I keep it simple because a 2D array has some very tricky side effects. The AMBAP is limited to 16-bits wide data anyway, for computation AND display.

Discussions