| 1 | package net.bmahe.genetics4j.gpu.opencl; | |
| 2 | ||
| 3 | import java.util.Arrays; | |
| 4 | import java.util.List; | |
| 5 | import java.util.Objects; | |
| 6 | ||
| 7 | import org.apache.commons.lang3.Validate; | |
| 8 | import org.jocl.CL; | |
| 9 | import org.jocl.Pointer; | |
| 10 | import org.jocl.Sizeof; | |
| 11 | import org.jocl.cl_device_id; | |
| 12 | import org.jocl.cl_platform_id; | |
| 13 | ||
| 14 | /** | |
| 15 | * Utility class providing convenient methods for OpenCL device discovery and information queries. | |
| 16 | * | |
| 17 | * <p>DeviceUtils encapsulates the low-level OpenCL API calls required for device enumeration and property retrieval, | |
| 18 | * providing a higher-level interface for GPU-accelerated evolutionary algorithm implementations. This class handles the | |
| 19 | * OpenCL buffer management and type conversions necessary for interacting with the native OpenCL runtime. | |
| 20 | * | |
| 21 | * <p>Key functionality includes: | |
| 22 | * <ul> | |
| 23 | * <li><strong>Device enumeration</strong>: Discover available devices on OpenCL platforms</li> | |
| 24 | * <li><strong>Property queries</strong>: Retrieve device characteristics and capabilities</li> | |
| 25 | * <li><strong>Type conversions</strong>: Convert between OpenCL native types and Java types</li> | |
| 26 | * <li><strong>Buffer management</strong>: Handle memory allocation for OpenCL information queries</li> | |
| 27 | * </ul> | |
| 28 | * | |
| 29 | * <p>Common usage patterns: | |
| 30 | * | |
| 31 | * <pre>{@code | |
| 32 | * // Enumerate devices on a platform | |
| 33 | * int deviceCount = DeviceUtils.numDevices(platformId); | |
| 34 | * List<cl_device_id> deviceIds = DeviceUtils.getDeviceIds(platformId, deviceCount); | |
| 35 | * | |
| 36 | * // Query device properties | |
| 37 | * String deviceName = DeviceUtils.getDeviceInfoString(deviceId, CL.CL_DEVICE_NAME); | |
| 38 | * int computeUnits = DeviceUtils.getDeviceInfoInt(deviceId, CL.CL_DEVICE_MAX_COMPUTE_UNITS); | |
| 39 | * long maxWorkGroupSize = DeviceUtils.getDeviceInfoLong(deviceId, CL.CL_DEVICE_MAX_WORK_GROUP_SIZE); | |
| 40 | * | |
| 41 | * // Query array properties | |
| 42 | * int maxDimensions = DeviceUtils.getDeviceInfoInt(deviceId, CL.CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS); | |
| 43 | * long[] maxWorkItemSizes = DeviceUtils | |
| 44 | * .getDeviceInfoLongArray(deviceId, CL.CL_DEVICE_MAX_WORK_ITEM_SIZES, maxDimensions); | |
| 45 | * }</pre> | |
| 46 | * | |
| 47 | * <p>Device type filtering: | |
| 48 | * <ul> | |
| 49 | * <li><strong>CL_DEVICE_TYPE_ALL</strong>: All available devices</li> | |
| 50 | * <li><strong>CL_DEVICE_TYPE_GPU</strong>: GPU devices only</li> | |
| 51 | * <li><strong>CL_DEVICE_TYPE_CPU</strong>: CPU devices only</li> | |
| 52 | * <li><strong>CL_DEVICE_TYPE_ACCELERATOR</strong>: Accelerator devices only</li> | |
| 53 | * </ul> | |
| 54 | * | |
| 55 | * <p>Error handling: | |
| 56 | * <ul> | |
| 57 | * <li><strong>Parameter validation</strong>: Validates all input parameters</li> | |
| 58 | * <li><strong>OpenCL error propagation</strong>: OpenCL errors are propagated as runtime exceptions</li> | |
| 59 | * <li><strong>Memory management</strong>: Automatically handles buffer allocation and cleanup</li> | |
| 60 | * </ul> | |
| 61 | * | |
| 62 | * @see Device | |
| 63 | * @see DeviceReader | |
| 64 | * @see net.bmahe.genetics4j.gpu.opencl.model.DeviceType | |
| 65 | */ | |
| 66 | public class DeviceUtils { | |
| 67 | ||
| 68 | private DeviceUtils() { | |
| 69 | ||
| 70 | } | |
| 71 | ||
| 72 | /** | |
| 73 | * Returns the number of OpenCL devices of the specified type available on the platform. | |
| 74 | * | |
| 75 | * @param platformId the OpenCL platform to query | |
| 76 | * @param deviceType the type of devices to count (e.g., CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_ALL) | |
| 77 | * @return the number of available devices of the specified type | |
| 78 | * @throws IllegalArgumentException if platformId is null | |
| 79 | */ | |
| 80 | public static int numDevices(final cl_platform_id platformId, final long deviceType) { | |
| 81 | Objects.requireNonNull(platformId); | |
| 82 | ||
| 83 |
1
1. numDevices : Substituted 1 with 0 → NO_COVERAGE |
final int[] numDevices = new int[1]; |
| 84 |
3
1. numDevices : Substituted 0 with 1 → NO_COVERAGE 2. numDevices : removed call to org/jocl/CL::clGetDeviceIDs → NO_COVERAGE 3. numDevices : replaced call to org/jocl/CL::clGetDeviceIDs with argument → NO_COVERAGE |
CL.clGetDeviceIDs(platformId, deviceType, 0, null, numDevices); |
| 85 | ||
| 86 |
2
1. numDevices : Substituted 0 with 1 → NO_COVERAGE 2. numDevices : replaced int return with 0 for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::numDevices → NO_COVERAGE |
return numDevices[0]; |
| 87 | } | |
| 88 | ||
| 89 | /** | |
| 90 | * Returns the total number of OpenCL devices available on the platform. | |
| 91 | * | |
| 92 | * <p>This is equivalent to calling {@link #numDevices(cl_platform_id, long)} with {@code CL_DEVICE_TYPE_ALL} as the | |
| 93 | * device type. | |
| 94 | * | |
| 95 | * @param platformId the OpenCL platform to query | |
| 96 | * @return the total number of available devices on the platform | |
| 97 | * @throws IllegalArgumentException if platformId is null | |
| 98 | */ | |
| 99 | public static int numDevices(final cl_platform_id platformId) { | |
| 100 |
3
1. numDevices : removed call to net/bmahe/genetics4j/gpu/opencl/DeviceUtils::numDevices → NO_COVERAGE 2. numDevices : Substituted -1 with 0 → NO_COVERAGE 3. numDevices : replaced int return with 0 for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::numDevices → NO_COVERAGE |
return numDevices(platformId, CL.CL_DEVICE_TYPE_ALL); |
| 101 | } | |
| 102 | ||
| 103 | /** | |
| 104 | * Returns a list of OpenCL device identifiers of the specified type from the platform. | |
| 105 | * | |
| 106 | * @param platformId the OpenCL platform to query | |
| 107 | * @param numDevices the number of devices to retrieve | |
| 108 | * @param deviceType the type of devices to retrieve (e.g., CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_ALL) | |
| 109 | * @return list of OpenCL device identifiers | |
| 110 | * @throws IllegalArgumentException if platformId is null or numDevices is not positive | |
| 111 | */ | |
| 112 | public static List<cl_device_id> getDeviceIds(final cl_platform_id platformId, final int numDevices, | |
| 113 | final long deviceType) { | |
| 114 | Objects.requireNonNull(platformId); | |
| 115 | Validate.isTrue(numDevices > 0); | |
| 116 | ||
| 117 | cl_device_id[] deviceIds = new cl_device_id[numDevices]; | |
| 118 |
2
1. getDeviceIds : replaced call to org/jocl/CL::clGetDeviceIDs with argument → NO_COVERAGE 2. getDeviceIds : removed call to org/jocl/CL::clGetDeviceIDs → NO_COVERAGE |
CL.clGetDeviceIDs(platformId, deviceType, numDevices, deviceIds, null); |
| 119 | ||
| 120 |
2
1. getDeviceIds : removed call to java/util/Arrays::asList → NO_COVERAGE 2. getDeviceIds : replaced return value with Collections.emptyList for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceIds → NO_COVERAGE |
return Arrays.asList(deviceIds); |
| 121 | } | |
| 122 | ||
| 123 | /** | |
| 124 | * Returns a list of all OpenCL device identifiers from the platform. | |
| 125 | * | |
| 126 | * <p>This is equivalent to calling {@link #getDeviceIds(cl_platform_id, int, long)} with {@code CL_DEVICE_TYPE_ALL} | |
| 127 | * as the device type. | |
| 128 | * | |
| 129 | * @param platformId the OpenCL platform to query | |
| 130 | * @param numDevices the number of devices to retrieve | |
| 131 | * @return list of all OpenCL device identifiers | |
| 132 | * @throws IllegalArgumentException if platformId is null or numDevices is not positive | |
| 133 | */ | |
| 134 | public static List<cl_device_id> getDeviceIds(final cl_platform_id platformId, final int numDevices) { | |
| 135 |
3
1. getDeviceIds : removed call to net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceIds → NO_COVERAGE 2. getDeviceIds : Substituted -1 with 0 → NO_COVERAGE 3. getDeviceIds : replaced return value with Collections.emptyList for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceIds → NO_COVERAGE |
return getDeviceIds(platformId, numDevices, CL.CL_DEVICE_TYPE_ALL); |
| 136 | } | |
| 137 | ||
| 138 | /** | |
| 139 | * Queries and returns a string property of the specified OpenCL device. | |
| 140 | * | |
| 141 | * <p>This method handles the OpenCL API calls and buffer management required to retrieve string properties from | |
| 142 | * devices, such as device name, vendor, or version information. | |
| 143 | * | |
| 144 | * @param deviceId the OpenCL device to query | |
| 145 | * @param parameter the OpenCL parameter constant (e.g., CL_DEVICE_NAME, CL_DEVICE_VENDOR) | |
| 146 | * @return the string value of the requested device property | |
| 147 | * @throws IllegalArgumentException if deviceId is null | |
| 148 | */ | |
| 149 | public static String getDeviceInfoString(final cl_device_id deviceId, final int parameter) { | |
| 150 | Objects.requireNonNull(deviceId); | |
| 151 | ||
| 152 |
1
1. getDeviceInfoString : Substituted 1 with 0 → NO_COVERAGE |
final long[] size = new long[1]; |
| 153 |
3
1. getDeviceInfoString : Substituted 0 with 1 → NO_COVERAGE 2. getDeviceInfoString : replaced call to org/jocl/CL::clGetDeviceInfo with argument → NO_COVERAGE 3. getDeviceInfoString : removed call to org/jocl/CL::clGetDeviceInfo → NO_COVERAGE |
CL.clGetDeviceInfo(deviceId, parameter, 0, null, size); |
| 154 | ||
| 155 |
1
1. getDeviceInfoString : Substituted 0 with 1 → NO_COVERAGE |
final byte[] buffer = new byte[(int) size[0]]; |
| 156 |
3
1. getDeviceInfoString : replaced call to org/jocl/CL::clGetDeviceInfo with argument → NO_COVERAGE 2. getDeviceInfoString : removed call to org/jocl/CL::clGetDeviceInfo → NO_COVERAGE 3. getDeviceInfoString : removed call to org/jocl/Pointer::to → NO_COVERAGE |
CL.clGetDeviceInfo(deviceId, parameter, buffer.length, Pointer.to(buffer), null); |
| 157 | ||
| 158 |
5
1. getDeviceInfoString : removed call to java/lang/String::<init> → NO_COVERAGE 2. getDeviceInfoString : Substituted 1 with 0 → NO_COVERAGE 3. getDeviceInfoString : replaced return value with "" for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoString → NO_COVERAGE 4. getDeviceInfoString : Substituted 0 with 1 → NO_COVERAGE 5. getDeviceInfoString : Replaced integer subtraction with addition → NO_COVERAGE |
return new String(buffer, 0, buffer.length - 1); |
| 159 | } | |
| 160 | ||
| 161 | /** | |
| 162 | * Queries and returns a long array property of the specified OpenCL device. | |
| 163 | * | |
| 164 | * <p>This method is useful for retrieving array properties such as maximum work-item sizes per dimension, which | |
| 165 | * require multiple values to fully describe the device capability. | |
| 166 | * | |
| 167 | * @param deviceId the OpenCL device to query | |
| 168 | * @param parameter the OpenCL parameter constant (e.g., CL_DEVICE_MAX_WORK_ITEM_SIZES) | |
| 169 | * @param size the number of long values to retrieve | |
| 170 | * @return array of long values for the requested device property | |
| 171 | * @throws IllegalArgumentException if deviceId is null or size is not positive | |
| 172 | */ | |
| 173 | public static long[] getDeviceInfoLongArray(final cl_device_id deviceId, final int parameter, final int size) { | |
| 174 | Objects.requireNonNull(deviceId); | |
| 175 | Validate.isTrue(size > 0); | |
| 176 | ||
| 177 | final long[] values = new long[size]; | |
| 178 |
5
1. getDeviceInfoLongArray : removed call to org/jocl/Pointer::to → NO_COVERAGE 2. getDeviceInfoLongArray : removed call to org/jocl/CL::clGetDeviceInfo → NO_COVERAGE 3. getDeviceInfoLongArray : Replaced integer multiplication with division → NO_COVERAGE 4. getDeviceInfoLongArray : replaced call to org/jocl/CL::clGetDeviceInfo with argument → NO_COVERAGE 5. getDeviceInfoLongArray : Substituted 8 with 9 → NO_COVERAGE |
CL.clGetDeviceInfo(deviceId, parameter, Sizeof.cl_long * size, Pointer.to(values), null); |
| 179 | ||
| 180 |
1
1. getDeviceInfoLongArray : replaced return value with null for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoLongArray → NO_COVERAGE |
return values; |
| 181 | } | |
| 182 | ||
| 183 | /** | |
| 184 | * Queries and returns a single long property of the specified OpenCL device. | |
| 185 | * | |
| 186 | * <p>This method is useful for retrieving single long value properties such as maximum work group size, global | |
| 187 | * memory size, or local memory size. | |
| 188 | * | |
| 189 | * @param deviceId the OpenCL device to query | |
| 190 | * @param parameter the OpenCL parameter constant (e.g., CL_DEVICE_MAX_WORK_GROUP_SIZE) | |
| 191 | * @return the long value of the requested device property | |
| 192 | * @throws IllegalArgumentException if deviceId is null | |
| 193 | */ | |
| 194 | public static long getDeviceInfoLong(final cl_device_id deviceId, final int parameter) { | |
| 195 | Objects.requireNonNull(deviceId); | |
| 196 | ||
| 197 |
2
1. getDeviceInfoLong : removed call to net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoLongArray → NO_COVERAGE 2. getDeviceInfoLong : Substituted 1 with 0 → NO_COVERAGE |
final long[] values = getDeviceInfoLongArray(deviceId, parameter, 1); |
| 198 | ||
| 199 |
2
1. getDeviceInfoLong : Substituted 0 with 1 → NO_COVERAGE 2. getDeviceInfoLong : replaced long return with 0 for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoLong → NO_COVERAGE |
return values[0]; |
| 200 | } | |
| 201 | ||
| 202 | /** | |
| 203 | * Queries and returns a single integer property of the specified OpenCL device. | |
| 204 | * | |
| 205 | * <p>This method is useful for retrieving integer properties such as maximum compute units, maximum clock frequency, | |
| 206 | * or maximum work-item dimensions. | |
| 207 | * | |
| 208 | * @param deviceId the OpenCL device to query | |
| 209 | * @param parameter the OpenCL parameter constant (e.g., CL_DEVICE_MAX_COMPUTE_UNITS) | |
| 210 | * @return the integer value of the requested device property | |
| 211 | * @throws IllegalArgumentException if deviceId is null | |
| 212 | */ | |
| 213 | public static int getDeviceInfoInt(final cl_device_id deviceId, final int parameter) { | |
| 214 | Objects.requireNonNull(deviceId); | |
| 215 | ||
| 216 |
1
1. getDeviceInfoInt : Substituted 1 with 0 → NO_COVERAGE |
final int[] values = new int[1]; |
| 217 |
4
1. getDeviceInfoInt : removed call to org/jocl/Pointer::to → NO_COVERAGE 2. getDeviceInfoInt : removed call to org/jocl/CL::clGetDeviceInfo → NO_COVERAGE 3. getDeviceInfoInt : replaced call to org/jocl/CL::clGetDeviceInfo with argument → NO_COVERAGE 4. getDeviceInfoInt : Substituted 4 with 5 → NO_COVERAGE |
CL.clGetDeviceInfo(deviceId, parameter, Sizeof.cl_int, Pointer.to(values), null); |
| 218 | ||
| 219 |
2
1. getDeviceInfoInt : Substituted 0 with 1 → NO_COVERAGE 2. getDeviceInfoInt : replaced int return with 0 for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoInt → NO_COVERAGE |
return values[0]; |
| 220 | } | |
| 221 | } | |
Mutations | ||
| 83 |
1.1 |
|
| 84 |
1.1 2.2 3.3 |
|
| 86 |
1.1 2.2 |
|
| 100 |
1.1 2.2 3.3 |
|
| 118 |
1.1 2.2 |
|
| 120 |
1.1 2.2 |
|
| 135 |
1.1 2.2 3.3 |
|
| 152 |
1.1 |
|
| 153 |
1.1 2.2 3.3 |
|
| 155 |
1.1 |
|
| 156 |
1.1 2.2 3.3 |
|
| 158 |
1.1 2.2 3.3 4.4 5.5 |
|
| 178 |
1.1 2.2 3.3 4.4 5.5 |
|
| 180 |
1.1 |
|
| 197 |
1.1 2.2 |
|
| 199 |
1.1 2.2 |
|
| 216 |
1.1 |
|
| 217 |
1.1 2.2 3.3 4.4 |
|
| 219 |
1.1 2.2 |