我在完成任务时遇到麻烦,我必须使用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();
}
}