4

在我的程序中,我通过体素网格跟踪大量粒子。粒子与体素的比率是任意的。在某个时刻,我需要知道哪些粒子位于哪些体素中,以及有多少。具体来说,体素必须准确地知道其中包含哪些粒子。由于我不能std::vector在 CUDA 中使用任何东西,我正在使用以下算法(在高级别):

  • 分配与体素数量大小相同的整数数组
  • 为所有粒子启动线程,确定每个粒子所在的体素,并在我的“桶”数组中增加适当的计数器
  • 分配一个指针数组大小的粒子数
  • 计算每个体素在这个新数组中的偏移量(将其前面的体素中的粒子数相加)
  • 将粒子以有序的方式放置在数组中(我稍后会使用这些数据来加速操作。速度的提高非常值得增加内存使用量)。

但是,这在第二步上就崩溃了。我很久没有在 CUDA 中编程了,只是发现线程之间同时写入全局内存中的同一位置会产生未定义的结果。这反映在我主要得到 1 的事实中buckets,偶尔会得到 2。这是我用于此步骤的代码的草图:

__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 中生成这些计数的正确方法是什么?

另外,有没有办法在体素中存储对粒子的引用?我看到的问题是体素中的粒子数量不断变化,因此几乎每一帧都必须重新分配和重新分配新数组。

4

1 回答 1

1

尽管可能有更有效的解决方案来计算存储桶计数,但第一个可行的解决方案是使用您当前的方法,但使用原子增量。这样,一次只有一个线程自动增加存储桶计数(在整个网格上同步):

if(tid < num_particles) {
    // ...
    atomicAdd(&buckets[index], 1);
}
于 2012-04-13T08:32:03.527 回答