私が直面している問題は、大規模なデータセット (最大 2048x2048x40x10000 x、y、z、t == 解凍された数テラバイト、ギブまたはテイク) をセグメント化することです。プラス面として、このデータセットの機能はかなり小さいです。最大20x20x20x20程度。
私が見る限り、これに対するすぐに使えるソリューションはありません(間違っている場合は修正してください)。これに対処する方法についてはいくつかの計画がありますが、フィードバックをお願いします。
1 つのタイムスライスは最大 600 MB です。典型的な状況下では少ない; 私は 4 GB メモリに一連のそのようなスライスを保持できます。
私の特徴のサイズが小さいことを考えると、私の直感では、あらゆる形式のセグメンテーションの巧妙さを避け、ラベルに対してローカルで反復的なフラッドフィルのような更新を行うのが最善であると考えています。隣人がより高いラベルを持っている場合は、それをコピーします。収束するまで繰り返します。反復回数は、任意の次元の最大クラスター サイズによって制限される必要がありますが、これも小さくする必要があります。
CUDA は自然に 3D を好むため、これを 2 段階のプロセスとして行うことができます。まだ収束していないすべての 3D ボリューム スライスを繰り返します。次に、連続するすべてのタイム スライスに対して単純に要素ごとのループを実行し、同じフラッディング ロジックを実行します。
単純なインクリメント ユニーク カウンターで反復を初期化するか、最初に極大値を見つけてそこにラベルをシードすることができます。後者が優先されるため、ラベルでインデックス付けされた配列を保持して、すべての領域の x、y、z、t の最小/最大範囲を格納できます (後処理としても実行できます)。リージョンが最新のタイムスライスまで拡張されていない場合、そのリージョンはデータから消去され、その場所がデータベースに書き込まれます。末尾のタイムスライスがそのように完全に使い果たされた (合計がゼロになる) 場合は、メモリから削除します。(または、メモリがオーバーフローした場合は、最新のものも削除します。このようにして作成された近似は我慢する必要があります)
それはうまくいくようです。z 次元のサイズが限られていることを考えると、x、y、z スレッドブロックを起動するか、x、y ブロックを起動して各スレッドを z 次元でループさせる方がよいと思いますか? それは「試してみる」ようなものですか、それともそれに対するストックアンサーはありますか?
私が思いついた別の最適化。x、y、z のブロックを共有メモリにロードした場合、とにかくそこにメモリを取得している間に、いくつかのフラッドフィル更新を実行する方が高速ではないでしょうか? おそらく、ローカルメモリを収束まで反復させてから先に進むのが最善です...それは、私が推測する上記の問題に関連しています。単一の近隣最大ルックアップは、おそらく次善の計算強度であるため、z をループするか、数回反復することでそれを相殺する必要があります。私は後者の方が好きだと思います。
別の質問です。このようなものはまだ存在していないようですが、同様のことを行うテンプレート コードを含むプロジェクトへのリンクは高く評価されます (最適化された 3D フラッドフィル コード?)。私の CUDA の知識はまだむらがあります。
ご意見やフィードバックをお寄せいただきありがとうございます。