1. 工作窃取的任务粒度中任务过小使窃取开销大于收益、过大导致负载不均,如何设置窃取阈值与队列策略?
解释工作窃取的任务粒度:为什么任务过小使窃取开销大于收益、过大导致负载不均,如何设置窃取阈值与队列策略?
- 任务粒度大小对窃取收益的影响
- 过小粒度窃取开销占比大
- 过大粒度负载不均
工作窃取中,任务切分粒度(granularity)至关重要。任务过小:每个任务只有很少计算量,窃取本身(从其它线程队列取走任务、同步、缓存未命中)的开销相对任务本身过大,导致"窃取开销 > 切分收益",整体效率下降。任务过大:可分离的任务单元少,负载均衡能力差,某线程任务多、其它线程空闲,负载不均。设置窃取阈值:通常用"切分阈值"(如数组长度小于某阈值则不继续递归切分,直接串行计算),使叶子任务足够大(如 1000-10000 元素)以摊薄切分/窃取开销,同时保持足够任务数支撑负载均衡。队列策略:每个线程用本地双端队列(deque),本线程从队尾(LIFO)取任务(缓存友好),窃取线程从队头(FIFO)取任务(减少竞争),配合"窃取失败就扩大任务"或读阈值调整。这是 ForkJoinPool 与 Cilk 的核心。经验法则:任务粒度使"串行计算量 ≈ 窃取/切分开销的平方根量级"最优。
核心是"粒度权衡":太细开销大、太粗负载不均。窃取阈值与"本地队尾 LIFO + 异地队头 FIFO"的队列策略配合,平衡缓存局部性与负载均衡。理解"粒度 = 开销与均衡的平衡点"是关键。