Question and Essential Details
I'm experimenting with Aparapi and I wanted to write a utility class to handle common operations; e.g.
public final class GPUUtils {
public static void add(final double[] sum, final double[] a, final double[] b, final int i) {
sum[i] = a[i] + b[i];
}
}
I wasn't sure whether this would work, as the website's documentation says it won't, but I've found that the website's documentation is rather out-of-date; e.g., Aparapi does indeed support 2D and 3D arrays now, but the documentation says otherwise.
To test this, I wrote the following test:
@Test
void testAdd() {
final double[] sum = new double[8];
final double[] a = new double[] { 1, 2, 3, 4, 5, 6, 7, 8};
final double[] b = new double[] { 1, 2, 3, 4, 5, 6, 7, 8};
final Kernel kernel = new Kernel() {
@Override
public void run() {
GPUUtils.add(sum, a, b, this.getGlobalId());
}
};
kernel.execute(Range.create(8));
final double[] expected = new double[] { 2, 4, 6, 8, 10, 12, 14, 16 };
assertArrayEquals(expected, sum);
kernel.dispose();
}
Which runs perfectly fine aside from the fact that the test fails because sum
is never modified (it's just [0, 0, 0, 0, 0, 0, 0, 0])
So, my question is this: is Aparapi meant to support static method calls/calls to added instance methods (see below for details on added instance methods)? Or is the fact that this isn't failing with an exception a bug?
If it doesn't support static method calls, I would expect an exception to be thrown when we go to try and create OpenCL.
Stuff I Tried:
I set the VM arg to print the generated OpenCL (-Dcom.aparapi.enableShowGeneratedOpenCL=true) and I get the following:
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
typedef struct This_s{
__global double *val$sum;
__global double *val$a;
__global double *val$b;
int passid;
}This;
int get_pass_id(This *this){
return this->passid;
}
void the_canonical_classname_GPUUtils__add( __global double* sum, __global double* a, __global double* b, int i){
sum[i] = a[i] + b[i];
return;
}
__kernel void run(
__global double *val$sum,
__global double *val$a,
__global double *val$b,
int passid
){
This thisStruct;
This* this=&thisStruct;
this->val$sum = val$sum;
this->val$a = val$a;
this->val$b = val$b;
this->passid = passid;
{
the_canonical_classname_GPUUtils__add(this->val$sum, this->val$a, this->val$b, get_global_id(0));
return;
}
}
Now, I don't know C
or OpenCL
, but to the untrained eye this looks o.k.
Another thing I tried was extending Kernel
to a different abstract class
locally and adding the utility methods there as instance methods.
Example:
public abstract class AparapiUtility extends Kernel {
void add(final double[] sum, final double[] a, final double[] b, final int i) {
sum[i] = a[i] + b[i];
}
}
The same test slightly modified with an AparapiUtility
anonymous inner-class rather than a Kernel
, still failed and I received the following OpenCL:
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
typedef struct This_s{
__global double *val$sum;
__global double *val$a;
__global double *val$b;
int passid;
}This;
int get_pass_id(This *this){
return this->passid;
}
void the_canonical_classname_AparapiUtility__add(This *this, __global double* sum, __global double* a, __global double* b, int i){
sum[i] = a[i] + b[i];
return;
}
__kernel void run(
__global double *val$sum,
__global double *val$a,
__global double *val$b,
int passid
){
This thisStruct;
This* this=&thisStruct;
this->val$sum = val$sum;
this->val$a = val$a;
this->val$b = val$b;
this->passid = passid;
{
the_canonical_classname_AparapiUtility__add(this, this->val$sum, this->val$a, this->val$b, get_global_id(0));
return;
}
}
which, again, looks fine.