JOCL v2.6.0-rc-20250722
JOCL, OpenCL® API Binding for Java™ (public API).
CLProgramTest.java
Go to the documentation of this file.
1/*
2 * Copyright 2010 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29package com.jogamp.opencl;
30
31import com.jogamp.opencl.test.util.UITestCase;
32import com.jogamp.opencl.util.CLBuildConfiguration;
33import com.jogamp.opencl.util.CLProgramConfiguration;
34import com.jogamp.common.nio.Buffers;
35import com.jogamp.opencl.CLProgram.Status;
36import com.jogamp.opencl.util.CLBuildListener;
37import com.jogamp.opencl.llb.CL;
38
39import java.io.File;
40import java.io.FileInputStream;
41import java.io.FileOutputStream;
42import java.io.IOException;
43import java.io.ObjectInputStream;
44import java.io.ObjectOutputStream;
45import java.nio.ByteBuffer;
46import java.util.Map;
47import java.util.concurrent.CountDownLatch;
48
49import org.junit.FixMethodOrder;
50import org.junit.Rule;
51import org.junit.Test;
52import org.junit.rules.TemporaryFolder;
53import org.junit.runners.MethodSorters;
54
55import static org.junit.Assert.*;
56import static java.lang.System.*;
57import static com.jogamp.common.os.Platform.is32Bit;
58import static com.jogamp.opencl.CLException.newException;
59import static com.jogamp.opencl.CLProgram.CompilerOptions.*;
60import static com.jogamp.opencl.llb.CL12.CL_KERNEL_GLOBAL_WORK_SIZE;
61import static com.jogamp.opencl.llb.CL.CL_SUCCESS;
62
63/**
64 *
65 * @author Michael Bien, et.al
66 */
67@FixMethodOrder(MethodSorters.NAME_ASCENDING)
68public class CLProgramTest extends UITestCase {
69
70 @Rule
71 public TemporaryFolder tmpFolder = new TemporaryFolder();
72
73
74 @Test
75 public void test01Enums() {
76
77 // CLProgram enums
78 for (final Status e : Status.values()) {
79 assertEquals(e, Status.valueOf(e.STATUS));
80 }
81 }
82
83 @Test
84 public void test02RebuildProgram() throws IOException {
85 final CLContext context = CLContext.create();
86 final CLProgram program = context.createProgram(getClass().getResourceAsStream("testkernels.cl"));
87
88 // only test kernel creation error on unbuilt program if we're not on AMD -- as of
89 // 3/8/2014, AMD drivers segfault on this instead of returning CL_INVALID_PROGRAM_EXECUTABLE
90 if(!context.getPlatform().isVendorAMD()) {
91 try{
92 program.createCLKernels();
93 fail("expected exception but got none :(");
94 }catch(final CLException ex) {
95 out.println("got expected exception: "+ex.getCLErrorString());
97 }
98 }
99
100 out.println(program.getBuildStatus());
101 program.build();
102 out.println(program.getBuildStatus());
103
104 assertTrue(program.isExecutable());
105
106 CLKernel kernel = program.createCLKernel("VectorAddGM");
107 assertNotNull(kernel);
108
109 // rebuild
110 // 1. release kernels (internally)
111 // 2. build program
112 program.build();
113 assertTrue(program.isExecutable());
114 out.println(program.getBuildStatus());
115
116 // try again with rebuilt program
117 kernel = program.createCLKernel("VectorAddGM");
118 assertNotNull(kernel);
119
120 context.release();
121 }
122
123 @Test
124 public void test03ProgramBinaries() throws IOException {
125 final CLContext context = CLContext.create();
126 CLProgram program = context.createProgram(getClass().getResourceAsStream("testkernels.cl"))
127 .build(ENABLE_MAD, WARNINGS_ARE_ERRORS);
128
129 // obtain binaries
130 final Map<CLDevice, byte[]> binaries = program.getBinaries();
131 assertFalse(binaries.isEmpty());
132
133 final CLDevice[] devices = program.getCLDevices();
134 for (final CLDevice device : devices) {
135 assertTrue(binaries.containsKey(device));
136 }
137
138 // 1. release program
139 // 2. re-create program with old binaries
140 program.release();
141
142 assertFalse(program.isExecutable());
143
144 assertNotNull(program.getBinaries());
145 assertEquals(program.getBinaries().size(), 0);
146
147 assertNotNull(program.getBuildLog());
148 assertEquals(program.getBuildLog().length(), 0);
149
150 assertNotNull(program.getSource());
151 assertEquals(program.getSource().length(), 0);
152
153 assertNotNull(program.getCLDevices());
154 assertEquals(program.getCLDevices().length, 0);
155
156 // make sure kernel creation does nothing after program release
157 {
158 final Map<String, CLKernel> kernels = program.createCLKernels();
159 assertNotNull(kernels);
160 assertEquals(kernels.size(), 0);
161 }
162 assertNull(program.createCLKernel("foo"));
163
164 program = context.createProgram(binaries);
165
166 // as of 10/25/2015, Intel shows recreated programs as executable
167 if(!context.getPlatform().isVendorIntel())
168 assertFalse(program.isExecutable());
169 else
170 assertTrue(program.isExecutable());
171
172 assertNotNull(program.getCLDevices());
173 assertTrue(program.getCLDevices().length != 0);
174
175 assertNotNull(program.getBinaries());
176 // as of 10/25/2015, Intel shows recreated programs binaries as having size
177 if(!context.getPlatform().isVendorIntel())
178 assertEquals(program.getBinaries().size(), 0);
179 else
180 assertTrue(program.getBinaries().size() > 0);
181
182 assertNotNull(program.getBuildLog());
183 assertTrue(program.getBuildLog().length() != 0);
184
185 assertNotNull(program.getSource());
186 assertEquals(program.getSource().length(), 0);
187
188 // only test kernel creation error on unbuilt program if we're not on AMD or Intel -- as of
189 // (3/8/2014, 10/31/2015) (AMD, Intel) drivers segfault on this instead of returning CL_INVALID_PROGRAM_EXECUTABLE
190 if(!context.getPlatform().isVendorAMD() && !context.getPlatform().isVendorIntel()) {
191 try{
192 final Map<String, CLKernel> kernels = program.createCLKernels();
193 fail("expected an exception from createCLKernels but got: "+kernels);
194 }catch(final CLException ex) {
195 // expected, not built yet
196 }
197 }
198
199 out.println(program.getBuildStatus());
200 program.build();
201 out.println(program.getBuildStatus());
202
203 assertNotNull(program.createCLKernel("Test"));
204
205 assertTrue(program.isExecutable());
206
207 context.release();
208
209 }
210
211 private void builderImpl(final boolean sync) throws IOException, ClassNotFoundException, InterruptedException {
212 final CLContext context = CLContext.create();
213 CLProgram program = context.createProgram(getClass().getResourceAsStream("testkernels.cl"));
214
215 // same as program.build()
216 program.prepare().build();
217
218 assertTrue(program.isExecutable());
219
220
221 // complex build
222 program.prepare().withOption(ENABLE_MAD)
223 .forDevice(context.getMaxFlopsDevice())
224 .withDefine("RADIUS", 5)
225 .withDefine("ENABLE_FOOBAR")
226 .build();
227
228 assertTrue(program.isExecutable());
229
230 // reusable builder
232 .withOption(ENABLE_MAD)
233 .forDevices(context.getDevices())
234 .withDefine("RADIUS", 5)
235 .withDefine("ENABLE_FOOBAR");
236
237 out.println(builder);
238
239 if( sync ) {
240 // sync build test
241 final CLProgram outerProgram = program;
242
243 builder.setProgram(program).build();
244 assertEquals(outerProgram, program);
245 } else {
246 // async build test
247 final CountDownLatch countdown = new CountDownLatch(1);
248 final CLProgram outerProgram = program;
249
250 final CLBuildListener buildCallback = new CLBuildListener() {
251 @Override
252 public void buildFinished(final CLProgram program) {
253 assertEquals(outerProgram, program);
254 countdown.countDown();
255 }
256 };
257 builder.setProgram(program).build(buildCallback);
258 countdown.await();
259 }
260
261 assertTrue(program.isExecutable());
262
263 // serialization test
264 final File file = tmpFolder.newFile("foobar.builder");
265 final ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
266 builder.save(oos);
267 oos.close();
268
269 // build configuration
270 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
271 final CLBuildConfiguration buildConfig = CLProgramBuilder.loadConfiguration(ois);
272 ois.close();
273
274 assertEquals(builder, buildConfig);
275
276 buildConfig.build(program);
277 assertTrue(program.isExecutable());
278
279 // program configuration
280 ois = new ObjectInputStream(new FileInputStream(file));
281 final CLProgramConfiguration programConfig = CLProgramBuilder.loadConfiguration(ois, context);
282 assertNotNull(programConfig.getProgram());
283 ois.close();
284 program = programConfig.build();
285 assertTrue(program.isExecutable());
286
287 // cloneing
288 assertEquals(builder, builder.clone());
289
290 context.release();
291 }
292
293
294 @Test
295 public void test10BuilderSync() throws IOException, ClassNotFoundException, InterruptedException {
296 builderImpl(true);
297 }
298
299 @Test
300 public void test11BuilderAsync() throws IOException, ClassNotFoundException, InterruptedException {
301 builderImpl(false);
302 }
303
304 private static final String test20KernelSource = "__attribute__((reqd_work_group_size(1, 1, 1))) kernel void foo(float a, int b, short c) { }\n";
305
306 @Test
307 public void test20Kernel() {
308 final CLContext context = CLContext.create();
309
310 try{
311 final CLProgram program = context.createProgram(test20KernelSource).build();
312 assertTrue(program.isExecutable());
313
314 final CLKernel kernel = program.createCLKernel("foo");
315 assertNotNull(kernel);
316
317 final long[] wgs = kernel.getCompileWorkGroupSize(context.getDevices()[0]);
318
319 out.println("compile workgroup size: " + wgs[0]+" "+wgs[1]+" "+wgs[2]);
320
321 assertEquals(1, wgs[0]);
322 assertEquals(1, wgs[1]);
323 assertEquals(1, wgs[2]);
324
325 // put args test
326 assertEquals(0, kernel.position());
327
328 kernel.putArg(1.0f);
329 assertEquals(1, kernel.position());
330
331 kernel.putArg(2);
332 assertEquals(2, kernel.position());
333
334 kernel.putArg((short)3);
335 assertEquals(3, kernel.position());
336
337 try{
338 kernel.putArg(3);
339 fail("exception not thrown");
340 }catch (final IndexOutOfBoundsException expected){ }
341
342 assertEquals(3, kernel.position());
343 assertEquals(0, kernel.rewind().position());
344
345 }finally{
346 context.release();
347 }
348
349 }
350
351 @Test
352 public void test21AllKernels() {
353 final String source = "kernel void foo(int a) { }\n"+
354 "kernel void bar(float b) { }\n";
355
356 final CLContext context = CLContext.create();
357 try{
358 final CLProgram program = context.createProgram(source).build();
359 assertTrue(program.isExecutable());
360
361 final Map<String, CLKernel> kernels = program.createCLKernels();
362 for (final CLKernel kernel : kernels.values()) {
363 out.println("kernel: "+kernel.toString());
364 }
365
366 assertNotNull(kernels.get("foo"));
367 assertNotNull(kernels.get("bar"));
368
369 kernels.get("foo").setArg(0, 42);
370 kernels.get("bar").setArg(0, 3.14f);
371
372
373 }finally{
374 context.release();
375 }
376
377 }
378
379 /**
380 * Test of getting new kernel work group information, including those from OpenCL versions newer than 1.1.
381 */
382 @Test
384 final CLContext context = CLContext.create();
385
386 try{
387 final CLProgram program = context.createProgram(test20KernelSource).build();
388 assertTrue(program.isExecutable());
389
390 final CLKernel kernel = program.createCLKernel("foo");
391 assertNotNull(kernel);
392
393 final long pwgsm = kernel.getPreferredWorkGroupSizeMultiple(context.getDevices()[0]);
394 out.println("preferred workgroup size multiple: " + pwgsm);
395
396 final long pms = kernel.getPrivateMemSize(context.getDevices()[0]);
397 out.println("private mem size: " + pms);
398 }finally{
399 context.release();
400 }
401 }
402
403// @Test
404 public void test60Load() throws IOException, ClassNotFoundException, InterruptedException {
405 for(int i = 0; i < 100; i++) {
406 test02RebuildProgram();
407 test11BuilderAsync();
408 test03ProgramBinaries();
409 }
410 }
411
412 public static void main(final String[] args) throws IOException {
413 final String tstname = CLProgramTest.class.getName();
414 org.junit.runner.JUnitCore.main(tstname);
415 }
416
417}
CLContext is responsible for managing objects such as command-queues, memory, program and kernel obje...
Definition: CLContext.java:79
CLDevice[] getDevices()
Returns all devices associated with this CLContext.
Definition: CLContext.java:638
CLProgram createProgram(final String src)
Creates a program from the given sources, the returned program is not build yet.
Definition: CLContext.java:243
static CLContext create()
Creates a context on all available devices (CL_DEVICE_TYPE_ALL).
Definition: CLContext.java:139
CLDevice getMaxFlopsDevice()
Returns the device with maximal FLOPS from this context.
Definition: CLContext.java:611
CLPlatform getPlatform()
Returns the CLPlatform this context is running on.
Definition: CLContext.java:569
This object represents an OpenCL device.
Definition: CLDevice.java:53
Main Exception type for runtime OpenCL errors and failed function calls (e.g.
String getCLErrorString()
Returns a human readable String for the OpenCL error code.
High level abstraction for an OpenCL Kernel.
Definition: CLKernel.java:53
CLKernel rewind()
Resets the argument index to 0.
Definition: CLKernel.java:158
long[] getCompileWorkGroupSize(final CLDevice device)
Returns the work-group size specified by the attribute((reqd_work_group_size(X, Y,...
Definition: CLKernel.java:342
int position()
Returns the argument index used in the relative putArt(...) methods.
Definition: CLKernel.java:166
CLKernel putArg(final CLMemory<?> value)
Definition: CLKernel.java:107
long getPrivateMemSize(final CLDevice device)
Returns the number of bytes of private memory used by each work item in the kernel.
Definition: CLKernel.java:370
long getPreferredWorkGroupSizeMultiple(final CLDevice device)
Returns the preferred multiple of workgroup size to use for kernel launch.
Definition: CLKernel.java:360
CLProgramBuilder is a helper for building programs with more complex configurations or building multi...
static CLBuildConfiguration createConfiguration()
Creates a new CLBuildConfiguration.
void test22KerneWorkGrouplInfo()
Test of getting new kernel work group information, including those from OpenCL versions newer than 1....
static void main(final String[] args)
Represents a OpenCL program executed on one or more CLDevices.
Definition: CLProgram.java:64
String getBuildLog()
Returns the build log of this program on all devices.
Definition: CLProgram.java:538
boolean isExecutable()
Returns true if the build status 'BUILD_SUCCESS' for at least one device of this program exists.
Definition: CLProgram.java:570
CLProgramConfiguration prepare()
Prepares the build for this program by returning a new CLProgramConfiguration.
Definition: CLProgram.java:403
Map< CLDevice, byte[]> getBinaries()
Returns the binaries for this program in an ordered Map containing the device as key and the program ...
Definition: CLProgram.java:624
String getSource()
Returns the source code of this program.
Definition: CLProgram.java:609
CLProgram build()
Builds this program for all devices associated with the context.
Definition: CLProgram.java:226
CLDevice[] getCLDevices()
Returns all devices associated with this program.
Definition: CLProgram.java:507
Map< CLDevice, Status > getBuildStatus()
Returns the build status enum of this program for each device as Map.
Definition: CLProgram.java:558
Map< String, CLKernel > createCLKernels()
Creates all kernels of this program and stores them a Map with the kernel name as key.
Definition: CLProgram.java:430
void release()
Releases this program with its kernels.
Definition: CLProgram.java:478
CLKernel createCLKernel(final String kernelName)
Creates a kernel with the specified kernel name.
Definition: CLProgram.java:410
Configures the mapping process.
Definition: CLMemory.java:402
static Status valueOf(final int clBuildStatus)
Definition: CLProgram.java:746
Java bindings to OpenCL, the Open Computing Language.
Definition: CL.java:26
static final int CL_INVALID_PROGRAM_EXECUTABLE
Define "CL_INVALID_PROGRAM_EXECUTABLE" with expression '-45', CType: int.
Definition: CL.java:201
Configuration representing everything needed to build an OpenCL program.
CLBuildConfiguration forDevices(CLDevice... devices)
Adds the devices as build target.
void save(ObjectOutputStream oos)
Saves this configuration to the ObjectOutputStream.
CLBuildConfiguration clone()
Clones this configuration.
CLBuildConfiguration withDefine(String name)
Adds the definition to the build configuration.
CLProgramConfiguration setProgram(CLProgram program)
Sets the program which should be build.
CLBuildConfiguration withOption(String option)
Adds the compiler option to the build configuration.
CLProgram build()
Builds or rebuilds a program.
CLProgramConfiguration forDevice(CLDevice device)
Adds the device as build target.
CLProgramConfiguration withDefine(String name)
Adds the definition to the build configuration.
CLProgramConfiguration withOption(String option)
Adds the compiler option to the build configuration.