多核调度策略
多核下的负载分担
一个任务给一个核, 执行完了再来一个.
依赖问题
同一个进程的线程很有可能有依赖关系
比如gcc file1.c file2.c file3.c -p a.o
, 这样需要先编译出三个文件, 然后合并到一起.
协同调度
整体同步并行(Bulk Synchronous Parallelism, BSP)计算模型
没有依赖关系的并行执行, 有依赖关系的等待下一轮运行.
群组调度
没有依赖关系的任务分在同一组, 以组为单位调度.
缓存问题
任务在CPU核心间频繁切换, 对缓存不友好.
两级调度
每个CPU都有一个本地调度器和调度队列, 全局调度器调度过来一个任务就放到调度队列里面去. 这样能让线程一直在同一个CPU上运行了, 缓存友好.
但是有一点问题, 那就是如果一个任务负担很重, 就会导致某些CPU占用很高, 其它CPU空闲. 负载不均衡.
每个任务特点不同, 不能用任务数量代表真实负载, 需要追踪CPU的负载情况, 将任务从高负载CPU迁移到负载低的CPU.
问题就在于怎么进行精准的负载追踪了. 有两种方法
- 以运行队列为粒度进行追踪负载
运行队列长就说明负载高. 但是要从一个高负载的运行队列拿走哪个任务无法确定, 缺少关键信息.
- 以调度实体为粒度追踪负载
以调度实体(单个任务)为粒度记录负载.
Linux3.8就开始使用了, Per Entity Load Tracking, PELT
PELT
记录每个调度实体对负载的贡献(有多少时间在运行)
每1024微秒周期, 记录线程处于可运行状态的时间x
线程t在第i个周期内的负载为
负载是在每个CPU独立计算的, 需要一个统一的标准. 性能高的CPU, Factor也更高.
总负载的计算
Linux设置的衰减因子
快速计算总负载:
调度进阶机制
操作系统允许程序主动选择使用哪个逻辑核心来运行.