package com.nativelibs4java.opencl;
import static com.nativelibs4java.opencl.JavaCL.createBestContext;
import static com.nativelibs4java.util.NIOUtils.directFloats;
import static org.junit.Assert.assertEquals;
import org.bridj.*;
import static org.bridj.Pointer.*;
import java.nio.FloatBuffer;
import org.junit.BeforeClass;
import org.junit.Test;
import com.nativelibs4java.util.NIOUtils;
public class OpenCL4JavaBasicTest {
public static final double ABSOLUTE_FLOAT_ERROR_TOLERANCE = 2e-4;
public static final double RELATIVE_FLOAT_ERROR_TOLERANCE = 5e-8;
@Test
public void simpleTest() {
try {
CLContext context = createBestContext();
int dataSize = 10000;
String src = "\n" +
"__kernel void aSinB( \n" +
" __global const float* a, \n" +
" __global const float* b, \n" +
" __global float* output) \n" +
"{ \n" +
" int i = get_global_id(0); \n" +
" output[i] = a[i] * sin(b[i]) + 1; \n" +
"} \n";
CLProgram program = context.createProgram(src).build();
CLKernel kernel = program.createKernel("aSinB");
CLQueue queue = context.createDefaultQueue();
/// Create direct NIO buffers and fill them with data in the correct byte order
Pointer<Float> a = allocateFloats(dataSize).order(context.getKernelsDefaultByteOrder());
Pointer<Float> b = allocateFloats(dataSize).order(context.getKernelsDefaultByteOrder());
for (int i = 0; i < dataSize; i++) {
float value = (float)i;
a.set(i, value);
b.set(i, value);
}
// Allocate OpenCL-hosted memory for inputs and output,
// with inputs initialized as copies of the NIO buffers
CLBuffer<Float> memIn1 = context.createBuffer(CLMem.Usage.Input, a, true); // 'true' : copy provided data
CLBuffer<Float> memIn2 = context.createBuffer(CLMem.Usage.Input, b, true);
CLBuffer<Float> memOut = context.createBuffer(CLMem.Usage.Output, Float.class, dataSize);
// Bind these memory objects to the arguments of the kernel
kernel.setArgs(memIn1, memIn2, memOut);
// Ask for execution of the kernel with global size = dataSize
// and workgroup size = 1
kernel.enqueueNDRange(queue, new int[]{dataSize});
// Wait for all operations to be performed
queue.finish();
// Copy the OpenCL-hosted array back to RAM
Pointer<Float> output = memOut.read(queue);
// Compute absolute and relative average errors wrt Java implem
double totalAbsoluteError = 0, totalRelativeError = 0;
for (int i = 0; i < dataSize; i++) {
float expected = i * (float) Math.sin(i) + 1;
float result = output.get(i);
double d = result - expected;
if (expected != 0) {
totalRelativeError += d / expected;
}
totalAbsoluteError += d < 0 ? -d : d;
}
double avgAbsoluteError = totalAbsoluteError / dataSize;
double avgRelativeError = totalRelativeError / dataSize;
System.out.println("Average absolute error = " + avgAbsoluteError);
System.out.println("Average relative error = " + avgRelativeError);
assertEquals("Bad relative error", 0, avgRelativeError, RELATIVE_FLOAT_ERROR_TOLERANCE);
assertEquals("Bad absolute error", 0, avgAbsoluteError, ABSOLUTE_FLOAT_ERROR_TOLERANCE);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}