开启-O2优化时,如何正确基准测试可能被重排的嵌入式C程序?
解决-O2优化下嵌入式基准测试计时为0的问题
问题根源
开启-O2优化后计时为0,核心原因是编译器的死代码消除优化:loop()函数中的fram_cnt变量没有被任何外部代码读取或使用,编译器判定这段循环对程序输出无影响,直接将整个循环(甚至整个loop()函数)从编译后的代码中删除,导致计时器几乎瞬间完成,返回时间为0。这不是代码重排导致的,而是冗余代码被完全移除。
解决方案(保持-O2优化)
1. 让循环结果被实际使用
最直接的方式是让loop()返回计算结果,并在main()中使用该结果(比如打印),迫使编译器保留整个循环逻辑:
uint16_t loop() { uint16_t fram_cnt = 0; for (uint16_t i = 0; i < VEC_SIZE; i++) { fram_cnt += (fram_dst[i] == i); } return fram_cnt; } int main() { init(); start_timer(); uint16_t check_result = loop(); uint32_t time = stop_timer(); // 必须使用check_result,否则仍可能被优化 msp_send_printf("loop time: %u, match count: %u", time, check_result); exit(); }
2. 用volatile阻止变量优化
如果不需要使用循环结果,可以将fram_cnt声明为volatile,强制编译器保留对该变量的所有读写操作,避免循环被消除:
void loop() { volatile uint16_t fram_cnt = 0; for (uint16_t i = 0; i < VEC_SIZE; i++) { fram_cnt += (fram_dst[i] == i); } }
注意:volatile仅阻止编译器对该变量的优化,不会影响循环内其他操作的正常优化,适合不需要结果但需要保留循环逻辑的场景。
3. 标记函数为不可优化(极端场景)
如果上述方法无效,可以给loop()函数添加编译器属性,强制编译器不优化该函数(以GCC为例):
void loop() __attribute__((optimize("O0"))); void loop() { uint16_t fram_cnt = 0; for (uint16_t i = 0; i < VEC_SIZE; i++) { fram_cnt += (fram_dst[i] == i); } }
这种方式仅对loop()函数关闭优化,其他代码仍保持-O2级别,适合特殊测试场景,但不推荐作为常规方案。
额外注意事项
由于你的CPU无乱序执行功能,无需添加内存屏障(如__sync_synchronize())来保证计时函数和测试代码的执行顺序,只需解决死代码消除问题即可。
内容的提问来源于stack exchange,提问作者Mingyuan Xiang
相关产品推荐
相关产品推荐

