オープン CL で (jocl フロント エンドを介して) カーネルを実行していますが、他のカーネルに比べて実行速度が非常に遅いため、高速化する理由と方法を理解しようとしています。このカーネルは非常に基本的なものです。唯一の仕事は、持っているサンプル ポイントの数を減らすことです。入力配列から N 番目ごとのポイントをより小さな出力配列にコピーして、配列サイズを縮小します。
カーネルには、「適切な」ポイント間でスキップするポイント数を指定する float が渡されます。したがって、1.5 を超えると、1 ポイント、10 ポイントを 2 つ、次に 1 ポイントをスキップして、スキップされる 1.5 ポイントごとの平均を維持します。入力配列は既に GPU 上にあり (以前のカーネルによって生成されたものです)、出力配列はカーネル上にとどまるため、CPU との間でデータを転送する費用はかかりません。
このカーネルは、他のどのカーネルよりも 3 倍から 5 倍遅く実行されます。一部の高速カーネルよりも 20 倍も遅くなります。配列へのアクセスを結合しないことでペナルティを受けていることに気付きました。しかし、それが私をこれほど遅く走らせる原因になるとは信じられません。他のすべてのカーネルが配列内のすべてのサンプルに触れた後、たとえ合体していなくても、配列内の X サンプルに触れることは、少なくとも配列内のすべてのサンプルに触れるのとほぼ同じ速度になるはずです。
元のカーネルは実際には、実データと虚データの 2 つの配列を一度にデシメートしていました。カーネルを 2 つのカーネル呼び出しに分割しようとしました。しかし、これはまったく役に立ちませんでした。同様に、1 つのスレッドが 3 ~ 4 ポイントの間引きを担当するようにして、カーネルを「展開」しようとしました。しかし、これは何の役にも立ちませんでした。各カーネル呼び出しに渡されるデータのサイズをいじってみました (つまり、何千ものデータ ポイントに対する 1 つのカーネル呼び出し、または少数のデータ ポイントに対するいくつかのカーネル呼び出し)。しかし、このカーネルが GPU に実装する価値があると見なされるために必要な桁数ではありません。
スケール感を示すために、このカーネルは反復ごとに実行に 98 ミリ秒かかりますが、FFT は同じ入力配列サイズで 32 ミリ秒しかかからず、他のすべてのカーネルは 5 ミリ秒以下かかります。このような単純なカーネルの実行が、実行中の残りのカーネルに比べて馬鹿げたほど遅いのは、他に何が原因でしょうか? GPUで実行することを保証するために、実際にこのカーネルを十分に最適化できない可能性はありますか? このカーネルを CPU よりも高速に実行する必要はありません。CPU に比べてそれほど遅くはないので、GPU ですべての処理を維持できます。