1

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.

Ryan Moser
  • 123
  • 1
  • 12

0 Answers0