早期的操作系统只需要关心CPU的调度策略,从而提高通用程序的运行效率,但是随着NPU和其他ASIC的普及,每个SOC下都支持了多个NPU和ASIC芯片。面对这样芯片的设计趋势,操作系统调度变得至关重要。调度不再只关心CPU内部,而是需要对所有资源进行有效调度。本文先简单讨论XPU调度的几个关注点
在没有XPU调度的环境下,其资源需要长期待命,一方面功耗无法降低,另一方面性能无法完全利用。
假设CPU下发一个需要CPU,DSP,GPU,NPU同时运行的任务,当CPU开始运行任务的时候,需要同时将DSP,GPU,NPU都上去启动到就绪状态,等待CPU将任务下发给不同的执行单元。这种情况下,假设SOC环境具备两个DSP单元,那么两个DSP单元都会同时启动,那么整个SOC环境下的功耗一直是以最大运行状态运行。
那么是不是可以让CPU在使用DSP的时候,尽可能调度在同一个DSP上,这样可以让另一个空闲的DSP得到关闭,降低功耗
假设CPU下发多个需要CPU,DSP,GPU,NPU同时运行的任务,当CPU开始运行多个任务的时候,因为在DSP/GPU/NPU的视角是谁来就运行谁的任务处于一种无序状态,所以无法有效的将DSP,GPU,NPU的利用率提升到100%。
为了有效的开发和设计XPU调度策略,需要统一的从如下几个维度进行分析和决策,如下
XPU完成任务的工作量。利用率根据管理的计算任务的数量和性质而变化。通过利用率可以看到设备的运行时间,空闲时间。 而调度策略的目的是降低设备的空闲时间。如果可降低的空闲时间为100%,那么将节省一个设备的核心
它是指每单位时间内完成的进程数量。通过有效地优先级排序和调度进程来提高吞吐量,从而在给定的时间范围内完成更多的任务。
假设XPU的利用率是100%,但是无序争用和有序的编排不同的是,有序的编排可以让某一段时间内的XPU吞吐量很高(因为运行短任务),同时让某一段时间内的吞吐量降低(此时可以通过降低设备频率获取功耗收益)
这指从进程开始到完成所经过的时间。周转时间是总等待时间,它包括进程在CPU,DSP,NPU,GPU,以及内存,IO,和调度算法内等待的总时间。
一方面,调度策略内应该保证所有任务在就绪队列中等待的时间都得到减少
另一方面,良好的调度策略可以降低单进程维度下的任务等待时间,从而满足具备实时特征的任务能够长期的保证其响应效果
在周转时间内已经提到,一个进程在就绪队列中花费的总时间称为等待时间。因此,调度算法决定了进程在获得XPU设备资源前的所有停留时间的长短
它是提交请求和收到第一个响应之间的时间。调度策略确保高优先级进程能够及时获得XPU设备资源,有助于减少响应时间并提升整体用户体验。
如果仅从调度本身来看,其实XPU的调度策略和通用CPU的调度策略是相通的。因为都是按照一定的指标选出最合适的任务。只不过CPU的调度面向的资源设备是CPU本身,而XPU的调度面向的资源设备是加入调度管理的多种多样的设备。
目前市场上XPU的调度策略都比较简单,本文先从简单调度策略说起
FCFS(先来先服务)算法根据进程就绪顺序,即基于任务的到达时间
SJF(最短作业优先)算法根据进程的预算时间分配资源,也就是说,运行时间短的进程会先获得访问权
SP(静态优先级)算法根据特定的数值表示更高的或更低的优先级,高优先级的进程会比低优先级的进程更早获得设备访问权
注意,一些系统上的设计,可能Priority越高,优先级越高,但是另一些系统上,可能Priority越低,优先级越高。为什么会有后者呢?主要还是因为红黑树的原因,红黑树找最小值的效率最高。所以设计系统时出现了常人认为的反直觉,也就是Priority越低,优先级越高。对红黑树兴趣的可以查看我其他文章《rb-tree实现》系列
RR(轮转调度)算法根据时间片周期的运行任务,这使得所有进入就绪的任务都能周期性的得到运行,体现了调度的公平性
根据上面可以看到,常规调度目前已经应用在各种XPU的中间件上,首先,他们是单独维护和服务于某一类型的设备,例如GPU,那么对应就是GPU驱动,例如NPU,那么就对于cuda库(以nvidia为例)。
这里再提供一些新的调度策略可用于XPU上。
常规的自适应调度策略例如动态优先级,动态时间片,基于负载均衡的调度都属于自适应调度策略。 这种调度策略会动态的修改任务的整体优先级排序情况,从而让任务更具备公平性,不被饿死。
在NPU领域,Shockwave也提出了基于市场调控的调度策略。也属于自适应调度策略的一种。
实时调度算法在通常应用在具备强实时环境中,例如硬实时操作系统中调度策略,或者确保具有严格时间约束的中间件,例如常规的速率单调调度(RMS)、最早截止日期优先(EDF)和截止日期单调调度(DMS)。
在XPU的调度中,我们更关心的是任务的实时性,可以牺牲不具备实时要求的任务的响应效果。
对于XPU环境下的调度策略,抢占是维系任务实时系的重要功能,抢占分两种
调度器抢占很好理解,例如实时调度算法EDF根据deadline来实施对任务的抢占,RR调度在时间片完成后,默认的轮转可以任务是抢占点
而用户抢占指的是提供了用户的接口,让用户执行任务前决定是否可以抢占设备。通过用户主动实施的任务抢占,可以让设备被抢占后保存上下文,从而运行下一个任务。
不过抢占都是具备开销的,过多的抢占会给系统带来很强的调度器负载,例如低时间片下的RR调度算法。过少的抢占又会影响XPU调度的实时效果。这里面要从实际情况中获取经验值。反哺到XPU调度算法的设计中去。
随着AI的逐步普及,目前的SOC设计都会带有NPU核心,同时带有多个DSP单元和其他的ASIC设计。这些设计不再像以前一样,只要用起来就行。我们需要关注整体实时性响应,性能效果,和功耗输出。所以将SOC中以这种XPU维度的调度策略越来越重要。