Gameoflife

Python Numpy

from __future__ import print_function

"""
Game of Life
------------

"""
from benchpress.benchmarks import util
import numpy as np

bench = util.Benchmark("Game of Life", "height*width*iterations*rules")

SURVIVE_LOW = 2
SURVIVE_HIGH = 3
SPAWN = 3


def world(height, width):
    state = np.ones((height + 2, width + 2), dtype=bench.dtype)
    state[2:-2, 2:-2] = bench.dtype(0)
    return state


def world_zeros(height, width):
    state = np.zeros((height + 2, width + 2), dtype=bench.dtype)
    return state


def play(state, iterations, version=1, visualize=False):
    cells = state[1:-1, 1:-1]
    ul = state[0:-2, 0:-2]
    um = state[0:-2, 1:-1]
    ur = state[0:-2, 2:]
    ml = state[1:-1, 0:-2]
    mr = state[1:-1, 2:]
    ll = state[2:, 0:-2]
    lm = state[2:, 1:-1]
    lr = state[2:, 2:]

    def update():
        """
        This is the first implementation of the game rules.
        """
        neighbors = ul + um + ur + ml + mr + ll + lm + lr  # count neighbors
        live = neighbors * cells  # extract live cells neighbors
        stay = (live >= SURVIVE_LOW) & (live <= SURVIVE_HIGH)  # find cells the stay alive
        dead = neighbors * (cells == 0)  # extract dead cell neighbors
        spawn = dead == SPAWN  # find cells that spaw new life

        cells[:] = stay | spawn  # save result for next iteration

    def update_optimized():
        """
        This is an optimized implementation of the game rules.
        """
        neighbors = ul + um + ur + ml + mr + ll + lm + lr  # Count neighbors

        c1 = (neighbors == SURVIVE_LOW)  # Life conditions
        c2 = (neighbors == SPAWN)

        cells[:] = cells * c1 + c2  # Update

    if version == 1:  # Select the update function
        update_func = update
    elif version == 2:
        update_func = update_optimized

    for i in range(iterations):  # Run the game
        if visualize:
            bench.plot_surface(state, "3d", 16, 1, 0)
        update_func()
        bench.flush()

    return state


def main():
    (H, W, I, V) = bench.args.size

    if V not in [1, 2]:
        raise Exception("Unsupported rule-implementation.")

    S = world(H, W)

    bench.start()
    R = play(S, I, V, bench.args.visualize)
    bench.stop()
    bench.save_data({'res': R})
    bench.pprint()


if __name__ == "__main__":
    main()

C99 Seq

Error

There are issues with the implementation.

In progress…

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <bp_util.h>

void world(double* state, int height, int width)
{
    for (int h=0; h<height; ++h) {
        for (int w=0; w<width; ++w) {
            state[h*width + w] = (((h < 2) && (h > (height-3))) ||
                                 ((w < 2) && (w > (width-3))));
        }
    }
}

void play(double* state, int height, int width, int iterations, int version)
{
    printf("%p %d %d %d %d\n", state, height, width, iterations, version);
}

int main (int argc, char **argv)
{
    bp_util_type bp = bp_util_create(argc, argv, 4); // Grab arguments
    if (bp.args.has_error) {
        return 1;
    }

    const int height    = bp.args.sizes[0];
    const int width     = bp.args.sizes[1];
    const int iter      = bp.args.sizes[2];
    const int version   = bp.args.sizes[3];

    size_t grid_size = height*width*sizeof(double);
    double *state = (double*)malloc(grid_size);

    world(state, height, width);

    bp.timer_start();
    play(state, height, width, iter, version);
    bp.timer_stop();

    bp.print("gameoflife(c99_seq)");

    free(state);
    return 0;
}

Cpp11 Omp

Error

There are issues with the implementation.

In progress…

#include <iostream>
#include <iomanip>
#include <bp_util.h>

#define HEIGHT 1000
#define WIDTH  1000

static double SURVIVE_LOW  = 2.0;
static double SURVIVE_HIGH = 3.0;
static double SPAWN        = 3.0;

using namespace std;

template <typename T>
void world(T state)
{
    #pragma omp parallel for collapse(2)
    for(int h=0; h<HEIGHT+2; ++h) {
        for(int w=0; w<WIDTH+2; ++w) {
            state[h][w] = (((h<2) and (h>WIDTH-3)) &&
                           ((w<2) and (w>HEIGHT-3)));
        }
    }
}

template <typename T>
void play(T state, int iterations, int version, int visualize)
{
    cout << state << SURVIVE_LOW << SURVIVE_HIGH << SPAWN << endl;
    cout << state << iterations << version << visualize << endl;
    
    T* cells, ul, um, ur, ml, mr, ll, lm, lr;
}

template <typename T>
void bench(bp_util_type& bp, const int I, const int V)
{
    auto state = new T[HEIGHT][WIDTH];              // Construct matrices
    world(state);

    bp.timer_start();                               // Start timer

    play(state, I, V, bp.args.visualize);

    bp.timer_stop();                                // Stop timer

    bp.print("gameoflife(cpp11_omp)");				// Print results..
    if (bp.args.verbose) {                          // ..and value.
        cout << fixed << setprecision(10)
             << "Result = " << endl;
    }
}

int main(int argc, char* argv[])
{
    bp_util_type bp = bp_util_create(argc, argv, 4);// Grab arguments
    if (bp.args.has_error) {
        return 1;
    }
    const int W = bp.args.sizes[0];
    const int H = bp.args.sizes[1];
    const int I = bp.args.sizes[2];
    const int V = bp.args.sizes[3];

    if (HEIGHT != H) {
        cout << "Multidimensional arrays in C11 does not support dynamic size, so it has to be: " << H << "." << endl;
        return 0;
    }
    if (WIDTH != W) {
        cout << "Multidimensional arrays in C11 does not support dynamic size, so it has to be: " << W << "." << endl;
        return 0;
    }

    bench<double>(bp, I, V);

    return 0;
}