gcc -O2优化下SJT算法代码运行时长异常,是否为编译器bug?
问题原因解答
这不是GCC -O2优化的bug,属于x86架构下指令地址对齐导致的正常性能波动。
核心原因
- 你测试的n=12场景下,SJT算法需要执行12! = 4.79亿次循环,CPU前端取指的微小开销会被放大到可观测的程度。
- 多余的
init调用会改变编译后二进制文件的代码布局:当保留三次init调用时,neighbour_exchange函数内部的热点循环入口地址没有对齐到CPU最优的16/32字节边界,每次循环取指都要额外消耗1~2个时钟周期,累加后总耗时刚好翻倍。 - 注意位于计时结束后的第三个
init调用本身并没有被计入耗时,它只是通过改变函数代码长度影响了前面neighbour_exchange的指令对齐状态,才出现了“后续代码影响前面代码执行速度”的假象。
验证方法
你可以通过以下方式验证结论:
- 给
neighbour_exchange函数添加GCC对齐属性:void __attribute__((aligned(32))) neighbour_exchange(),重新编译后无论保留几次init调用,耗时都会稳定在同一水平。 - 使用
perf stat ./你的可执行文件分别运行两个版本,慢的版本会显示更高的前端周期、指令缓存未命中计数,可确认是CPU取指瓶颈导致的性能差异。
额外优化建议
你代码里while (s[j] != c) j++;的遍历操作可以优化掉,额外加一个数组记录每个字符的位置,不用每次扫描字符串,整体性能还能再提升数倍。
内容的提问来源于stack exchange,提问作者cht233
相关产品推荐
相关产品推荐

