在本教程的指导下,我正在使用 Xcode 4.5.1 和 Grand Central Dispatch 在 OpenCL 中开发一个加速组件。
完整的内核在 GPU 上不断失败,发出信号 SIGABRT。除此之外,我无法在解释错误方面取得太大进展。
但是我打破了内核的各个方面进行测试,我发现了一些非常特殊的事情,涉及将某些值分配给循环内数组中的位置。
测试场景:给每个线程一个固定范围的数组索引来初始化。
kernel void zero(size_t num_buckets, size_t positions_per_bucket, global int* array) {
size_t bucket_index = get_global_id(0);
if (bucket_index >= num_buckets) return;
for (size_t i = 0; i < positions_per_bucket; i++)
array[bucket_index * positions_per_bucket + i] = 0;
}
上述内核失败。但是,当我分配 1 而不是 0 时,内核成功(并且我的主机代码打印出 1 的数组)。基于对各种整数值的少量测试,我只遇到了 0 和 -1 的问题。
我试图用 1-1、(int) 0 等来超越编译器,但没有成功。不过,将零作为内核参数传入是可行的。
赋值为零确实在 for 循环的上下文之外起作用:
array[bucket_index * positions_per_bucket] = 0;
上述发现在两台不同配置的机器上得到证实。(OSX 10.7 + GeForce,OSX 10.8 + Radeon。)此外,内核在 CL_DEVICE_TYPE_CPU 上运行时没有问题——它只是在 GPU 上。
显然,发生了一些荒谬的事情,而且一定是在我的尽头,因为“零”不能被打破。希望这很简单。谢谢您的帮助。
主机代码:
#include <stdio.h>
#include <OpenCL/OpenCL.h>
#include "zero.cl.h"
int main(int argc, const char* argv[]) {
dispatch_queue_t queue = gcl_create_dispatch_queue(CL_DEVICE_TYPE_GPU, NULL);
size_t num_buckets = 64;
size_t positions_per_bucket = 4;
cl_int* h_array = malloc(sizeof(cl_int) * num_buckets * positions_per_bucket);
cl_int* d_array = gcl_malloc(sizeof(cl_int) * num_buckets * positions_per_bucket, NULL, CL_MEM_WRITE_ONLY);
dispatch_sync(queue, ^{
cl_ndrange range = { 1, { 0 }, { num_buckets }, { 0 } };
zero_kernel(&range, num_buckets, positions_per_bucket, d_array);
gcl_memcpy(h_array, d_array, sizeof(cl_int) * num_buckets * positions_per_bucket);
});
for (size_t i = 0; i < num_buckets * positions_per_bucket; i++)
printf("%d ", h_array[i]);
printf("\n");
}