Skip to content

Latest commit

 

History

History
96 lines (55 loc) · 3.33 KB

aparapi-kernel-guidelines.md

File metadata and controls

96 lines (55 loc) · 3.33 KB

内核编程指南

哪些代码可以被转换为 OpenCL

遵守一些约定可以提高将 Java 代码转换为 OpenCL 的成功率.

下面的指南/限制仅针对 Kernel.run() 和其可及方法, 其它 Java 方法不受相关约束.

部分指南/限制可能在未来的 Aparapi 中移除/放松.

数据类型

只有 Java 值类型中的 boolean, byte, short, int, long, float 和对应的一维数组受支持, 对 double 的支持视情况而定. Aparapi 会在运行时检查显卡, 驱动和 OpenCL 版本等信息来决定是否支持 double. 如果你的平台不支持 double, Aparapi 将会退回至 Java 线程池模式运行.

值类型 char 不受支持.

字段

内核代码可以 读写 值类型数组字段中的数据.

需要注意的是 Java 为了处理匿名内部类中的值类型数组可能会创建隐藏字段, 就好像它们是内核类的字段一样.

值类型数组字段只能由内核代码 . 因为内核和其可及代码是以不确定的顺序并行执行的, 即使是在 Java 线程池模式下运行, 也不推荐对值类型数组结果进行修改.

静态常量字段可以被内核代码 .

静态变量字段不支持 读写, 请考虑将其常量化.

数组

只有一维数组受支持.

数组不能被其它局部变量引用或作为形参传递给方法.

不支持 Java 5新增的 foreach 语法, 因为这会对原数组进行浅拷贝.

方法

直接通过 Java 对象而不是内核实例对其它数据进行操作都会使 Aparapi 不能把代码转换为 OpenCL.

上述规则的例外情况是, 你可以调用对象数组内元素的 getter 和 setter.

Aparapi 不支持静态方法.

不支持递归, 不论是直接还是间接的. Aparapi 会对 this 递归做静态检查, 但是开发者应自己注意而不是完全交给 Aparapi.

带有变长形参的方法不受支持.

重载方法 (同名不同参) 方法不受支持. 这是因为 OpenCL 基于 C99 而 C99 不支持方法重载.

内核基类内包含对几乎所有 java.lang.Math 类方法的封装层. 当 Aparapi 运行在线程池模式时调用这些方法会委托至 java.lang.Math, 而运行在 OpenCL 模式时会被翻译成等价的 OpenCL.

其它限制

异常处理不受支持.

实例化不受支持, 无论是数组或对象.

同步块和同步方法不受支持.

只有简单循环体和条件语句受支持. switch, breakcontinue 不受支持.

不能将表达式返回值或方法返回值用于变量的初始化赋值. 例如下面的代码就不能运行至 GPU:

int foo(int a) {
   // . . .
}
public void run() {
  int z;
  foo(z = 3);
}

这应被视为一种错误. 作为变通, 你应在变量初始化时就显式赋值, 即使是初始化为0.

留意代码副作用

OpenCL 基于 C99, 规范上与 Java 有很大不同, 不能认为所有 Java 代码都能在 OpenCL 中产生相同结果. 例如, Java 明确规定了下面的代码

arra[i++] = arrb[i++];

等价于

arra[i] = arrb[i+1];
i += 2;

但 C99/OpenCL 标准并没有做出如上规范, 所以这段代码的运行结果是未定义的.

运行时异常

当运行在 GPU 模式时, 数组越界访问不会导致 ArrayIndexOutOfBoundsException, 除0运算等也不会抛出 ArithmeticException. 这些行为的结果是无法预料的.