このチュートリアルに従って、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;
}
上記のカーネルは失敗します。ただし、0 の代わりに 1 を割り当てると、カーネルは成功します (ホスト コードは 1 の配列を出力します)。さまざまな整数値に対するいくつかのテストに基づいて、0 と -1 でのみ問題が発生しました。
1-1、(int) 0 などでコンパイラの裏をかこうとしましたが、成功しませんでした。ただし、カーネル引数としてゼロを渡すことは機能しました。
ゼロへの割り当ては、for ループのコンテキスト外で機能します。
array[bucket_index * positions_per_bucket] = 0;
上記の調査結果は、構成の異なる 2 台のマシンで確認されました。(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");
}