You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

并行网格点分桶算法:低同步开销的已发表方案咨询

基于网格单元格的点分组排序:低同步多线程算法调研

问题背景

我们有一组按网格模式排列的2D/3D单元格,以及分布在该网格中的点集:每个点归属于某一单元格,部分单元格包含多个点。需要完成两个核心目标:

  • 对原始点数组进行重排,使同一单元格内的所有点在内存中连续存储
  • 获取每个单元格对应的点数组范围(起始、结束索引)

单线程朴素实现

伪代码如下:

for p in points:
   cell_id = cell_id(p)
   cell_counts[cell_id] += 1

cumulative_counts = add_cumulative_integers(cell_counts)
starts = cumulative_counts
for p in points:
    cell_id = cell_id(p)
    new_points[cumulative_counts[cell_id]] = p
    cumulative_counts[cell_id] += 1
ends = cumulative_counts

核心逻辑:先统计每个单元格包含的点数量,计算前缀和得到各单元格的起始偏移,最后根据偏移量将点重排到目标数组中。

低同步多线程已发表算法

针对多线程场景,已有多种成熟算法可最小化同步开销,核心思路都是通过原子操作、局部计算或任务划分来减少全局锁依赖:

1. 原子计数+并行前缀和算法

这是最直接的优化方向,对应单线程逻辑的并行化:

  • 计数阶段:每个线程独立处理一部分点,使用原子操作(如fetch_add)更新对应单元格的计数,无需全局锁。原子操作的粒度仅为单个单元格的计数变量,同步开销远低于全局锁。
  • 前缀和阶段:采用并行扫描算法(如Hillis-Steele扫描、Blelloch扫描),这类算法能在O(log n)时间复杂度内完成全局前缀和的并行计算,仅需少量线程间同步。
  • 重排阶段:每个线程再次处理自己负责的点集,根据预先计算的起始偏移,用原子操作获取当前单元格的写入位置并完成写入,避免跨线程写入冲突。

2. 局部计数+批量合并算法

该思路通过减少同步次数来降低开销:

  • 局部计数:每个线程先维护一份本地的单元格计数副本,处理完分配给自己的点集后,再将本地计数批量合并到全局计数数组中(合并时使用原子操作或细粒度锁)。这样每个线程仅在合并阶段进行同步,而非每次计数都触发同步。
  • 并行前缀和:同样使用并行扫描算法计算全局起始偏移。
  • 无冲突重排:由于每个点的目标位置由全局起始偏移和单元格内计数唯一确定,线程可直接写入对应位置,无需额外同步。

3. 基于样本排序的单元格分组算法

将单元格分组问题转化为并行排序问题,利用成熟的并行排序框架:

  • 采样划分:先从点集中采样部分点的单元格ID,确定划分阈值,将整个单元格ID范围划分为多个连续区间。
  • 并行处理:每个线程负责处理属于某一区间的点,直接将这些点排序后写入预先分配好的内存区域。区间边界预先确定,线程间无写入冲突,无需同步。
  • 结果合并:由于区间是连续的,最终同一单元格的点自然连续存储,直接提取各单元格的起始、结束索引即可。

内容的提问来源于stack exchange,提问作者Makogan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.03 21:12:32