用JOCL实现康威的生命游戏

时间:2015-05-30 08:42:42

标签: java parallel-processing opencl jocl

我在完成任务时遇到麻烦,我必须使用JOCL(http://jocl.org/)来实现Conway的生命游戏,就像你可能已经猜到的OpenCL for Java

目前它编译得很好,但是内核执行后的输出只是零,在这种情况下只是输出数组的默认初始化。

编辑:即使我将整个输出数组初始化为1,它仍然从读缓冲区返回为0s

我认为它可能是内核中的一个问题,但即使它只是输出[gid] = 1,它也无法修改输出数组。但后来我也看不到JOCL实现的任何问题

任何建议都会受到高度赞赏

内核:

__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;
}
}

爪哇:

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 个答案:

没有答案