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