OpenCL: get binary file of compiled kernel

Started by mwrod, April 20, 2018, 21:39:59

Previous topic - Next topic

mwrod

Hello,
I am currently trying to retrieve the binary file of a compiled kernel I am building with the OpenCL bindings of LWJGL, but I am getting a SIGSEGV everytime I try it. Can somebody help me finding the origin of the error?

I am first getting the size of the binary file:

ByteBuffer size = BufferUtils.createByteBuffer(8);
int ret = CL10.clGetProgramInfo(program, CL10.CL_PROGRAM_BINARY_SIZES, size.capacity(), size, null);
checkCLError(ret);
int binarySize = size.getInt();


This part is working and I am getting the size of the built program. Then I am trying to retrieve the bytes of the binary file:

ByteBuffer binary = BufferUtils.createByteBuffer(binarySize);
ret = CL10.clGetProgramInfo(program, CL10.CL_PROGRAM_BINARIES, binarySize, binary, null);
checkCLError(ret);


But then I am getting a fatal error by the Java Runtime Environment (SIGSEGV). I dont know if I am doing something wrong, but that should be the way to retrieve the binary file...

Is there some kind of bug or what am I missing? I would appreciate any help.

I attached the whole error log.

KaiHH

Please read the documentation of clGetProgramInfo: https://www.khronos.org/registry/OpenCL/sdk/1.1/docs/man/xhtml/clGetProgramInfo.html
especially the note on CL_PROGRAM_BINARY_SIZES and CL_PROGRAM_BINARIES.

Also try to find examples of those calls, such as this:
https://github.com/victusfate/opencl-book-examples/blob/master/src/Chapter_6/HelloBinaryWorld/HelloBinaryWorld.cpp#L249-L291

In essence: You are not given the size or bytes of a single binary file, but an array of the size of devices associated with the binary. So, you will have one more indirection/pointer.

mwrod

Thanks for the quick answer.

I already read the documentation of clGetProgramInfo, but since I am using only one device I thought I didnt have to retrieve the number of devices and the associated device IDs. But I did try it anyway the way it is described in the link you posted and I get the same error again. Since I am only using one device the size of the binary file buffer didnt change with that method. That is the way I am currently trying it:

int ret;

// Retrieve count of devices
ByteBuffer numDevicesBuf = BufferUtils.createByteBuffer(8);
ret = CL10.clGetProgramInfo(program, CL10.CL_PROGRAM_NUM_DEVICES, numDevicesBuf.capacity(), numDevicesBuf, null);
checkCLError(ret);

int numDevices = numDevicesBuf.getInt();

// Retrieve device ids
ByteBuffer deviceIdBuf = BufferUtils.createByteBuffer(8 * numDevices);
ret = CL10.clGetProgramInfo(program, CL10.CL_PROGRAM_DEVICES, deviceIdBuf.capacity(), deviceIdBuf, null);
checkCLError(ret);

List<Long> deviceIds = new ArrayList<>();
for(int i = 0; i < numDevices; i++) deviceIds.add(deviceIdBuf.getLong());

// Retrieve binary size of devices
ByteBuffer binarySizesBuf = BufferUtils.createByteBuffer(8 * numDevices);
ret = CL10.clGetProgramInfo(program, CL10.CL_PROGRAM_BINARY_SIZES, binarySizesBuf.capacity(), binarySizesBuf, null);
checkCLError(ret);

List<Long> binarySizes = new ArrayList<>();
long binarySize = 0;
for(int i = 0; i < numDevices; i++) {
    binarySizes.add(binarySizesBuf.getLong());
    binarySize += binarySizes.get(i);
}

// Retrieve binary files
ByteBuffer binaryBuf = BufferUtils.createByteBuffer((int) binarySize);
ret = CL10.clGetProgramInfo(program, CL10.CL_PROGRAM_BINARIES, binarySize, binaryBuf, null);
checkCLError(ret);


I am still unsure about the last part. I know that clGetProgramInfo with CL_PROGRAM_BINARIES is returning an array .Is it then the right way to have a single ByteBuffer "binaryBuf" with the size of all binary files together?

I saw in your provided example, that you just need pass the pointer, but how should it be implemented in Java then?

mwrod

I found a solution to my problem. If anyone is reading this and had the same problem, here is my solution:

int ret;

// get count of devices
int numDevices = Info.clGetProgramInfoInt(program, CL10.CL_PROGRAM_NUM_DEVICES);

// get all devices
PointerBuffer devices = PointerBuffer.allocateDirect(numDevices);
ret = CL10.clGetProgramInfo(program, CL10.CL_PROGRAM_DEVICES, devices, null);
checkCLError(ret);

// get index of current device
int index = -1;
for (int i=0; i<numDevices; ++i) {
    if (devices.get(i) == device.address()) {
        index = i;
    }
}
if (index == -1) return -1;

// get size of binary
PointerBuffer sizes = PointerBuffer.allocateDirect(numDevices);
ret = CL10.clGetProgramInfo(program, CL10.CL_PROGRAM_BINARY_SIZES, sizes, null);
checkCLError(ret);
int size = (int) sizes.get(index);

// set binary pointers
PointerBuffer binaryPointers = PointerBuffer.allocateDirect(numDevices);
for (int i = 0; i < binaryPointers.capacity(); ++i) {
    binaryPointers.put(0L);
}
binaryPointers.rewind();
ByteBuffer binaries = ByteBuffer.allocateDirect(size);
binaryPointers.put(index, binaries);

// get binary file
ret = CL10.clGetProgramInfo(program, CL10.CL_PROGRAM_BINARIES, binaryPointers, null);
checkCLError(ret);