CPU 内的并行编程
CPU 内的并行编程
CPU 内的并行编程
什么是 CPU?
概念:无情的执行指令的机器
mini-rv32ima 中的 MiniRV32IMAStep()
实际的 CPU (Instruction-level Parallelism)
多个核心,共享内存 (relaxed memory model)
一些指令 (fence, atomic, ...) 实现内存一致性控制
没有想到的是:你一直都在 (自动)
并行编程
每个 CPU 核心都是一个
编译器
动态 (运行时) 数据流分析和指令调度
服务器 CPU 上可能
同时有上千条指令在执行
可以看看平时用的程序的 IPC 是多少?
CPU 内的并行编程
这意味着什么?
在
能效
和
性能
之间,CPU 选择了后者
跑得越快,浪费得越多
每一个门电路的翻转都会产生
热量
CPU 里的编译器会消耗巨量的能量
这些能量使计算 “尽快完成”
但并不等同于 “单位时间完成尽可能多的计算”
Dark Silicon “暗硅时代”
P
=
C
⋅
V
2
⋅
f
P = C \cdot V^2 \cdot f
P
=
C
⋅
V
2
⋅
f
“功耗墙”:纵使有更大的电路,热功耗限制了性能上限
CPU 内的并行编程
面对功耗墙
P
=
C
⋅
V
2
⋅
f
P = C \cdot V^2 \cdot f
P
=
C
⋅
V
2
⋅
f
如何在降低
V
V
V
和
f
f
f
的同时,用面积换性能?
1. 让一条指令能处理更多的数据
SIMD (Single Instruction, Multiple Data)
“一条指令” 浪费的能量大致是定数
处理的数据越多,浪费越少
2. 用更多更简单的处理器
多处理器系统、异构多处理器
同等面积,处理器越简单,数量越多
CPU 内的并行编程
1. 让一条指令能处理更多的数据
Single Instruction, Multiple Data (SIMD)
可以一次让一条指令对
连续的操作数做相同运算
!
比如,对 4 个 float 做 4 次乘法
Intel MMX: MultiMedia eXtension
CPU 内的并行编程
Single Instruction, Multiple Data (SIMD)
增加一些 “超大” 的寄存器
64-bit “mm” 寄存器
57 条指令实现 “packed register” 操作 (
手册
)
CPU 内的并行编程
MMX
→
\to
→
SSE
→
\to
→
AVX
→
\to
→
AVX-512
寄存器宽度
64 (mm)
→
\to
→
128 (xmm)
→
\to
→
256 (ymm)
→
\to
→
512 (zmm)
数据类型
int8/16/32
→
\to
→
float32
→
\to
→
float64
更多运算 (三操作数模式)
Shuffle:
c
[
i
]
=
a
[
b
[
i
]
]
c[i] = a[b[i]]
c
[
i
]
=
a
[
b
[
i
]]
FMA:
a
×
b
+
c
a \times b + c
a
×
b
+
c
,一条指令完成
CPU 内的并行编程
SIMD: 没能完全解决问题
SIMD 指令依然是在 CPU 里调度的
参与到缓存和动态流水线中
宽度不能做得太宽
并行度有限
我们实在是太想要性能了
只能
横向扩展
单 CPU
→
\to
→
多 CPU
多 CPU
→
\to
→
大小核 CPU
CPU 内的并行编程
2. 同等面积可以放置更多 “高能效” 计算单元
Apple M1: 4 Performance + 4 Efficiency
Trick: 降低频率 = 降低电压 (“热功耗分配”)