次の問題があります: GPU のツリー構造に基づいて、値の包括的スキャン (例:プレフィックスの合計) を計算する必要があります。これらのスキャンは、ルート ノード (トップダウン) またはリーフ ノード (ボトムアップ) から行われます。単純なチェーンの場合は簡単に処理できますが、ツリー構造のため並列化を効率的に実装するのはかなり困難です。
たとえば、トップダウン インクルーシブ スキャンの後、(12)
が保持(0)[op](6)[op](7)[op](8)[op](11)[op](12)
され、ボトムアップ インクルーシブ スキャンの場合、(8)
が保持されます(8)[op](9)[op](10)[op](11)[op](12)
。ここ[op]
で、 は指定されたバイナリ演算子 (行列の加算、乗算など) です。
また、次の点も考慮する必要があります。
- 典型的なシナリオでは、異なるブランチの長さは長すぎないように (~10)、5 から 10 のブランチのようにする必要があります。そのため、これはブロック内で実行され、作業はスレッド間で分割されます。異なるブロックは、ノードの異なる値を処理するだけです。これは占有率に関して明らかに最適ではありませんが、これは後で取り組む問題に対する制約です。今のところ、命令レベルの並列処理に依存します。
- グラフの構造は変更できない (実際のシステムを記述する) ため、バランスを取ることはできません (または
(6)
、新しいルートとして使用するなど、ツリーのルートを変更することによってのみ)。それにもかかわらず、典型的な木はバランスが崩れすぎてはいけません。 - 私は現在、GPGPU に CUDA を使用しているため、この問題を解決できる CUDA 対応のテンプレート ライブラリを受け入れることができます。
- ノード データは既にグローバル メモリにあり、結果は他の CUDA カーネルによって使用されるため、大きなボトルネックにならないようにこれを達成することが目的です。
- 「サイクル」はありません。つまり、ブランチはツリーの下にマージできません。
- ツリーの構造は固定され、初期化フェーズで設定されます。
- 単一の二項演算は非常にコストがかかる場合があります (たとえば、多項式行列の乗算、つまり、各要素が特定の次数の多項式である)。
この場合、この問題を解決するための「最適な」データ構造 (ツリー構造の場合) と最適なアルゴリズム (包括的なスキャン/プレフィックスの合計の場合) は何でしょうか?