并发编程中的任务调度与工作分配
在并发编程中,任务调度和工作分配是实现高效多线程计算的关键环节。我们将探讨如何通过合理的调度和分配策略,让线程保持忙碌,从而提升系统的整体性能。
1. 调度界限与贪心调度
在任务调度中,我们希望找到一种能让线程尽可能不空闲的调度方式。通过分析可知,贪心调度是一种简单且实用的方法,它能让调度结果接近最优。具体来说,贪心调度中最长的有向路径长度与空闲步骤的数量相关,经过推导可以得出,空闲桶中最多包含 $T_{\infty}(P - 1)$ 个令牌,其中 $T_{\infty}$ 是初始时的最长有向路径长度,$P$ 是处理器数量。所有桶中的令牌总数满足 $\sum_{i = 0}^{T - 1} p_i \leq T_1 + T_{\infty}(P - 1)$,这个界限与最优调度的界限相差不超过两倍。由于实现最优调度是一个 NP 完全问题,贪心调度成为了一种可行的选择。
2. 工作分配策略
为了实现良好的加速比,关键在于为用户级线程持续提供任务,使调度尽可能贪心。然而,多线程计算会动态地创建和销毁任务,这就需要一个高效的工作分配算法,将就绪任务分配给空闲线程。
常见的工作分配方法有工作交易和工作窃取。工作交易是指负载过重的线程将任务卸载到负载较轻的线程,但如果大多数线程都过载,这种方法会导致任务交换的徒劳尝试,浪费资源。而工作窃取则是当一个线程的任务执行完后,它会随机选择一个“受害者”线程,从其任务队列的顶部“窃取”任务。这种方法的优势在于,当所有线程都忙碌时,不会浪费时间进行任务卸载。
3. 工作窃取的实现
每个线程都维护一个双端队列(DEQueue)来存储待执行
超级会员免费看
订阅专栏 解锁全文
3515

被折叠的 条评论
为什么被折叠?



