this linkで説明した最初の問題の続きを取り上げます。還元の最終的な方法
OpenCLで複数の合計を減らす方法を適用したいと思います(私のGPUデバイスはOpenCL 1.2のみをサポートしています)。
現在のところ、1回の合計削減(つまり、1回の繰り返し )のバージョンを作成しました。このバージョンでは、簡単にするために、順次CPUループを使用して各部分合計の合計を計算し、合計の最終値を取得しました。
私の前例のアドバイスから、私の問題は、NDRangeKernel
関数をもう一度呼び出して(つまり、2度目のカーネルコードを実行して)最終合計を実行する方法がわからないことです。
実際、2回目の呼び出しでは、部分的な合計(それ自体が最初の呼び出しNDRangeKernel
から計算されたもの)の合計を得るために、常に同じ問題に直面します。再帰的な問題です。
入力配列のサイズが10240000
で、WorkGroup size
が16
の場合、10000*2^10/2^4 = 10000*2^6 = 640000 WorkGroups
となります。
だから、最初の呼び出しの後、私は640000 partial sums
を取得する:すべてのこれらの部分和の最終サメイションをどのように扱いますか?私はカーネルコード別の時間を呼び出すと、例えば、WorkGroup size = 16
とグローバルsize = 640000
、私はnWorkGroups = 640000/16 = 40000 partial sums
を取得しますので、私はカーネルコードをもう一度呼び出し、nWorkGroups < WorkGroup size
まで、このプロセスを繰り返す必要があります。誰かがカーネルのものを、この上記のコードスニペットを説明できる場合
たぶん私は非常によく第二段階、「2段減速」(on this link, I think this is the case of searching for minimum into input array)
__kernel
void reduce(__global float* buffer,
__local float* scratch,
__const int length,
__global float* result) {
int global_index = get_global_id(0);
float accumulator = INFINITY;
// Loop sequentially over chunks of input vector
while (global_index < length) {
float element = buffer[global_index];
accumulator = (accumulator < element) ? accumulator : element;
global_index += get_global_size(0);
}
// Perform parallel reduction
...
からカーネルコードの大部分はこの部分を理解していませんコードは行います。
還元の第2段階、すなわち最終合算との関係はありますか?
は、あなたが私の問題を理解していない場合は、私に詳細を聞いてお気軽に。
感謝のコメントで述べたように
私はこの640000ワークグループの計算が正しくないと思います。私はまた、最初にこの記事を理解するのに苦労しました。 [この回答](http://stackoverflow.com/a/10975985/3182664)はちょっと助けました。各作業グループの*結果が* 1になることは明らかです。多数の要素でさえも「少数」の要素に縮小され、ホスト上で削減できます。 – Marco13
@ Marco13なぜ640000の作業グループの計算が正しくないと思いますか? – youpilat13
"任意の"ワークグループサイズを定義できると思います。しかし、10240000要素の場合、例えば64個の結果を計算する64個のワークグループを使用することができます。各作業グループは10240000/64要素を処理します(しかし、確かに、私の記憶をリフレッシュしてより明確なステートメント - 申し訳ありませんが、私がコメントした理由です) – Marco13