11. 真实世界的并发编程
1 我们身边的并发编程
1.1 互联网的开始:Web1.0
从 PC 时代到互联网时代 (1990s)
- Amazon (1994), Yahoo (1994), eBay (1995), Google (1998)
- HTTP (对,没有 HTTPS), HTML,但没有 CSS
- 中国互联网初代 “三巨头”:新浪、搜狐、网易诞生
<font>
,<table>
, vbscript 和切图工程师一统天下
1.2 Web2.0
Asynchronous JavaScript and XML (Ajax; ~1999)
- 允许网页实现 “后台刷新”
- 悄悄请求后端,然后更新 DOMTree
- “应用” 可以做的,网页也都可以做了!
- (你没看错,竟然不是 JSON)
- 原因:后端 (Java) 应用广泛使用 XML
jQuery $ (2006)
- 允许 Javascript 代码优雅地修改 DOMTree
$('h3').replaceWith('XXX');
从此,做“任何事”都只要浏览器就行
甚至诞生了 ChromeOS
- HTML + CSS 构建应用的方便程度超过传统 GUI 编程
- GTK, Qt, MFC 谁用谁知道
Web2.0时代的并发编程
Challenges
- 线程 (在 1990s) 开销很大
- 线程同步很难写对
Solution: Event-based concurrency (动态计算图)
- 允许随时创建计算节点
- 例如网络请求、定时器
- 禁止计算节点并行
- 网络访问占大部分时间;浏览器内计算只是小部分
- 以事件为单位调度
- 事件可以在浏览器里看到!
“Callback hell (回调地狱)”
- 2024 年,教务系统里还能看到明文
1 | $.ajax({ |
ECMAScript 2015 (ES6)
- 一统第三方库 “军阀混战” 的局面
- 开源生态开始起飞
现代前端的代表作品
- Angular, React, Vue
- Express.js, Next.js
- Bootstrap, Tailwindcss
- Electron (vscode)
- 2016 年,还用先烈 Github Atom 做过实验
Promise: 描述动态计算图
1 | useEffect(() => { |
1 | Promise.all([ |
1.3 历史车轮碾过
PC → Web → Web 2.0 (UGC) → AI (AGI)
- “框架” 是驱动技术发展的原动力
- 我们需要好的抽象来表达人类世界中的需求
- 简单可靠,聚集大量行业开发者
- 灵活通用,构造各种应用程序
单机 → 互联网 → 移动计算 → ???
- 机遇和不确定
- 风险和回报
2 高性能计算中的并发编程
2.1 CRAY-1 超级计算机
“The world’s most expensive love-seat” (1976)
- 138 MFLOPS @ 115kW (Apple M3: 4.1 TFLOPS @ 20W)
2.2 高性能计算
“A technology that harnesses the power of supercomputers or computer clusters to solve complex problems requiring massive computation.” (IBM)
源自数值密集型科学计算任务
- 物理系统模拟
- 天气预报、航天、制造、能源、制药、……
- 大到宇宙小到量子,有模型就能模拟
- 矿厂
- AI: 新时代的高性能计算 (之后专门讲解)
- HPC-China 100
物理世界具有 “空间局部性”
- “模拟物理世界” 的系统具有 embarrassingly parallel 的特性
2.3 高性能计算中的并行编程
通常计算图容易静态切分 (机器-线程两级任务分解)
- 生产者-消费者解决一切
- MPI - “message passing libraries”, OpenMP - “multi-platform shared-memory parallel programming (C/C++ and Fortran)”
1 |
|
Challenges
- 网络通信、功耗管理、稳定性和容错、软件和工具链
3 数据中心中的并发编程
3.1数据中心程序:特点
“A network of computing and storage resources that enable the delivery of shared applications and data.” (CISCO)
以海量分布式数据 (存储) 为中心
- 实时的 “小数据处理”
- 内容分发、用户认证、视频直播、弹幕……
- 离线的 “大数据处理”
- 内容索引、数据挖掘……
我们的生活离不开数据中心应用
- AI、搜索、社交、支付、游戏……
3.2 数据中心里的并发编程
Challenge: 高可靠、低延迟的多副本分布式存储和计算
- 数据保持一致 (Consistency)、服务时刻可用 (Availability)、容忍机器离线 (Partition tolerance) 不可兼得
高吞吐 (QPS) & 低延迟的事件处理
- 处理事件可能需要读写持久存储或请求网络上的服务
- 延迟不确定
- 线程维护和上下文切换都会带来开销
假设有数千/数万个请求同时到达服务器……
- “Denial of Service, DoS”
- 全国的小爱音箱在小米汽车发布会上同步瘫痪
3.3 协程:操作系统 “不感知” 的上下文切换
和线程概念相同 (独立堆栈、共享内存)
- 但 “一直执行”,直到 yield() 主动放弃处理器
- yield() 是函数调用
- 只需保存/恢复 non-volatile 的寄存器
- (线程切换需要保存/恢复全部寄存器)
- yield() 是函数调用
- 但 sleep (I/O) 时,所有协程都 “卡住了”
- 失去了并行
1 | // 只可能是 1122 或 2211 |
3.4 Go 和 Goroutine
小孩子才做选择,多处理器并行和轻量级并发我全都要!
- Goroutine: 概念上是线程,实现是线程和协程的混合体
Goroutine 实现
- 每个 CPU 上有一个 Go Worker,运行协程
- 协程执行 blocking API (sleep, read)
- 偷偷调用 non-blocking 的版本
- 成功 → 立即继续执行
- 失败 → 立即 yield 到另一个需要 CPU 的 goroutine
- 太巧妙了!完全不浪费!
3.5 Go 语言中的同步与通信
Do not communicate by sharing memory; instead, share memory by communicating. ——Effective Go
共享内存 = 万恶之源
- 信号量/条件变量:实现了同步,但没有实现 “通信”
- 数据传递完全靠手工 (没上锁就错了)
但 UNIX 时代就有一个实现并行的机制了
cat *.txt | wc -l
- 管道是一个天然的生产者/消费者!
- 为什么不用 “管道” 实现协程/线程间的同步 + 通信呢?
- Channels in Go
“Leader/follower” 架构
- 有一个集中的 “总控” 负责调度
- 在可靠的消息机制上实现任务分派
- Leader 串行处理所有请求
- 例子:哲学家吃饭时,由服务员掌管叉子
你可能会觉得,管叉子的人是性能瓶颈?
- 一大桌人吃饭,每个人都叫服务员的感觉
- Premature optimization is the root of all evil (D. E. Knuth)
抛开 workload 谈优化就是耍流氓
- 吃饭的时间通常远远大于请求服务员的时间
- 如果一个 manager 搞不定,可以分多个 (fast/slow path)
- The Google File System (SOSP’03) 开启大数据时代
4 人工智能时代的并发编程
4.1 大语言模型背后的计算
“Attention Is All You Need”
- “Transformers”:类似人处理问题的思维方式(注意力机制)。
4.2 机器学习系统中的并发编程
Challenge: 既计算密集,又数据密集
- 推理
- GPT-3: 175B 参数 (~300GB VRAM, FP-16)
- GPT-3 single training run cost: ~$5,000,000
- LLaMA2: 70B 参数 (~65GB VRAM, FP-16)
- 美国人断供芯片 = 三体人行为
- GPT-3: 175B 参数 (~300GB VRAM, FP-16)
- 训练
- 320TB 语料
- 相比图片和视频,还是小弟弟
解决:所有能想到的技术,全部都用上了!
对并发编程的争议一直存在,例如 “Threads cannot be implemented as a library”。实际上,我们在很多应用领域看到了 “领域特定” 的解决方案:Web 中的异步编程、高性能计算中的 MPI 和 OpenMI、数据中心中的 goroutines、人工智能时代的 CUDA。更有趣的是,我们可以看到:改变世界的技术,往往只是一个小小的奇思妙想, 最终坚持到底得到的——它们很难被 “规划” 出来,而是需要一些 “背道而驰” 的人坚持到底。在当今的社会环境下,我们最缺少的是有能力背道而驰的人——有了下一代人的进步,才会有包容他们的土壤。