View Javadoc
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 }