清晨七点的城市交通指挥中心,大屏上跳动着成千上万个光点:公交车沿着固定路线匀速行驶,出租车在楼宇间灵活穿行,地铁在地下隧道里呼啸而过,还有几辆救护车闪着灯赶往医院。指挥员的任务,不是让所有车跑得一样快,而是让合适的车出现在合适的位置——用公交车运送大客流,用出租车服务点到点需求,为救护车优先让出通道。 AI Runtime系统中的异构计算调度,正是AI世界的“交通指挥中心”。你在手机上打开智能助手,背后其实是一支混合车队:CPU精于处理复杂逻辑,GPU擅长成千上万个小任务并行计算,NPU则像专线地铁,把神经网络算子的吞吐拉到极致。而调度策略,就是指挥员手里的“指挥手册”:谁来接单、走哪条路线、遇到拥堵怎么办、救护车来了怎么让行。 本文将从调度基础概念讲到静态与动态策略、核心算法、异构感知优化、抢占优先级,最后落到工程实践与未来趋势,带你完整理解异构调度的决策智慧。

岗位关联

掌握异构调度的核心策略,是AI系统工程师优化推理延迟、降低部署成本的必备能力,也是从“调通模型”走向“调优系统”的分水岭。

目录
  1. 可视化演示
  2. 调度基础概念
  3. 静态调度策略
  4. 动态调度策略
  5. 核心调度算法
  6. 异构感知优化
  7. 抢占与优先级
  8. 工程实践要点
  9. 未来发展趋势
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

演示贪婪调度、负载均衡、启发式三种调度策略在多异构核心上的任务分配过程,对比吞吐和负载均衡效果。

本节配有交互动效(进入视口后自动加载,约 3KB)。

异构调度策略对比 贪婪调度:先来先分配,实现简单但负载不均 轮询均衡:循环分配,均衡性较好但可能有局部热点 堆排序:始终分配给最轻负载核心,吞吐与均衡最优

调度基础概念

城市交通调度中心在派单前,需要先摸清家底:出租车灵活但单次载客少,公交车载客多但需固定路线,地铁运量最大却只能走专线。异构计算的第一步同样如此——识别你手上有哪些“交通工具”。在AI Runtime系统中,CPU是出租车,擅长处理逻辑复杂、分支繁多的通用计算;GPU是公交车,拥有几百上千个计算核心,适合大规模并行数据处理;NPU是地铁专线,为神经网络算子专门设计,跑推理任务效率极高。

调度器就是指挥中心里的那位“总调度员”。它需要把AI计算图切分成合适的调度单元——可以小到单个算子,也可以大到整张子图,这在术语中称为任务粒度。切分得越细,调度越灵活,但调度开销也越大;切分得越粗,整体调度越简单,但容易造成设备空等和资源碎片化。

调度目标决定了指挥员的行为准则。有的场景追求极低延迟——比如自动驾驶的紧急制动,晚一毫秒都可能导致事故;有的场景追求高吞吐——比如离线批量训练,让GPU满载跑满小时级别也无妨;还有的场景需要控制功耗——比如手机端AI,电池电量比速度更重要。调度器在编译期或运行期根据这些目标,把任务映射到合适的设备上。

就像指挥员必须同时记着“让谁走、让谁等、何时让”这三件事,异构调度器的本质也是时间与空间的统筹艺术——用最合适的设备、在最合适的时间,执行最合适的任务。

静态调度策略

公交车时刻表是静态调度的典型代表:每天凌晨,调度室根据固定路线、固定发车间隔,把一天的班次表打印出来。发车后,司机严格按表执行,即使某站临时拥堵也不会临时改道。这种“先规划、后执行”的思路,在异构调度中被称为静态调度策略。

静态调度在编译期完成所有决策。编译器分析计算图的结构,通过内置的成本模型估算每个任务在不同设备上的执行开销,然后确定每个任务被分配到哪块设备。程序运行时,调度器不再干预,设备严格按照编译结果执行。这样做的好处是运行时开销几乎为零,行为可预测,非常适合离线调度场景,比如批处理推理、模型预编译部署。

成本模型是静态调度的心脏。它以历史基准数据为依据,对每个任务-设备组合给出预估完成时间:

静态调度的局限也像时刻表一样明显:如果某辆公交车突然抛锚(设备过载),或者演唱会散场涌出大量乘客(任务突增),预设方案就难以应对。因此,静态调度适合任务特征稳定、设备状态可控的场景。

T^(taski,devicej)=WiPj+DiBj\displaystyle \hat{T}(task_i, device_j) = \frac{W_i}{P_j} + \frac{D_i}{B_j}
这条公式告诉调度器:任务的预计完成时间等于“计算量除以设备算力”再加上“数据量除以设备带宽”,即计算时间与数据传输时间之和。
  1. 计算时间预估任务的计算量 W_i 除以设备 j 的峰值算力 P_j,得到纯计算耗时。
    WiPj\frac{W_i}{P_j}
  2. 数据传输预估任务的数据量 D_i 除以设备 j 的带宽 B_j,得到数据搬运耗时。
    DiBj\frac{D_i}{B_j}
  3. 总耗时相加两者相加得到该任务在设备 j 上的预估完成时间。
    T^(taski,devicej)\hat{T}(task_i, device_j)

动态调度策略

晚高峰开车回家,有经验的司机会打开实时导航——前方拥堵就立刻改道,导航每30秒重新计算一次路线。这种“边跑边看、随时修正”的思路,就是动态调度策略的精髓。

动态调度在运行时持续监控各设备的实时负载、任务队列长度和任务到达情况。每当新任务到达,调度器立刻评估所有设备的当前状态,把任务分配到“预测等待时间最短”的那一个。为此,调度器维护一个全局任务队列,并根据设备反馈持续更新负载均衡监控信息。

动态调度的核心决策逻辑,可以写成一个带负载修正的评分公式。设备当前越空闲,被选中的概率越大:

动态调度的在线自适应能力让它能应对突发任务峰值和设备故障,但代价是每次决策都有运行时开销,且需要可靠的状态监控管道。在推理服务、在线推荐系统等负载波动大的场景中,动态调度是首选方案。

Adjustedj=T^i,j1−Uj\displaystyle Adjusted_j = \frac{\hat{T}_{i,j}}{1 - U_j}
设备利用率 U_j 越高,分母越接近0,修正后的预计时间被放大得越厉害,该设备越不容易被选中;反之,空闲设备的评分会更低,吸引任务到来。
  1. 基准预估时间沿用静态调度中的 $\hat{T}_{i,j}$,表示任务在设备理想状态下的完成时间。
    T^i,j\hat{T}_{i,j}
  2. 负载惩罚系数用 $1 - U_j$ 衡量设备剩余容量,U_j 是当前利用率,取值范围0到1。
    1−Uj1 - U_j
  3. 修正评分基准时间除以负载惩罚,得到考虑排队效应后的实际预计时间。
    T^i,j1−Uj\frac{\hat{T}_{i,j}}{1 - U_j}

核心调度算法

如果说调度策略是“指挥手册”,那么调度算法就是手册里一条条可执行的“条例”。交通信号灯有固定的配时方案,调度算法同样有几种经典范式:优先级调度让高优先级任务插队先行,轮转调度让所有任务轮流使用资源,最短任务优先则像快餐店的“小单先做”原则,把预估耗时最短的任务排在最前。

在实时系统中,最早截止时间优先(EDF)算法尤为重要。它给每个任务定义一个紧急程度——截止时间越近,优先级越高。这个“紧急度”可以直接用公式表示:

当任务数量巨大时,精确求解最优调度是NP难问题,工程上常用启发式搜索——比如遗传算法、模拟退火和蚁群算法。这些方法不追求数学上的最优解,而是在可接受时间内找到“足够好”的调度方案,就像经验丰富的老司机不追求理论上最短路径,而是选择一路上最不堵、最稳妥的路线。

Pi=1deadlinei−tnow\displaystyle P_i = \frac{1}{\text{deadline}_i - t_{\text{now}}}
剩余时间越短,P_i 越大,任务越紧急。调度器每次选择P_i最大的任务执行,确保截止时间紧迫的任务优先得到处理。
  1. 剩余截止时间用任务截止时间减去当前时刻,得到还能等待多久。
    deadlinei−tnow\text{deadline}_i - t_{\text{now}}
  2. 取倒数计算紧急度剩余时间越短,倒数越大,表示任务越紧急。
    1deadlinei−tnow\frac{1}{\text{deadline}_i - t_{\text{now}}}

异构感知优化

老练的调度员不仅知道每辆车的牌子和型号,还了解它们的油耗、轮胎磨损甚至司机的驾驶习惯。异构感知优化,就是让调度器对每块设备建立起同样精细的“画像”。

设备性能画像包括峰值算力、内存带宽、功耗曲线、缓存行为和散热状态。任务特征提取则分析任务的算子类型、数据规模、并行度和访存模式。调度器把这两张表做匹配,就能避开“让出租车去拉一整车货物”式的低效安排。比如一个访存密集而计算稀疏的任务,就不适合丢给以算力见长的GPU,因为瓶颈在带宽上。

数据在异构系统中的位置也是一笔隐形账。数据局部性原则主张“计算跟着数据走”:如果训练数据已经驻留在GPU显存中,再把计算分配到CPU端就白白多付了 Host→Device 的搬运开销。一个有效的设备评分模型可以这样表达:

功耗感知调度在移动端和边缘设备上尤其重要。调度器可以在性能允许范围内,优先把任务调度到能效比更高的NPU上,延长设备的电池续航,就像出租车司机知道哪条路省油就走哪条。

Scorej=PjEj×Li,j\displaystyle Score_j = \frac{P_j}{E_j \times L_{i,j}}
设备评分等于设备算力除以功耗与数据局部性惩罚的乘积。算力越强、功耗越低、数据越靠近,评分越高,调度器越倾向于选择它。
  1. 算力指标P_j 表示设备 j 的峰值计算能力,是正向贡献因子。
    PjP_j
  2. 功耗代价E_j 表示预估完成任务消耗的功耗,越高越扣分。
    EjE_j
  3. 局部性惩罚L_{i,j} 表示数据不在设备本地时的远程访问惩罚系数,L ≥ 1。
    Li,jL_{i,j}

抢占与优先级

早晚高峰的环路上,急救车拉响警报,社会车辆纷纷靠边让行——这就是抢占。在异构调度中,当高优先级任务到达时,调度器可以暂停正在运行的低优先级任务,把设备让给更紧急的任务。被抢占的任务并非终止,而是像靠边停车一样,保存现场,等设备空闲后再恢复执行。

优先级反转是抢占调度中最经典的陷阱:假设有一个中等优先级任务在排队,而低优先级任务正持有高优先级任务需要的锁。若低权限任务被高优先级任务抢占,它就无法释放锁,高优先级任务反而被它“卡住”,形成倒挂。解决方案是优先级继承——锁持有者临时获得等待者中最高优先级:

此外,死锁避免策略包括资源排序分配和超时重试:每个任务按固定顺序申请资源,拿不到就主动释放已有资源并重试,就像交通调度规定“所有车辆先直行再左转”,从根上消除相互等待的循环。做好这些设计,才能保障自动驾驶、工业控制等场景的实时性要求。

Priorityholder=max⁡(Priorityholder,Priorityblocked)\displaystyle \text{Priority}_{\text{holder}} = \max\left(\text{Priority}_{\text{holder}}, \text{Priority}_{\text{blocked}}\right)
低优先级任务持有锁时,会临时提升到被阻塞任务中最高者的优先级,从而不被中等优先级任务抢占,快速释放锁,解除高优先级任务的等待。
  1. 获取持有者优先级读取当前资源锁持有者的原始优先级。
    Priorityholder\text{Priority}_{\text{holder}}
  2. 获取被阻塞最高优先级寻找所有等待该资源的任务中优先级最高者。
    Priorityblocked\text{Priority}_{\text{blocked}}
  3. 取最大并更新锁持有者继承较高的优先级,保证它能先于中等优先级任务执行并释放锁。
    max⁡(Priorityholder,Priorityblocked)\max\left(\text{Priority}_{\text{holder}}, \text{Priority}_{\text{blocked}}\right)

工程实践要点

调度中心的大屏上跳动着实时流量数据,一旦某条路拥堵,值班员立即介入疏导——工程实践中的调度系统同样需要这样的“仪表盘”和“应急预案”。

性能剖析工具是第一步。NVIDIA Nsight、Intel VTune 和火焰图可以告诉你:每个算子到底在设备上花了多少时间、数据搬运占了多大比例、GPU利用率是真是假。有了数据之后,调度参数调优才能真正发力——调整批处理大小、并行线程数、队列深度,甚至改变任务切分粒度,往往能带来数倍的性能提升。

衡量调优效果需要一把统一的尺子,系统吞吐率就是最常用的指标之一:

生产环境的调度系统还必须具备监控与告警能力——Prometheus 采集设备利用率、排队长度、失败率等指标,Grafana 展示趋势,告警规则在指标越界时自动触发钉钉或邮件通知。异常恢复机制则负责兜底:任务超时自动重试、设备心跳丢失自动隔离、失败任务转移到备用设备。这些机制就像城市的应急车道和备援公交,确保系统在异常中依然能维持基本服务。

Throughput=∑i=1nWiTtotal\displaystyle \text{Throughput} = \frac{\sum_{i=1}^{n} W_i}{T_{\text{total}}}
吞吐率是单位时间内系统完成的总工作量。调优的目标,就是在不违反实时性约束的前提下,尽量提高这个数值。
  1. 完成总工作量把每个已完成任务的计算量 W_i 从第一个加到第 n 个。
    ∑i=1nWi\sum_{i=1}^{n} W_i
  2. 总耗时T_total 表示从第一个任务到达至最后一个任务完成的墙钟时间。
    TtotalT_{\text{total}}
  3. 取比值工作量除以总耗时,得到单位时间内完成的平均计算量。
    ∑i=1nWiTtotal\frac{\sum_{i=1}^{n} W_i}{T_{\text{total}}}

未来发展趋势

从人工编排到自动导航,调度系统的进化正在加速。AI智能调度是当前最热门的方向:用强化学习模型学习历史调度日志,让调度器在真实环境中不断试错、自我改进。传统启发式规则是“人写的固定套路”,而AI调度器则像一位逐渐摸清全城路况的老司机,能将高峰期出行时间缩短20%以上。

自适应策略让调度器可以根据负载特征自动切换模式——流量平稳时用静态策略减少开销,突发时无缝切换为动态策略。异构融合计算则在硬件层面打破藩篱:3D堆叠、Chiplet、统一内存架构让CPU与GPU共享同一块物理内存,“搬运数据”的概念逐渐被“指针传递”取代。

云边端协同调度让决策跨越了单机边界:云端训练大模型,边缘设备做初步推理过滤,终端设备执行轻量级确认。调度器不仅要考虑“哪个设备跑得快”,还要考虑“哪里的网络带宽更充裕、哪里的数据隐私更敏感”。

一个可能的强化学习调度目标函数是:

回望这条进化之路,从固定时刻表到实时导航,再到自我学习的智能调度,异构调度正从“被动适配”走向“主动规划”——就像交通指挥中心正在升级为全自动驾驶的城市大脑。

R=−(α×Latency+β×Energy)\displaystyle R = -\left(\alpha \times \text{Latency} + \beta \times \text{Energy}\right)
奖励 R 是延迟与功耗的负加权和。调度策略越优,系统总延迟越低、总功耗越小,获得的奖励越高,强化学习模型就沿着这个方向持续优化自身策略。
  1. 延迟惩罚项α 是延迟权重,Latency 是任务端到端平均延迟。
    α×Latency\alpha \times \text{Latency}
  2. 功耗惩罚项β 是功耗权重,Energy 是完成所有任务消耗的总能量。
    β×Energy\beta \times \text{Energy}
  3. 取负作为奖励负号让优化方向从“最小化损失”转为“最大化奖励”。
    −(α×Latency+β×Energy)-\left(\alpha \times \text{Latency} + \beta \times \text{Energy}\right)

AI 应用场景

大模型推理服务的异构调度

阶段:模型部署与Runtime优化

解决的问题:传统方式下,推理服务把所有请求都打到GPU上,导致GPU在低峰期大量闲置,而CPU和NPU的资源被白白浪费。AI Runtime系统的异构调度器根据请求大小和模型类型动态路由:大请求走GPU、小请求走CPU、特定算子走NPU,实现资源利用率最大化。

具体案例:某智能客服平台日均处理百万级问答请求,任务呈现明显的潮汐特征。通过引入异构调度策略,将短文本分类任务调度到CPU,将长文本生成任务调度到GPU,将意图识别任务调度到NPU,整体吞吐提升2.3倍,单次请求平均成本下降38%。

自动驾驶多任务实时调度

阶段:车端推理与实时控制

解决的问题:自动驾驶车辆同时运行目标检测、车道线识别、路径规划等多个AI任务,计算资源有限且对延迟极度敏感。异构调度器为每个任务分配优先级和截止时间,确保紧急制动任务抢占感知任务获得GPU资源,同时利用CPU执行非实时的日志分析任务。

具体案例:某L4级自动驾驶方案在Jetson AGX Orin平台上部署异构调度器,将障碍物检测延迟从45ms降至28ms,满足安全标准的同时使整体功耗降低22%,有效延长了电动车的续航里程。

Python 演示

python78 行
"""异构调度器模拟:最短预测时间优先策略"""import randomfrom dataclasses import dataclass  @dataclassclass Task:    """计算任务:包含计算量(百万指令)和数据量(MB)"""    tid: int    workload: float    data_size: float  class Device:    """异构设备抽象:算力(百万指令/秒)与带宽(MB/s)"""     def __init__(self, name, compute_speed, bandwidth):        self.name = name        self.compute_speed = compute_speed        self.bandwidth = bandwidth        self.queue = []        self.busy_time = 0.0     def predict_time(self, task):        compute_time = task.workload / self.compute_speed        transfer_time = task.data_size / self.bandwidth        return compute_time + transfer_time     def assign(self, task):        self.queue.append(task)     def execute_next(self):        if not self.queue:            return None        task = self.queue.pop(0)        self.busy_time += self.predict_time(task)        return task  class HeteroScheduler:    """调度器:将每个任务分配到预估时间最短的设备"""     def __init__(self, devices):        self.devices = devices     def schedule(self, task):        best = min(self.devices, key=lambda d: d.predict_time(task))        best.assign(task)        return best.name     def run(self, tasks):        result = []        for task in tasks:            dev_name = self.schedule(task)            result.append((task.tid, dev_name))        for d in self.devices:            d.execute_next()        return result  if __name__ == "__main__":    cpu = Device("CPU", compute_speed=800, bandwidth=40000.0)    gpu = Device("GPU", compute_speed=12000, bandwidth=8000.0)    npu = Device("NPU", compute_speed=20000, bandwidth=15000.0)    scheduler = HeteroScheduler([cpu, gpu, npu])     tasks = []    for i in range(12):        if i % 3 == 0:            tasks.append(Task(i, workload=2000, data_size=600))        elif i % 3 == 1:            tasks.append(Task(i, workload=30000, data_size=40))        else:            tasks.append(Task(i, workload=9000, data_size=180))     results = scheduler.run(tasks)    for tid, dev in results:        print(f"Task{tid} -> {dev}")
目的:实现一个最小化的异构调度器,模拟CPU、GPU、NPU三种设备,用“最短预测时间优先”策略为每个任务选择最优设备。你可以修改任务参数并观察调度结果的变化。
  1. class Device定义异构设备的核心属性:算力、带宽和任务队列,相当于交通工具的“性能参数表”。
  2. def predict_time(self, task)用公式 workload / compute_speed + data_size / bandwidth 预估任务在该设备上的完成时间,对应正文中的成本模型。
  3. def schedule(self, task)遍历所有设备,用 min 函数挑选预测时间最短的那个,这是整个调度器的核心决策逻辑。
  4. best.assign(task)将任务加入选定设备的队列末尾,模拟“把乘客派给最合适的车辆”。
  5. for i in range(12)生成12个具有不同计算量和数据量的任务,模拟混合负载下的调度场景。
  6. print(f"Task{tid} -> {dev}")打印调度结果,直观展示每一个任务被分配到了哪类设备。

常见误区

误区动态调度能实时感知负载,看起来更“聪明”,所以应该在任何场景都用动态调度替代静态调度。

正解动态调度虽然灵活,但每次决策都有运行时开销——需要采集状态、计算评分、更新队列。在任务特征稳定、负载可预测的离线批处理场景中,静态调度的固定映射反而开销更低、可预测性更强。就像公交时刻表在客流平稳的郊区比实时导航更高效,因为导航本身也消耗电量。

为何常见:人们容易被“智能”“实时”等词汇吸引,却忽略了调度本身的成本。工程上不存在绝对的优劣势,只有是否适配场景。

误区既然GPU能加速深度学习,那所有计算任务都该交给GPU,CPU在AI系统中只是配角。

正解GPU擅长大规模并行计算,但在处理强逻辑分支、小批量计算和串行依赖的任务时,它的优势会被浪费,甚至因频繁启动内核和执行开销而比CPU更慢。异构调度的核心价值就是识别任务类型——把“公交车”与“地铁”各归其位,而不是让所有乘客都挤上公交车。

为何常见:深度学习热潮让GPU名声大噪,人们容易把“加速”的结论泛化到所有任务,忽略了任务特征与硬件特征的匹配关系。

误区抢占会暂停正在运行的任务、保存现场、再恢复执行,这些上下文切换开销巨大,所以抢占总是有害的。

正解抢占确实有开销,但它换来了更宝贵的实时性和公平性。在自动驾驶场景中,让紧急制动任务等一个正在运行的视频编解码任务完成,代价可能是事故。抢占的正确设计思路是控制抢占频率、合理设置优先级、支持优先级继承,让开销发生在“值得打断”的时刻——就像救护车闯红灯不是常态,但关键时候必须闯。

为何常见:初学者看到的是单一的“切换开销”,忽略了抢占带来的整体系统收益,把局部开销当成了全局损耗。

误区监控面板上GPU利用率达到100%是最好的状态,说明硬件没有浪费。

正解利用率接近100%往往意味着任务排队时间急剧增加——新任务要等很久才能上设备执行。就像高速公路的利用率在100%时并不是最高效的,而是彻底堵死了。调度器需要在利用率和延迟之间做平衡,通常将目标利用率设定在80%~90%之间,保留缓冲应对突发负载。

为何常见:性能监控工具让工程师倾向于追求数值最大化,忽略了利用率与延迟之间的L型曲线关系,没有建立“排队论”的直觉。

误区只要成本模型足够精确,编译期算出的调度方案就永远是最优的,运行时不需要再调整。

正解成本模型基于历史基准和静态预估,但真实运行时的设备温度、频率降级、内存碎片都会让实际执行时间偏离预估。而且AI负载本身就有波动——某个模型分支的输入数据量可能因用户行为而完全不同。真正可靠的调度系统需要“静态预估打底、动态监控纠偏”的双层结构。

为何常见:静态分析给人“精确可控”的错觉,人们容易低估真实系统的不确定性和环境噪声。

面试题

Q1. 异构计算中“异构”最核心的含义是:

单选题 · easy

  • A.数据存储介质不同
  • B.计算设备类型不同← 正确答案
  • C.网络协议栈不同
  • D.操作系统版本不同

答案:B。异构计算的“异构”特指系统中存在多种指令集架构或计算能力差异显著的设备,如CPU、GPU、NPU,它们像公交、地铁、出租车一样各有专长。存储介质、网络协议和操作系统差异不构成“异构计算”的定义。

Q2. 静态调度最主要的优势是:

单选题 · easy

  • A.运行时开销小且可预测← 正确答案
  • B.能实时感知设备负载
  • C.天然支持任务抢占
  • D.无需成本模型支撑

答案:A。静态调度在编译期完成所有映射决策,运行时直接执行,避免了实时的状态采集和决策计算开销。它就像公交时刻表,发车时间和路线完全确定。动态感知负载、支持抢占都需要运行时机制,且成本模型恰恰是静态调度的基础而非可选项。

Q3. 轮转调度(Round-Robin)的核心思想是:

单选题 · easy

  • A.按预估执行时间最短优先
  • B.分配固定时间片轮流执行← 正确答案
  • C.截止时间最早的先执行
  • D.随机选择下一个任务

答案:B。轮转调度把CPU时间切成等长的时间片,每个任务轮流获得一个时间片,执行完或时间片耗尽就切到下一个。它的核心是“轮流”而非“最短优先”或“最早截止”,保证了公平性,就像路口红绿灯按固定周期轮流放行不同方向的车流。

Q4. 在最短任务优先(SJF)调度中,任务被选择执行的依据是:

单选题 · mid

  • A.任务到达队列的顺序
  • B.预估执行时间的长短← 正确答案
  • C.任务携带数据的多少
  • D.设备编号的大小顺序

答案:B。SJF在选择下一个执行的任务时,只看预估执行时间,耗时最短的先执行,这与快餐店“小单先做”同理,能有效降低平均等待时间。到达顺序对应FCFS,数据多少不直接作为优先级依据,设备编号更与任务本身无关。

Q5. 设备性能画像通常包含哪些维度:

多选题 · mid

  • A.峰值计算能力← 正确答案
  • B.内存带宽大小← 正确答案
  • C.功耗特性曲线← 正确答案
  • D.开发者的编程习惯

答案:ABC。设备性能画像是调度器做决策的“车辆参数手册”,包括峰值算力、带宽、功耗、缓存大小等硬件属性。开发者的编程习惯属于人为因素,不构成设备的内在画像维度,也不应影响设备层面的调度决策。

Q6. 数据局部性优化主要解决的问题是:

单选题 · mid

  • A.任务启动时创建线程的开销
  • B.数据在异构设备间搬运的开销← 正确答案
  • C.编译器优化掉冗余代码
  • D.任务结束时回收内存的延迟

答案:B。在异构系统中,数据从CPU内存传往GPU显存或NPU内存的PCIe/NVLink传输往往是最大的性能瓶颈。数据局部性原则主张“计算跟着数据走”,尽量减少跨设备搬运。线程创建、编译优化和内存回收与数据局部性是两个维度的问题。

Q7. 优先级反转的根本原因是:

单选题 · hard

  • A.高优先级任务总是抢占CPU资源
  • B.低优先级任务持有高优先级任务需要的锁← 正确答案
  • C.所有任务使用相同的优先级数值
  • D.任务队列采用先进先出策略

答案:B。当低优先级任务持有资源锁却被中等优先级任务抢占时,它无法释放锁,导致等待该锁的高优先级任务被“间接阻塞”——这就是优先级反转。常见解决办法是优先级继承或优先级天花板。高优先级抢占、相同优先级和FCFS并不会造成这种倒挂现象。

Q8. 下列属于避免调度死锁的有效方法:

多选题 · hard

  • A.对多资源申请进行全局排序← 正确答案
  • B.引入超时重试并释放已持有锁← 正确答案
  • C.彻底取消任务间所有同步
  • D.使用优先级继承协议← 正确答案

答案:ABD。死锁的四个必要条件是互斥、持有并等待、不可剥夺、循环等待。资源排序打破“循环等待”;超时重试打破“持有并等待”;优先级继承通过提升优先级使持锁者尽快释放锁,间接打破僵局。完全取消同步在真实AI系统中不可行,反而会引入数据竞争。

Q9. 在动态调度中,Adjusted_j = T_ij / (1 - U_j) 公式中,分母 (1 - U_j) 的含义是:

单选题 · mid

  • A.设备的剩余可用容量比例← 正确答案
  • B.设备的历史故障率
  • C.设备的当前温度系数
  • D.任务的数据压缩比率

答案:A。U_j 是设备当前利用率,1 减去 U_j 就是剩余可用容量。比如利用率80%时,分母为0.2,调整后的预计时间被放大5倍,反映任务在排队中等待的时间代价。这与温熵、故障率和数据压缩均无关。

Q10. 在强化学习驱动的AI调度器中,奖励函数设定为 R = -(aL + bE) 的主要目的是:

单选题 · extreme

  • A.使延迟和功耗的加权和最小化← 正确答案
  • B.使任务队列长度无限增长
  • C.让所有设备以最高功耗运行
  • D.完全忽略延迟只关注吞吐

答案:A。负号将“最小化延迟与功耗的加权和”转化为“最大化奖励”,强化学习智能体沿着奖励上升的方向优化策略。该设计同时兼顾延迟 L 和功耗 E,通过权重 a、b 可灵活调节侧重点,而非极端地只关注某一项。