TBB中parallel_reduce与parallel_deterministic_reduce的选择及性能优化问询
TBB中parallel_reduce与parallel_deterministic_reduce的选择及性能优化问询
嗨,我来帮你理清这两个TBB函数的选择逻辑和性能优化点:
一、函数选择:速度 vs 结果确定性
先明确两者核心差异:
parallel_reduce:子任务的合并顺序是不确定的,会根据硬件并发度、系统实时负载动态调整,调度灵活性更高,性能通常更好,但结果的确定性依赖于运算的数学特性。parallel_deterministic_reduce:强制固定合并顺序,无论硬件并发多少、其他进程/线程负载如何,最终结果完全一致,但因为要维护固定顺序,调度上有额外开销,性能略低于前者。
分场景分析:
1. 整数向量求和
整数加法严格满足结合律和交换律,不管合并顺序怎么变,最终结果都完全一致。所以如果追求最快速度,优先选parallel_reduce;如果想避免后续可能的疑惑(比如担心某些极端情况),用parallel_deterministic_reduce也没问题,只是性能稍差一点,但结果绝对可靠。
2. 浮点数向量求和
浮点数加法不满足严格结合律,不同的合并顺序会导致微小的精度差异(比如先累加多个小数再加大数,和先把大数加起来再加小数,结果可能有细微差别)。
- 如果你要求结果完全一致(不受并发环境影响),必须选
parallel_deterministic_reduce; - 如果可以接受极微小的精度误差,追求极致性能,就选
parallel_reduce。
二、关于parallel_deterministic_reduce的grain size问题
先解读那个警告:
Since simple_partitioner does not automatically coarsen ranges, make sure to specify an appropriate grain size
simple_partitioner是TBB的一种分区策略,它不会自动根据系统情况调整任务粒度(即每个子任务处理的元素数量)。如果不指定grain size,它可能会把任务拆得过于细碎,导致大量小任务的调度开销,反而拉低性能。
如何设置grain size?
- 优先推荐使用
auto_partitioner:它会自动根据硬件并发能力、任务的计算开销动态调整粒度,不需要手动设置,大多数场景下都能获得不错的性能,完全可以避开手动调参的麻烦。 - 如果一定要用
simple_partitioner:- 经验起点:可以先设置为几百到几千个元素(比如浮点数加法,建议每个子任务处理1000~5000个元素),然后在你的目标硬件上测试调整;
- 经验公式:
grain_size = 总元素数 / (4 * 线程数),这个数值可以作为调参的起点,再根据实际性能测试优化。
备注:内容来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

