Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 20
JavaCLGenerator
If you're doing OpenCL stuff from Java, you don't want to miss out on the JavaCL Generator : it integrates your OpenCL code to your Java code seamlessly !
The JavaCL Generator is a Maven plugin that automatically parses any OpenCL source file present in src/main/opencl and generates a Java wrapper class that lets you call the kernel very easily from Java.
In the rest of this page, we'll consider the following kernels (from the tutorial), saved in the file src/main/opencl/tutorial/TutorialKernels.cl:
__kernelvoidadd_floats(__globalconstfloat*a, __globalconstfloat*b, __globalfloat*out, intn) {
inti=get_global_id(0);
if (i >= n)
return;
out[i] =a[i] +b[i];
}
__kernelvoidfill_in_values(__globalfloat*a, __globalfloat*b, intn) {
inti=get_global_id(0);
if (i >= n)
return;
a[i] =cos((float)i);
b[i] =sin((float)i);
}This is the configuration needed in your pom.xml to make use of the generator (it adds up to the JavaCL dependency and NativeLibs4Java repository configuration) :
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>com.nativelibs4java</groupId>
<artifactId>javacl-generator</artifactId>
<version>1.0.0-RC1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>At each Maven compilation, the JavaCL Generator plugin will automatically generate the following wrapper as target/generated-sources/main/java/tutorial/TutorialKernels.java :
packagecom.mycompany;
importcom.nativelibs4java.opencl.CLAbstractUserProgram;
importcom.nativelibs4java.opencl.CLBuffer;
importcom.nativelibs4java.opencl.CLBuildException;
importcom.nativelibs4java.opencl.CLContext;
importcom.nativelibs4java.opencl.CLEvent;
importcom.nativelibs4java.opencl.CLKernel;
importcom.nativelibs4java.opencl.CLProgram;
importcom.nativelibs4java.opencl.CLQueue;
importjava.io.IOException;
/// Wrapper around the OpenCL program TutorialKernelspublicclassTutorialKernelsextendsCLAbstractUserProgram {
publicTutorialKernels(CLContextcontext) throwsIOException {
super(context, readRawSourceForClass(TutorialKernels.class));
}
publicTutorialKernels(CLProgramprogram) throwsIOException {
super(program, readRawSourceForClass(TutorialKernels.class));
}
CLKerneladd_floats_kernel;
publicsynchronizedCLEventadd_floats(CLQueuecommandQueue, CLBuffer<Float > a, CLBuffer<Float > b, CLBuffer<Float > out, intn, intglobalWorkSizes[], intlocalWorkSizes[], CLEvent... eventsToWaitFor) throwsCLBuildException {
if (add_floats_kernel == null) add_floats_kernel = createKernel("add_floats");
add_floats_kernel.setArgs(a, b, out, n);
returnadd_floats_kernel.enqueueNDRange(commandQueue, globalWorkSizes, localWorkSizes, eventsToWaitFor);
}
CLKernelfill_in_values_kernel;
publicsynchronizedCLEventfill_in_values(CLQueuecommandQueue, CLBuffer<Float > a, CLBuffer<Float > b, intn, intglobalWorkSizes[], intlocalWorkSizes[], CLEvent... eventsToWaitFor) throwsCLBuildException {
if (fill_in_values_kernel == null) fill_in_values_kernel = createKernel("fill_in_values");
fill_in_values_kernel.setArgs(a, b, n);
returnfill_in_values_kernel.enqueueNDRange(commandQueue, globalWorkSizes, localWorkSizes, eventsToWaitFor);
}
}With the generator, you get compile-time checks of the argument types of your kernels, with complete synchronization with your OpenCL sources.
The alternative is to call CLKernel.setArgs(Object...) on your kernels prior to enqueuing them for execution, and it's dangerous for you might not be using the correct number of arguments or the correct argument types : your program will then crash at runtime or just be buggy and make you cry.
Remember why you're using Java/Scala instead of Php/Ruby ? Get the free compile-time checks for OpenCL now ;-)
Compare this (with the generator) :
TutorialKernelskernels = newTutorialKernels(context);
int[] globalSizes = newint[] { n };
CLEventfillEvt = kernels.fill_in_values(queue, a, b, n, globalSizes, null);
CLEventaddEvt = kernels.add_floats(queue, a, b, out, n, globalSizes, null, fillEvt);To that (without the generator) :
// Read the program sources and compile them :Stringsrc = IOUtils.readText(JavaCLTutorial1.class.getResource("TutorialKernels.cl"));
CLProgramprogram = context.createProgram(src);
CLKernelfillValuesKernel = program.createKernel("fill_in_values");
CLKerneladdFloatsKernel = program.createKernel("add_floats");
// Get and call the kernel :int[] globalSizes = newint[] { n };
fillValuesKernel.setArgs(a, b, n);
CLEventfillEvt = fillValuesKernel.enqueueNDRange(queue, globalSizes);
addFloatsKernel.setArgs(a, b, out, n);
CLEventaddEvt = addFloatsKernel.enqueueNDRange(queue, globalSizes, fillEvt);Well, it's just a derivative of [JNAerator] (which is written by the same https://ochafik.com/ original author as JavaCL ;-))
The generated Java sources (OpenCL wrappers) are explicitly left free of any copyright/licensing bullshit from nativelibs4java, so you can do whatever you want with them (they mainly reflect your OpenCL code anyway).
The generator itself, however, is currently licensed under the LGPL, as it is a derivative of [JNAerator] (it is planned to switch it to the BSD license, CreditsAndLicense as JavaCL itself, but JNAerator needs to decouple from JNA first so it may take a while...).