使用GCC编译添加-mfma时触发非法指令问题求助
解决SandyBridge平台添加
-mfma编译选项后触发非法指令的问题 这问题其实很好解释——你的Intel E5-2670属于SandyBridge架构,根本不支持FMA(融合乘加)指令集,手动加-mfma相当于逼着GCC生成CPU认不出的指令,自然会炸。
为什么-march=native能正常运行?
-march=native的核心作用是让GCC自动探测当前CPU的指令集支持,只生成该CPU能执行的指令。SandyBridge是2011年的老架构,FMA是2013年Haswell才引入的特性,所以-march=native在你的机器上根本不会开启FMA优化,编译出来的代码全是SandyBridge能处理的指令,当然没问题。
但你手动加了-mfma就不一样了——这个选项会强制GCC生成FMA指令,完全忽略当前CPU的实际支持情况,CPU碰到这些陌生指令直接就抛出非法指令错误了。
关于GDB回溯的补充
你说GDB栈回溯看起来正常,这完全符合我们的判断:这不是内存问题(比如野指针越界),而是指令不兼容导致的崩溃。非法指令错误是在CPU执行环节直接触发的,还没到内存访问出问题的阶段,所以栈回溯不会显示内存相关的异常信息。
怎么解决?
- 首选方案:删掉
-mfma选项:你的CPU不支持FMA,加这个选项除了搞崩程序没有任何好处。保留-march=native就足够让GCC针对SandyBridge生成最优的合法代码了。 - 如果代码里有依赖FMA的逻辑:可以用条件编译做兼容处理,比如在代码里判断编译器是否开启了FMA支持,或者检测CPU架构,只在支持的平台上启用相关逻辑:
#ifdef __FMA__ // 仅在支持FMA的平台运行的代码 #else // 给SandyBridge这类老平台的替代实现 #endif - 检查Eigen的配置:你用到了Eigen,要注意Eigen在开启
-mfma时会生成依赖FMA的代码。确保Eigen的优化选项和你的CPU匹配,别强行启用不兼容的指令集。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

