1 package net.bmahe.genetics4j.gpu.spec; 2 3 import java.util.List; 4 import java.util.Optional; 5 import java.util.Set; 6 7 import org.apache.commons.lang3.Validate; 8 import org.immutables.value.Value; 9 10 /** 11 * Specification for OpenCL programs containing kernel source code, build options, and compilation settings. 12 * 13 * <p>Program represents a complete OpenCL program specification that includes kernel source code 14 * (either as direct content or resource references), kernel definitions, and compilation options. 15 * This specification is used by the GPU EA system to compile and execute OpenCL kernels for 16 * fitness evaluation on GPU devices. 17 * 18 * <p>A program can contain: 19 * <ul> 20 * <li><strong>Source content</strong>: Direct OpenCL C code as strings</li> 21 * <li><strong>Resource references</strong>: Paths to OpenCL source files in the classpath</li> 22 * <li><strong>Kernel definitions</strong>: Names of kernels to be compiled and made available</li> 23 * <li><strong>Build options</strong>: Compiler flags and preprocessor definitions</li> 24 * </ul> 25 * 26 * <p>Program compilation workflow: 27 * <ol> 28 * <li><strong>Source loading</strong>: Load content from strings and resource files</li> 29 * <li><strong>Source concatenation</strong>: Combine all sources into a single compilation unit</li> 30 * <li><strong>Compilation</strong>: Compile with specified build options for target devices</li> 31 * <li><strong>Kernel extraction</strong>: Create kernel objects for specified kernel names</li> 32 * <li><strong>Validation</strong>: Verify all kernels were successfully created</li> 33 * </ol> 34 * 35 * <p>Common usage patterns: 36 * <pre>{@code 37 * // Simple single-kernel program from resource 38 * Program basicProgram = Program.ofResource("/kernels/fitness.cl", "evaluate_fitness"); 39 * 40 * // Program with build options for optimization 41 * Program optimizedProgram = Program.ofResource( 42 * "/kernels/optimization.cl", 43 * "fitness_kernel", 44 * "-O3 -DPOPULATION_SIZE=1000 -DUSE_FAST_MATH" 45 * ); 46 * 47 * // Complex program with multiple sources and kernels 48 * Program complexProgram = Program.builder() 49 * .addContent("#define PROBLEM_SIZE 256") // Direct content 50 * .addResources("/kernels/common.cl") // Common utilities 51 * .addResources("/kernels/fitness.cl") // Main fitness logic 52 * .addKernelNames("fitness_eval") // Primary kernel 53 * .addKernelNames("data_preparation") // Helper kernel 54 * .buildOptions("-cl-fast-relaxed-math -DLOCAL_SIZE=64") 55 * .build(); 56 * }</pre> 57 * 58 * <p>Build options support: 59 * <ul> 60 * <li><strong>Optimization flags</strong>: -O0, -O1, -O2, -O3 for performance tuning</li> 61 * <li><strong>Math optimizations</strong>: -cl-fast-relaxed-math for numerical performance</li> 62 * <li><strong>Preprocessor definitions</strong>: -DMACRO=value for compile-time configuration</li> 63 * <li><strong>Warning control</strong>: -w to disable warnings, -Werror to treat warnings as errors</li> 64 * <li><strong>Standards compliance</strong>: -cl-std=CL1.2 for specific OpenCL version targeting</li> 65 * </ul> 66 * 67 * <p>Resource loading considerations: 68 * <ul> 69 * <li><strong>Classpath resolution</strong>: Resources loaded relative to classpath</li> 70 * <li><strong>Encoding</strong>: Source files assumed to be UTF-8 encoded</li> 71 * <li><strong>Include simulation</strong>: Manual concatenation instead of OpenCL #include</li> 72 * <li><strong>Error handling</strong>: Resource loading failures result in compilation errors</li> 73 * </ul> 74 * 75 * <p>Validation and constraints: 76 * <ul> 77 * <li><strong>Kernel names required</strong>: At least one kernel name must be specified</li> 78 * <li><strong>Source availability</strong>: Either content or resources must provide source code</li> 79 * <li><strong>Name uniqueness</strong>: Kernel names must be unique within the program</li> 80 * <li><strong>Compilation validity</strong>: Source code must compile successfully for target devices</li> 81 * </ul> 82 * 83 * @see net.bmahe.genetics4j.gpu.GPUFitnessEvaluator 84 * @see net.bmahe.genetics4j.gpu.spec.GPUEAConfiguration 85 * @see net.bmahe.genetics4j.gpu.opencl.OpenCLExecutionContext 86 */ 87 @Value.Immutable 88 public abstract class Program { 89 90 /** 91 * Returns the direct OpenCL source code content as strings. 92 * 93 * <p>Content represents OpenCL C source code provided directly as strings 94 * rather than loaded from resources. Multiple content strings are concatenated 95 * during compilation to form a single compilation unit. 96 * 97 * @return list of OpenCL source code strings 98 */ 99 @Value.Parameter 100 public abstract List<String> content(); 101 102 /** 103 * Returns the classpath resource paths containing OpenCL source code. 104 * 105 * <p>Resources are loaded from the classpath at compilation time and 106 * concatenated with any direct content to form the complete program source. 107 * Resource paths should be relative to the classpath root. 108 * 109 * @return set of classpath resource paths for OpenCL source files 110 */ 111 @Value.Parameter 112 public abstract Set<String> resources(); 113 114 /** 115 * Returns the names of kernels to be extracted from the compiled program. 116 * 117 * <p>Kernel names specify which functions in the OpenCL source should be 118 * made available as executable kernels. These names must correspond to 119 * functions declared with the {@code __kernel} qualifier in the source code. 120 * 121 * @return set of kernel function names to extract after compilation 122 */ 123 @Value.Parameter 124 public abstract Set<String> kernelNames(); 125 126 /** 127 * Returns the OpenCL compiler build options for program compilation. 128 * 129 * <p>Build options are passed to the OpenCL compiler to control optimization, 130 * define preprocessor macros, and configure compilation behavior. Common options 131 * include optimization levels, math optimizations, and macro definitions. 132 * 133 * @return optional build options string for OpenCL compilation 134 */ 135 public abstract Optional<String> buildOptions(); 136 137 @Value.Check 138 protected void check() { 139 Validate.notNull(kernelNames()); 140 Validate.isTrue(kernelNames().isEmpty() == false); 141 } 142 143 /** 144 * Creates a program from direct OpenCL source content with a single kernel. 145 * 146 * <p>This factory method creates a simple program specification with source code 147 * provided directly as a string and a single kernel to be extracted. 148 * 149 * @param content the OpenCL source code as a string 150 * @param kernelName the name of the kernel function to extract 151 * @return a new program specification with the given content and kernel 152 * @throws IllegalArgumentException if content or kernelName is null or blank 153 */ 154 public static Program ofContent(final String content, final String kernelName) { 155 Validate.notBlank(content); 156 Validate.notBlank(kernelName); 157 158 return ImmutableProgram.builder() 159 .addContent(content) 160 .addKernelNames(kernelName) 161 .build(); 162 } 163 164 /** 165 * Creates a program from a classpath resource with a single kernel. 166 * 167 * <p>This factory method creates a program specification that loads OpenCL source 168 * code from a classpath resource and extracts a single named kernel. 169 * 170 * @param resource the classpath path to the OpenCL source file 171 * @param kernelName the name of the kernel function to extract 172 * @return a new program specification with the given resource and kernel 173 * @throws IllegalArgumentException if resource or kernelName is null or blank 174 */ 175 public static Program ofResource(final String resource, final String kernelName) { 176 Validate.notBlank(resource); 177 Validate.notBlank(kernelName); 178 179 return ImmutableProgram.builder() 180 .addResources(resource) 181 .addKernelNames(kernelName) 182 .build(); 183 } 184 185 /** 186 * Creates a program from a classpath resource with a single kernel and build options. 187 * 188 * <p>This factory method creates a program specification that loads OpenCL source 189 * code from a classpath resource, extracts a single named kernel, and applies 190 * the specified build options during compilation. 191 * 192 * @param resource the classpath path to the OpenCL source file 193 * @param kernelName the name of the kernel function to extract 194 * @param buildOptions the build options for OpenCL compilation 195 * @return a new program specification with the given resource, kernel, and build options 196 * @throws IllegalArgumentException if resource or kernelName is null or blank 197 */ 198 public static Program ofResource(final String resource, final String kernelName, final String buildOptions) { 199 Validate.notBlank(resource); 200 Validate.notBlank(kernelName); 201 202 return ImmutableProgram.builder() 203 .addResources(resource) 204 .addKernelNames(kernelName) 205 .buildOptions(buildOptions) 206 .build(); 207 } 208 209 /** 210 * Creates a new builder for constructing complex program specifications. 211 * 212 * <p>The builder provides a fluent interface for creating programs with multiple 213 * source files, kernels, and advanced configuration options. 214 * 215 * @return a new builder instance for creating program specifications 216 */ 217 public static ImmutableProgram.Builder builder() { 218 return ImmutableProgram.builder(); 219 } 220 }