Implementating Conway's Game of Life with JOCL

192 Views Asked by At

I'm having trouble with my assignment where I have to implement Conway's Game of Life using JOCL (http://jocl.org/), which is as you might've guessed OpenCL for Java

Currently it compiles fine, but the output after the kernel execution is just zeros which in this case is just the default initialization of the output array.

Edit: Even if I initialize the entire output array to 1 it still returns from the read buffer as 0s

I thought it might have been a problem in the kernel but even if it's just output[gid] = 1 it fails to modify the output array. But then I also can't see any problems with the JOCL implementation

Any advice would be deeply appreciated

Kernel:

__kernel void gameOfLife(
__global constant int *input,
__global int *output ) {

int gid = get_global_id( 0 );

int rowUp = gid - 100;
int rowDown = gid + 100;

bool offGrid = (i < 100);
offGrid |= (i >= (100 * (100 - 1)));
offGrid |= (i % 100 == 0);
offGrid |= (i % 100 == 100 - 1);

if (offGrid) {
    output[gid] = 0;
    return;
}

int neighbours = input[rowUp-1] + input[rowUp] + input[rowUp+1];
neighbours += input[gid-1] + input[gid+1];
neighbours += input[rowDown-1] + input[rowDown] + input[rowDown+1];

if (neighbours == 3 || ((neighbours == 2) && (input[gid] == 1))) {
    output[gid] = 1;
}
else {
    output[gid] = 0;
}
}

Java:

import org.jocl.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Random;
import java.util.stream.Collectors;
import static org.jocl.CL.*;

public class GOLifeOpenCL {
    public static void main(String[] args) {
        // TODO: Initialization
        int width = 100;
        int height = 100;
        int cells = width * height;
        int[] board = new int[cells];

        int[] input = new int[cells];
        int[] output = new int[cells];

        final Pointer inputBoardPointer = Pointer.to(input);
        final Pointer outputBoardPointer = Pointer.to(output);

        cl_mem inputMem;
        cl_mem outputMem;

        final Random random = new Random(2015);

        for (int i = 0; i < board.length; i++) {
            if (random.nextBoolean()) {
                board[i] = 1;
            }
            else {
                board[i] = 0;
            }

        }

        for (int i = 0; i < board.length; i++) {
            System.out.print(board[i]);
        }

        System.arraycopy(board, 0, input, 0, board.length);

        PrintBoard(board, width, height);


        // TODO: Set up platform, contextproperties, device, context, commandqueue

        // Number of platforms
        // Finding number of platforms
        // Find the platform, grab the first one
        // Can utilize more platforms if has AMD + INTEL etc
        final int numOfPlatforms[] = new int[ 1 ];
        clGetPlatformIDs( 0, null, numOfPlatforms );
        System.out.println("Platforms: " + numOfPlatforms[0]);

        final cl_platform_id platforms[] = new cl_platform_id[numOfPlatforms[0]];
        clGetPlatformIDs( numOfPlatforms[0], platforms, null);

        final cl_platform_id platform = platforms[0];
        System.out.println(platform);

        final cl_context_properties contextProperties = new cl_context_properties();
        contextProperties.addProperty( CL_CONTEXT_PLATFORM, platform);

        int numOfDevices[] = new int[ 1 ];
        clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, null, numOfDevices);
        System.out.println("Devices: " + numOfDevices[0]);

        final cl_device_id[] devices = new cl_device_id[numOfDevices[0]];
        clGetDeviceIDs( platform, CL_DEVICE_TYPE_ALL, numOfDevices[0], devices, null);

        final cl_device_id device = devices[0];

        final cl_context context = clCreateContext( contextProperties, 1, new cl_device_id[]{ device }, null, null, null );

        final cl_command_queue commandQueue = clCreateCommandQueue( context, device, 0, null);

        // TODO: Read in kernel, compile it

        // Read kernel file from resources
        final String programSource = new BufferedReader( new InputStreamReader(
                GOLifeOpenCL.class.getResourceAsStream( "gameOfLife.cl" )
        ) ).lines().parallel().collect( Collectors.joining("\n") );

        final cl_program program = clCreateProgramWithSource( context, 1, new String[]{programSource}, null, null );
        clBuildProgram( program, 0, null, null, null, null);

        cl_kernel kernel = clCreateKernel(program, "gameOfLife", null);

        // TODO: Memory objects

        inputMem = clCreateBuffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, Sizeof.cl_int * input.length, inputBoardPointer, null );
        outputMem = clCreateBuffer( context, CL_MEM_WRITE_ONLY, Sizeof.cl_int * output.length, null, null);

        //TODO: Local group size, kernel arguments

        final long workGroupSize[] = new long[1];
        final long oneWGS[] = new long[]{1};
        Pointer workGroupSizePointer = Pointer.to(workGroupSize);
        clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_WORK_GROUP_SIZE, Sizeof.cl_long, workGroupSizePointer, null);


        clSetKernelArg(kernel, 0, Sizeof.cl_mem, Pointer.to(inputMem));
        clSetKernelArg(kernel, 1, Sizeof.cl_mem, Pointer.to(outputMem));

        long[] boardLen = new long[1];
        boardLen[0] = input.length;

        //clEnqueueWriteBuffer(commandQueue, inputMem, CL_TRUE, 0, cells * Sizeof.cl_int, inputBoardPointer, 0, null, null);

        //TODO: Execute kernel on cells

        clEnqueueNDRangeKernel( commandQueue, kernel, 1, null, new long[]{100*100}, oneWGS, 0, null, null);

        //TODO: Read results from output
        int err;
        err = clEnqueueReadBuffer( commandQueue, outputMem, CL_TRUE, 0, cells * Sizeof.cl_int, outputBoardPointer , 0, null,null);
        if (err != CL_SUCCESS) {
            System.out.println("Unable to read results");
        } else if (err == CL_INVALID_COMMAND_QUEUE) {
            System.out.println("Invalid Command Queue");
        }

        for (int i = 0; i < output.length; i++) {
            System.out.print(output[i]);
        }

        //Copy output to input for next round and board for printing
        System.arraycopy(output, 0, input, 0, output.length);
        System.arraycopy(output, 0, board, 0, output.length);

        PrintBoard(output, width, height);
    }



    private static void PrintBoard(int[] board, int width, int height) {
        int i = 0;
        System.out.println("Printing board...");
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                if (board[i++] == 1) {
                    System.out.print("*");
                }
                else {
                    System.out.print(" ");
                }
            }
            System.out.println();
        }
        System.out.println();
        System.out.println();
        System.out.println();
    }
}
0

There are 0 best solutions below