You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

g++ -O3编译选项如何优化循环?为何耗时未随runtime增长?

关于GCC -O3优化导致循环耗时不随迭代次数增长的问题分析

你使用以下代码测试程序运行耗时:

#include <stdint.h>
#include <time.h>
#include <math.h>
#include <random>

#define N 1000
#define DIM 1000
#define NS_PER_SECOND 1000000000

void sub_timespec(struct timespec t1, struct timespec t2, struct timespec *td)
{
    td->tv_nsec = t2.tv_nsec - t1.tv_nsec;
    td->tv_sec = t2.tv_sec - t1.tv_sec;
    if (td->tv_sec > 0 && td->tv_nsec < 0)
    {
        td->tv_nsec += NS_PER_SECOND;
        td->tv_sec--;
    }
    else if (td->tv_sec < 0 && td->tv_nsec > 0)
    {
        td->tv_nsec -= NS_PER_SECOND;
        td->tv_sec++;
    }
}

float cal_data_sqrtf(float *data, int data_length) {
    float sum = 0;
    for (int i = 0; i < data_length; i++) {
        sum += data[i] * data[i];
    }
    return sqrtf(sum);
}

int main() {
    float db_feat[N][DIM];
    float db_feat_norm[N];
    for (int j = 0; j < N; j++) {
        for (int i = 0; i < DIM; i++) {
            db_feat[j][i] = rand()/float(RANDMAX);
        }
        db_feat_norm[j] = cal_data_sqrtf(db_feat[j], DIM);
    }
    float features[DIM];
    for (int i = 0; i < DIM; i++) {
        features[i] = rand()/float(RANDMAX);
    }
    float features_norm = cal_data_sqrtf(features, DIM);

    int runtime = 10;
    struct timespec start, end, delta;
    clock_gettime(CLOCK_REALTIME, &start);
    float view_sim[N];
    for (int k = 0; k < runtime; k++) {
        for (int j = 0; j < N; j++) {
            float sum = 0;
            for (int i = 0; i < N; i++) {
                sum += db_feat[j][i] * features[i];
            }
            if (sum < 0)
                sum = 0;
            view_sim[j] = sum / (db_feat_norm[j] * features_norm);
        }
    }
    clock_gettime(CLOCK_REALTIME, &end);
    sub_timespec(start, end, &delta);
    printf("running time: %d.%.9ld\n", (int)delta.tv_sec, delta.tv_nsec);
}

使用g++ -std=c++11 -o main main.c编译时,程序运行时间与runtime变量成正比;但添加-O3优化(g++ -std=c++11 -O3 -o main main.c)后,即便把runtime设为1000000,运行时间依然极短(0.000000128秒),完全不随runtime增长。下面是-O3做的关键优化:

  • 死代码消除:这是核心原因。外层for (int k = 0; k < runtime; k++)的每一轮迭代,计算逻辑完全重复——所有输入数据在循环开始前就已固定,每次算出的view_sim结果也完全相同,而且程序最终根本没用到view_sim的任何值(只是不断被覆盖)。-O3级别的编译器会直接判定这个外层循环是无意义的重复计算,直接删掉整个循环,自然不会随runtime增加耗时。
  • 常量传播与冗余计算消除:编译器会识别出db_feat_norm[j] * features_norm是固定常量(两个值都是循环前计算好的),不会在每轮内层循环里重复计算这个乘积,减少了冗余操作。
  • 循环向量化:对于内层计算点积的循环,-O3会自动启用SIMD指令(如AVX、SSE),一次性批量计算多个元素的乘积和,大幅加快单次计算的速度,但这不是耗时不随runtime变化的核心原因。
  • 无用变量优化:因为view_sim数组的结果既没被输出,也没被后续逻辑使用,编译器甚至可能直接跳过整个view_sim的计算逻辑,只保留计时和打印代码,导致不管runtime多大,实际执行的有效代码都极少。

内容的提问来源于stack exchange,提问作者Chuck Liu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:24:51