STM32G473上cosf(x)比arm_cos_f32(x)快近6倍?测试存疑
问题分析与解答
核心结论
你的测试结果主要是DEBUG编译模式导致的,而非math.h的cosf天生比ARM Math函数快5-6倍。
具体原因
- 编译优化级别的影响
DEBUG模式(通常对应-O0优化)会关闭几乎所有编译器优化,同时保留大量调试信息:
- 标准库的
cosf在ARM GCC环境下,默认会直接生成FPU硬件指令(比如VCOS.F32),无需函数调用开销,执行速度极快; - 而ARM Math库的
arm_cos_f32/arm_cos_q15在DEBUG模式下,会保留完整的函数调用流程、未展开的内部循环、调试用的变量检查等,这些额外开销会让执行速度大幅下降。
- 实现机制的差异(DEBUG下被放大)
cosf依赖硬件FPU的原生余弦指令,是硬件级的单周期(或少数周期)计算;- ARM Math的余弦函数是软件实现(查表+插值算法),在无优化的DEBUG模式下,函数调用、循环展开、内存访问的开销被无限放大,导致速度远慢于硬件指令。
- 测试代码的优化漏洞
你的测试用例中输入值是固定的0.0F,在RELEASE模式下编译器会直接将整个循环优化为value = 1.0F,完全跳过循环执行。这种测试结果没有参考意义,需要修改测试逻辑避免被优化。
正确的测试建议
切换到RELEASE模式测试
开启-O2或-O3优化(这是嵌入式产品实际运行的模式),此时ARM Math函数会被编译器优化,函数调用开销降低、内部循环展开,性能会大幅提升,甚至在部分场景下和cosf持平或更优。修改测试代码避免编译优化
使用volatile修饰变量,或者让输入值随循环动态变化,确保编译器无法提前计算结果:
#define REPS 1000000 uint32_t rep = REPS; uint32_t start = HAL_GetTick(); volatile float value; volatile float input = 0.0F; while(rep--) { value = cosf(input); input += 0.00001F; // 防止input溢出 if(input > 2*M_PI) input -= 2*M_PI; } uint32_t end = HAL_GetTick(); duration[0] = end - start; // ARM Math函数测试同理修改输入值 rep = REPS; start = HAL_GetTick(); input = 0.0F; while(rep--) { value = arm_cos_f32(input); input += 0.00001F; if(input > 2*M_PI) input -= 2*M_PI; } end = HAL_GetTick(); duration[1] = end - start;
内容的提问来源于stack exchange,提问作者Chris_B
相关产品推荐
相关产品推荐

