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