DeviceUtils.java

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
Location : numDevices
Killed by : none
Substituted 1 with 0 → NO_COVERAGE

84

1.1
Location : numDevices
Killed by : none
Substituted 0 with 1 → NO_COVERAGE

2.2
Location : numDevices
Killed by : none
removed call to org/jocl/CL::clGetDeviceIDs → NO_COVERAGE

3.3
Location : numDevices
Killed by : none
replaced call to org/jocl/CL::clGetDeviceIDs with argument → NO_COVERAGE

86

1.1
Location : numDevices
Killed by : none
Substituted 0 with 1 → NO_COVERAGE

2.2
Location : numDevices
Killed by : none
replaced int return with 0 for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::numDevices → NO_COVERAGE

100

1.1
Location : numDevices
Killed by : none
removed call to net/bmahe/genetics4j/gpu/opencl/DeviceUtils::numDevices → NO_COVERAGE

2.2
Location : numDevices
Killed by : none
Substituted -1 with 0 → NO_COVERAGE

3.3
Location : numDevices
Killed by : none
replaced int return with 0 for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::numDevices → NO_COVERAGE

118

1.1
Location : getDeviceIds
Killed by : none
replaced call to org/jocl/CL::clGetDeviceIDs with argument → NO_COVERAGE

2.2
Location : getDeviceIds
Killed by : none
removed call to org/jocl/CL::clGetDeviceIDs → NO_COVERAGE

120

1.1
Location : getDeviceIds
Killed by : none
removed call to java/util/Arrays::asList → NO_COVERAGE

2.2
Location : getDeviceIds
Killed by : none
replaced return value with Collections.emptyList for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceIds → NO_COVERAGE

135

1.1
Location : getDeviceIds
Killed by : none
removed call to net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceIds → NO_COVERAGE

2.2
Location : getDeviceIds
Killed by : none
Substituted -1 with 0 → NO_COVERAGE

3.3
Location : getDeviceIds
Killed by : none
replaced return value with Collections.emptyList for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceIds → NO_COVERAGE

152

1.1
Location : getDeviceInfoString
Killed by : none
Substituted 1 with 0 → NO_COVERAGE

153

1.1
Location : getDeviceInfoString
Killed by : none
Substituted 0 with 1 → NO_COVERAGE

2.2
Location : getDeviceInfoString
Killed by : none
replaced call to org/jocl/CL::clGetDeviceInfo with argument → NO_COVERAGE

3.3
Location : getDeviceInfoString
Killed by : none
removed call to org/jocl/CL::clGetDeviceInfo → NO_COVERAGE

155

1.1
Location : getDeviceInfoString
Killed by : none
Substituted 0 with 1 → NO_COVERAGE

156

1.1
Location : getDeviceInfoString
Killed by : none
replaced call to org/jocl/CL::clGetDeviceInfo with argument → NO_COVERAGE

2.2
Location : getDeviceInfoString
Killed by : none
removed call to org/jocl/CL::clGetDeviceInfo → NO_COVERAGE

3.3
Location : getDeviceInfoString
Killed by : none
removed call to org/jocl/Pointer::to → NO_COVERAGE

158

1.1
Location : getDeviceInfoString
Killed by : none
removed call to java/lang/String::<init> → NO_COVERAGE

2.2
Location : getDeviceInfoString
Killed by : none
Substituted 1 with 0 → NO_COVERAGE

3.3
Location : getDeviceInfoString
Killed by : none
replaced return value with "" for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoString → NO_COVERAGE

4.4
Location : getDeviceInfoString
Killed by : none
Substituted 0 with 1 → NO_COVERAGE

5.5
Location : getDeviceInfoString
Killed by : none
Replaced integer subtraction with addition → NO_COVERAGE

178

1.1
Location : getDeviceInfoLongArray
Killed by : none
removed call to org/jocl/Pointer::to → NO_COVERAGE

2.2
Location : getDeviceInfoLongArray
Killed by : none
removed call to org/jocl/CL::clGetDeviceInfo → NO_COVERAGE

3.3
Location : getDeviceInfoLongArray
Killed by : none
Replaced integer multiplication with division → NO_COVERAGE

4.4
Location : getDeviceInfoLongArray
Killed by : none
replaced call to org/jocl/CL::clGetDeviceInfo with argument → NO_COVERAGE

5.5
Location : getDeviceInfoLongArray
Killed by : none
Substituted 8 with 9 → NO_COVERAGE

180

1.1
Location : getDeviceInfoLongArray
Killed by : none
replaced return value with null for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoLongArray → NO_COVERAGE

197

1.1
Location : getDeviceInfoLong
Killed by : none
removed call to net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoLongArray → NO_COVERAGE

2.2
Location : getDeviceInfoLong
Killed by : none
Substituted 1 with 0 → NO_COVERAGE

199

1.1
Location : getDeviceInfoLong
Killed by : none
Substituted 0 with 1 → NO_COVERAGE

2.2
Location : getDeviceInfoLong
Killed by : none
replaced long return with 0 for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoLong → NO_COVERAGE

216

1.1
Location : getDeviceInfoInt
Killed by : none
Substituted 1 with 0 → NO_COVERAGE

217

1.1
Location : getDeviceInfoInt
Killed by : none
removed call to org/jocl/Pointer::to → NO_COVERAGE

2.2
Location : getDeviceInfoInt
Killed by : none
removed call to org/jocl/CL::clGetDeviceInfo → NO_COVERAGE

3.3
Location : getDeviceInfoInt
Killed by : none
replaced call to org/jocl/CL::clGetDeviceInfo with argument → NO_COVERAGE

4.4
Location : getDeviceInfoInt
Killed by : none
Substituted 4 with 5 → NO_COVERAGE

219

1.1
Location : getDeviceInfoInt
Killed by : none
Substituted 0 with 1 → NO_COVERAGE

2.2
Location : getDeviceInfoInt
Killed by : none
replaced int return with 0 for net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceInfoInt → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.25.7 support