1 | package net.bmahe.genetics4j.gpu; | |
2 | ||
3 | import java.io.IOException; | |
4 | import java.nio.charset.StandardCharsets; | |
5 | import java.util.ArrayList; | |
6 | import java.util.HashMap; | |
7 | import java.util.List; | |
8 | import java.util.Map; | |
9 | import java.util.Set; | |
10 | import java.util.concurrent.CompletableFuture; | |
11 | import java.util.concurrent.ExecutorService; | |
12 | ||
13 | import org.apache.commons.collections4.ListUtils; | |
14 | import org.apache.commons.io.IOUtils; | |
15 | import org.apache.commons.lang3.Validate; | |
16 | import org.apache.commons.lang3.tuple.Pair; | |
17 | import org.apache.logging.log4j.LogManager; | |
18 | import org.apache.logging.log4j.Logger; | |
19 | import org.jocl.CL; | |
20 | import org.jocl.cl_command_queue; | |
21 | import org.jocl.cl_context; | |
22 | import org.jocl.cl_context_properties; | |
23 | import org.jocl.cl_device_id; | |
24 | import org.jocl.cl_kernel; | |
25 | import org.jocl.cl_platform_id; | |
26 | import org.jocl.cl_program; | |
27 | import org.jocl.cl_queue_properties; | |
28 | ||
29 | import net.bmahe.genetics4j.core.Genotype; | |
30 | import net.bmahe.genetics4j.core.evaluation.FitnessEvaluator; | |
31 | import net.bmahe.genetics4j.gpu.opencl.DeviceReader; | |
32 | import net.bmahe.genetics4j.gpu.opencl.DeviceUtils; | |
33 | import net.bmahe.genetics4j.gpu.opencl.KernelInfoReader; | |
34 | import net.bmahe.genetics4j.gpu.opencl.OpenCLExecutionContext; | |
35 | import net.bmahe.genetics4j.gpu.opencl.PlatformReader; | |
36 | import net.bmahe.genetics4j.gpu.opencl.PlatformUtils; | |
37 | import net.bmahe.genetics4j.gpu.opencl.model.Device; | |
38 | import net.bmahe.genetics4j.gpu.opencl.model.KernelInfo; | |
39 | import net.bmahe.genetics4j.gpu.opencl.model.Platform; | |
40 | import net.bmahe.genetics4j.gpu.spec.GPUEAConfiguration; | |
41 | import net.bmahe.genetics4j.gpu.spec.GPUEAExecutionContext; | |
42 | import net.bmahe.genetics4j.gpu.spec.Program; | |
43 | ||
44 | /** | |
45 | * GPU-accelerated fitness evaluator that leverages OpenCL for high-performance evolutionary algorithm execution. | |
46 | * | |
47 | * <p>GPUFitnessEvaluator implements the core {@link FitnessEvaluator} interface to provide GPU acceleration for fitness | |
48 | * computation in evolutionary algorithms. This evaluator manages the complete OpenCL lifecycle, from device discovery | |
49 | * and kernel compilation to memory management and resource cleanup. | |
50 | * | |
51 | * <p>Key responsibilities include: | |
52 | * <ul> | |
53 | * <li><strong>OpenCL initialization</strong>: Platform and device discovery, context creation, and kernel | |
54 | * compilation</li> | |
55 | * <li><strong>Resource management</strong>: Managing OpenCL contexts, command queues, programs, and kernels</li> | |
56 | * <li><strong>Population partitioning</strong>: Distributing work across multiple OpenCL devices</li> | |
57 | * <li><strong>Asynchronous execution</strong>: Coordinating concurrent GPU operations with CPU-side logic</li> | |
58 | * <li><strong>Memory lifecycle</strong>: Ensuring proper cleanup of GPU resources</li> | |
59 | * </ul> | |
60 | * | |
61 | * <p>Architecture overview: | |
62 | * <ol> | |
63 | * <li><strong>Initialization ({@link #preEvaluation})</strong>: Discover platforms/devices, compile kernels, create | |
64 | * contexts</li> | |
65 | * <li><strong>Evaluation ({@link #evaluate})</strong>: Partition population, execute fitness computation on GPU</li> | |
66 | * <li><strong>Cleanup ({@link #postEvaluation})</strong>: Release all OpenCL resources and contexts</li> | |
67 | * </ol> | |
68 | * | |
69 | * <p>Multi-device support: | |
70 | * <ul> | |
71 | * <li><strong>Device filtering</strong>: Selects devices based on user-defined criteria (type, capabilities)</li> | |
72 | * <li><strong>Load balancing</strong>: Automatically distributes population across available devices</li> | |
73 | * <li><strong>Parallel execution</strong>: Concurrent fitness evaluation on multiple GPUs or devices</li> | |
74 | * <li><strong>Asynchronous coordination</strong>: Non-blocking execution with CompletableFuture-based results</li> | |
75 | * </ul> | |
76 | * | |
77 | * <p>Resource management patterns: | |
78 | * <ul> | |
79 | * <li><strong>Lazy initialization</strong>: OpenCL resources created only when needed</li> | |
80 | * <li><strong>Automatic cleanup</strong>: Guaranteed resource release through lifecycle methods</li> | |
81 | * <li><strong>Error recovery</strong>: Robust handling of OpenCL errors and device failures</li> | |
82 | * <li><strong>Memory optimization</strong>: Efficient GPU memory usage and transfer patterns</li> | |
83 | * </ul> | |
84 | * | |
85 | * <p>Example usage in GPU EA system: | |
86 | * | |
87 | * <pre>{@code | |
88 | * // GPU configuration with OpenCL kernel | |
89 | * Program fitnessProgram = Program.ofResource("/kernels/optimization.cl"); | |
90 | * GPUEAConfiguration<Double> config = GPUEAConfigurationBuilder.<Double>builder() | |
91 | * .program(fitnessProgram) | |
92 | * .fitness(new MyGPUFitness()) | |
93 | * // ... other EA configuration | |
94 | * .build(); | |
95 | * | |
96 | * // Execution context with device preferences | |
97 | * GPUEAExecutionContext<Double> context = GPUEAExecutionContextBuilder.<Double>builder() | |
98 | * .populationSize(2000) | |
99 | * .deviceFilter(device -> device.type() == DeviceType.GPU) | |
100 | * .platformFilter(platform -> platform.profile() == PlatformProfile.FULL_PROFILE) | |
101 | * .build(); | |
102 | * | |
103 | * // Evaluator handles all OpenCL lifecycle automatically | |
104 | * GPUFitnessEvaluator<Double> evaluator = new GPUFitnessEvaluator<>(context, config, executorService); | |
105 | * | |
106 | * // Used by EA system - lifecycle managed automatically | |
107 | * EASystem<Double> system = EASystemFactory.from(config, context, executorService, evaluator); | |
108 | * }</pre> | |
109 | * | |
110 | * <p>Performance characteristics: | |
111 | * <ul> | |
112 | * <li><strong>Initialization overhead</strong>: One-time setup cost for OpenCL compilation and context creation</li> | |
113 | * <li><strong>Scalability</strong>: Performance scales with population size and problem complexity</li> | |
114 | * <li><strong>Memory bandwidth</strong>: Optimal for problems with high computational intensity</li> | |
115 | * <li><strong>Concurrency</strong>: Supports concurrent evaluation across multiple devices</li> | |
116 | * </ul> | |
117 | * | |
118 | * <p>Error handling: | |
119 | * <ul> | |
120 | * <li><strong>Device failures</strong>: Graceful degradation when devices become unavailable</li> | |
121 | * <li><strong>Memory errors</strong>: Proper cleanup and error reporting for GPU memory issues</li> | |
122 | * <li><strong>Compilation errors</strong>: Clear error messages for kernel compilation failures</li> | |
123 | * <li><strong>Resource leaks</strong>: Guaranteed cleanup even in exceptional circumstances</li> | |
124 | * </ul> | |
125 | * | |
126 | * @param <T> the type of fitness values produced, must be comparable for selection operations | |
127 | * @see FitnessEvaluator | |
128 | * @see GPUEAConfiguration | |
129 | * @see GPUEAExecutionContext | |
130 | * @see OpenCLExecutionContext | |
131 | * @see net.bmahe.genetics4j.gpu.fitness.OpenCLFitness | |
132 | */ | |
133 | public class GPUFitnessEvaluator<T extends Comparable<T>> implements FitnessEvaluator<T> { | |
134 | public static final Logger logger = LogManager.getLogger(GPUFitnessEvaluator.class); | |
135 | ||
136 | private final GPUEAExecutionContext<T> gpuEAExecutionContext; | |
137 | private final GPUEAConfiguration<T> gpuEAConfiguration; | |
138 | private final ExecutorService executorService; | |
139 | ||
140 | private List<Pair<Platform, Device>> selectedPlatformToDevice; | |
141 | ||
142 |
2
1. <init> : Removed assignment to member variable clContexts → NO_COVERAGE 2. <init> : removed call to java/util/ArrayList::<init> → NO_COVERAGE |
final List<cl_context> clContexts = new ArrayList<>(); |
143 |
2
1. <init> : removed call to java/util/ArrayList::<init> → NO_COVERAGE 2. <init> : Removed assignment to member variable clCommandQueues → NO_COVERAGE |
final List<cl_command_queue> clCommandQueues = new ArrayList<>(); |
144 |
2
1. <init> : Removed assignment to member variable clPrograms → NO_COVERAGE 2. <init> : removed call to java/util/ArrayList::<init> → NO_COVERAGE |
final List<cl_program> clPrograms = new ArrayList<>(); |
145 |
2
1. <init> : Removed assignment to member variable clKernels → NO_COVERAGE 2. <init> : removed call to java/util/ArrayList::<init> → NO_COVERAGE |
final List<Map<String, cl_kernel>> clKernels = new ArrayList<>(); |
146 |
2
1. <init> : Removed assignment to member variable clExecutionContexts → NO_COVERAGE 2. <init> : removed call to java/util/ArrayList::<init> → NO_COVERAGE |
final List<OpenCLExecutionContext> clExecutionContexts = new ArrayList<>(); |
147 | ||
148 | /** | |
149 | * Constructs a GPU fitness evaluator with the specified configuration and execution context. | |
150 | * | |
151 | * <p>Initializes the evaluator with GPU-specific configuration and execution parameters. The evaluator will use the | |
152 | * provided executor service for coordinating asynchronous operations between CPU and GPU components. | |
153 | * | |
154 | * <p>The constructor performs minimal initialization - the actual OpenCL setup occurs during | |
155 | * {@link #preEvaluation()} to follow the fitness evaluator lifecycle pattern. | |
156 | * | |
157 | * @param _gpuEAExecutionContext the GPU execution context with device filters and population settings | |
158 | * @param _gpuEAConfiguration the GPU EA configuration with OpenCL program and fitness function | |
159 | * @param _executorService the executor service for managing asynchronous operations | |
160 | * @throws IllegalArgumentException if any parameter is null | |
161 | */ | |
162 | public GPUFitnessEvaluator(final GPUEAExecutionContext<T> _gpuEAExecutionContext, | |
163 | final GPUEAConfiguration<T> _gpuEAConfiguration, final ExecutorService _executorService) { | |
164 | Validate.notNull(_gpuEAExecutionContext); | |
165 | Validate.notNull(_gpuEAConfiguration); | |
166 | Validate.notNull(_executorService); | |
167 | ||
168 |
1
1. <init> : Removed assignment to member variable gpuEAExecutionContext → NO_COVERAGE |
this.gpuEAExecutionContext = _gpuEAExecutionContext; |
169 |
1
1. <init> : Removed assignment to member variable gpuEAConfiguration → NO_COVERAGE |
this.gpuEAConfiguration = _gpuEAConfiguration; |
170 |
1
1. <init> : Removed assignment to member variable executorService → NO_COVERAGE |
this.executorService = _executorService; |
171 | ||
172 |
2
1. <init> : removed call to org/jocl/CL::setExceptionsEnabled → NO_COVERAGE 2. <init> : Substituted 1 with 0 → NO_COVERAGE |
CL.setExceptionsEnabled(true); |
173 | } | |
174 | ||
175 | private String loadResource(final String filename) { | |
176 | Validate.notBlank(filename); | |
177 | ||
178 | try { | |
179 |
3
1. loadResource : replaced call to org/apache/commons/io/IOUtils::resourceToString with argument → NO_COVERAGE 2. loadResource : replaced return value with "" for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::loadResource → NO_COVERAGE 3. loadResource : removed call to org/apache/commons/io/IOUtils::resourceToString → NO_COVERAGE |
return IOUtils.resourceToString(filename, StandardCharsets.UTF_8); |
180 | } catch (IOException e) { | |
181 |
1
1. loadResource : removed call to java/lang/IllegalStateException::<init> → NO_COVERAGE |
throw new IllegalStateException("Unable to load resource " + filename, e); |
182 | } | |
183 | } | |
184 | ||
185 | private List<String> grabProgramSources() { | |
186 |
1
1. grabProgramSources : removed call to net/bmahe/genetics4j/gpu/spec/GPUEAConfiguration::program → NO_COVERAGE |
final Program programSpec = gpuEAConfiguration.program(); |
187 | ||
188 | logger.info("Load program source: {}", programSpec); | |
189 | ||
190 |
1
1. grabProgramSources : removed call to java/util/ArrayList::<init> → NO_COVERAGE |
final List<String> sources = new ArrayList<>(); |
191 | ||
192 |
2
1. grabProgramSources : removed call to net/bmahe/genetics4j/gpu/spec/Program::content → NO_COVERAGE 2. grabProgramSources : removed call to java/util/List::addAll → NO_COVERAGE |
sources.addAll(programSpec.content()); |
193 | ||
194 |
1
1. grabProgramSources : removed call to net/bmahe/genetics4j/gpu/spec/Program::resources → NO_COVERAGE |
programSpec.resources() |
195 |
1
1. grabProgramSources : removed call to java/util/Set::stream → NO_COVERAGE |
.stream() |
196 |
5
1. lambda$grabProgramSources$0 : replaced call to net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::loadResource with argument → NO_COVERAGE 2. grabProgramSources : removed call to java/util/stream/Stream::map → NO_COVERAGE 3. lambda$grabProgramSources$0 : replaced return value with "" for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::lambda$grabProgramSources$0 → NO_COVERAGE 4. lambda$grabProgramSources$0 : removed call to net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::loadResource → NO_COVERAGE 5. grabProgramSources : replaced call to java/util/stream/Stream::map with receiver → NO_COVERAGE |
.map(resource -> loadResource(resource)) |
197 |
1
1. grabProgramSources : removed call to java/util/stream/Stream::forEach → NO_COVERAGE |
.forEach(program -> { |
198 |
1
1. lambda$grabProgramSources$1 : removed call to java/util/List::add → NO_COVERAGE |
sources.add(program); |
199 | }); | |
200 | ||
201 |
1
1. grabProgramSources : replaced return value with Collections.emptyList for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::grabProgramSources → NO_COVERAGE |
return sources; |
202 | } | |
203 | ||
204 | /** | |
205 | * Initializes OpenCL resources and prepares GPU devices for fitness evaluation. | |
206 | * | |
207 | * <p>This method performs the complete OpenCL initialization sequence: | |
208 | * <ol> | |
209 | * <li><strong>Platform discovery</strong>: Enumerates available OpenCL platforms</li> | |
210 | * <li><strong>Device filtering</strong>: Selects devices based on configured filters</li> | |
211 | * <li><strong>Context creation</strong>: Creates OpenCL contexts for selected devices</li> | |
212 | * <li><strong>Queue setup</strong>: Creates command queues with profiling and out-of-order execution</li> | |
213 | * <li><strong>Program compilation</strong>: Compiles OpenCL kernels from source code</li> | |
214 | * <li><strong>Kernel preparation</strong>: Creates kernel objects and queries execution info</li> | |
215 | * <li><strong>Fitness initialization</strong>: Calls lifecycle hooks on the fitness function</li> | |
216 | * </ol> | |
217 | * | |
218 | * <p>Device selection process: | |
219 | * <ul> | |
220 | * <li>Applies platform filters to discovered OpenCL platforms</li> | |
221 | * <li>Enumerates devices for each qualifying platform</li> | |
222 | * <li>Applies device filters to select appropriate devices</li> | |
223 | * <li>Validates that at least one device is available</li> | |
224 | * </ul> | |
225 | * | |
226 | * <p>The method creates separate OpenCL contexts for each selected device to enable concurrent execution and optimal | |
227 | * resource utilization. Each context includes compiled programs and kernel objects ready for fitness evaluation. | |
228 | * | |
229 | * @throws IllegalStateException if no compatible devices are found | |
230 | * @throws RuntimeException if OpenCL initialization, program compilation, or kernel creation fails | |
231 | */ | |
232 | @Override | |
233 | public void preEvaluation() { | |
234 | logger.trace("Init..."); | |
235 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/core/evaluation/FitnessEvaluator::preEvaluation → NO_COVERAGE |
FitnessEvaluator.super.preEvaluation(); |
236 | ||
237 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/PlatformReader::<init> → NO_COVERAGE |
final var platformReader = new PlatformReader(); |
238 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/DeviceReader::<init> → NO_COVERAGE |
final var deviceReader = new DeviceReader(); |
239 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/KernelInfoReader::<init> → NO_COVERAGE |
final var kernelInfoReader = new KernelInfoReader(); |
240 | ||
241 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/PlatformUtils::numPlatforms → NO_COVERAGE |
final int numPlatforms = PlatformUtils.numPlatforms(); |
242 | logger.info("Found {} platforms", numPlatforms); | |
243 | ||
244 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/PlatformUtils::platformIds → NO_COVERAGE |
final List<cl_platform_id> platformIds = PlatformUtils.platformIds(numPlatforms); |
245 | ||
246 | logger.info("Selecting platform and devices"); | |
247 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/GPUEAExecutionContext::platformFilters → NO_COVERAGE |
final var platformFilters = gpuEAExecutionContext.platformFilters(); |
248 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/GPUEAExecutionContext::deviceFilters → NO_COVERAGE |
final var deviceFilters = gpuEAExecutionContext.deviceFilters(); |
249 | ||
250 |
1
1. preEvaluation : removed call to java/util/List::stream → NO_COVERAGE |
selectedPlatformToDevice = platformIds.stream() |
251 | .map(platformReader::read) | |
252 |
2
1. preEvaluation : replaced call to java/util/stream/Stream::filter with receiver → NO_COVERAGE 2. preEvaluation : removed call to java/util/stream/Stream::filter → NO_COVERAGE |
.filter(platformFilters) |
253 |
2
1. preEvaluation : replaced call to java/util/stream/Stream::flatMap with receiver → NO_COVERAGE 2. preEvaluation : removed call to java/util/stream/Stream::flatMap → NO_COVERAGE |
.flatMap(platform -> { |
254 |
1
1. lambda$preEvaluation$3 : removed call to net/bmahe/genetics4j/gpu/opencl/model/Platform::platformId → NO_COVERAGE |
final var platformId = platform.platformId(); |
255 |
1
1. lambda$preEvaluation$3 : removed call to net/bmahe/genetics4j/gpu/opencl/DeviceUtils::numDevices → NO_COVERAGE |
final int numDevices = DeviceUtils.numDevices(platformId); |
256 | logger.trace("\tPlatform {}: {} devices", platform.name(), numDevices); | |
257 | ||
258 |
1
1. lambda$preEvaluation$3 : removed call to net/bmahe/genetics4j/gpu/opencl/DeviceUtils::getDeviceIds → NO_COVERAGE |
final var deviceIds = DeviceUtils.getDeviceIds(platformId, numDevices); |
259 |
2
1. lambda$preEvaluation$3 : removed call to java/util/List::stream → NO_COVERAGE 2. lambda$preEvaluation$3 : replaced return value with Stream.empty for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::lambda$preEvaluation$3 → NO_COVERAGE |
return deviceIds.stream() |
260 |
4
1. lambda$preEvaluation$3 : replaced call to java/util/stream/Stream::map with receiver → NO_COVERAGE 2. lambda$preEvaluation$3 : removed call to java/util/stream/Stream::map → NO_COVERAGE 3. lambda$preEvaluation$2 : removed call to org/apache/commons/lang3/tuple/Pair::of → NO_COVERAGE 4. lambda$preEvaluation$2 : replaced return value with null for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::lambda$preEvaluation$2 → NO_COVERAGE |
.map(deviceId -> Pair.of(platform, deviceId)); |
261 | }) | |
262 |
2
1. preEvaluation : replaced call to java/util/stream/Stream::map with receiver → NO_COVERAGE 2. preEvaluation : removed call to java/util/stream/Stream::map → NO_COVERAGE |
.map(platformToDeviceId -> { |
263 |
1
1. lambda$preEvaluation$4 : removed call to org/apache/commons/lang3/tuple/Pair::getLeft → NO_COVERAGE |
final var platform = platformToDeviceId.getLeft(); |
264 |
1
1. lambda$preEvaluation$4 : removed call to net/bmahe/genetics4j/gpu/opencl/model/Platform::platformId → NO_COVERAGE |
final var platformId = platform.platformId(); |
265 |
1
1. lambda$preEvaluation$4 : removed call to org/apache/commons/lang3/tuple/Pair::getRight → NO_COVERAGE |
final var deviceID = platformToDeviceId.getRight(); |
266 | ||
267 |
3
1. lambda$preEvaluation$4 : replaced return value with null for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::lambda$preEvaluation$4 → NO_COVERAGE 2. lambda$preEvaluation$4 : removed call to net/bmahe/genetics4j/gpu/opencl/DeviceReader::read → NO_COVERAGE 3. lambda$preEvaluation$4 : removed call to org/apache/commons/lang3/tuple/Pair::of → NO_COVERAGE |
return Pair.of(platform, deviceReader.read(platformId, deviceID)); |
268 | }) | |
269 |
6
1. lambda$preEvaluation$5 : removed call to java/util/function/Predicate::test → NO_COVERAGE 2. preEvaluation : removed call to java/util/stream/Stream::filter → NO_COVERAGE 3. lambda$preEvaluation$5 : replaced boolean return with true for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::lambda$preEvaluation$5 → NO_COVERAGE 4. lambda$preEvaluation$5 : replaced boolean return with false for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::lambda$preEvaluation$5 → NO_COVERAGE 5. lambda$preEvaluation$5 : removed call to org/apache/commons/lang3/tuple/Pair::getRight → NO_COVERAGE 6. preEvaluation : replaced call to java/util/stream/Stream::filter with receiver → NO_COVERAGE |
.filter(platformToDevice -> deviceFilters.test(platformToDevice.getRight())) |
270 |
2
1. preEvaluation : Removed assignment to member variable selectedPlatformToDevice → NO_COVERAGE 2. preEvaluation : removed call to java/util/stream/Stream::toList → NO_COVERAGE |
.toList(); |
271 | ||
272 | if (logger.isTraceEnabled()) { | |
273 | logger.trace("============================"); | |
274 | logger.trace("Selected devices:"); | |
275 |
1
1. preEvaluation : removed call to java/util/List::forEach → NO_COVERAGE |
selectedPlatformToDevice.forEach(pd -> { |
276 | logger.trace("{}", pd.getLeft()); | |
277 | logger.trace("\t{}", pd.getRight()); | |
278 | }); | |
279 | logger.trace("============================"); | |
280 | } | |
281 | ||
282 | Validate.isTrue(selectedPlatformToDevice.size() > 0); | |
283 | ||
284 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::grabProgramSources → NO_COVERAGE |
final List<String> programs = grabProgramSources(); |
285 |
3
1. preEvaluation : removed call to java/util/List::size → NO_COVERAGE 2. preEvaluation : replaced call to java/util/List::toArray with argument → NO_COVERAGE 3. preEvaluation : removed call to java/util/List::toArray → NO_COVERAGE |
final String[] programsArr = programs.toArray(new String[programs.size()]); |
286 | ||
287 | for (final var platformAndDevice : selectedPlatformToDevice) { | |
288 |
1
1. preEvaluation : removed call to org/apache/commons/lang3/tuple/Pair::getLeft → NO_COVERAGE |
final var platform = platformAndDevice.getLeft(); |
289 |
1
1. preEvaluation : removed call to org/apache/commons/lang3/tuple/Pair::getRight → NO_COVERAGE |
final var device = platformAndDevice.getRight(); |
290 | ||
291 | logger.info("Processing platform [{}] / device [{}]", platform.name(), device.name()); | |
292 | ||
293 | logger.info("\tCreating context"); | |
294 |
1
1. preEvaluation : removed call to org/jocl/cl_context_properties::<init> → NO_COVERAGE |
cl_context_properties contextProperties = new cl_context_properties(); |
295 |
3
1. preEvaluation : Substituted 4228 with 4229 → NO_COVERAGE 2. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/model/Platform::platformId → NO_COVERAGE 3. preEvaluation : removed call to org/jocl/cl_context_properties::addProperty → NO_COVERAGE |
contextProperties.addProperty(CL.CL_CONTEXT_PLATFORM, platform.platformId()); |
296 | ||
297 |
3
1. preEvaluation : Substituted 1 with 0 → NO_COVERAGE 2. preEvaluation : Substituted 0 with 1 → NO_COVERAGE 3. preEvaluation : Substituted 1 with 0 → NO_COVERAGE |
final cl_context context = CL |
298 |
2
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/model/Device::deviceId → NO_COVERAGE 2. preEvaluation : removed call to org/jocl/CL::clCreateContext → NO_COVERAGE |
.clCreateContext(contextProperties, 1, new cl_device_id[] { device.deviceId() }, null, null, null); |
299 | ||
300 | logger.info("\tCreating command queue"); | |
301 |
1
1. preEvaluation : removed call to org/jocl/cl_queue_properties::<init> → NO_COVERAGE |
final cl_queue_properties queueProperties = new cl_queue_properties(); |
302 |
3
1. preEvaluation : Substituted 4243 with 4244 → NO_COVERAGE 2. preEvaluation : Substituted 3 with 4 → NO_COVERAGE 3. preEvaluation : removed call to org/jocl/cl_queue_properties::addProperty → NO_COVERAGE |
queueProperties.addProperty(CL.CL_QUEUE_PROPERTIES, |
303 | CL.CL_QUEUE_PROFILING_ENABLE | CL.CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE); | |
304 | final cl_command_queue commandQueue = CL | |
305 |
2
1. preEvaluation : removed call to org/jocl/CL::clCreateCommandQueueWithProperties → NO_COVERAGE 2. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/model/Device::deviceId → NO_COVERAGE |
.clCreateCommandQueueWithProperties(context, device.deviceId(), queueProperties, null); |
306 | ||
307 | logger.info("\tCreate program"); | |
308 |
1
1. preEvaluation : removed call to org/jocl/CL::clCreateProgramWithSource → NO_COVERAGE |
final cl_program program = CL.clCreateProgramWithSource(context, programsArr.length, programsArr, null, null); |
309 | ||
310 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/GPUEAConfiguration::program → NO_COVERAGE |
final var programSpec = gpuEAConfiguration.program(); |
311 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/Program::buildOptions → NO_COVERAGE |
final var buildOptions = programSpec.buildOptions() |
312 |
2
1. preEvaluation : replaced call to java/util/Optional::orElse with argument → NO_COVERAGE 2. preEvaluation : removed call to java/util/Optional::orElse → NO_COVERAGE |
.orElse(null); |
313 | logger.info("\tBuilding program with options: {}", buildOptions); | |
314 |
3
1. preEvaluation : Substituted 0 with 1 → NO_COVERAGE 2. preEvaluation : replaced call to org/jocl/CL::clBuildProgram with argument → NO_COVERAGE 3. preEvaluation : removed call to org/jocl/CL::clBuildProgram → NO_COVERAGE |
CL.clBuildProgram(program, 0, null, buildOptions, null, null); |
315 | ||
316 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/GPUEAConfiguration::program → NO_COVERAGE |
final Set<String> kernelNames = gpuEAConfiguration.program() |
317 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/Program::kernelNames → NO_COVERAGE |
.kernelNames(); |
318 | ||
319 |
1
1. preEvaluation : removed call to java/util/HashMap::<init> → NO_COVERAGE |
final Map<String, cl_kernel> kernels = new HashMap<>(); |
320 |
1
1. preEvaluation : removed call to java/util/HashMap::<init> → NO_COVERAGE |
final Map<String, KernelInfo> kernelInfos = new HashMap<>(); |
321 | for (final String kernelName : kernelNames) { | |
322 | ||
323 | logger.info("\tCreate kernel {}", kernelName); | |
324 |
1
1. preEvaluation : removed call to org/jocl/CL::clCreateKernel → NO_COVERAGE |
final cl_kernel kernel = CL.clCreateKernel(program, kernelName, null); |
325 | Validate.notNull(kernel); | |
326 | ||
327 |
2
1. preEvaluation : removed call to java/util/Map::put → NO_COVERAGE 2. preEvaluation : replaced call to java/util/Map::put with argument → NO_COVERAGE |
kernels.put(kernelName, kernel); |
328 | ||
329 |
2
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/KernelInfoReader::read → NO_COVERAGE 2. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/model/Device::deviceId → NO_COVERAGE |
final var kernelInfo = kernelInfoReader.read(device.deviceId(), kernel, kernelName); |
330 | logger.trace("\t{}", kernelInfo); | |
331 |
2
1. preEvaluation : replaced call to java/util/Map::put with argument → NO_COVERAGE 2. preEvaluation : removed call to java/util/Map::put → NO_COVERAGE |
kernelInfos.put(kernelName, kernelInfo); |
332 | } | |
333 | ||
334 |
1
1. preEvaluation : removed call to java/util/List::add → NO_COVERAGE |
clContexts.add(context); |
335 |
1
1. preEvaluation : removed call to java/util/List::add → NO_COVERAGE |
clCommandQueues.add(commandQueue); |
336 |
1
1. preEvaluation : removed call to java/util/List::add → NO_COVERAGE |
clKernels.add(kernels); |
337 |
1
1. preEvaluation : removed call to java/util/List::add → NO_COVERAGE |
clPrograms.add(program); |
338 | ||
339 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext::builder → NO_COVERAGE |
final var openCLExecutionContext = OpenCLExecutionContext.builder() |
340 |
2
1. preEvaluation : replaced call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::platform with receiver → NO_COVERAGE 2. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::platform → NO_COVERAGE |
.platform(platform) |
341 |
2
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::device → NO_COVERAGE 2. preEvaluation : replaced call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::device with receiver → NO_COVERAGE |
.device(device) |
342 |
2
1. preEvaluation : replaced call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::clContext with receiver → NO_COVERAGE 2. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::clContext → NO_COVERAGE |
.clContext(context) |
343 |
2
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::clCommandQueue → NO_COVERAGE 2. preEvaluation : replaced call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::clCommandQueue with receiver → NO_COVERAGE |
.clCommandQueue(commandQueue) |
344 |
2
1. preEvaluation : replaced call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::kernels with receiver → NO_COVERAGE 2. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::kernels → NO_COVERAGE |
.kernels(kernels) |
345 |
2
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::kernelInfos → NO_COVERAGE 2. preEvaluation : replaced call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::kernelInfos with receiver → NO_COVERAGE |
.kernelInfos(kernelInfos) |
346 |
2
1. preEvaluation : replaced call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::clProgram with receiver → NO_COVERAGE 2. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::clProgram → NO_COVERAGE |
.clProgram(program) |
347 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/opencl/OpenCLExecutionContext$Builder::build → NO_COVERAGE |
.build(); |
348 | ||
349 |
1
1. preEvaluation : removed call to java/util/List::add → NO_COVERAGE |
clExecutionContexts.add(openCLExecutionContext); |
350 | } | |
351 | ||
352 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/GPUEAConfiguration::fitness → NO_COVERAGE |
final var fitness = gpuEAConfiguration.fitness(); |
353 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/fitness/OpenCLFitness::beforeAllEvaluations → NO_COVERAGE |
fitness.beforeAllEvaluations(); |
354 | for (final OpenCLExecutionContext clExecutionContext : clExecutionContexts) { | |
355 |
1
1. preEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/fitness/OpenCLFitness::beforeAllEvaluations → NO_COVERAGE |
fitness.beforeAllEvaluations(clExecutionContext, executorService); |
356 | } | |
357 | } | |
358 | ||
359 | /** | |
360 | * Evaluates fitness for a population of genotypes using GPU acceleration. | |
361 | * | |
362 | * <p>This method implements the core fitness evaluation logic by distributing the population across available OpenCL | |
363 | * devices and executing fitness computation concurrently. The evaluation process follows these steps: | |
364 | * | |
365 | * <ol> | |
366 | * <li><strong>Population partitioning</strong>: Divides genotypes across available devices</li> | |
367 | * <li><strong>Parallel dispatch</strong>: Submits evaluation tasks to each device asynchronously</li> | |
368 | * <li><strong>GPU execution</strong>: Executes OpenCL kernels for fitness computation</li> | |
369 | * <li><strong>Result collection</strong>: Gathers fitness values from all devices</li> | |
370 | * <li><strong>Result aggregation</strong>: Combines results preserving original order</li> | |
371 | * </ol> | |
372 | * | |
373 | * <p>Load balancing strategy: | |
374 | * <ul> | |
375 | * <li>Automatically calculates partition size based on population and device count</li> | |
376 | * <li>Round-robin assignment of partitions to devices for balanced workload</li> | |
377 | * <li>Asynchronous execution allows devices to work at their optimal pace</li> | |
378 | * </ul> | |
379 | * | |
380 | * <p>The method coordinates with the configured fitness function through lifecycle hooks: | |
381 | * <ul> | |
382 | * <li>{@code beforeEvaluation()}: Called before each device partition evaluation</li> | |
383 | * <li>{@code compute()}: Executes the actual GPU fitness computation</li> | |
384 | * <li>{@code afterEvaluation()}: Called after each device partition completes</li> | |
385 | * </ul> | |
386 | * | |
387 | * <p>Concurrency and performance: | |
388 | * <ul> | |
389 | * <li>Multiple devices execute evaluation partitions concurrently</li> | |
390 | * <li>CompletableFuture-based coordination for non-blocking execution</li> | |
391 | * <li>Automatic workload distribution across available GPU resources</li> | |
392 | * </ul> | |
393 | * | |
394 | * @param generation the current generation number for context and logging | |
395 | * @param genotypes the population of genotypes to evaluate | |
396 | * @return fitness values corresponding to each genotype in the same order | |
397 | * @throws IllegalArgumentException if genotypes is null or empty | |
398 | * @throws RuntimeException if GPU evaluation fails or OpenCL errors occur | |
399 | */ | |
400 | @Override | |
401 | public List<T> evaluate(final long generation, final List<Genotype> genotypes) { | |
402 | ||
403 |
1
1. evaluate : removed call to net/bmahe/genetics4j/gpu/spec/GPUEAConfiguration::fitness → NO_COVERAGE |
final var fitness = gpuEAConfiguration.fitness(); |
404 | ||
405 | /** | |
406 | * TODO make it configurable from execution context | |
407 | */ | |
408 |
5
1. evaluate : removed call to java/util/List::size → NO_COVERAGE 2. evaluate : Replaced double division with multiplication → NO_COVERAGE 3. evaluate : removed call to java/util/List::size → NO_COVERAGE 4. evaluate : removed call to java/lang/Math::ceil → NO_COVERAGE 5. evaluate : replaced call to java/lang/Math::ceil with argument → NO_COVERAGE |
final int partitionSize = (int) (Math.ceil((double) genotypes.size() / clExecutionContexts.size())); |
409 |
2
1. evaluate : replaced call to org/apache/commons/collections4/ListUtils::partition with argument → NO_COVERAGE 2. evaluate : removed call to org/apache/commons/collections4/ListUtils::partition → NO_COVERAGE |
final var subGenotypes = ListUtils.partition(genotypes, partitionSize); |
410 | logger.debug("Genotype decomposed in {} partition(s)", subGenotypes.size()); | |
411 | if (logger.isTraceEnabled()) { | |
412 |
6
1. evaluate : removed conditional - replaced comparison check with true → NO_COVERAGE 2. evaluate : negated conditional → NO_COVERAGE 3. evaluate : changed conditional boundary → NO_COVERAGE 4. evaluate : Substituted 0 with 1 → NO_COVERAGE 5. evaluate : removed call to java/util/List::size → NO_COVERAGE 6. evaluate : removed conditional - replaced comparison check with false → NO_COVERAGE |
for (int i = 0; i < subGenotypes.size(); i++) { |
413 |
1
1. evaluate : removed call to java/util/List::get → NO_COVERAGE |
final List<Genotype> subGenotype = subGenotypes.get(i); |
414 | logger.trace("\tPartition {} with {} elements", i, subGenotype.size()); | |
415 | } | |
416 | } | |
417 | ||
418 |
1
1. evaluate : removed call to java/util/ArrayList::<init> → NO_COVERAGE |
final List<CompletableFuture<List<T>>> subResultsCF = new ArrayList<>(); |
419 |
6
1. evaluate : removed conditional - replaced comparison check with false → NO_COVERAGE 2. evaluate : removed call to java/util/List::size → NO_COVERAGE 3. evaluate : Substituted 0 with 1 → NO_COVERAGE 4. evaluate : removed conditional - replaced comparison check with true → NO_COVERAGE 5. evaluate : negated conditional → NO_COVERAGE 6. evaluate : changed conditional boundary → NO_COVERAGE |
for (int i = 0; i < subGenotypes.size(); i++) { |
420 |
3
1. evaluate : removed call to java/util/List::size → NO_COVERAGE 2. evaluate : removed call to java/util/List::get → NO_COVERAGE 3. evaluate : Replaced integer modulus with multiplication → NO_COVERAGE |
final var openCLExecutionContext = clExecutionContexts.get(i % clExecutionContexts.size()); |
421 |
1
1. evaluate : removed call to java/util/List::get → NO_COVERAGE |
final var subGenotype = subGenotypes.get(i); |
422 | ||
423 |
1
1. evaluate : removed call to net/bmahe/genetics4j/gpu/spec/fitness/OpenCLFitness::beforeEvaluation → NO_COVERAGE |
fitness.beforeEvaluation(generation, subGenotype); |
424 |
1
1. evaluate : removed call to net/bmahe/genetics4j/gpu/spec/fitness/OpenCLFitness::beforeEvaluation → NO_COVERAGE |
fitness.beforeEvaluation(openCLExecutionContext, executorService, generation, subGenotype); |
425 | ||
426 |
1
1. evaluate : removed call to net/bmahe/genetics4j/gpu/spec/fitness/OpenCLFitness::compute → NO_COVERAGE |
final var resultsCF = fitness.compute(openCLExecutionContext, executorService, generation, subGenotype) |
427 |
2
1. evaluate : removed call to java/util/concurrent/CompletableFuture::thenApply → NO_COVERAGE 2. evaluate : replaced call to java/util/concurrent/CompletableFuture::thenApply with receiver → NO_COVERAGE |
.thenApply((results) -> { |
428 | ||
429 |
1
1. lambda$evaluate$7 : removed call to net/bmahe/genetics4j/gpu/spec/fitness/OpenCLFitness::afterEvaluation → NO_COVERAGE |
fitness.afterEvaluation(openCLExecutionContext, executorService, generation, subGenotype); |
430 |
1
1. lambda$evaluate$7 : removed call to net/bmahe/genetics4j/gpu/spec/fitness/OpenCLFitness::afterEvaluation → NO_COVERAGE |
fitness.afterEvaluation(generation, subGenotype); |
431 | ||
432 |
1
1. lambda$evaluate$7 : replaced return value with Collections.emptyList for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::lambda$evaluate$7 → NO_COVERAGE |
return results; |
433 | }); | |
434 | ||
435 |
1
1. evaluate : removed call to java/util/List::add → NO_COVERAGE |
subResultsCF.add(resultsCF); |
436 | } | |
437 | ||
438 |
2
1. evaluate : removed call to java/util/ArrayList::<init> → NO_COVERAGE 2. evaluate : removed call to java/util/List::size → NO_COVERAGE |
final List<T> resultsEvaluation = new ArrayList<>(genotypes.size()); |
439 | for (final CompletableFuture<List<T>> subResultCF : subResultsCF) { | |
440 |
1
1. evaluate : removed call to java/util/concurrent/CompletableFuture::join → NO_COVERAGE |
final var fitnessResults = subResultCF.join(); |
441 |
1
1. evaluate : removed call to java/util/List::addAll → NO_COVERAGE |
resultsEvaluation.addAll(fitnessResults); |
442 | } | |
443 |
1
1. evaluate : replaced return value with Collections.emptyList for net/bmahe/genetics4j/gpu/GPUFitnessEvaluator::evaluate → NO_COVERAGE |
return resultsEvaluation; |
444 | } | |
445 | ||
446 | /** | |
447 | * Cleans up OpenCL resources and releases GPU memory after evaluation completion. | |
448 | * | |
449 | * <p>This method performs comprehensive cleanup of all OpenCL resources in the proper order to prevent memory leaks | |
450 | * and ensure clean shutdown. The cleanup sequence follows OpenCL best practices for resource deallocation: | |
451 | * | |
452 | * <ol> | |
453 | * <li><strong>Fitness cleanup</strong>: Calls lifecycle hooks on the fitness function</li> | |
454 | * <li><strong>Kernel release</strong>: Releases all compiled kernel objects</li> | |
455 | * <li><strong>Program release</strong>: Releases compiled OpenCL programs</li> | |
456 | * <li><strong>Queue release</strong>: Releases command queues and pending operations</li> | |
457 | * <li><strong>Context release</strong>: Releases OpenCL contexts and associated memory</li> | |
458 | * <li><strong>Reference cleanup</strong>: Clears internal data structures and references</li> | |
459 | * </ol> | |
460 | * | |
461 | * <p>Resource management guarantees: | |
462 | * <ul> | |
463 | * <li>All GPU memory allocations are properly released</li> | |
464 | * <li>OpenCL objects are released in dependency order to avoid errors</li> | |
465 | * <li>No resource leaks occur even if individual cleanup operations fail</li> | |
466 | * <li>Evaluator returns to a clean state ready for potential reinitialization</li> | |
467 | * </ul> | |
468 | * | |
469 | * <p>The method coordinates with the configured fitness function to ensure any fitness-specific resources (buffers, | |
470 | * textures, etc.) are also properly cleaned up through the {@code afterAllEvaluations()} lifecycle hooks. | |
471 | * | |
472 | * @throws RuntimeException if cleanup operations fail (logged but not propagated to prevent interference with EA | |
473 | * system shutdown) | |
474 | */ | |
475 | @Override | |
476 | public void postEvaluation() { | |
477 | ||
478 |
1
1. postEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/GPUEAConfiguration::fitness → NO_COVERAGE |
final var fitness = gpuEAConfiguration.fitness(); |
479 | ||
480 | for (final OpenCLExecutionContext clExecutionContext : clExecutionContexts) { | |
481 |
1
1. postEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/fitness/OpenCLFitness::afterAllEvaluations → NO_COVERAGE |
fitness.afterAllEvaluations(clExecutionContext, executorService); |
482 | } | |
483 |
1
1. postEvaluation : removed call to net/bmahe/genetics4j/gpu/spec/fitness/OpenCLFitness::afterAllEvaluations → NO_COVERAGE |
fitness.afterAllEvaluations(); |
484 | ||
485 | logger.debug("Releasing kernels"); | |
486 | ||
487 | for (final Map<String, cl_kernel> kernels : clKernels) { | |
488 |
1
1. postEvaluation : removed call to java/util/Map::values → NO_COVERAGE |
for (final cl_kernel clKernel : kernels.values()) { |
489 |
1
1. postEvaluation : removed call to org/jocl/CL::clReleaseKernel → NO_COVERAGE |
CL.clReleaseKernel(clKernel); |
490 | } | |
491 | } | |
492 |
1
1. postEvaluation : removed call to java/util/List::clear → NO_COVERAGE |
clKernels.clear(); |
493 | ||
494 | logger.debug("Releasing programs"); | |
495 | for (final cl_program clProgram : clPrograms) { | |
496 |
1
1. postEvaluation : removed call to org/jocl/CL::clReleaseProgram → NO_COVERAGE |
CL.clReleaseProgram(clProgram); |
497 | } | |
498 |
1
1. postEvaluation : removed call to java/util/List::clear → NO_COVERAGE |
clPrograms.clear(); |
499 | ||
500 | logger.debug("Releasing command queues"); | |
501 | for (final cl_command_queue clCommandQueue : clCommandQueues) { | |
502 |
1
1. postEvaluation : removed call to org/jocl/CL::clReleaseCommandQueue → NO_COVERAGE |
CL.clReleaseCommandQueue(clCommandQueue); |
503 | } | |
504 |
1
1. postEvaluation : removed call to java/util/List::clear → NO_COVERAGE |
clCommandQueues.clear(); |
505 | ||
506 | logger.debug("Releasing contexts"); | |
507 | for (final cl_context clContext : clContexts) { | |
508 |
1
1. postEvaluation : removed call to org/jocl/CL::clReleaseContext → NO_COVERAGE |
CL.clReleaseContext(clContext); |
509 | } | |
510 |
1
1. postEvaluation : removed call to java/util/List::clear → NO_COVERAGE |
clContexts.clear(); |
511 | ||
512 |
1
1. postEvaluation : removed call to java/util/List::clear → NO_COVERAGE |
clExecutionContexts.clear(); |
513 |
1
1. postEvaluation : Removed assignment to member variable selectedPlatformToDevice → NO_COVERAGE |
selectedPlatformToDevice = null; |
514 | ||
515 |
1
1. postEvaluation : removed call to net/bmahe/genetics4j/core/evaluation/FitnessEvaluator::postEvaluation → NO_COVERAGE |
FitnessEvaluator.super.postEvaluation(); |
516 | } | |
517 | } | |
Mutations | ||
142 |
1.1 2.2 |
|
143 |
1.1 2.2 |
|
144 |
1.1 2.2 |
|
145 |
1.1 2.2 |
|
146 |
1.1 2.2 |
|
168 |
1.1 |
|
169 |
1.1 |
|
170 |
1.1 |
|
172 |
1.1 2.2 |
|
179 |
1.1 2.2 3.3 |
|
181 |
1.1 |
|
186 |
1.1 |
|
190 |
1.1 |
|
192 |
1.1 2.2 |
|
194 |
1.1 |
|
195 |
1.1 |
|
196 |
1.1 2.2 3.3 4.4 5.5 |
|
197 |
1.1 |
|
198 |
1.1 |
|
201 |
1.1 |
|
235 |
1.1 |
|
237 |
1.1 |
|
238 |
1.1 |
|
239 |
1.1 |
|
241 |
1.1 |
|
244 |
1.1 |
|
247 |
1.1 |
|
248 |
1.1 |
|
250 |
1.1 |
|
252 |
1.1 2.2 |
|
253 |
1.1 2.2 |
|
254 |
1.1 |
|
255 |
1.1 |
|
258 |
1.1 |
|
259 |
1.1 2.2 |
|
260 |
1.1 2.2 3.3 4.4 |
|
262 |
1.1 2.2 |
|
263 |
1.1 |
|
264 |
1.1 |
|
265 |
1.1 |
|
267 |
1.1 2.2 3.3 |
|
269 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
270 |
1.1 2.2 |
|
275 |
1.1 |
|
284 |
1.1 |
|
285 |
1.1 2.2 3.3 |
|
288 |
1.1 |
|
289 |
1.1 |
|
294 |
1.1 |
|
295 |
1.1 2.2 3.3 |
|
297 |
1.1 2.2 3.3 |
|
298 |
1.1 2.2 |
|
301 |
1.1 |
|
302 |
1.1 2.2 3.3 |
|
305 |
1.1 2.2 |
|
308 |
1.1 |
|
310 |
1.1 |
|
311 |
1.1 |
|
312 |
1.1 2.2 |
|
314 |
1.1 2.2 3.3 |
|
316 |
1.1 |
|
317 |
1.1 |
|
319 |
1.1 |
|
320 |
1.1 |
|
324 |
1.1 |
|
327 |
1.1 2.2 |
|
329 |
1.1 2.2 |
|
331 |
1.1 2.2 |
|
334 |
1.1 |
|
335 |
1.1 |
|
336 |
1.1 |
|
337 |
1.1 |
|
339 |
1.1 |
|
340 |
1.1 2.2 |
|
341 |
1.1 2.2 |
|
342 |
1.1 2.2 |
|
343 |
1.1 2.2 |
|
344 |
1.1 2.2 |
|
345 |
1.1 2.2 |
|
346 |
1.1 2.2 |
|
347 |
1.1 |
|
349 |
1.1 |
|
352 |
1.1 |
|
353 |
1.1 |
|
355 |
1.1 |
|
403 |
1.1 |
|
408 |
1.1 2.2 3.3 4.4 5.5 |
|
409 |
1.1 2.2 |
|
412 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
413 |
1.1 |
|
418 |
1.1 |
|
419 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
420 |
1.1 2.2 3.3 |
|
421 |
1.1 |
|
423 |
1.1 |
|
424 |
1.1 |
|
426 |
1.1 |
|
427 |
1.1 2.2 |
|
429 |
1.1 |
|
430 |
1.1 |
|
432 |
1.1 |
|
435 |
1.1 |
|
438 |
1.1 2.2 |
|
440 |
1.1 |
|
441 |
1.1 |
|
443 |
1.1 |
|
478 |
1.1 |
|
481 |
1.1 |
|
483 |
1.1 |
|
488 |
1.1 |
|
489 |
1.1 |
|
492 |
1.1 |
|
496 |
1.1 |
|
498 |
1.1 |
|
502 |
1.1 |
|
504 |
1.1 |
|
508 |
1.1 |
|
510 |
1.1 |
|
512 |
1.1 |
|
513 |
1.1 |
|
515 |
1.1 |