假设你是除夕年夜饭的总指挥,家里来了四个厨艺不错的亲戚。你面前有两条路。第一条路:把大家全塞进唯一的大厨房,共用一张桌子——葱姜蒜、酱油醋全摊在桌上,谁需要谁伸手拿,所有人听着同一个节拍器“一、二、三,下锅!”一起动铲子。这条路又快又简单,但桌子要够大、拿东西不能排队——现实中哪有这种魔法厨房?第二条路:每家在自己厨房先炒各自的拿手菜,约好每半小时端着半成品到村口大槐树下集合,互相交换需要的菜,然后各自回家继续做。这条路慢一点,但每一步都清清楚楚、井然有序。 这两条路,就是并行计算世界里两个最经典的模型:PRAM 和 BSP。第一条路叫 PRAM,它设想一堆处理器共享一块内存、步调一致地工作,是理论家画算法蓝图的“理想厨房”;第二条路叫 BSP,它把计算切成一个个“超步”,每个超步先各干各的,再统一通信、全体集合,是工程师设计大规模系统的“村口集合制”。后来的 LogP 模型、MapReduce、Spark,都能从这两张蓝图中找到影子。这篇文章,就是带你把这桌“并行年夜饭”的后厨逻辑彻底看明白——饼为什么这么烙、队为什么这么排、活为什么这么分。
这套模型是并行系统工程师的“度量衡”:看懂它,你就能在大模型分布式训练、Spark 作业调优中一眼定位瓶颈是在计算、通信还是同步等待。
可视化演示
PRAM和BSP是两种经典并行计算理论模型,为并行算法设计提供理论基础。本文讲解PRAM模型的并行随机访问机器... 切换模式查看不同维度。
本节配有交互动效(进入视口后自动加载,约 3KB)。
PRAM并行:核心原理 动态展示关键流程与数据流动 交互控件调节参数实时渲染 f(x) = transform(x) 核心概念的可视化呈现
PRAM模型概述
假设你是除夕年夜饭的总指挥,把四个亲戚全塞进一个大厨房。大家共用一张大桌子,葱姜蒜、酱油醋全摊在桌上,谁需要谁伸手拿;所有人还听着同一个节拍器,喊到“一、二、三”,一起落刀、一起翻锅。这种“一个厨房、一张桌子、一个节拍”的想象,正是 PRAM 模型的核心。
PRAM 全称 Parallel Random Access Machine,即并行随机访问机器,由 Fortune 和 Wyllie 在 1978 年提出。它假设 p 个处理器共享一块全局内存,每个时钟周期所有处理器同步地执行一条指令——读内存、做计算、写回,步调完全一致,而且存取内存不花额外时间。设计者可以暂时忘掉缓存、总线、网络这些现实烦恼,只专注一件事:任务怎么切、结果怎么合并。
这个“理想厨房”让算法设计者能做一件现实中做不到的事:在零成本共享的假设下先画出最优并行算法,得出理论下界,再拿去真实机器上改造。例如,用 p 个处理器归约求和 n 个数,先让每个处理器算出 n/p 个数的局部和,再做两两合并:
在魔法厨房里,每人切十根葱,再两两拼盘,最后只要 log 次碰面就能端出整桌菜。但请注意:这个厨房“拿葱”是免费的,现实中共享内存要经过缓存、总线、一致性协议,跑一趟腿要花真金白银。所以 PRAM 是理论家的菜谱纸,不是硬件说明书——它告诉我们“最理想能多快”,而不承诺“现实一定这么快”。
- 本地切分阶段p 个处理器各分到 n/p 个数,各算各的局部和,耗时正比于本地任务量,这是并行带来的直接收益。
- 两两合并轮数把 p 个局部和合并成最终结果,归约树的深度是 log₂p,每轮只需要常数时间。
- 总代价上界把本地处理和合并轮数相加,用大 O 记号表示整个并行归约的渐进耗时。
PRAM读写变体
共享一张桌子,麻烦立刻来了:两个厨师同时伸手去抓同一根葱怎么办?就像课堂上抢着发言,必须有点纪律。于是研究者给 PRAM 定了几种“课堂纪律”,形成不同的模型变体。纪律越宽松,效率越高,但对“黑板”硬件的要求也越高。
第一种是 EREW(Exclusive Read Exclusive Write,互斥读互斥写):任何时刻,一个内存单元只允许一个处理器读或写,最严格也最贴近真实硬件。第二种是 CREW(Concurrent Read Exclusive Write,并发读互斥写):大家可以同时看黑板,但写黑板时只有一个人能写,很适合“广播”场景。第三种是 CRCW(Concurrent Read Concurrent Write,并发读并发写):读和写都能并发,但必须处理“多人同时写同一个格子”的冲突。
CRCW 的写冲突通常有三种仲裁策略。Common:所有处理器必须写相同的值才允许并发写,写不同值则行为未定义;Arbitrary:随便哪个处理器写成功都算赢,结果不可预测但保证是其中之一;Priority:编号最小的处理器获胜,结果确定。以广播为例,不同变体的代价差异一目了然:
课堂纪律越宽松,抢答效率越高,但教室得多装几块电子黑板。真实芯片里多端口内存很贵,所以 EREW 最接近硬件现实,而 CRCW 更多是理论家的加速道具——它证明了“如果硬件愿意,某些问题可以快到不可思议”,但也仅此而已。
- EREW 情况内存单元同一时刻只允许一个处理器读,广播必须经过二叉传播树,每轮只能翻倍扩散,耗时随 p 对数增长。
- CREW 情况允许所有人同时读同一个单元,大家直接盯着黑板看,一个时钟周期广播完成。
- 两者的差距这就是并发读带来的加速,本质上是硬件多端口能力的体现,现实中多端口内存是奢侈品。
BSP超步模型
后来年夜饭改规矩了:各家在自己厨房炒菜,约好每半小时端着半成品到村口大槐树下集合,互相换需要的菜,再回家继续炒。这个“到点集合、交换物资、再散开”的循环,就是 BSP 所说的“超步”。
BSP 全称 Bulk Synchronous Parallel,即整体同步并行,由 Valiant 于 1989 年提出。一个 BSP 程序被划分成一系列超步(superstep),每个超步严格分三段:先是局部计算,只用本地数据,不碰别人家的锅;再是通信,互相发送数据请求、交换半成品;最后是屏障同步,所有人到齐才放行进入下一个超步。
为什么要把同步设计得这么“死板”?因为并行程序最大的噩梦是数据竞争和消息乱序:你读到的到底是别人上一步的成果,还是上上步的旧账?屏障同步保证:屏障之后,所有通信数据全部可见,谁也不会读到“过期的菜”。一个超步的成本由三部分叠加:
半小时一轮的集合制,让协作变得可预测——每轮大家都干同样的活、走同样的流程。代价是:你菜炒好了也得等到集合时间才能出发,这多出来的等待,就是同步交的“税”。BSP 的设计哲学很直白:与其让混乱的异步协作不可预测,不如用纪律换确定性。
- 局部计算 w一个超步内,所有处理器本地计算耗时的最大值。大家并行干活,整轮看最慢的那个。
- 通信项 g×hh 表示该超步中每个处理器最多发送或接收的消息条数(称为 h-relation),乘以每单位数据的传输时间 g。
- 同步项 L屏障同步本身的固定开销,包括等待最慢者、交换同步消息的时间。
- 超步总成本三段严格串行,不能重叠,所以直接相加得到总耗时。
BSP关键参数
要定村口集合的规矩,先得丈量三件事:村里有几户人家、村口的路有多窄、集合点名要多久。这三件事,就是 BSP 用三个参数描述一台并行机的全部家底。
参数 p 是处理器数量,决定并行度的上限,就像村里有多少户人家能同时开火;参数 g 是通信带宽的倒数,即传送一个单位数据需要的时间,g 越大表示路越窄、通信越贵;参数 L 是屏障同步的开销,同时也是“完成一个超步所需的最短时间”——哪怕这一轮完全没有通信,也要付 L 的时间做同步点名。
如果程序共有 S 个超步,把每个超步的局部计算、通信、同步分别累加,就得到总成本公式。这个公式是 BSP 算法分析的核心工具,也是判断“该减少通信还是减少同步”的判决书:
窄路村落里,聪明的做法是少串门、一次把货带足;集合规矩多的村子,就要少开会、每轮多干点活。BSP 的价值,就是把“该少做什么”从感觉变成可计算的数字:g 大就压缩通信量 H,L 大就压缩超步数 S。这套账本,后来成了工业界设计分布式系统的底稿。
- 计算总量 W所有超步的局部计算耗时之和,即 W = Σw_s,取决于算法本身的算术量。
- 通信总量 g×HH 是所有超步通信量之和,乘以 g 后变成总通信时间,g 越大通信越贵。
- 同步总量 S×L每个超步都要付一次屏障开销 L,S 个超步就付 S 次,超步数越多开销越大。
- 总成本公式三者相加,就是 BSP 程序总运行时间的估算式。
屏障同步机制
“集合”有三个铁律:必须所有人都到齐才开讲;到齐后大家把带来的菜互相递一圈;全村都得等走得最慢的王大爷。王大爷落后多少,这轮集合就晚多久——这就是并行计算里著名的木桶效应。
屏障同步(barrier synchronization)是 BSP 的灵魂,也正是它区别于 PRAM 的地方。PRAM 假设同步是免费的、每步都同步;BSP 承认同步要花钱,于是把同步集中到每个超步的结尾一次性支付。屏障保证两件事:一是所有处理器到达后才能继续,二是屏障之前发出去的消息,屏障之后一定可见。消息不会迟到,数据不会串台。
但这份确定性有代价:一轮超步的实际耗时由最慢的处理器决定。设第 i 个处理器局部计算耗时为 wᵢ,通信耗时为 g·hᵢ,则一轮超步的实际时间约等于:
想让年夜饭早开席,要么给王大爷“开小灶”(负载均衡),要么把他的活分给别人(任务迁移),要么把多个小通信合并成大通信减少会面次数(聚合通信)。屏障同步既是 BSP 的纪律来源,也是它最主要的开销账单——理解这一点,就理解了为什么分布式系统里总有“等 straggler”的痛。
- 局部耗时取最大第 i 个处理器局部计算耗时 wᵢ,因为大家并行执行且互不等候,整轮以最大值 mᴀx wᵢ 为准。
- 同步固定开销无论干多干少,集合点名都要付 L,这个开销与工作量无关,只与同步次数有关。
- 一轮超步实际耗时局部最大值加上同步开销,得到一轮的真实成本。通信项已并入更精细的 g·h 分析。
LogP模型扩展
集合制还有个大短板:它假设村里任何两家之间串门的时间都一样,即通信延迟与目标位置无关。但真实世界不是这样——去村东头的路窄,去村西头的路宽,出门还得先穿鞋。LogP 模型就是给 BSP 装上“交通导航”,把所有路况细节标给算法看。
LogP 由 Culler 等人在 1993 年提出,用四个参数刻画真实网络的脾气:L(Latency)是消息在网络上端到端延迟的上限;o(overhead)是发送或接收一条消息时 CPU 付出的打包、拆包开销;g(gap)是连续发送两条消息之间的最小间隔,本质是带宽的倒数;P 是处理器个数。相比 BSP 的“均匀通信”假设,LogP 把每次消息的代价拆得更细。
有了这些参数,算法设计者就能精算“发一条消息到底要多少钱”。一条小消息从发送到接收,整体代价大约由延迟和双重开销构成:
LogP 就像一份交通地图:哪里有红绿灯(o)、哪里限速(g)、哪条路很长(L)。算法设计者据此决定消息该多大、该多频繁地发——这是 MPI 级消息优化的必修课。但注意,精细是有代价的:LogP 分析起来更繁琐,所以工业界的粗粒度框架依然偏爱 BSP 的简洁。
- 线路延迟 L消息在网络上从一个节点传到另一个节点花费的时间,由物理距离和网络设备决定。
- 双重开销 2o发送端打包一次付出 o,接收端解包再付出 o,所以是两倍的 o。
- 端到端总时间短消息太小,链路带宽的间隔 g 派不上用场,只保留延迟和双重开销。
工业系统映射
互联网大厂既没有魔法厨房,也没有村口大槐树,他们用的是流水线食堂:Map 是每位窗口师傅先把分到的菜洗好切好;Shuffle 是传菜通道,把切好的菜按菜名统一送到指定窗口;Reduce 是窗口大师傅把分到的材料汇总成菜。Spark 还在食堂里加了“记账本”(RDD 血缘),菜被碰倒了(节点故障),翻账本就能重做。
MapReduce 的两大阶段天然构成一个超步:所有 Map 任务必须全部完成,才能开始 Shuffle,然后进入 Reduce。“等待所有 Map 完成”这一条,正是屏障同步的语义。Spark 更进一步:以 Shuffle 为边界划分 stage,一个 stage 内是窄依赖的本地管道计算,stage 之间宽依赖触发的 Shuffle 就是超步间的屏障。
一个作业的总耗时可以近似拆成三段,分别对应超步的局部计算、通信和归约。这也是数据工程师排查 Spark 作业慢的入手点——先看卡在哪一段:
流水线食堂能在大厂运转,靠的正是严格继承超步的纪律:Map 没做完,Reduce 窗口绝不打开。数据工程师写的 map/reduce 算子,本质上就是在指定“每一轮超步的局部计算函数”;Spark 的 RDD 血缘则是给超步加了容错——哪一桌菜洒了,按记账本从头重做那一轮,而不是全食堂重来。
- Map 阶段耗时所有 Map 任务并行执行,整个阶段取完成时间的最大值,一个超慢的 Map 任务会拖垮整段。
- Shuffle 阶段耗时中间数据在网络中重排,通信量与数据规模成正比,类似 BSP 的 g×H 通信开销。
- Reduce 阶段耗时所有 Reduce 任务并行归约,同样取向最慢者看齐。
算法设计指导
学完这些模型,等于拿到一份择业指南:想当理论厨师,先在 PRAM 的理想厨房里锤炼刀工,搞清楚“最少几步能出菜”;想到真实饭店后厨干活,按 BSP 的轮次安排出菜,算清楚每轮该备多少料;要精算物流成本,用 LogP 的路线图优化每趟配送。
不同模型服务于不同的抽象层次。PRAM 帮你想清楚“并行度的理论下限”:某些问题无论怎么切都有最短时间,适合推导算法下界;BSP 帮你在“计算与通信之间权衡”:用 g 和 L 估时间,决定每个超步装多少活;LogP 帮你在消息层面精算:消息发多大、发多频繁。三者不是替代关系,而是不同精细度的尺子。
评价一个并行算法好不好,有个通用指标叫并行效率,它衡量“花钱雇了 p 个厨师,有没有真的快 p 倍”:
就像考厨师证前先画菜谱蓝图——纸上设计里省下的每一次白跑,都是上线后的真金白银。实践中有个朴素的决策口诀:g 很大时优先减少通信量 H,L 很大时优先减少超步数 S,E 长期低于一半就该考虑换算法或换并行策略。这三张蓝图,分别对应理论、工程、精细优化三个层次,按需取用,才是成熟工程师的姿势。
- 串行最优时间 T_s单处理器解决同一问题的最优耗时,是衡量并行收益的基准线。
- 并行总资源 p×T_pp 个处理器并行执行花了 T_p 时间,总资源消耗是 p×T_p,其中包含同步与通信造成的浪费。
- 效率定义两者相除,E 接近 1 表示接近线性加速,E 远小于 1 表示开销吃掉了并行收益。
AI 应用场景
大模型分布式训练中的梯度同步
阶段:模型训练(分布式训练)
解决的问题:千亿参数的大模型单卡放不下,必须数据并行。若没有同步纪律,各卡用各自的小批量梯度更新参数,模型会漂移不一致。借鉴 BSP 的超步思想:每个训练步就是一个超步——前向与反向传播是局部计算,AllReduce 通信交换梯度是 h-relation,全局屏障后再统一更新权重。传统的朴素做法是各卡各自更新、完全不设屏障,模型质量难以保证。
具体案例:训练 Llama 这类模型时往往动用数百到数千张 GPU,每张卡的梯度要通过 AllReduce 汇总。某张卡因为散热降频变慢,整个训练步都被拖长——这就是屏障同步下的木桶效应。工程团队用梯度压缩、通信与计算重叠(把通信藏进下一层计算里)来降低超步成本。
Spark 特征工程中的 Shuffle 屏障
阶段:数据处理与特征工程
解决的问题:AI 项目 80% 的时间花在洗数据上。传统单机脚本处理亿级日志既慢又容易内存溢出;Spark 将每个 stage 视为一个“超步”,工程师只需写 map/filter/reduceByKey 这类局部算子,Shuffle 的屏障、容错与调度全部交给框架。理解了超步模型,就明白为什么一个倾斜的 key(少数 key 数据量巨大)会拖垮整个 stage——它让那次 Shuffle 的通信量 h 暴涨。
具体案例:某推荐系统每天处理 10 亿条用户行为日志,用 Spark 的 map 提取字段、reduceByKey 按用户聚合特征。某个热门用户产生海量点击,造成数据倾斜,对应 Reduce 任务成为 straggler。工程师借鉴“负载均衡”思想,用加盐预聚合把大 key 拆小,再二次聚合,本质就是给“王大爷”分活。
多卡推理的张量并行
阶段:模型推理与部署
解决的问题:在线推理要求低延迟,单卡装不下大模型时要把张量切到多卡。每次前向传播都要 all-gather 交换激活值,通信开销接近 BSP 的 g×h 模型;用 LogP 参数估算每轮通信耗时,可以决定张量并行度、batch 大小,以及是否值得做流水线并行。
具体案例:vLLM 和 TensorRT-LLM 等推理框架中,8 卡推理一个大模型时,每一层 Transformer 的前向都是一次微型的“超步”:本地矩阵乘 + all-gather 通信 + 屏障等待。工程师用带宽 g 和延迟 L 评估,发现通信占比过高时会改用张量切分更少但更深的流水线并行,减少每轮通信量。
Python 演示
"""用 Python 模拟 BSP 超步模型: 4 位厨师协作准备年夜饭. 超步 1: 局部计算, 各厨师在自家厨房处理手头食材屏障 1: 全员到齐, 谁也不能提前进入通信超步 2: 通信, 把局部结果写到共享黑板屏障 2: 确认黑板写齐全超步 3: 主厨汇总所有成果(归约输出)"""import randomimport threadingimport time class Chef(threading.Thread): """一位厨师 = 一个 BSP 处理器, 只做自己手里的活.""" def __init__(self, wid, dishes, barrier, blackboard): super().__init__() self.wid = wid self.dishes = dishes self.barrier = barrier self.blackboard = blackboard self.local_result = 0 def cook(self, dish): # 每道菜耗时不同, 有的厨师快有的慢, 模拟负载不均 time.sleep(random.uniform(0.05, 0.25)) return len(dish) # 每道菜折算成份数 def run(self): # 超步 1: 局部计算, 只碰自己的食材 for dish in self.dishes: self.local_result += self.cook(dish) self.barrier.wait() # 屏障 1: 等所有厨师做完这一步 # 超步 2: 通信, 把局部结果写到共享黑板 self.blackboard[self.wid] = self.local_result self.barrier.wait() # 屏障 2: 保证黑板写齐全 # 超步 3: 只有主厨汇总, 避免写冲突 (类似 EREW 纪律) if self.wid == 0: total = sum(self.blackboard.values()) print("最终总份数 =", total) if __name__ == "__main__": random.seed(42) menu = { 0: ["番茄", "鸡蛋"], 1: ["土豆", "牛肉"], 2: ["青菜", "豆腐"], 3: ["鱼", "姜丝"], } barrier = threading.Barrier(4) # 4 个参与者到齐才放行 blackboard = {} chefs = [Chef(wid, menu[wid], barrier, blackboard) for wid in range(4)] for chef in chefs: chef.start() for chef in chefs: chef.join()
class Chef(threading.Thread):每个厨师是一个独立线程,对应 BSP 中的一个处理器,只做自己手里的活。self.barrier = barrier所有厨师持有同一个屏障对象,保证同步的是同一批人,这正是 BSP 的“全村集合”。time.sleep(random.uniform(0.05, 0.25))模拟不同厨师速度不同,制造负载不均,让木桶效应真实发生。self.barrier.wait()屏障同步:线程阻塞在此,直到 4 位厨师全部到齐才放行,对应超步结尾的同步。self.blackboard[self.wid] = self.local_result通信阶段:把局部结果写到共享“黑板”,供主厨读取。if self.wid == 0:只让主厨汇总,避免多线程同时写结果,这是 EREW 式互斥纪律的体现。threading.Barrier(4)创建可容纳 4 个参与者的屏障,参与者数量必须与厨师线程数一致,否则会卡死或报错。chef.join()主线程等待所有厨师线程结束,相当于程序终点的最后一次同步。
常见误区
误区“PRAM 假设大家共享一块内存,那我写好的程序直接放到一台大内存服务器上跑,速度自然就快了吧?”
正解PRAM 是理论模型,它的“共享内存”假设每一步存取都零成本、带宽无限大。现实中的共享内存要经过缓存、总线、缓存一致性协议,来回跑一趟的代价高得多。PRAM 只用来做算法正确性分析和下界推导,不能当硬件手册。就像“理想厨房”里随手拿葱不花时间,真实厨房的冰箱来回跑腿会累死人。
为何常见:模型名字里带“机器”二字,初学者很容易把抽象模型直接等同于实物,忽略了它建立在大量理想化假设之上。
误区“多设几个屏障,大家多集合几次,数据不就一直一致了吗?同步开销应该可以忽略不计。”
正解每次屏障都要付固定成本 L,而且所有处理器要集体等待最慢者。屏障太少可能产生数据竞争,屏障太多则性能暴跌。BSP 的核心权衡就是:总成本 T = W + gH + SL,超步数 S 每多一个就多付一份 L。工程师的目标是“够用就好”,而不是“越多越好”。
为何常见:单线程编程里没有“等人”的概念,很多人意识不到同步不是零成本的,更意识不到等一个慢节点的代价。
误区“CRCW 允许并发读并发写,约束最少,理论上步数最少,肯定选它设计算法最划算。”
正解CRCW 确实能把某些问题的理论步数从 O(log n) 降到 O(1),比如找最大值。但并发写需要硬件支持冲突仲裁(Common/Arbitrary/Priority),真实芯片几乎不支持,软件模拟反而要加锁,成本更高。因此实际系统里的算法大多按 EREW 或 CREW 设计,CRCW 主要用于理论证明“理想情况下能多快”。
为何常见:只看纸面上的算法步数,忽略了模型假设在硬件上的实现成本,把理论加速误当成免费午餐。
误区“BSP 假设任意两处理器通信时间相同,太假了;LogP 参数更细更真实,所以直接抛弃 BSP 就好。”
正解BSP 的均匀通信假设让它非常适合粗粒度的算法设计和性能预测——简单、可算、易推广;LogP 增加 o/g/L 细节,适合消息级优化,比如 MPI 程序的消息尺寸规划。两者抽象层次不同,工业界的 MapReduce 和 Spark 结构上更接近 BSP 而非 LogP。更精细不等于更正确,简洁模型在工程中往往更有生命力。
为何常见:人们容易把“参数更细致”误认为“更先进”,却忽略了分析复杂度和使用场景的匹配。
误区“Shuffle 就是把 Map 的输出发给 Reduce,纯粹是数据传输,跟屏障同步没有半点关系。”
正解框架必须等所有 Map 任务完成后才开始 Shuffle,Reduce 才能启动,这个“等待全部完成”正是屏障语义。Spark 的 stage 边界也以 Shuffle 触发的宽依赖划分,前后阶段天然超步化。理解这点,才能解释为什么一个拖沓的 Map 任务(straggler)会拖垮整个作业——木桶效应在工业系统里每天都在发生。
为何常见:用户只看到 map/reduce 算子,看不到调度器背后的同步机制,于是把框架的纪律当成透明背景。
面试题
Q1. PRAM 模型的英文全称是?
- A.Parallel Random Access Machine← 正确答案
- B.Parallel Real Access Memory
- C.Processor Random Arithmetic Model
- D.Parallel Reduced Abstract Machine
答案:A。PRAM 全称是 Parallel Random Access Machine,即并行随机访问机器,强调多个处理器通过共享内存进行随机访问。B、C、D 都是编造的词组,混淆了 Access 的宾语(Machine 而非 Memory)和模型性质(随机访问而非运算)。
Q2. BSP 模型中,一个超步结束时所有处理器必须执行的机制是?
- A.抢占式调度
- B.屏障同步← 正确答案
- C.消息重传
- D.缓存刷新
答案:B。BSP 的每个超步以屏障同步收尾,所有处理器到齐才放行进入下一超步,类似“年夜饭人到齐才开席”。抢占式调度是操作系统概念,消息重传是网络容错,缓存刷新是硬件一致性,都不是 BSP 的同步机制。
Q3. PRAM 模型中,多个处理器如何访问数据?
- A.通过消息传递互发数据
- B.共享一块全局内存← 正确答案
- C.通过磁盘交换数据
- D.通过数据库读写数据
答案:B。PRAM 的核心假设是共享一块全局内存,任何处理器都能在常数时间内随机访问任意单元,类似于多位厨师共用一张大桌子。消息传递是 MPI 等并行模型的思路,磁盘和数据库的访问代价远高于共享内存,不符合 PRAM 的零成本假设。
Q4. 在 CRCW 的写冲突处理策略中,Priority(优先写)的含义是?
- A.所有处理器写入的值必须相同
- B.编号最小的处理器写入成功← 正确答案
- C.任意一个处理器写入成功
- D.所有处理器轮流写入同一个单元
答案:B。Priority 策略规定按优先级(通常是处理器编号)决定谁获胜,编号最小者写入成功,结果确定。A 是 Common 策略,C 是 Arbitrary 策略,D 则不属于标准 CRCW 冲突处理策略。三种策略的差别在于“谁来定胜负”:大家商量、随便赢、还是按资历排。
Q5. 一个 BSP 超步包含哪三个阶段?
- A.读取、计算、写回
- B.局部计算、通信、屏障同步← 正确答案
- C.划分、映射、归约
- D.加载、执行、存储
答案:B。BSP 超步的三段是:局部计算(只用本地数据)、通信(互相交换数据请求)、屏障同步(全员到齐才放行),成本公式为 w + g·h + L。A 是单条指令的执行流程,C 是 MapReduce 的思维框架,D 是冯·诺依曼结构的取指-执行-访存描述,都混淆了抽象层次。
Q6. 在 MapReduce 中,哪一阶段最接近 BSP 超步间的屏障同步?
- A.Map 阶段的内部循环
- B.Shuffle 阶段(等待所有 Map 完成后重排中间数据)← 正确答案
- C.输入数据的分片阶段
- D.输出结果落盘阶段
答案:B。框架必须等所有 Map 任务全部完成后才开始 Shuffle,Reduce 才能启动,“等待全部完成”正是屏障同步的语义。Map 内部循环是局部计算,分片是任务划分,落盘是输出持久化,它们都不涉及“全员到齐”的同步约束。
Q7. BSP 模型中参数 g 表示什么?
- A.处理器的计算主频
- B.单位数据的通信时间(带宽的倒数)← 正确答案
- C.屏障同步发生的次数
- D.本地缓存的容量大小
答案:B。g 是通信带宽的倒数,即传送一个单位数据所需的时间,g 越大表示通信越昂贵,算法应尽量减少通信量 H。处理器主频是硬件性能指标,同步次数属于超步数 S 的范畴,缓存容量则不是 BSP 描述的参数。
Q8. 4 个处理器做各自任务,局部计算耗时分别为 10 秒、8 秒、12 秒、15 秒,执行一轮带屏障同步的超步(忽略通信),该轮总耗时约为?
- A.15 秒← 正确答案
- B.10 秒
- C.45 秒
- D.12 秒
答案:A。屏障同步要求所有处理器到齐才放行,所以整轮耗时由最慢者决定,即 15 秒,这就是木桶效应。45 秒是把四个耗时相加,误以为串行执行;10 秒和 12 秒都忽略了最慢的 15 秒处理器。快处理器完成后再快也得等待,同步的代价正在于此。
Q9. 以下哪些属于 PRAM 模型的读写变体?
- A.EREW(互斥读互斥写)← 正确答案
- B.CREW(并发读互斥写)← 正确答案
- C.CRCW(并发读并发写)← 正确答案
- D.BSP(整体同步并行)
答案:ABC。PRAM 按并发读写能力分为 EREW、CREW、CRCW 三个经典变体,对应“课堂纪律”从严格到宽松。BSP 是另一种独立的并行计算模型,强调超步和屏障同步,不属于 PRAM 的变体。注意区分“内存访问纪律”与“同步计算模型”两个不同维度。
Q10. 关于 LogP 模型,下列说法正确的有?
- A.L 表示消息端到端延迟的上限← 正确答案
- B.o 表示发送或接收消息时 CPU 打包解包的开销← 正确答案
- C.g 表示连续发送两条消息的最小间隔(带宽倒数)← 正确答案
- D.P 表示可用的消息缓存条数
答案:ABC。LogP 的四个参数是 L(Latency,端到端延迟上限)、o(overhead,收发消息的 CPU 开销)、g(gap,连续消息间的最小间隔,即带宽倒数)、P(处理器个数)。D 把 P 说成消息缓存条数,是对参数含义的误读。LogP 相对 BSP 的贡献,正是把通信成本拆成了延迟、开销、带宽三个维度。