Skip to content

Latest commit

 

History

History
42 lines (23 loc) · 2.63 KB

aparapi-private-memory-space.md

File metadata and controls

42 lines (23 loc) · 2.63 KB

私有缓冲区

在 Aparapi 内核中使用私有缓冲区

介绍

私有权限标识符 private 可以限定某个字段中的数据不与其它内核实例共享, 不能被其它内核访问. 对于非数组字段无需声明便是如此; 数组字段必须明确声明才能使其变为私有内存.

私有缓冲区一般只适合存放小型数组. 对于某些算法来说这是必需的, 例如排序算法必须拷贝一份原数组数据.

细节

Aparapi 中提供了两套将内核转换为 OpenCL 代码时标记某个内核字段属于私有缓冲区的机制. 其一, 可以在字段名增加一个缓冲区大小长度:

protected short[] myBuffer_$private$32 = new short[32];

其二, 使用注解 Kernel.PrivateMemorySpace:

protected @PrivateMemorySpace(32) short[] myBuffer = new short[32];

应优先使用注解方式.

OpenCL 要求任何内核私有数组大小在编译时就固定下来, 所以单一内核子类不可能支持变长缓冲区. 实际应用时可能需要创建多个缓冲区大小不同的内核子类.

当然, 创建一个缓冲区特别大的内核子类直接满足各种情况也不是不行.

由于私有缓冲区不共享, 会比相同容量的局部或全局缓冲区占用更多显存, 应当尽量少用, 用到也应尽量缩小私有缓冲区长度, 否则可能在低端 GPU 上执行出错.

然而, 私有缓冲区是所有 OpenCL 内存空间中速度最快的. 即使内核不需要修改缓冲区数据, 使用共享缓冲区就足够了, 也可以使用私有缓冲区来提高运行速度, 比如提供一个小型查找表来代替昂贵的函数调用.

如果不做修改, 带有私有缓冲区的内核可能在 Java 线程池模式下无法工作, 因为缓冲区会被多个线程共享. 我们为这种情况提供了一个机制, 允许私有缓冲区在 Java 线程池模式下还能继续安全使用.

Kernel.NoCL 注解用来标记标记某些代码必须在 Java 线程池模式下工作, 在 GPU 运行时不会被调用. 在 Kernel.run() 方法上增加 NoCL 注解, 将使私有缓冲区变为从 ThreadLocal 中获取的数组. 这对 OpenCL 的执行没有影响, 但能保证代码运行于 Java 线程池时安全执行.

在示例项目的 com.aparapi.sample.median 包给出了一个中值图像过滤器示例. 它用到一个私有缓冲区储存像素数据, 对本地窗口中的像素使用 "破坏性" 的中值算法. 这个例子还演示了如何使用 ThreadLocal 来保证代码运行于非 OpenCL 模式时的正确执行.

http://code.google.com/p/aparapi/source/browse/trunk/samples/median/src/com/amd/aparapi/sample/median/MedianDemo.java