2025-11-19 21:36:02
Amdahl 定律 vs Gustafson 定律:完整教程、推导、应用场景及 Python 绘图
理解并行加速:通过代码讲解 Amdahl 定律和 Gustafson 定律
并行计算基础:Amdahl 定律、Gustafson 定律及加速建模
并行加速原理:Amdahl 和 Gustafson 定律完整指南
并行扩展解析:推导并比较 Amdahl 和 Gustafson 定律
Amdahl vs Gustafson:并行加速完整指南(含 Python 代码)
并行性能建模:Amdahl 定律、Gustafson 定律及实际应用
学习并行加速:数学、直觉、应用场景及 Python 可视化
并行计算:必须掌握的两条定律(Amdahl & Gustafson)
工程师的并行加速:Amdahl 定律、Gustafson 定律及 Python 实现
从理论到代码:用 Amdahl 和 Gustafson 建模并行加速
实用并行加速指南:Amdahl 定律、Gustafson 定律及可视化
为什么并行不是无限的:简单解释 Amdahl vs Gustafson
并行加速真相:Amdahl 限制 vs Gustafson 扩展
并行计算神话与现实:Amdahl 和 Gustafson 的教训
并行计算在现代计算中至关重要:多核 CPU、GPU、分布式集群、云工作负载、LLM 训练以及 HPC 模拟。
为了分析程序在更多处理器下能加速多少,主要有两种数学模型:
这两条定律并不矛盾,它们回答的是 不同的问题。
本教程涵盖推导、直觉、比较、实际应用场景,以及展示两条定律的 Python 绘图脚本。
加速比衡量程序在 N 个处理器上运行速度提升多少:

如果程序在一个处理器上运行 10 秒,两处理器运行 5 秒,则加速比为:

完美线性加速为:

但实际系统存在串行瓶颈,这正是 Amdahl 定律和 Gustafson 定律描述的内容。
Amdahl 假设:
设:
f = 串行比例1 - f = 可并行比例一个处理器的运行时间:

定义:

因此:


N 个处理器的运行时间:

加速比:

其中 f 是串行工作比例,
是可并行工作。Amdahl 公式也可以写成:

其中
,

如果串行比例为 10%(f = 0.1):

即使处理器无限,也无法超过该值。
Amdahl 适合优化固定任务的 延迟:
Gustafson 反过来问:
“增加处理器,我能在相同时间内解决多大的问题?”
这反映了真实 HPC 工作负载:更多 CPU → 更高分辨率 → 更大模拟。
假设程序在 N 个处理器上运行 1 个时间单位。
设:
f = 串行比例(按规模测量)可并行部分随处理器数量扩展,因此其运行时间保持与 N 成比例。
一个处理器的时间:

加速比:

Gustafson 公式的 “N 减” 形式:

或者,如果定义并行比例
,公式也可写为:

“N 减” 形式用 p 表示:

随着 N 增加,加速比趋近于:

对于小串行比例,几乎呈线性增长。
Gustafson 适用于 吞吐量扩展 或可增加问题规模的工作负载:
| 项目 | Amdahl | Gustafson |
|---|---|---|
| 工作负载 | 固定 | 随 N 扩展 |
| 目标 | 降低延迟 | 增加吞吐量 |
| 加速比上限 | 有界:
|
近似线性:
|
| 悲观/乐观 | 悲观 | 乐观 |
| 应用场景 | 优化现有任务 | 扩展大规模工作量 |
下面代码生成 Amdahl 与 Gustafson 加速比曲线图。
可以调整 f(串行比例)和处理器数量 N。
脚本绘制两条曲线在同一张图上。
包括部分
的值,例如串行部分:
import numpy as np
import matplotlib.pyplot as plt
def amdahl_speedup(N, s):
return 1.0 / (s + (1 - s) / N)
def gustafson_speedup(N, s):
return s + (1 - s) * N
# Number of processors
N = np.arange(1, 65)
# Serial fractions to consider
Serial = [0.05, 0.1, 0.2, 0.3, 0.5, 0.8, 0.9, 1.0]
plt.figure(figsize=(10, 6))
for f in Serial:
plt.plot(N, amdahl_speedup(N, f), linestyle='-', label=f"Amdahl Serial={f}")
plt.plot(N, gustafson_speedup(N, f), linestyle='--', label=f"Gustafson Serial={f}")
plt.title("Amdahl's Law")
plt.xlabel("Number of Processors (N)")
plt.ylabel("Speedup")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.savefig("parallel-speedup-amdahl-vs-gustafson.png")
## plt.show()
下面是 Amdahl 与 Gustafson 曲线图示。
f 越高,两种模型差距越大。Amdahl 定律展示了固定工作负载下的并行 上限,适合延迟优化。Gustafson 定律展示了随工作负载扩展的并行 潜力。
它们共同构成现代并行系统性能分析基础,从 HPC 到 LLM 训练,再到 GPU 计算。
英文:The Truth About Parallel Speedup: Amdahl’s Limits vs Gustafson’s Scaling
本文一共 1384 个汉字, 你数一下对不对.
2025-11-19 05:20:08
今天早上,我突然收到了一大堆报警,我手下的15个网站都报警了,收到了很多邮件,这很不正常,有的时候是报警的程序自己的问题,因为其中的一个邮件报警是我自己写的。 但是我核实了一下,确实打不开,显示是500服务器内部错误,这个错误一般就是服务器配置错误崩溃造成的。但我细眼一看,是CloudFlare的服务器的问题。这可是我第一次见。
Cloudflare 已经是互联网基础设施级服务,一旦宕机影响面巨大。这次事故暴露了去中心化互联网在实际运行中高度中心化的问题。
CloudFlare按现在最新数据,有750万个网站,排名/流量最高的1万个中有33%是用CloudFlare,所以这次宕机的影响之深,还好,这次友宕机也就三个小时左右,这次宕机影响到了很多服务,其中X和ChatGPT都打不开了,中间还陆陆续续间断的恢复过几分钟时间。
18 日,全球知名的网络基础设施服务商 Cloudflare 发布公告称,其全球网络出现大范围异常,导致大量网站和应用出现访问中断。受影响的平台包括 X(前 Twitter)、ChatGPT 等多家核心互联网服务,有媒体报道称 Spotify、亚马逊部分服务也出现了故障。
受此次事故影响,Cloudflare 股价在盘前一度下跌超过 5%。
按照官网介绍,Cloudflare 是一家全球性的云网络平台,为各类规模的企业提供安全加速、内容分发、DNS、零信任等服务。其数据传输网络覆盖全球 125 个国家、330 座城市,是互联网“入口层”的关键基础设施之一。Cloudflare 于 2019 年 9 月 13 日在纽约证券交易所上市。
北京时间 19:17(伦敦时间 11:17),Cloudflare 状态页显示,其支持门户出现故障,客户在查看或回复支持工单时可能遇到错误。大约半小时后,Cloudflare 再次更新称公司正在经历“内部服务故障”,部分服务可能会出现间歇性异常。
又过了约 20 分钟,Cloudflare 表示整体中断情况已开始缓解,但仍在调查问题根源。至北京时间 21:13,官方最新状态指出,部分服务的错误率“已恢复到事件发生前的水平”,同时团队正在继续恢复其余受影响的服务。
X、ChatGPT 等多个互联网平台仍受到此次故障影响。X 上用户的帖子会显示“无法载入”等提示,访问仍不稳定。
NET。| 编码 | 说明 |
|---|---|
| 500 | 通用错误,source 或 Cloudflare 本身都可能产生。 |
| 502 | Bad Gateway,Cloudflare→源站连接问题。 |
| 520 | 源站返回空或格式不正确的响应。 |
| 521 | 源站拒绝连接。 |
| 522 | Cloudflare→源站连接超时。 |
| 524 | 源站处理超时。 |
curl -I -H "Host: yourdomain.com" http://YOUR_ORIGIN_IP
server: cloudflare 或 cf-ray。https://www.cloudflarestatus.com/
再强的基础设施也会宕机。互联网架构虽然理论去中心化,但现实中高度依赖少数大型服务商。
前几周的AWS因为dynamodb的DNSRace Condition的BUG,也是影响了互联网大半个江山,因为都是互联网基础服务,不过CloudFlare更是,因为从用户在浏览器打域名后,CloudFlare就接管了,只是到最后面的服务器不是在CloudFlare,前面的流量都被CF牢牢控制。从另一个角度也说明了CF的重要性,掌握了入口和流量。
这次 Cloudflare 宕机是一次非常典型的 “单点故障课” – Single Point of Failure。
没法摸鱼,因为微软网站都可以用,还得继续搬砖写代码。不过ChatGPT用不了,感觉效率大大降低(但是可以试试其它服务,比如Copilot)
2025-11-16 04:44:45
视频:油管/Youtube | B站/小破站 | 微博视频 | 西瓜视频 | 微信视频号 | X/推特 | 小红书 | Facebook
组合计数是在顺序不重要时选择项目的方式。我们从一个简单的格子行走示例出发建立直觉,介绍二项式记号,推导公式,解释递推关系
,并把所有内容联系到帕斯卡三角。
想象你只能向右(R)或向上(U)移动。要从左下走到需要三次向右和两次向上的点,每一条最短路径都是由五步组成的序列,其中包含三个 R 和两个 U。
每条有效路径只是从五个位置中选择两个放 U(其余为 R)。所以这样的路径数就是“从 5 中选 2”,记作
(等于
)。
示例序列:
R R U R U U R R R U R U R R U R R R U U U U R R R
从
个项目中选出
个(顺序不重要)的方式数记为

或

两者都表示“从 n 中选 m”。
先计算有序选择(排列):从 n 个不同项目中取出长度为
的有序列表的数量为

每一个无序的
项集合对应
个有序列表(即这 m 项的排列)。除以
得到组合数:

对于总步数
和向上步数
:

因此共有 10 条不同的最短路径。
个位置中选择放置 U 的
个位置;这就是
。把
写成行可以形成帕斯卡三角:
1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1
这些项满足递推关系

然后,我们可以很容易的写出至顶向下的动态规划算法实现(用@cache实现记忆化式的递归搜索):
from functools import cache
@cache
def C(n, m):
if m == 0:
return 1 # C(n, 0) = 1
if m == n:
return 1 # C(n, n) = 1
return C(n-1, m-1) + C(n-1, m)
当然,也可以用自底向上的方式实现:
def C_bottom_up(n, m):
dp = [[0]*(m+1) for _ in range(n+1)]
for i in range(n+1):
dp[i][0] = 1 # C(i, 0) = 1
for j in range(1, min(i, m)+1):
if j == i:
dp[i][j] = 1 # C(i, i) = 1
else:
dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
return dp[n][m]
这个自底向上的实现直接从小问题累加到大问题,避免了递归开销,同时也很容易扩展到计算整个帕斯卡三角。
组合数的自底向上 DP 可以用 一维数组优化,利用 滚动数组 原理,因为每一行的计算只依赖上一行。重点是从 右往左更新,这样不会覆盖还没用到的数据。
下面是实现示例:
def C_one_dim(n, m):
dp = [0] * (m+1)
dp[0] = 1 # C(i, 0) = 1
for i in range(1, n+1):
# 从右往左更新,避免覆盖上一行数据
for j in range(min(i, m), 0, -1):
dp[j] = dp[j] + dp[j-1]
return dp[m]
示例:
print(C_one_dim(5, 2)) # 输出 10
✅ 优点:
想要从
个苹果中选
个。考虑最后一个苹果(编号为 n):
如果你选了它,那就必须从前面的
个中选剩下的
个:有
种方法。
如果你不选它,那就必须从前面的
个中选出全部
个:有
种方法。
这两个互不相交的情况覆盖了所有可能,因此

(该恒等式正是构造帕斯卡三角的规则。)
在格子上,观察到达某点的任意路径的最后一步:要么是 R,要么是 U。以 R 结尾的路径来自某个前一点,以 U 结尾的路径来自另一个前一点。把这两组路径分别计数并相加就得到相同的加法规则。
(选择零个)。
(选择一个)。
(选择全部)。
当
时的小表:
C(5,0)=1 C(5,1)=5 C(5,2)=10 C(5,3)=10 C(5,4)=5 C(5,5)=1
组合出现在路径计数、二项式展开(系数)、概率与选择问题中。阶乘公式提供直接计算方法,而帕斯卡三角与递推关系则提供归纳直觉和高效构造数值的方式。格子行走示例是将“选择位置”等同于“选择步序”这一组合核心思想可视化的具体方法。
英文:Teaching Kids Programming – Introduction to Combinatorial Mathematics 1
本文一共 1176 个汉字, 你数一下对不对.
2025-11-16 03:30:46
1. 性能的真正秘密:数据放在哪里决定一切
2. 决定系统快慢的不是 CPU,而是数据的距离
3. 缓存才是现代计算性能的核心
4. 忽视数据局部性,一切性能优化都是徒劳
5. 性能瓶颈不在算力,而在内存层级
6. 数据局部性:被低估的性能决定因素
7. CPU 在等你的内存:缓存层级的真实代价
8. 系统速度快的真正原因:一切都与缓存有关
9. 别再关注 CPU 速度了——数据局部性才是制胜关键
10. 为什么缓存是所有高性能系统的幕后引擎
11. 性能的关键不在于 GHz,而在于距离
12. 你的 CPU 正在等待内存:缓存不为人知的故事
13. 数据局部性:计算机领域最重要却鲜为人知的因素
14. 数据存储位置决定一切
15. 缓存主宰一切:性能指南
16. 内存层次结构:性能的隐形杀手(或救星)
17. 为什么现代性能之战是与延迟的较量,而非与计算能力的较量
我们喜欢讨论 CPU 频率,但在实际系统中,关键问题是:你的数据存放在哪里?
现代 CPU 依赖一个分层的内存体系(寄存器 → L1 → L2 → L3 → DRAM)。L1 访问可能只需约 4 个周期;而 DRAM 访问可能需要 200+ 个周期——那是 50× 更慢。如果你的工作集能放进缓存,一切飞快;如果不能,CPU 就会阻塞等待。
分组处理是一个典型例子。每个数据包都会触发表查找。如果这些表能保持在缓存中,你可以每秒处理数百万个包;一旦溢出到 DRAM,吞吐量会崩塌。
真正的设计问题: 它能放进缓存吗?
缓存不仅仅关乎数据。指令缓存未命中也会毁掉尾延迟。有些高频交易系统会让热路径持续执行,只在需要发包时才打开网卡,从而保持 指令缓存持续命中。在交易环路中,一个 I-cache 停顿就可能占据全部延迟预算。
“全都上云”这类高层策略常忽略底层现实。虚拟化网络功能依赖于诸如:
销售演示会说“可以工作”,但细则通常是:需要 3 倍硬件、3 倍许可证,性能仍然无法与裸机匹配。 一旦你依赖缓存行为、核亲和和 NUMA 局部性,平台就不再可互换。
即便在 AI 领域,物理规律也没变。模型越来越大,但数据移动依旧主导计算。局部性仍然是王道。
在多轴运动控制中,第一个轴会“预热”缓存并承担缺失惩罚;后续轴的计算因为数据已经热化而耗时减半。相同的原理:局部性 = 速度。
IBM 的 Telum 处理器把这个想法推到了极端:
该架构可以按需将 L2 转作 L3 使用。IBM 尚未公开这些缓存层的具体访问延迟,但在如此大规模的缓存下,大小、互连距离与命中延迟之间的折衷会非常有趣。
性能归根结底由数据和指令能离核心多近来决定。
为局部性而设计,你的系统会表现出色。忽视它,再多的 GHz 或再多的云抽象也救不了你。
我们经常谈论 CPU 速度,却很少关注数据存储的位置。
性能主要取决于数据存储的便利程度。寄存器、L1 缓存、L2 缓存、L3 缓存、主内存——每一步都会增加延迟并降低吞吐量。访问主内存可能需要 200 个时钟周期,比 L1 缓存慢 50 倍。
当工作集能够放入缓存时,代码运行速度极快。否则,CPU 只能等待。
在数据包处理中,这种差异决定了一切。每个数据包都会触发表查找。如果这些表保存在 缓存 中,您可以每秒处理数百万个数据包。否则,吞吐量将急剧下降。
所以,下次设计数据结构时,请问问自己:
它能放进缓存吗?
因为在对性能要求极高的系统中,缓存不仅仅是一种优化手段,它定义了整个系统。
而且不仅是数据,指令也一样!我见过高频交易工程师讨论他们的策略,他们将热路径编程为始终处于激活状态,并且只在数据包需要离开系统时才启用网卡。这样也能保持指令缓存处于热状态。
保持指令缓存处于热状态与保持数据缓存处于热状态同样重要,尤其是在对可预测性要求很高的工作负载中。优化热路径,使 CPU 始终保持在指令缓存中至关重要,因为即使是很小的停顿也可能导致尾延迟显著增加。这很好地提醒我们,架构设计的真正目的是尽可能地将指令和数据都放在靠近核心的位置。
很多技术决策者都固守一刀切的策略:例如……万物皆可云——他们认为任何虚拟化工作负载都可以在任何虚拟化环境中运行,底层硬件和虚拟化技术都只是商品而已。但这并不适用于虚拟化网络功能,因为厂商们早就知道,独占线程核心绑定可以让执行线程独占使用 CPU 缓存。厂商们也知道,在虚拟化环境中,中断合并可以降低“CPU 使用率”,但会增加延迟。他们了解 NUMA 局部性,甚至把这些都写进了文档里。当然,销售人员来了之后,他们希望与高层战略保持一致,使用最佳优化基准测试,然后就云或虚拟机管理程序支持的问题展开另一场不加任何细节的讨论。没错,这行得通*但附注:你需要三倍的许可证/硬件,而且仍然无法获得最佳性能。人们对底层性能如此缺乏兴趣,技能差距如此之大,以至于似乎只能通过增加抽象层和厂商来掩盖责任。如果珠穆朗玛峰是检验技术领导力还是厂商责任的试金石,那么我们很想知道,究竟是哪一方会坚持到底,还是会在山脚下卖羽绒服。完全正确。一旦你依赖缓存行为、核心绑定和NUMA局部性,平台就不再具有可互换性了。底层细节远比大多数高层策略重要得多。
大多数繁重的AI工作负载仍然会遇到相同的内存层次结构限制。模型规模不断扩大,但芯片内部数据传输的物理机制并没有发生太大变化。理解局部性仍然是获得良好性能的关键。
数组能够为CPU提供它真正需要的东西:连续的内存和可预测的访问模式。这意味着预取器可以真正发挥作用,缓存行可以得到高效利用,并且避免了分散结构带来的指针追踪惩罚。这是保持缓存友好性的最简单方法之一。
机器人多轴运动控制也是如此。第一个轴预热缓存并承受缓存未命中的影响,下一个轴的计算时间缩短了一半。
IBM Telum处理器可以验证这一点,它能够按需将L2缓存转换为L3缓存,并且L4缓存可以被任何其他CPU访问。此外,该芯片的时钟频率始终保持在 5.5 GHz。它包含十个 36 MB 的二级缓存¹,以及扩展的虚拟三级缓存(360 MB)和四级缓存(2.8 GB)。
这是一款令人着迷的芯片。与大多数架构相比,其缓存容量巨大,这让我不禁好奇这会对各级缓存的访问延迟产生怎样的影响。可惜的是,我找不到任何关于 Telum 缓存的公开延迟数据,否则我很想了解 IBM 在实际应用中是如何平衡缓存容量、交换空间距离和命中延迟的。
英文:The Hidden Engine of Performance: It’s All About Where the Data Lives (Cache is the King)
本文一共 2349 个汉字, 你数一下对不对.
2025-11-12 19:42:49
强化学习(Reinforcement Learning, RL)是一种让智能体/Agent通过与环境交互、试错学习来获得最优行为策略的机器学习方法。本文用一个简单的 Q-learning 迷宫示例,帮助你快速理解强化学习的基本原理。
强化学习入门:从试错中学习的艺术
Reinforcement Learning 101: The Art of Learning by Trial and Error深度解析强化学习:Q-Learning算法详解
Deep Dive into Reinforcement Learning: Understanding the Q-Learning Algorithm机器如何学会自己做决定?强化学习告诉你答案
How Do Machines Learn to Make Their Own Decisions? Reinforcement Learning Explained从奖励中学习:人工智能的“试错智慧”
Learning from Rewards: The Trial-and-Error Intelligence Behind AI
强化学习的世界中包含五个关键要素:
智能体的目标是学习一个策略 π(a|s),让它在每个状态下选择最优动作,从而获得最大的累积奖励。

其中
(0 ≤
≤ 1)是折扣因子,用于衡量未来奖励相对于即时奖励的重要程度。
Q-learning 是最经典的强化学习算法之一。它通过学习一个 Q 表(Q-table)来记录每个“状态-动作”对的价值。
更新公式如下:

其中:
:学习率(Learning Rate)
:折扣因子(Discount Factor)
:奖励(Reward)
:下一状态(Next State)定义一个 3×5 的迷宫:
import numpy as np
import random
# 1️⃣ 定义迷宫
maze = np.array([
[0, 0, 0, -1, 1],
[0, -1, 0, -1, 0],
[0, 0, 0, 0, 0]
])
n_rows, n_cols = maze.shape
actions = ['up', 'down', 'left', 'right']
Q = np.zeros((n_rows, n_cols, len(actions)))
# 2️⃣ 超参数
alpha = 0.1
gamma = 0.9
epsilon = 0.1
episodes = 500
# 3️⃣ 辅助函数
def is_valid(state):
r, c = state
return 0 <= r < n_rows and 0 <= c < n_cols and maze[r, c] != -1
def next_state(state, action):
r, c = state
if action == 'up': r -= 1
elif action == 'down': r += 1
elif action == 'left': c -= 1
elif action == 'right': c += 1
return (r, c)
def get_reward(state):
r, c = state
if maze[r, c] == 1: return 10
elif maze[r, c] == -1: return -1
return -0.1
# 4️⃣ 训练循环
for episode in range(episodes):
state = (2, 0)
done = False
while not done:
if random.uniform(0, 1) < epsilon:
action_idx = random.randint(0, len(actions)-1)
else:
action_idx = np.argmax(Q[state[0], state[1]])
action = actions[action_idx]
next_s = next_state(state, action)
if not is_valid(next_s):
reward = -1
next_s = state
else:
reward = get_reward(next_s)
Q[state[0], state[1], action_idx] += alpha * (
reward + gamma * np.max(Q[next_s[0], next_s[1]]) - Q[state[0], state[1], action_idx]
)
state = next_s
if maze[state[0], state[1]] == 1:
done = True
print("✅ 训练完成!")
# 5️⃣ 查看学到的路径
state = (2, 0)
path = [state]
while maze[state[0], state[1]] != 1:
action_idx = np.argmax(Q[state[0], state[1]])
next_s = next_state(state, actions[action_idx])
if not is_valid(next_s) or next_s in path:
break
state = next_s
path.append(state)
print("🗺️ 学到的路径:", path)
运行上面的代码后,你会看到类似输出:
✅ 训练完成!
🗺️ 学到的路径: [(2, 0), (2, 1), (2, 2), (1, 2), (0, 2), (0, 3), (0, 4)]
这说明智能体成功学会了走出迷宫 🎯
强化学习使机器能够通过反馈学习最优策略,这类似于人类通过经验学习的方式。
Q-Learning 是许多现代强化学习算法的基础,包括深度 Q 网络(Deep Q-Networks, DQN)。
这个简单的示例展示了完整的强化学习循环:探索 → 反馈 → 改进。
强化学习的魅力在于,它不需要显式答案,而是让机器自己“摸索”出最优策略。你可以在此基础上继续扩展,比如加入 matplotlib 动画可视化 或使用 神经网络(Deep Q-Learning) 解决更复杂的任务。
英文:How Do Machines Learn to Make Their Own Decisions? Reinforcement Learning Explained
本文一共 705 个汉字, 你数一下对不对.