计算机体系结构 26:并行程序的扩展上限
计算机体系结构 26:并行程序的扩展上限
核心问题
线程数翻倍,运行时间为什么很少恰好减半?固定问题规模时,可并行部分只是上限的一项。线程创建与归约会增加额外工作,共享缓存和内存通道会引入竞争,任务划分还可能让部分线程提前空闲。
本篇只分析强扩展:总工作量固定为 300000 次写入,线程数取 1、2、4。它回答当前宿主上的样本怎样读,不把一次短基准外推成处理器的固定扩展率。
附件:26-scaling.json。
范围与证据等级
实验包含三组工作负载。independent 把不同下标分给不同线程;compact 让线程更新相邻的 C11 relaxed 原子计数器;spaced256 把计数器间距扩大到 256 字节。每个组合运行 5 次,计时覆盖 pthread_create 和 pthread_join,每次都校验结果。
证据等级为真机测量,但结论只适用于当前 Linux x86-64 宿主、固定输入和本次进程状态。没有绑核、固定频率、PMU、缓存缺失计数或内存带宽计数,因此不能把耗时变化归因为某个硬件事件。
理想上限为什么不等于测量结果
若串行占比为 s,并行部分能被 p 个执行者均分,Amdahl 上限为:
1 | |
这个式子假定增加线程不会产生额外代价。真实程序还要支付线程管理、同步、末级缓存和内存带宽竞争。固定总工作量又使每个线程分到的任务越来越小,管理成本占比随之上升。
本次 independent 的中位时间从 1 线程的 1.330 ms 变为 2 线程的 1.002 ms,4 线程为 1.534 ms。4 线程变慢只能证明这组短任务没有继续扩展,不能单凭墙钟判断是带宽饱和、调度迁移还是线程管理占主导。
核心案例:相邻计数器与间隔计数器
compact 与 spaced256 都执行相同次数的原子加法,最终校验和都是 300000。它们改变的是计数器地址布局。当前样本中,4 线程 compact 中位时间为 4.467 ms,spaced256 为 1.548 ms。
这组对照符合伪共享的典型症状:线程写不同变量,但变量可能落在同一 cache line,所有权仍会反复迁移。不过 256 字节间距和墙钟差异不能单独证明缓存行大小,也不能排除调度与频率变化。要把“符合”升级为“确认”,还需要缓存行信息、线程亲和性和 coherence/PMU 计数。
模式:先固定工作,再拆新增成本
并行扩展实验可以写成:
1 | |
数据库分片、并行编译和批处理归约都能复用这个拆法。先固定输入与结果,再改变并行度;若总工作也随线程数改变,就不再是同一组强扩展实验。
验收结果
运行命令:
1 | |
本批产生 3 类工作负载 × 3 个线程数 × 5 次重复,共 45 个样本;所有 checksum == expected。CLI 的 --help 成功,负数、尾部垃圾和超过 64 的线程数都以非零状态拒绝。
验收结论是:固定问题规模下,当前宿主的 2 线程样本有收益,4 线程没有继续缩短独立写入的中位时间;相邻原子计数器在本次 4 线程样本中明显慢于 256 字节间隔布局。没有证据把差异唯一归因于带宽或伪共享。
练习
若串行占比为 10%,计算 4 线程的理想加速上限。再说明为什么这个值不能代替真实测量。
把总工作量随线程数同比增加后再比较吞吐,这属于强扩展还是弱扩展?此时哪些成本口径需要重新定义?
模式速查
| 观察 | 优先检查 | 不能直接下的结论 |
|---|---|---|
| 加线程后变慢 | 粒度、启动、同步、调度 | 已证明内存带宽饱和 |
| 相邻计数器更慢 | 地址间距、亲和性、cache line 事件 | 差异只来自伪共享 |
| 校验和相同 | 功能结果一致 | 性能机制已经定位 |






