指令级并行
指令级并行(ILP)
超标量
一个周期发射多条指令(现代 CPU 4~6 发射)。
乱序执行(Out-of-Order)
指令的实际执行顺序可以不同于程序顺序,只要数据依赖允许。
1. 发射(In-order): 指令进入 reorder buffer
2. 执行(Out-of-order): 操作数就绪就执行
3. 提交(In-order): 按程序顺序写回,保证精确异常关键:看起来是顺序执行的(对程序员可见的状态),实际是乱序的(内部优化)。
寄存器重命名
消除假依赖(WAR、WAW):
原始: add r1, r2, r3 写 r1
sub r1, r4, r5 又写 r1(WAW 依赖,但其实无关)
重命名: add p1, p2, p3
sub p4, p4, p5 ← 用不同的物理寄存器,可以并行x86 只有 16 个架构寄存器,但物理寄存器有 100+ 个。
SIMD
一条指令处理多个数据:
| 指令集 | 宽度 |
|---|---|
| SSE | 128 bit(4× float) |
| AVX / AVX2 | 256 bit(8× float) |
| AVX-512 | 512 bit(16× float) |
| NEON(ARM) | 128 bit |
// 编译器自动向量化(需要 -O3 且循环结构简单)
for (int i = 0; i < n; i++) c[i] = a[i] + b[i];
// 手动
#include <immintrin.h>
__m256 va = _mm256_load_ps(&a[i]);
__m256 vb = _mm256_load_ps(&b[i]);
__m256 vc = _mm256_add_ps(va, vb);
_mm256_store_ps(&c[i], vc);自动向量化的障碍:
- 循环次数未知(可用
#pragma omp simd或-fno-tree-vectorize检查) - 数据依赖(如累加
sum += a[i],可用-ffast-math允许重排) - 非连续访问(gather/scatter)
- 别名问题(
restrict关键字)
许可协议:CC BY
作者:Davids
本文链接:https://hustjjd.github.io/computer/architecture/instruction-level-parallelism/
更新于:2026年10月12日