L2·最佳实践
计算与内存 — 最佳实践
Compute & Memory
工程实践中的经验总结
核心抽象:指令执行与存储5 分钟阅读1,678 字更新于 2026/09/19
最佳实践
1. 理解内存层次结构
各级内存的延迟对比:
| 存储层级 | 典型延迟 | 相对比例 |
|---|---|---|
| 寄存器 | ~0.3ns | 1x |
| L1 缓存 | ~1ns | 3x |
| L2 缓存 | ~4ns | 13x |
| L3 缓存 | ~20ns | 67x |
| 主存 | ~100ns | 333x |
2. 缓存友好的数据结构
原则: 使用连续存储的数据结构,按顺序遍历数据。
c
// 好的做法:紧凑排列
struct GoodParticle {
double mass; // 8 字节
double charge; // 8 字节
float x; // 4 字节
float y; // 4 字节
};
// 总大小:24 字节,无浪费3. 最小化缓存未命中
循环分块(Loop Tiling): 将大数组分成小块处理。
c
// 分块版本——缓存友好
const int BLOCK = 64;
for (int ii = 0; ii < N; ii += BLOCK)
for (int jj = 0; jj < N; jj += BLOCK)
for (int kk = 0; kk < N; kk += BLOCK)
for (int i = ii; i < ii+BLOCK; i++)
for (int j = jj; j < jj+BLOCK; j++)
for (int k = kk; k < kk+BLOCK; k++)
C[i][j] += A[i][k] * B[k][j];4. 寄存器分配策略
- 将大函数拆分为小函数
- 避免在长循环中使用过多的临时变量
- 使用
restrict关键字帮助编译器优化
5. 避免流水线停顿
c
// 改善:交错独立的指令
a = b + c; // 计算 a
x = y + z; // 独立计算 x
d = a + e; // 此时 a 已准备好
w = x + v; // 独立计算 w
f = d + g; // 此时 d 已准备好6. 内存对齐最佳实践
c
#include <stdalign.h>
alignas(32) float data[256]; // 对齐到 32 字节,支持 AVX7. NUMA 感知编程
- 确保线程访问的内存分配在该线程所在的 NUMA 节点上
- 使用
numactl或线程亲和性将线程绑定到特定的 CPU 核心
8. 预取策略
c
#include <xmmintrin.h>
for (int i = 0; i < N; i++) {
_mm_prefetch((char *)&array[i + 8], _MM_HINT_T0);
process(array[i]);
}9. 避免伪共享
c
struct Counters {
alignas(64) int thread1_count; // 各自占一个缓存行
alignas(64) int thread2_count;
};10. 高效使用 SIMD 指令
c
#include <immintrin.h>
void add_arrays_avx2(float *a, float *b, float *c, int n) {
for (int i = 0; i + 8 <= n; i += 8) {
__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);
}
}交互沙盒
亲手操作验证本层概念,沙盒状态可编码进 URL 分享。