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; import static com.mbien.opencl.CLException.*; /** * * @author Michael Bien */ public final class CLDevice { /** * Enumeration for the type of a device. */ public enum Type { /** * CL_DEVICE_TYPE_CPU */ CPU(CL.CL_DEVICE_TYPE_CPU), /** * CL_DEVICE_TYPE_GPU */ GPU(CL.CL_DEVICE_TYPE_GPU), /** * CL_DEVICE_TYPE_ACCELERATOR */ ACCELERATOR(CL.CL_DEVICE_TYPE_ACCELERATOR), /** * CL_DEVICE_TYPE_DEFAULT */ DEFAULT(CL.CL_DEVICE_TYPE_DEFAULT); /** * 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(CL.CL_DEVICE_TYPE_DEFAULT): return DEFAULT; case(CL.CL_DEVICE_TYPE_CPU): return CPU; case(CL.CL_DEVICE_TYPE_GPU): return GPU; case(CL.CL_DEVICE_TYPE_ACCELERATOR): return ACCELERATOR; } return null; } } private final CL cl; private CLContext context; /** * OpenCL device id for this device. */ public final long ID; CLDevice(CL cl, long id) { this.cl = cl; this.ID = id; } CLDevice(CLContext context, long id) { this.context = context; this.cl = context.cl; this.ID = id; } public CLCommandQueue createCommandQueue() { return createCommandQueue(0); } public CLCommandQueue createCommandQueue(long properties) { if(context == null) throw new IllegalStateException("this device is not associated with a context"); return context.createCommandQueue(this, properties); } /*keep this package private for now, may be null*/ CLContext getContext() { return context; } /** * Returns the name of this device. */ public String getName() { return getInfoString(CL.CL_DEVICE_NAME); } /** * 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 getExtensions() { String ext = getInfoString(CL.CL_DEVICE_EXTENSIONS); Scanner scanner = new Scanner(ext); Set extSet = new HashSet(); 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(ID, key, bb.capacity(), bb, null, 0); checkForError(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); int ret = cl.clGetDeviceInfo(ID, key, bb.capacity(), bb, longBuffer, 0); checkForError(ret, "can not receive device info string"); return new String(bb.array(), 0, (int)longBuffer[0]); } @Override public String toString() { return "CLDevice [id: " + ID + " name: " + getName() + " type: " + getType() + " profile: " + getProfile()+"]"; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final CLDevice other = (CLDevice) obj; if (this.ID != other.ID) { return false; } return true; } @Override public int hashCode() { int hash = 3; hash = 79 * hash + (int) (this.ID ^ (this.ID >>> 32)); return hash; } }