私のプログラムでは、ボクセル グリッドを介して多数の粒子を追跡しています。ボクセルに対するパーティクルの比率は任意です。ある時点で、どのパーティクルがどのボクセルにあり、いくつあるかを知る必要があります。具体的には、ボクセルは、どの粒子が含まれているかを正確に認識している必要があります。CUDA のようなものは使用できないためstd::vector
、次のアルゴリズムを (高レベルで) 使用しています。
- ボクセル数のサイズの int の配列を割り当てます
- すべてのパーティクルのスレッドを起動し、各パーティクルが存在するボクセルを特定し、「バケット」配列の適切なカウンターを増やします
- 粒子の数のサイズのポインターの配列を割り当てます
- この新しい配列への各ボクセルのオフセットを計算します (その前のボクセル内の粒子の数を合計します)
- パーティクルを配列内に順序どおりに配置します (このデータを使用して、後で操作を高速化します。速度の向上は、メモリ使用量の増加に見合うだけの価値があります)。
ただし、これは2番目のステップで崩壊します。私は長い間 CUDA でプログラミングを行っていませんが、スレッド間でグローバル メモリ内の同じ場所に同時に書き込むと、未定義の結果が生じることがわかりました。これは、ほとんどの場合 で 1 を取得し、ときどき 2 を取得するという事実に反映されていbuckets
ます。このステップで使用しているコードのスケッチを次に示します。
__global__ void GPU_AssignParticles(Particle* particles, Voxel* voxels, int* buckets) {
int tid = threadIdx.x + blockIdx.x*blockDim.x;
if(tid < num_particles) { // <-- you can assume I actually passed this to the function :)
// Some math to determine the index of the voxel which this particle
// resides in.
buckets[index] += 1;
}
}
私の質問は、CUDA でこれらのカウントを生成する適切な方法は何ですか?
また、ボクセル内のパーティクルへの参照を保存する方法はありますか? 私が目にする問題は、ボクセル内の粒子の数が絶えず変化することです。そのため、新しい配列はほぼすべてのフレームで割り当てを解除して再割り当てする必要があります。