Skip to content

CallingOpenCLKernelsFromJava

Olivier Chafik edited this page Nov 10, 2022 · 3 revisions

How to call OpenCL Kernels with JavaCL

Introduction

Let's assume you wrote the following kernel in file com/mypackage/MyProgram.cl:

__kernel void myKernel(__global const float* input, __global float* output, float multFactor) {
   int i = get_global_id(0);
   output[i] = input[i] * multFactor;
}

Then you have two ways to call it from JavaCL : a generic dynamic way, which is loosely typed, and a hard-typed precompiled way.

Common Host Setup code

CLContext context = ... ; // e.g. JavaCL.createBestContext()
CLQueue queue = ... ; // e.g. context.createDefaultQueue()

int dataSize = 128;
CLBuffer<Float> input = context.createFloatBuffer(CLMem.Usage.Input, dataSize);
CLBuffer<Float> output = context.createFloatBuffer(CLMem.Usage.Output, dataSize);
float multFactor = 0.5f;

Generic 'Dynamic' Call

Setup the kernel :

String sources = ... ; // read the source file from resources / from a file
CLProgram program = context.createProgram(sources).build();
CLKernel kernel = program.createKernel("myKernel");

Then call it :

CLEvent kernelCompletion;
// The same kernel can be safely used by different threads, as long as setArgs + enqueueNDRange are in a synchronized block
synchronized (kernel) {
    // setArgs will throw an exception at runtime if the types / sizes of the arguments are incorrect
    kernel.setArgs(input, output, multFactor);

   // Ask for 1-dimensional execution of length dataSize, with auto choice of local workgroup size :
    kernelCompletion = kernel.enqueueNDRange(queue, new int[] { dataSize }, null);
}
kernelCompletion.waitFor(); // better not to wait for it but to pass it as a dependent event to some other queuable operation (CLBuffer.read, for instance)

Read [UnderstandOpenCLKernelArguments] to know which JavaCL type is appropriate for a given OpenCL C type.

Autogenerated Type-Safe Kernel Wrapper

This documentation only covers the wrapper autogeneration from within the Maven build system, but a standalone utility is also available and can be documented on demand.

Maven Project Setup

Start by adding the following required repositories to your project's pom.xml file :

<repositories>
  <repository>
    <id>nativelibs4java</id>
    <url>https://nativelibs4java.sourceforge.net/maven</url>
  </repository>
  <repository>
    <id>jnaerator</id>
    <url>https://jnaerator.sourceforge.net/maven</url>
  </repository>
</repositories>

Setup the JavaCL Generator Maven Plugin :

<plugin>
  <groupId>com.nativelibs4java</groupId>
  <artifactId>javacl-generator</artifactId>
  <version>1.0-SNAPSHOT</version>
  <executions>
    <execution>
  	<phase>generate-sources</phase>
  	<goals>
  	  <goal>compile</goal>
  	</goals>
    </execution>
  </executions>
</plugin>

Use the autogenerated kernel wrappers

Start by setting up the kernel :

// The JavaCL Generator Maven Plugin will autogenerate a MyProgram class out of the MyProgram.cl file :
import com.mypackage.MyProgram;
...
MyProgram myProgram = new MyProgram(context);

Then call it :

// This call is statically typed and thread-safe :
CLEvent kernelCompletion = myProgram.myKernel(queue, input, output, multFactor, new int[] { dataSize }, null);