
优化一个需要执行 1 万次的 for 循环,可以从 算法优化、并行计算、编译器优化、内存访问优化 等多个方面入手。以下是具体的优化策略和示例:
使用三角恒等式 sin(x)cos(x) = sin(2x)/2 减少计算:
// 优化后 - 使用数学恒等式
for (int i = 0; i < 10000; i++) {
double result = std::sin(2 * i) / 2.0; // 只需一次函数调用
}优化效果:
// 优化后 - 预计算所有值
std::vector<double> sin_cache(10000);
std::vector<double> cos_cache(10000);
// 预先计算所有三角函数值(只需一次)
for (int i = 0; i < 10000; i++) {
sin_cache[i] = std::sin(i);
cos_cache[i] = std::cos(i);
}
// 主循环使用缓存值
for (int i = 0; i < 10000; i++) {
double result = sin_cache[i] * cos_cache[i];
}优化效果:
#include <immintrin.h>
// 优化后 - 使用AVX指令集
for (int i = 0; i < 10000; i += 4) {
// 一次加载4个整数
__m128i indices = _mm_set_epi32(i+3, i+2, i+1, i);
// 转换为浮点数(需要额外处理)
__m128 floats = _mm_cvtepi32_ps(indices);
// 计算sin(2x)(实际实现更复杂,这里简化表示)
__m128 results = fast_sin(_mm_add_ps(floats, floats));
// 除以2
results = _mm_div_ps(results, _mm_set1_ps(2.0f));
// 存储结果
_mm_storeu_ps(&output[i], results);
}优化效果:
减少循环控制开销,手动或让编译器展开循环:
// 手动展开(每次循环处理 4 次计算)
for (int i = 0; i < 10000; i += 4) {
process(i);
process(i + 1);
process(i + 2);
process(i + 3);
}
// 编译器优化(GCC/Clang 使用 `#pragma unroll`)
#pragma unroll(4)
for (int i = 0; i < 10000; i++) {
process(i);
}适用场景:循环体简单,分支预测开销大。
#include <omp.h>
#pragma omp parallel for
for (int i = 0; i < 10000; i++) {
process(i); // 自动分配到多个线程
}适用场景:循环迭代之间无依赖。
#include <immintrin.h>
for (int i = 0; i < 10000; i += 8) {
__m256 data = _mm256_load_ps(input + i);
__m256 result = _mm256_mul_ps(data, data); // 一次处理 8 个 float
_mm256_store_ps(output + i, result);
}适用场景:数据密集型计算(如矩阵运算)。
尽量让数据连续访问:
// 优化前(跳跃访问)
for (int i = 0; i < 10000; i++) {
arr[index[i]] = process(i); // index 是随机顺序
}
// 优化后(顺序访问)
std::sort(index.begin(), index.end()); // 先排序
for (int i = 0; i < 10000; i++) {
arr[index[i]] = process(i);
}例如,用 std::vector 代替链表。
-O3(最高优化)、-march=native(启用本地 CPU 指令集)。/O2 或 /Ox。避免循环内部有复杂分支:
// 优化前(分支预测开销大)
for (int i = 0; i < 10000; i++) {
if (i % 2 == 0) {
processA(i);
} else {
processB(i);
}
}
// 优化后(拆分成两个循环)
for (int i = 0; i < 10000; i += 2) {
processA(i);
}
for (int i = 1; i < 10000; i += 2) {
processB(i);
}如果循环是某种计算(如求和、查找),考虑更优算法:
// 优化前(O(n²))
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 10000; j++) {
// ...
}
}
// 优化后(O(n log n))
std::sort(data.begin(), data.end());
// ...优化方法 | 适用场景 | 优化效果 |
|---|---|---|
减少重复计算 | 循环内有重复运算 | ⭐⭐⭐ |
循环展开 | 简单循环体 | ⭐⭐ |
多线程(OpenMP) | 无数据依赖 | ⭐⭐⭐⭐ |
SIMD 向量化 | 数据并行计算 | ⭐⭐⭐⭐ |
内存访问优化 | 大数据遍历 | ⭐⭐⭐ |
编译器优化 | 所有情况 | ⭐⭐ |
减少分支预测 | 循环内有 if | ⭐⭐ |
更优算法 | 存在低复杂度替代 | ⭐⭐⭐⭐⭐ |
建议步骤:
perf、VTune)。这样可以显著提升 1 万次循环的执行速度! 🚀