github链接
Aparapi 主要是用jni调用openCL封装库, 有点像javacv和opencv的感觉,那么我为什么不用JavaCL呢,因为SparkCL用的是Aparapi,所以惯性惰性就用这个了。(有人说javaCL更多底层调用,Aparapi注重high-level的)
Kernel.java
最核心的就是这个,sparkCL也是通过override这里面的run函数来实现的。
另外,线程的并行不是用implement runnable或者extends Thread来实现的,而是利用java.util.concurrent这个包。
/**
* A <i>kernel</i> encapsulates a data parallel algorithm that will execute either on a GPU
* (through conversion to OpenCL) or on a CPU via a Java Thread Pool.
* <p>
* To write a new kernel, a developer extends the <code>Kernel</code> class and overrides the <code>Kernel.run()</code> method.
* To execute this kernel, the developer creates a new instance of it and calls <code>Kernel.execute(int globalSize)</code> with a suitable 'global size'. At runtime
* Aparapi will attempt to convert the <code>Kernel.run()</code> method (and any method called directly or indirectly
* by <code>Kernel.run()</code>) into OpenCL for execution on GPU devices made available via the OpenCL platform.
* <p>
* Note that <code>Kernel.run()</code> is not called directly. Instead,
* the <code>Kernel.execute(int globalSize)</code> method will cause the overridden <code>Kernel.run()</code>
* method to be invoked once for each value in the range <code>0...globalSize</code>.
* <p>
* On the first call to <code>Kernel.execute(int _globalSize)</code>, Aparapi will determine the EXECUTION_MODE of the kernel.
* This decision is made dynamically based on two factors:
* <ol>
* <li>Whether OpenCL is available (appropriate drivers are installed and the OpenCL and Aparapi dynamic libraries are included on the system path).</li>
* <li>Whether the bytecode of the <code>run()</code> method (and every method that can be called directly or indirectly from the <code>run()</code> method)
* can be converted into OpenCL.</li>
* </ol>
* <p>
* Below is an example Kernel that calculates the square of a set of input values.
* <p>
* <blockquote><pre>
* class SquareKernel extends Kernel{
* private int values[];
* private int squares[];
* public SquareKernel(int values[]){
* this.values = values;
* squares = new int[values.length];
* }
* public void run() {
* int gid = getGlobalID();
* squares[gid] = values[gid]*values[gid];
* }
* public int[] getSquares(){
* return(squares);
* }
* }
* </pre></blockquote>
* <p>
* To execute this kernel, first create a new instance of it and then call <code>execute(Range _range)</code>.
* <p>
* <blockquote><pre>
* int[] values = new int[1024];
* // fill values array
* Range range = Range.create(values.length); // create a range 0..1024
* SquareKernel kernel = new SquareKernel(values);
* kernel.execute(range);
* </pre></blockquote>
* <p>
* When <code>execute(Range)</code> returns, all the executions of <code>Kernel.run()</code> have completed and the results are available in the <code>squares</code> array.
* <p>
* <blockquote><pre>
* int[] squares = kernel.getSquares();
* for (int i=0; i< values.length; i++){
* System.out.printf("%4d %4d %8d\n", i, values[i], squares[i]);
* }
* </pre></blockquote>
* <p>
* A different approach to creating kernels that avoids extending Kernel is to write an anonymous inner class:
* <p>
* <blockquote><pre>
*
* final int[] values = new int[1024];
* // fill the values array
* final int[] squares = new int[values.length];
* final Range range = Range.create(values.length);
*
* Kernel kernel = new Kernel(){
* public void run() {
* int gid = getGlobalID();
* squares[gid] = values[gid]*values[gid];
* }
* };
* kernel.execute(range);
* for (int i=0; i< values.length; i++){
* System.out.printf("%4d %4d %8d\n", i, values[i], squares[i]);
* }
*
* </pre></blockquote>
* <p>
*
* @author gfrost AMD Javalabs
* @version Alpha, 21/09/2010
*/