diff options
-rw-r--r-- | resources/cl-if.cfg | 4 | ||||
-rw-r--r-- | resources/clImplCustomCode.c | 28 | ||||
-rw-r--r-- | resources/clImplCustomCode.java | 8 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLContext.java | 84 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLDevice.java | 179 | ||||
-rw-r--r-- | src/com/mbien/opencl/CLPlatform.java | 11 | ||||
-rw-r--r-- | test/com/mbien/opencl/JOCLTest.java | 52 |
7 files changed, 330 insertions, 36 deletions
diff --git a/resources/cl-if.cfg b/resources/cl-if.cfg index 6d23789d..08e21dcc 100644 --- a/resources/cl-if.cfg +++ b/resources/cl-if.cfg @@ -17,11 +17,11 @@ Ignore CL_GL_.*|cl.*GL.* #custom implementations Ignore clCreateContext CustomJavaCode CL /** Interface to C language function: <br> <code> cl_context clCreateContext(intptr_t * , uint32_t, cl_device_id * , void (*pfn_notify)(const char *, const void *, size_t, void *), void *, int32_t * ); </code> */ -CustomJavaCode CL public long clCreateContext(IntBuffer properties, int arg1, long[] devices, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret); +CustomJavaCode CL public long clCreateContext(IntBuffer properties, int properties_offset, long[] devices, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret, int errcode_offset); Ignore clCreateContextFromType CustomJavaCode CL /** Interface to C language function: <br> <code> cl_context clCreateContextFromType(cl_context_properties *properties, cl_device_type device_type, void (*pfn_notify)(const char *errinfo, const void *private_info, size_t cb, void *user_data), void *user_data, cl_int *errcode_ret) ; </code> */ -CustomJavaCode CL public long clCreateContextFromType(IntBuffer properties, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret); +CustomJavaCode CL public long clCreateContextFromType(IntBuffer properties, int properties_offset, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret, int errcode_offset); Ignore clBuildProgram #TODO.. diff --git a/resources/clImplCustomCode.c b/resources/clImplCustomCode.c index a9847833..83d25938 100644 --- a/resources/clImplCustomCode.c +++ b/resources/clImplCustomCode.c @@ -23,6 +23,12 @@ Java_com_mbien_opencl_impl_CLImpl_clCreateContextFromType0(JNIEnv *env, jobject intptr_t * _props_ptr = NULL; int32_t * _errcode_ptr = NULL; +/* + printf("jlong: %zu \n", sizeof(jlong) ); + printf("intptr_t: %zu \n", sizeof(intptr_t)); + printf("size_t: %zu \n", sizeof(size_t)); +*/ + cl_context _res; if (props != NULL) { @@ -38,14 +44,34 @@ Java_com_mbien_opencl_impl_CLImpl_clCreateContextFromType0(JNIEnv *env, jobject return (jlong) (intptr_t) _res; } -//clCreateContext0(IntBuffer properties, int size, long[] devices, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret, int size2) + /* JNIEXPORT jlong JNICALL Java_com_mbien_opencl_impl_CLImpl_clCreateContext0(JNIEnv *env, jobject _unused, jobject props, jint props_byte_offset, jlong device_type, jobject cb, jobject data, jobject errcode, jint errcode_byte_offset) { + intptr_t * _props_ptr = NULL; + int32_t * _errcode_ptr = NULL; + void * _device_ptr = NULL; + cl_context _res; + if (props != NULL) { + _props_ptr = (intptr_t *) (((char*) (*env)->GetDirectBufferAddress(env, props)) + props_byte_offset); + } + + if (device_type != NULL) { + _device_ptr = (void *) (((char*) (*env)->GetPrimitiveArrayCritical(env, device_type, NULL))); + } + + _res = clCreateContext(); + + if (device_type != NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, device_type, _device_ptr, 0); + } + return (jlong) (intptr_t) _res; } */ + + diff --git a/resources/clImplCustomCode.java b/resources/clImplCustomCode.java index 2fa48d64..5ccc3b02 100644 --- a/resources/clImplCustomCode.java +++ b/resources/clImplCustomCode.java @@ -1,13 +1,13 @@ - public long clCreateContext(IntBuffer properties, int arg1, long[] devices, CreateContextCallback cb, Object userData, IntBuffer errcode_ret) { - return this.clCreateContext0(properties, arg1, devices, cb, null, errcode_ret, 0); + public long clCreateContext(IntBuffer properties, int offset1, long[] devices, CreateContextCallback cb, Object userData, IntBuffer errcode_ret, int offset2) { + return this.clCreateContext0(properties, offset1, devices, cb, null, errcode_ret, offset2); } private native long clCreateContext0(IntBuffer properties, int size, long[] devices, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret, int size2); - public long clCreateContextFromType(IntBuffer arg0, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret) { - return this.clCreateContextFromType0(arg0, 0, device_type, pfn_notify, null, errcode_ret, 0); + public long clCreateContextFromType(IntBuffer arg0, int offset1, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret, int offset2) { + return this.clCreateContextFromType0(arg0, offset1, device_type, pfn_notify, null, errcode_ret, offset2); } private native long clCreateContextFromType0(IntBuffer arg0, int size, long device_type, CreateContextCallback pfn_notify, Object userData, IntBuffer errcode_ret, int size2); diff --git a/src/com/mbien/opencl/CLContext.java b/src/com/mbien/opencl/CLContext.java index dc3c7279..533d45d4 100644 --- a/src/com/mbien/opencl/CLContext.java +++ b/src/com/mbien/opencl/CLContext.java @@ -1,14 +1,18 @@ package com.mbien.opencl; import com.mbien.opencl.impl.CLImpl; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; /** * * @author Michael Bien */ -public class CLContext { +public final class CLContext { private final static CL cl; + public final long contextID; static{ System.loadLibrary("gluegen-rt"); @@ -16,6 +20,84 @@ public class CLContext { cl = new CLImpl(); } + private CLContext(long contextID) { + this.contextID = contextID; + } + + /** + * Creates a default context on all available devices. + */ + public static CLContext create() { + IntBuffer ib = IntBuffer.allocate(1); + long context = cl.clCreateContextFromType(null, 0, CL.CL_DEVICE_TYPE_ALL, null, null, null, 0); + +// int errorCode = ib.get(); +// if(errorCode != CL.CL_SUCCESS) +// throw new CLException(errorCode, "can not create CL context"); + + return new CLContext(context); + } + + /** + * Creates a default context on the specified device types. + */ + public static CLContext create(CLDevice.Type... deviceTypes) { + + int type = deviceTypes[0].CL_TYPE; + for (int i = 1; i < deviceTypes.length; i++) { + type |= deviceTypes[i].CL_TYPE; + } + + long context = cl.clCreateContextFromType(null, 0, type, null, null, null, 0); + return new CLContext(context); + } + + /** + * Releases the context and all resources. + */ + public void release() { + int ret = cl.clReleaseContext(contextID); + if(CL.CL_SUCCESS != ret) + throw new CLException(ret, "error releasing context"); + } + + /** + * Gets the device with maximal FLOPS from this context. + */ + public CLDevice getMaxFlopsDevice() { + + //TODO not finished + + long[] longBuffer = new long[1]; +// ByteBuffer bb = ByteBuffer.allocate(8); +// bb.order(ByteOrder.nativeOrder()); + + int ret = cl.clGetContextInfo(contextID, CL.CL_CONTEXT_DEVICES, 0, null, longBuffer, 0); + if(CL.CL_SUCCESS != ret) + throw new CLException(ret, "can not receive context info"); + + System.out.println("#devices: "+longBuffer[0]); + + long[] deviceIDs = new long[(int)longBuffer[0]]; + ret = cl.clGetContextInfo(contextID, CL.CL_CONTEXT_DEVICES, 0, null, deviceIDs, 0); + + if(CL.CL_SUCCESS != ret) + throw new CLException(ret, "can not receive context info"); + + for (int i = 0; i < deviceIDs.length; i++) { + long l = deviceIDs[i]; + System.out.println("device id"+l); + } + + // get the list of GPU devices associated with context +// ciErrNum = clGetContextInfo(cxGPUContext, CL_CONTEXT_DEVICES, 0, NULL, &dataBytes); +// cl_device_id *cdDevices = (cl_device_id *)malloc(dataBytes); +// ciErrNum |= clGetContextInfo(cxGPUContext, CL_CONTEXT_DEVICES, dataBytes, cdDevices, NULL); +// shrCheckError(ciErrNum, CL_SUCCESS); + + return null; + } + /** * Lists all available OpenCL implementaitons. * @throws CLException if something went wrong initializing OpenCL diff --git a/src/com/mbien/opencl/CLDevice.java b/src/com/mbien/opencl/CLDevice.java index 58d35fa9..3db2511f 100644 --- a/src/com/mbien/opencl/CLDevice.java +++ b/src/com/mbien/opencl/CLDevice.java @@ -1,15 +1,71 @@ package com.mbien.opencl; import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Collections; +import java.util.HashSet; +import java.util.Scanner; +import java.util.Set; /** - * + * * @author Michael Bien */ -public class CLDevice { +public final class CLDevice { + + //FIXME gluegen does not generate CL_DEVICE_TYPE_* remove hardcoded values ASAP + + /** + * Enumeration for the type of a device. + */ + public enum Type { + /** + * CL_DEVICE_TYPE_CPU + */ + CPU(1 << 1), + /** + * CL_DEVICE_TYPE_GPU + */ + GPU(1 << 2), + /** + * CL_DEVICE_TYPE_ACCELERATOR + */ + ACCELERATOR(1 << 3), + /** + * CL_DEVICE_TYPE_DEFAULT + */ + DEFAULT(1 << 0); + + /** + * Value of wrapped OpenCL device type. + */ + public final int CL_TYPE; + + private Type(int CL_TYPE) { + this.CL_TYPE = CL_TYPE; + } + + public static Type valueOf(int clDeviceType) { + switch(clDeviceType) { + case(1 << 0): + return DEFAULT; + case(1 << 1): + return CPU; + case(1 << 2): + return GPU; + case(1 << 3): + return ACCELERATOR; + } + return null; + } + } private final CL cl; - private final long deviceID; + + /** + * OpenCL device id for this device. + */ + public final long deviceID; CLDevice(CL cl, long id) { this.cl = cl; @@ -23,7 +79,96 @@ public class CLDevice { return getInfoString(CL.CL_DEVICE_NAME); } - public String getInfoString(int key) { + /** + * Returns the OpenCL profile of this device. + */ + public String getProfile() { + return getInfoString(CL.CL_DEVICE_PROFILE); + } + + /** + * Returns the vendor of this device. + */ + public String getVendor() { + return getInfoString(CL.CL_DEVICE_VENDOR); + } + + /** + * Returns the type of this device. + */ + public Type getType() { + return Type.valueOf((int)getInfoLong(CL.CL_DEVICE_TYPE)); + } + + /** + * Returns the maximal number of compute units. + */ + public int getMaxComputeUnits() { + return (int) getInfoLong(CL.CL_DEVICE_MAX_COMPUTE_UNITS); + } + + /** + * Returns the maximal work group size. + */ + public int getMaxWorkGroupSize() { + return (int) getInfoLong(CL.CL_DEVICE_MAX_WORK_GROUP_SIZE); + } + + /** + * Returns the max clock frequency in Hz. + */ + public int getMaxClockFrequency() { + return (int) (getInfoLong(CL.CL_DEVICE_MAX_CLOCK_FREQUENCY)); + } + + /** + * Returns the global memory size in Bytes. + */ + public long getGlobalMemSize() { + return getInfoLong(CL.CL_DEVICE_GLOBAL_MEM_SIZE); + } + + /** + * Returns the local memory size in Bytes. + */ + public long getLocalMemSize() { + return getInfoLong(CL.CL_DEVICE_LOCAL_MEM_SIZE); + } + + /** + * Returns all device extension names as unmodifiable Set. + */ + public Set<String> getExtensions() { + + String ext = getInfoString(CL.CL_DEVICE_EXTENSIONS); + + Scanner scanner = new Scanner(ext); + Set<String> extSet = new HashSet<String>(); + + while(scanner.hasNext()) + extSet.add(scanner.next()); + + return Collections.unmodifiableSet(extSet); + } + + //TODO CL_DEVICE_IMAGE_SUPPORT + //TODO CL_DEVICE_MAX_WORK_ITEM_SIZES + + + private final long getInfoLong(int key) { + + ByteBuffer bb = ByteBuffer.allocate(8); + bb.order(ByteOrder.nativeOrder()); + + int ret = cl.clGetDeviceInfo(deviceID, key, bb.capacity(), bb, null, 0); + + if(CL.CL_SUCCESS != ret) + throw new CLException(ret, "can not receive device info"); + + return bb.getLong(); + } + + public final String getInfoString(int key) { long[] longBuffer = new long[1]; ByteBuffer bb = ByteBuffer.allocate(512); @@ -31,12 +176,32 @@ public class CLDevice { int ret = cl.clGetDeviceInfo(deviceID, key, bb.capacity(), bb, longBuffer, 0); if(CL.CL_SUCCESS != ret) - throw new CLException(ret, "can not receive info string"); + throw new CLException(ret, "can not receive device info string"); return new String(bb.array(), 0, (int)longBuffer[0]); } -// ret = cl.clGetDeviceInfo(device, CL.CL_DEVICE_TYPE, bb.capacity(), bb, longBuffer, 0); -// assertEquals(CL.CL_SUCCESS, ret); + + @Override + public String toString() { + return "CLPlatform [name:" + getName() + + " type:" + getType() + + " profile: " + getProfile()+"]"; + } + + @Override + public boolean equals(Object obj) { + if(obj != null && obj instanceof CLDevice) + return ((CLDevice)obj).deviceID == deviceID; + return false; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 79 * hash + (int) (this.deviceID ^ (this.deviceID >>> 32)); + return hash; + } + } diff --git a/src/com/mbien/opencl/CLPlatform.java b/src/com/mbien/opencl/CLPlatform.java index 582e8abc..252872dc 100644 --- a/src/com/mbien/opencl/CLPlatform.java +++ b/src/com/mbien/opencl/CLPlatform.java @@ -6,9 +6,13 @@ import java.nio.ByteBuffer; * * @author Michael Bien */ -public class CLPlatform { +public final class CLPlatform { + + /** + * OpenCL platform id for this platform. + */ + public final long platformID; - private final long platformID; private final CL cl; CLPlatform(CL cl, long id) { @@ -16,6 +20,9 @@ public class CLPlatform { this.cl = cl; } + /** + * Lists all physical devices available on this platform. + */ public CLDevice[] listCLDevices() { int[] intBuffer = new int[1]; diff --git a/test/com/mbien/opencl/JOCLTest.java b/test/com/mbien/opencl/JOCLTest.java index 3fdd4536..89292320 100644 --- a/test/com/mbien/opencl/JOCLTest.java +++ b/test/com/mbien/opencl/JOCLTest.java @@ -1,9 +1,8 @@ package com.mbien.opencl; import com.mbien.opencl.impl.CLImpl; -import java.nio.Buffer; import java.nio.ByteBuffer; -import java.nio.CharBuffer; +import java.nio.ByteOrder; import java.util.Arrays; import org.junit.After; import org.junit.Before; @@ -27,27 +26,41 @@ public class JOCLTest { public void tearDownClass() throws Exception { } - @Test +// @Test public void highLevelTest() { System.out.println(" - - - highLevelTest - - - "); CLPlatform[] clPlatforms = CLContext.listCLPlatforms(); for (CLPlatform platform : clPlatforms) { - + System.out.println("platform info:"); - System.out.println(platform.getName()); - System.out.println(platform.getProfile()); - System.out.println(platform.getVersion()); - System.out.println(platform.getVendor()); + System.out.println("name: "+platform.getName()); + System.out.println("profile: "+platform.getProfile()); + System.out.println("version: "+platform.getVersion()); + System.out.println("vendor: "+platform.getVendor()); CLDevice[] clDevices = platform.listCLDevices(); for (CLDevice device : clDevices) { System.out.println("device info:"); - System.out.println(device.getName()); + System.out.println("name: "+device.getName()); + System.out.println("profile: "+device.getProfile()); + System.out.println("vendor: "+device.getVendor()); + System.out.println("type: "+device.getType()); + System.out.println("global mem: "+device.getGlobalMemSize()/(1024*1024)+" MB"); + System.out.println("local mem: "+device.getLocalMemSize()/1024+" KB"); + System.out.println("clock: "+device.getMaxClockFrequency()+" MHz"); + System.out.println("max work group size: "+device.getMaxWorkGroupSize()); + System.out.println("max compute units: "+device.getMaxComputeUnits()); + System.out.println("extensions: "+device.getExtensions()); } } + + CLContext ctx = CLContext.create(); + CLDevice device = ctx.getMaxFlopsDevice(); + System.out.println("max FLOPS device: " + device); + ctx.release(); } @Test @@ -55,10 +68,10 @@ public class JOCLTest { System.out.println(" - - - lowLevelTest - - - "); // already loaded -// System.out.print("loading native libs..."); -// System.loadLibrary("gluegen-rt"); -// System.loadLibrary("jocl"); -// System.out.println("done"); + System.out.print("loading native libs..."); + System.loadLibrary("gluegen-rt"); + System.loadLibrary("jocl"); + System.out.println("done"); CreateContextCallback cb = new CreateContextCallback() { @Override @@ -86,6 +99,7 @@ public class JOCLTest { // print platform info long[] longBuffer = new long[1]; ByteBuffer bb = ByteBuffer.allocate(128); + bb.order(ByteOrder.nativeOrder()); for (int i = 0; i < platformId.length; i++) { @@ -123,9 +137,10 @@ public class JOCLTest { assertEquals(CL.CL_SUCCESS, ret); System.out.println(" device: "+new String(bb.array(), 0, (int)longBuffer[0])); -// ret = cl.clGetDeviceInfo(device, CL.CL_DEVICE_TYPE, bb.capacity(), bb, longBuffer, 0); -// assertEquals(CL.CL_SUCCESS, ret); - + ret = cl.clGetDeviceInfo(device, CL.CL_DEVICE_TYPE, bb.capacity(), bb, longBuffer, 0); + assertEquals(CL.CL_SUCCESS, ret); + System.out.println(" type: " + CLDevice.Type.valueOf(bb.get())); + bb.rewind(); } @@ -133,16 +148,15 @@ public class JOCLTest { Arrays.fill(longBuffer, 0); - long context = cl.clCreateContextFromType(null, CL.CL_DEVICE_TYPE_ALL, cb, null, null); + long context = cl.clCreateContextFromType(null, 0, CL.CL_DEVICE_TYPE_ALL, cb, null, null, 0); System.out.println("context handle: "+context); ret = cl.clGetContextInfo(context, CL.CL_CONTEXT_DEVICES, 0, null, longBuffer, 0); assertEquals(CL.CL_SUCCESS, ret); System.out.println("CL_CONTEXT_DEVICES result: "+longBuffer[0]); -// System.out.println("CL_CONTEXT_DEVICES result: "+buffer[1]); - + cl.clReleaseContext(context); } |