一.基于任务窃取的分布式调度
下图是典型的分布式调度线程池示意图(Eigen中的线程池,MindSpore与其类似):
主要逻辑:
1.线程池初始化时,一般根据系统的CPU核数创建相应的线程数(也可传递参数配置)
2.开始一般会有一个不属于线程池内的线程向线程池任务队列提交任务(可能随机选择一个队列提交)
3.每个线程在创建时绑定一个Run函数,函数逻辑:先尝试从本地队列(线程自己的任务队列)取任务(一般从头部取,第5条解释),如果本地队列没有任务,则尝试从其它线程的队列尾部(第5条解释)偷取任务执行。在满足一定条件时(如长时间未有效获取到任务,只是在浪费CPU资源)进入休眠状态,等待被唤醒
4.线程在执行完某个任务(例如深度学习计算图中某个算子)后,可能会产生新的任务,将该任务提交到本地任务队列
5. 之所以每个线程从本地队列取任务是从头部,提交任务也是向头部提交,而偷取别的队列任务是从尾部,是为了提高cache的数据亲和性进而提高执行效率。举例来说:线程0完成算子A的执行,生成了新任务(算子B),那么很可能算子A的输出数据就是算子B的输入,此时线程0所在的CPU核的cache中还缓存着A的输出数据,