0

私はOpenCLでハウスドルフ距離を実装しようとしていますが、次のカーネルがその基礎を形成しているか、完全に実装する必要があるため、そうしていると思います。そうは言っても、私はいくつかの提案を得ることができますか、それともこのカーネルを最適化する方法はありますか?基本的に、ヘルパー関数を呼び出すカーネル関数のforループを削除するにはどうすればよいですか。

OpenCLカーネルとそのヘルパー関数:

void helper( int a_1, __global int* b_1, __global int* c_1 ){
        int i = get_global_id(0);
        c_1[i] = a_1 - b_1[i];
}

__kernel void test_call( __global int* a,             //input buffer of size [100000, 1]
                         __global int* b,             //input buffer of size [100000, 1]
                         __global int* c ){           //output buffer of size [100000, 1]
        for ( int iter = 0 ; iter < 100000 ; iter++ ){
                helper ( a[iter], b, c );
                // once array c is obtained by calling the above function,
                // it will be used in further processing that will take place inside 
                // this for loop itself
}

基本的に、ここで私が行おうとしているのは、入力バッファー「a」の各要素を入力バッファー「b」の各要素から減算することです。複雑さはO(n 2)になります。

ちなみに、この素​​朴な実装自体は2.5秒以内に結果を生成します。これのシリアル実装は、実行を完了するのに数分かかります。

4

1 に答える 1

3

タイリングスキームを使用することで、コードを改善できると思います。現在の実装では、すべての作業項目がバッファ'a'のすべての値をロードします。現時点では、同期されていない方法でこれを行っています。タイリングスキームを使用すると、デバイスにオフチップメモリ​​から「a」の各値を1回だけロードさせることで、キャッシュアーキテクチャをより有効に活用できる可能性があります。

このスキームはここで最もよく説明されています:http ://software.intel.com/file/24571 (PDFファイル)。

あなたの場合、タイル並列アプローチは次の擬似コードのようになります。

forall values of b in parallel {
    foreach tile q {
        forall work_items p in work_group in parallel {
            local[p] = a[q*tile_size + p]
        }
        synchronize work items in work group
        foreach body j in tile q {
            c[i] = local[j] - b[i];
        }
        synchronize work items in work group
    }
}

重要なアイデアは、すべてのwork_itemが、同じグループ内の他のwork_itemsによってすでにロードされているバッファー「a」の値を利用できることです。'a'のすべてのエントリは、(理想的には)メモリから1回だけフェッチされ、キャッシュからtile_size-1回フェッチされます。

于 2012-10-24T10:50:05.713 に答える