想象一家开在闹市区的“智慧餐厅”。每天饭点,订单像雪片一样飞来:宫保鸡丁、清蒸鲈鱼、佛跳墙……如果只靠一位大厨从洗菜、切菜、炒菜到装盘一路包办,顾客怕是要等到花儿都谢了。聪明的餐厅会这样运营:让擅长大火爆炒的师傅管热菜,让擅长火候的师傅管蒸煮,再安排一位专研秘方的老师傅负责招牌炖品——三位师傅同时开工,同一时刻能端出好几道菜。这,就是“并行执行”。而主厨如何派单、如何协调食材传递、如何让每位师傅都不闲下来,便是“调度”的艺术。AI 系统里的情形如出一辙:CPU、GPU、NPU 就像各有所长的厨师,计算任务就像一道道菜。走进这间“异构厨房”,你会发现:并行执行不是简单地把人招满,而是一场关于分工、协作与等待的精密运营。
理解并行执行与调度逻辑,是 AI 工程化的核心能力。掌握它,你就能在实际部署推理、训练系统时快速定位性能瓶颈,设计出合理的多设备方案,这是迈向高级 AI 系统工程师的必修课。
可视化演示
动态展示异构计算中并行执行的分解-分配-编排三步骤、Flynn四类分类、串并行加速对比(4x)及AI训练中的数据/张量/流水线并行组合。
本节配有交互动效(进入视口后自动加载,约 3KB)。
并行执行概念
在传统小饭馆里,老板一个人既负责点单又负责炒菜,客人再多也只能一桌一桌慢慢来——这是“串行”(Serial Execution)。而当智慧餐厅开业,老板请来多位厨师,热菜、冷盘、汤品由不同师傅同时制作,翻台率立刻翻了几倍——这就是“并行”(Parallel Execution)。并行的本质,是把“一件接一件地做”变成“多件同时推进”,让时间从加法变成取最大值。
在 AI 计算的世界里,模型推理和训练包含海量矩阵运算、卷积计算和数据处理,等价于一张张“订单”。如果处理器只有一个,这些运算只能排队;而 AI Runtime 系统会把一个大计算图拆成许多相互独立的小块,同时交给多个计算单元处理,让一条条数据流平行推进。这种“同时运行多个计算任务”的能力,正是现代深度学习框架与芯片协同设计的基石。
并行执行要成立,需要两个关键条件:一是“可拆分”,任务之间不能有无法解开的依赖;二是“可同时”,硬件必须提供多个计算通道。理想情况下,n 个任务在 n 个设备上运行,耗时从 n 段之和缩短为其中最长的单段。
就像智慧餐厅的翻台率取决于出菜最慢的那道菜,并行系统的总耗时也由最慢的任务钉死。要想再快,要么把慢任务继续拆分,要么给慢任务指派更快的“师傅”——这是后面每一节都要反复用到的直觉。
- 串行总耗时串行执行时,所有任务一个接一个地完成,总耗时等于每个任务耗时的累加,就像一位厨师炒完一道菜再炒下一道。
- 并行总耗时并行执行时,n 个任务同时启动、互不等待,总耗时由最慢的那个任务决定,就像一桌菜同时上,吃得最久的那位决定了这桌的用餐时长。
- 收益关系因为任意一项 $t_i$ 都不可能超过所有项之和,所以并行时间在数学上一定不劣于串行时间。
硬件并行基础
智慧餐厅的厨房里,灶台各有脾性:炒锅火旺,适合爆炒;蒸箱一次能蒸几十份,适合批量出品;还有一台老火汤煲,专门对付那些要炖上数小时的菜。厨师团队也因“台”制宜——不同的工作台,天生适合不同的菜式。异构计算(Heterogeneous Computing)讲的就是这个道理。
AI 系统里的“工作台”就是各种处理器。CPU 核心数不多,但单个核心能力强、逻辑判断出色,像那位什么都能做的全能大厨;GPU 有成百上千个简单计算核心,像那排能同时蒸几十份点心的蒸箱;NPU 则是为神经网络运算量身定制的专用电路,像那台专炖老火汤的汤煲。三者组合,便构成了一间“异构厨房”。
硬件并行能力决定了系统能同时“开几桌”。多核 CPU 提供 4 到 64 个通用计算通道;GPU 提供数千个并行线程;NPU 内部则排列着大量乘加单元阵列。一个处理器的理论算力,可以近似看作三个因素的乘积:
其中 $N_{\text{cores}}$ 是核心数,$f$ 是时钟频率,$\text{IPC}$ 是每个时钟周期执行的指令数。核心越多、频率越高、单周期干得越多,算力越强。
异构系统的高明之处,是不逼着所有菜都走同一个灶台——把向量密集的矩阵运算交给 GPU 的“蒸箱”,把控制逻辑留给 CPU 的“炒锅”,把神经网络算子交给 NPU 的“汤煲”。各展所长,整体出菜速度自然远超任何一位单干的大厨。
- 核心数量核心数 $N_{\text{cores}}$ 决定了能够真正同时干活的计算单元数量,如同厨房里灶台的数量,灶台越多,能同时下锅的菜越多。
- 时钟频率频率 $f$ 表示每个核心每秒能推进多少个工作周期,如同厨师手脚的快慢,频率越高,单核动作越快。
- 单周期能力IPC 表示每个时钟周期内能完成的指令数,流水线越宽、向量化越好,IPC 越高,相当于厨师一个动作同时翻炒多道菜。
- 综合算力三者相乘得到每秒完成的指令总量 $P$,即整个设备的“出菜能力”上限。
调度粒度划分
切菜的刀法决定烹饪的节奏。萝卜切成大块,炖得快但不易入味;切成细丝,容易熟却极费刀工。任务拆分也是同样的道理——粒度太大,并行度不够;粒度太小,拆分和传递的功夫反而拖慢全局。厨房里的“切菜哲学”,正是并行系统中的“粒度权衡”。
调度粒度(Granularity)指的是并行执行的基本任务单元的大小。AI Runtime 系统通常按三种粒度组织计算:最高层是任务级并行,一个模型的前向计算被拆成若干可独立执行的子图;中间是算子级并行,单个算子(如矩阵乘)内部被切分到多个设备上;底层是指令级并行,处理器在单个核心内部同时执行多条指令。
粒度越细,潜在并行度越高,但每个任务对应的调度、分发、通信开销也随之增加。设单任务调度开销为 $O_s$,总工作量为 $W$,切分为 $N$ 个任务后,总耗时可以建模为:
第一项随任务数线性上涨,第二项随任务数下降。最优粒度正是让两者之和最小的平衡点。
回到厨房:切太细,厨师光顾着切菜没空炒菜;切太粗,一个大块头霸占灶台,旁的灶台只能干瞪眼。好的总厨会依据食材性质和人力数量,选择恰到好处的“刀法”,让每个灶台都刚好有活干,这就是粒度调度的艺术。
- 调度开销项$N \times O_s$ 表示每切一刀都要付出的“切菜成本”,任务数量越多,累积的调度与分发开销越大。
- 均摊执行项$\frac{W}{N}$ 是每个任务分到的工作量。切得越细,单个任务工作量越小,各设备并行摊薄的时间越短。
- 最优粒度对总耗时求最小值,得到最优任务数 $N^*$,此时的粒度让调度成本与执行成本达到平衡。
运行时调度策略
主厨怎么派单?最简单的做法是开张前就排好班表,定死谁负责哪些桌——这是“静态调度”。但现实总有客人临时加菜、某个灶台突然出故障,于是主厨改为随时观察:哪位厨师闲着,就把菜塞给他——这是“动态调度”。更妙的是,经验丰富的餐厅还会让闲下来的厨师直接去同行面前“偷”半成品来帮炒——这就是工作窃取(Work Stealing)。
AI Runtime 系统中的调度策略,解决的是“哪个任务在哪个设备上、什么时候执行”的问题。静态调度在编译期就生成完整的执行计划,适合结构固定、耗时已知的部署模型,调度零运行时开销;动态调度则根据运行时设备负载、数据位置临时决策,适合输入形状变化大、设备状态波动的推理场景。
工作窃取是动态调度的经典实现:每个设备维护一个本地任务队列,空闲设备从其他设备的队列尾部“偷”任务执行,让负载自动趋于均衡。无论采用哪种策略,最终收益都集中体现在加速比上:
加速比大于 1 说明并行有收益;接近 1 则说明调度与同步开销已经吃掉了并行红利。
好的派单策略,是让每位厨师手上总有活、且不多到做不完。静态调度像固定班表,稳定但死板;动态调度像临场应变,灵活但每次决策都有成本;工作窃取则让闲人自动补位,是现代调度器(如 TBB、Java Fork-Join)的首选方案。
- 串行基线$T_{\text{serial}}$ 是所有任务在单个设备上依次执行的时间,作为对照的“标准出餐时间”。
- 并行耗时$T_{\text{parallel}}$ 是在当前调度策略下多设备协同完成的总耗时。
- 加速比两者相除得到加速比 Speedup,衡量并行执行比串行快了多少倍,数值越大,调度越成功。
同步与通信
厨房里最怕的不是菜多,而是配合出错。炒好的牛肉要递给负责勾芡的师傅,腌制的时间没到就不能下锅——菜与菜之间存在“先后顺序”和“食材传递”。任何一处等不到位,整条流水线就会卡壳。厨师们在共享一袋盐、一口锅时,还必须遵守默契的“先来后到”。
并行任务之间同样存在两类约束。依赖关系:一条任务的结果是另一条任务的输入,决定任务必须按序执行;同步机制:屏障(Barrier)、互斥锁(Mutex)等保证多个设备在共享数据上达成一致。此外,数据在异构设备间的搬运——从 CPU 内存拷贝到 GPU 显存——是并行执行中最为昂贵的通信成本之一。
这些同步与通信开销,让并行系统的加速比有了硬上限。Amdahl 定律给出了最经典的结论:设程序中可并行部分占比为 $p$,使用的设备数为 $N$,则:
即便设备数 $N$ 趋向无穷大,加速比也无法超过 $1/(1-p)$。那些不可并行的串行部分,就是永远拖后腿的“等菜时间”。
同步与通信就是厨房里的传菜窗口:窗口太少,师傅们互相堵塞;传递太频繁,传菜的功夫又超过了做菜本身。工程上常用“计算通信重叠”来掩盖短板——在等待数据时,先做不依赖它的其他菜,让等待时间与计算时间交错利用。
- 串行比例$1-p$ 是程序必须串行的部分占比,比如结果汇总、依赖更新,相当于必须由一人完成的收尾工序。
- 并行时间$\frac{p}{N}$ 是理想情况下并行部分被 $N$ 台设备平分后的时间占比。
- 加速后总时间分母是串行部分与并行部分的时间之和,构成整体加速后的归一化耗时。
- 极限加速比当 $N$ 趋于无穷时,$\frac{p}{N}$ 趋近 0,加速比收敛于 $\frac{1}{1-p}$,这就是硬件堆不出来的天花板。
性能分析指标
怎么判断一家餐厅经营得好不好?菜出得快(吞吐量)、等位时间短(加速比)、厨师不闲着(利用率),三者缺一不可。若只宣传“出餐速度提升十倍”,却忽略一半灶台在闲置,这样的业绩并不是真正的胜利。并行系统同样需要用多维指标来体检。
并行系统的核心指标有三类。加速比衡量“快了多少倍”,是并行最直观的成绩;吞吐量衡量“单位时间完成多少任务”,关注整体处理能力;资源利用率衡量“设备有多少时间在真正计算而非空转等待”。三者相互关联,但也可能彼此矛盾——堆上更多设备可能提高吞吐,却因为同步开销拉低利用率。
在上节 Amdahl 公式的基础上,我们可以引入并行效率 $E$,它表示加入的每台设备平均贡献了多少有效加速:
当 $E$ 接近 1 时,每加一台设备都近乎线性收益;当 $E$ 明显小于 1 时,说明大量时间在空转——此时加机器不如优化算法。
下次再听到“我们系统吞吐量翻倍”时,不妨追问一句:效率掉到了多少?就像餐厅老板不会只为翻台率开心,还会盯着后厨的闲忙比——两个指标齐平,才是健康的并行系统。
- 效率定义并行效率 $E$ 是加速比 $S$ 与设备数 $N$ 的比值,表示平均每台设备贡献了多少倍加速。
- 代入推导把加速比公式代入效率定义,得到一个关于 $N$ 和 $p$ 的显式表达。
- 趋势判断当 $N$ 增大时,分母中的 $N(1-p)$ 随之增大,效率 $E$ 持续下降——这反映了“人越多、协调损耗越大”的常识。
典型应用场景
不同餐厅有不同经营模式。连锁快餐店把所有菜品批量复制,来多少客人都照同一配方做——这是“数据并行”;私房菜馆让每位大厨专攻一道工序,协作完成一整桌菜——这是“模型并行”;农家流水席把传菜队伍排成一条线,菜在线上逐站加工——这是“流水线并行”。三种模式,构成了 AI 并行执行的主力阵容。
数据并行把训练样本切分到多台设备,每台设备持有完整模型副本,梯度汇总后统一更新,这是大模型训练的基础;模型并行把模型参数切分到多设备,每个设备只存一部分参数,解决单卡放不下完整模型的问题;流水线并行则把模型按层切分成多个阶段,设备之间像流水线一样接力计算,让计算和数据传输重叠起来。
流水线并行的节奏由最慢的阶段决定。设第 $i$ 个阶段的耗时为 $t_i$,则整条流水线的周期为:
一个阶段慢,整条流水线都跟着慢,出菜节奏被“短板工序”钉死。
三种模式可以叠加使用。大模型训练经常采用“数据并行 × 流水线并行 × 张量并行”的组合拳,把几百亿参数塞进上千张 GPU,靠的正是这几套“厨房经营模式”的排列组合。理解了场景,才能真正理解调度器为何要如此设计。
- 阶段时间每个阶段 $i$ 有固定的处理耗时 $t_i$,如同流水线上每道工序的加工时长。
- 流水周期流水线每个周期推进一个任务,周期长度等于所有阶段耗时的最大值。
- 吞吐率单位时间内完成的产物数量是周期的倒数,周期越短,单位时间走出来成品越多。
优化策略
厨房运营的终极命题是:在现有灶台和人手下,如何让出菜速度逼近理论上限?答案藏在一个朴素的道理里——让每个人都忙起来,让每道菜都少等。AI 并行系统的优化,同样围绕“消灭空闲”和“压缩等待”展开。
落到工程上,有三大优化方向。负载均衡:让各设备的工作量尽可能均等,避免“旱的旱死、涝的涝死”;关键路径优化:找到耗时最长的依赖链,给链上的任务分配更多资源或进一步拆分;调度开销控制:减少任务调度本身的频率和成本,例如批量派单、合并小任务、复用工线程池。
负载是否均衡,可以量化衡量。设各设备工作量中的最大者为 $W_{\max}$,平均值为 $W_{\text{avg}}$,则负载不均衡度定义为:
该值越接近 0,各设备负载越均衡,空闲等待越少。
回到智慧餐厅:主厨调整排班表、控制传菜窗口的开合节奏、把午市高峰备餐分成几拨——每一次优化都是在与“等待”作斗争。并行执行没有魔法,不过是把每一份等待都转化成计算,让厨房的每一秒都物有所值。
- 最大负载$W_{\max}$ 是所有设备中最繁忙那台的工作量,它决定了整体完成时间。
- 平均负载$W_{\text{avg}} = \frac{1}{N}\sum_i W_i$ 是总工作量被 $N$ 台设备平分的理想值,是均衡状态的基准。
- 不均衡度最大负载与平均负载的差值除以平均负载,得到偏离理想均衡状态的相对程度,值越小越好。
AI 应用场景
大模型分布式训练
阶段:训练阶段的数据并行与流水线调度
解决的问题:千亿参数模型单卡放不下,单机训练耗时数月。AI Runtime 将训练数据分片、模型参数按层切分,调度器把计算图并行分配到上千张 GPU。相比传统单机训练,训练时间从数月压缩到数天。
具体案例:某团队训练 70B 参数大模型,使用 512 张 A100,同时采用数据并行(每卡相同模型、不同数据)加流水线并行(按层切分成 16 个 stage),调度器动态调整微批次大小,最终训练吞吐提升约 40 倍。期间还通过工作窃取思想平衡各 stage 的负载差异。
推理服务集群的动态批处理
阶段:推理阶段的请求聚合与多设备调度
解决的问题:线上推理请求到达不均匀,传统排队方式会让 GPU 在空闲期浪费算力。Runtime 系统把请求聚合为动态 batch,由调度器按设备实时负载分发,空闲设备自动“偷”取待处理请求,实现资源和延迟的双赢。
具体案例:某云厂商的 LLM 推理服务在业务高峰时请求量突增 10 倍。调度器将文本预处理交给 CPU、模型推理交给多张 GPU、部分算子卸载到 NPU 加速,P99 延迟稳定在 200ms 以内,GPU 利用率从 35% 提升到 78%。
端侧异构芯片协同
阶段:端侧部署阶段的 CPU/GPU/NPU 协同
解决的问题:手机、汽车等端侧设备功耗和算力受限,必须按算子类型分配到最合适的处理器。调度器根据功耗模型与算子特性,把卷积类算子放到 NPU、控制类算子放到 CPU、图像处理算子放到 GPU,让整个模型并行跑起来。
具体案例:某旗舰手机运行实时人像分割模型,Runtime 将模型划分为 120 个子算子,调度到 CPU/GPU/NPU 上并行执行,相比纯 CPU 运行,帧率从 8fps 提升到 45fps,功耗下降 60%。
Python 演示
"""异构并行调度模拟: 串行 vs 多设备并行执行对比"""import heapq # 任务列表: (工作量, 偏好设备)TASKS = [ (10, 'CPU'), (20, 'GPU'), (15, 'NPU'), (8, 'CPU'), (12, 'GPU'), (25, 'NPU'), (18, 'CPU'), (6, 'GPU'),] # 设备及其速度(单位工作量/时间)DEVICES = {'CPU': 10, 'GPU': 20, 'NPU': 15} def serial_time(tasks): """串行: 所有任务在单个CPU上依次执行""" return sum(work / DEVICES['CPU'] for work, _ in tasks) def parallel_time(tasks, devices): """并行: 调度器每次把任务派给最早空闲的设备""" heap = [(0.0, name) for name in devices] # (空闲时刻, 设备名) heapq.heapify(heap) for work, pref in tasks: free_at, dev = heapq.heappop(heap) # 若偏好设备更早空闲, 则改派给它 cand = [(t, n) for t, n in heap if n == pref] if cand and cand[0][0] < free_at: heapq.heappush(heap, (free_at, dev)) free_at, dev = cand[0] heap.remove(cand[0]) heapq.heapify(heap) heapq.heappush(heap, (free_at + work / devices[dev], dev)) return max(heap)[0] def main(): serial = serial_time(TASKS) parallel = parallel_time(TASKS, DEVICES) print(f"串行总耗时: {serial:.2f} 时间单位") print(f"并行总耗时: {parallel:.2f} 时间单位") print(f"加速比: {serial / parallel:.2f}x") if __name__ == '__main__': main()
heap = [(0.0, name) for name in devices]初始化每个设备的“空闲时刻”,0 表示最开始全部空闲。free_at, dev = heapq.heappop(heap)弹出当前最早空闲的设备来接收下一个任务。cand = [(t, n) for t, n in heap if n == pref]在其余设备中查找是否存在偏好设备,尊重任务与设备的亲和性。heapq.heappush(heap, (free_at + work / devices[dev], dev))计算任务在该设备上的完成时刻,并放回堆中等待下次调度。return max(heap)[0]所有任务完成后,堆中最大的空闲时刻就是并行执行的总耗时。
常见误区
误区我觉得并行执行很简单啊,Python 里 `ThreadPoolExecutor(max_workers=100)` 一开,一百个线程一起跑,速度不就上去了?
正解多线程只是并行的形式之一,真正的并行需要硬件有多核或多设备支撑。Python 由于 GIL 的存在,多线程在 CPU 密集任务上甚至比单线程更慢;而且线程一多,调度与同步开销迅速膨胀,负载不均时大量线程在空转等待。这就像餐厅招来 100 个厨师挤在一个小厨房,转个身都难,出菜速度反而下降。
为何常见:人们容易把“并发”(看起来同时发生)与“并行”(真正同时执行)混为一谈,误以为线程数就等于并行能力。
误区我把一个大矩阵乘切成 1000 份,每份一个线程,这样并行度最高,一定最快。
正解任务粒度与并行效率呈倒 U 形关系。粒度太细时,线程创建、任务调度、数据拆分合并的开销会超过计算本身省下的时间。第 3 节的公式 $T = N \times O_s + W/N$ 说明存在最优粒度,工程上通常以“计算时间与通信时间之比”来粗调,而不是越细越好。
为何常见:“拆分”是并行最直观的动作,人们容易忽视拆分这个动作本身也要付出代价,尤其是调度与通信成本。
误区Amdahl 定律?我们集群有 1024 张卡,随便加,总能把训练时间压到接近零。
正解Amdahl 定律指出,只要存在一点必须串行的部分(比如梯度汇总、最终结果合并),加速比就有严格上限 $1/(1-p)$。假设 5% 的串行比例,极限加速比只有 20 倍。这也是为什么 8 卡能近乎线性加速,但 1024 卡时强扩展(Strong Scaling)收益极小的原因。
为何常见:人们习惯用“线性外推”的直觉看待资源扩容,忽视了并行系统中天然存在的串行瓶颈,以及通信与同步的边际成本。
误区既然有 CPU、GPU、NPU,那我把任务随便分配,反正都是做计算嘛。
正解不同设备有完全不同的擅长的计算领域和独立的内存空间。矩阵乘法在 GPU 上可能快 10 倍,但把算子搬到 GPU 前,需要先把数据从 CPU 内存拷贝到显存,一次拷贝可能耗费数百微秒;对于小算子,拷贝开销反而让整体更慢。调度器必须综合考虑设备亲和性、数据搬运成本和算子形状,才能做出合理决策。
为何常见:只盯着“设备算力峰值”一个指标,忽略了数据传输延迟与设备特性差异这两个分量,导致“看起来能跑”但“实际更慢”。
面试题
Q1. 并行执行的基本思路是什么?
- A.将大任务拆成小任务同时完成← 正确答案
- B.将大任务压缩后再依次执行
- C.让多个任务排队逐个依次执行
- D.给任务分配更高的运行优先级
答案:A。并行执行的核心是把一个大任务拆解成多个可独立执行的小任务,并让它们在不同处理单元上同时运行,就像多个厨师同时烹饪不同菜品。压缩、排队、提优先级都仍是串行逻辑,不能真正缩短总耗时。
Q2. 异构计算中的“异构”指的是什么?
- A.使用不同类型处理器协同工作← 正确答案
- B.使用多个相同型号的 CPU
- C.将程序放到不同机房去运行
- D.使用不同的操作系统和版本
答案:A。异构指多种不同类型处理器(如 CPU、GPU、NPU)协同计算,各自发挥所长,如同厨房里炒锅、蒸箱、汤煲各司其职。多颗同型号 CPU 是“同构”;不同机房和 OS 属于部署环境差异,与硬件异构无关。
Q3. Amdahl 定律指出程序加速比上限主要取决于?
- A.程序中可以并行执行的比例← 正确答案
- B.处理器主频能够达到的高度
- C.内存容量和带宽的大小
- D.磁盘读写速度的快慢程度
答案:A。Amdahl 定律 $S=1/((1-p)+p/N)$ 表明,串行部分占比 $1-p$ 决定了加速比天花板。即使加再多处理器,串行部分也无法被并行消除,因此可并行比例 $p$ 是决定性因素,主频、内存、磁盘都不是该定律的直接变量。
Q4. 工作窃取调度的核心思想是什么?
- A.空闲线程偷取忙碌线程的任务← 正确答案
- B.主线程预先平均分配好任务
- C.所有任务在所有线程间轮转
- D.把全部任务交给最快的线程
答案:A。工作窃取让每个线程维护本地任务队列,当某线程空闲时,从其他线程的队列尾部偷取任务执行,从而使负载自动均衡。预先平均分配是静态调度的思路,轮转和“全部给最快线程”都不符合动态自均衡的思想。
Q5. 并行任务粒度为何不宜划分过细?
- A.调度与通信开销会显著增加← 正确答案
- B.过细的任务难以被系统识别
- C.细粒度任务占更多磁盘空间
- D.细粒度任务会导致编译变慢
答案:A。任务粒度越细,调度、分发、数据传递的相对开销占比越大,$T=N\times O_s+W/N$ 中的第一项会吞噬并行收益。细粒度任务并不会“难以识别”,占磁盘或导致编译变慢也不是本质原因。
Q6. 流水线并行中吞吐率主要由什么决定?
- A.耗时最长的一个流水阶段← 正确答案
- B.所有流水阶段的耗时总和
- C.流水线包含的阶段总数
- D.任务进入流水线的先后顺序
答案:A。流水线周期 $T=\max_i(t_i)$,整条流水线每完成一个产物所需的时间由最慢阶段钉死,吞吐率是周期的倒数。总耗时之和、阶段数量、进入顺序都不直接决定吞吐率,短板效应才是关键。
Q7. 某程序只有 10% 可并行化,理论加速比上限约为?
- A.约 1.1 倍← 正确答案
- B.约 10 倍
- C.约 100 倍
- D.约 50 倍
答案:A。Amdahl 定律中 $p=0.1$,加速比 $S=1/((1-0.1)+0.1/N)$,当 $N\to\infty$ 时 $S\to 1/0.9\approx1.11$。许多人误以为“10% 可并行”对应“10 倍加速”,实际恰恰相反——只有极少部分能并行,加速比上限就被压得很低。
Q8. 以下哪些属于常见的并行执行模式?
- A.数据并行:数据拆分到多设备← 正确答案
- B.模型并行:模型切分到多设备← 正确答案
- C.流水线并行:按阶段分工合作← 正确答案
- D.文件压缩后并行解压的方式
答案:ABC。数据并行、模型并行、流水线并行是 AI 系统中的三大经典并行模式,分别对应“样本分片”“参数分片”“按层分阶段”。并行解压虽然涉及并行,但并非文中讨论的 AI 并行执行模式,属于干扰项。
Q9. 并行执行中需要重点处理的开销有哪些?
- A.设备间的数据拷贝通信开销← 正确答案
- B.任务调度的系统运行时开销← 正确答案
- C.同步等待造成的设备空闲← 正确答案
- D.代码注释带来的编译额外开销
答案:ABC。数据拷贝、调度决策、同步等待是并行执行三大开销源,分别对应通信成本、调度成本和空闲成本。代码注释在编译期会被忽略,不产生运行时开销,因此不属于并行系统需要处理的性能开销。
Q10. 以下措施中哪些能提升异构并行效率?
- A.按设备擅长领域分配任务← 正确答案
- B.平衡各设备之间的负载← 正确答案
- C.尽量缩短关键路径长度← 正确答案
- D.增加任务间的同步屏障数
答案:ABC。按设备特性分配提升亲和性,负载均衡减少设备空转,缩短关键路径直接压低总时长,这三者都能提升并行效率。增加同步屏障会让设备更多等待,反而降低效率,是错误选项。