的性能thrust::count
很好,这是您尝试使用它的方式对性能有问题。如果您有很多粒子并且只有几个单元格,那么您的实现使用thrust::count
可能不是一个坏主意。你的问题是你有 1500 个细胞。count
这意味着每次您想要进行计算时,需要1500 次调用和 1500 次设备到主机内存传输。正如您所发现的,所有内核启动和所有 PCI-e 总线副本的延迟都会降低性能。
对于大量单元格的更好方法是这样的:
thrust::device_ptr<int> rawin = thrust::device_pointer_cast(dev_particle_cell_indices);
// Sort a scratch copy of the cell indices by value
thrust::device_vector<int> cidx(num_particles);
thrust::copy(rawin, rawin+num_particles, cidx.begin());
thrust::sort(cidx.begin(), cidx.end());
// Use binary search to extract all the cell counts/offsets
thrust::counting_iterator<int> cellnumber(0);
thrust::device_vector<int> offsets(num_cells), counts(num_cells);
// Offsets come from lower_bound of the ordered cell numbers
thrust::lower_bound(cidx.begin(), cidx.end(), cellnumber, cellnumber+num_cells, offsets.begin());
// Counts come from the adjacent_difference of the upper_bound of the ordered cell numbers
thrust::upper_bound(cidx.begin(), cidx.end(), cellnumber, cellnumber+num_cells, counts.begin());
thrust::adjacent_difference(counts.begin(), counts.end(), counts.begin());
// Copy back to the host pointer
thrust::copy(counts.begin(), counts.end(), particle_counts);
thrust::copy(offsets.begin(), offsets.end(), particle_offsets);
在这里,我们首先对单元格索引的本地副本进行排序,然后使用推力二分搜索函数执行与您的代码相同的操作,但通过 GPU 内存中的数据要少得多,并且只需两个设备到主机内存副本即可获得将所有结果返回给主机。
当我thrust::count
使用上面发布的代码对您的实现进行基准测试时(在 OS X 上使用 CUDA 4.1 的 GeForce 320M 上的 10000 个随机粒子和 2000 个单元),我发现您的版本运行大约需要 0.95 秒,而排序/搜索版本运行大约需要 0.003 秒。因此,如果您使用更有效的策略和更合适的算法,则使用推力可能会获得数百倍的加速。