使用PGI编译器编译Eigen库时出现重载匹配及链接错误
解决PGI编译器编译Eigen时的_mm_prefetch匹配与链接错误
我之前在macOS平台上用PGI编译器搭配Eigen开发时,也碰到过几乎一模一样的问题——先是_mm_prefetch重载匹配失败,改了指针类型又出现链接错误。结合我踩过的坑,给你整理了一套针对性的解决方案:
先搞清楚问题根源
- _mm_prefetch匹配错误:PGI对SIMD指令的类型检查比GCC严格不少,Eigen源码里默认的预取调用没有显式转换指针类型,导致PGI找不到对应的重载函数。
- x86_64未定义符号链接错误:PGI和GCC的ABI细节、默认链接库存在差异,尤其是Eigen里的一些模板实例化、架构相关内联函数,在PGI编译后链接阶段找不到对应符号。
分步解决
1. 快速搞定_mm_prefetch匹配问题
不用手动修改Eigen的源码,直接通过编译宏就能绕开:
- 编译时添加
-DEIGEN_HAS_MM_PREFETCH=0,强制Eigen禁用_mm_prefetch指令的使用,这是最省心的方式,对大多数场景性能影响可以忽略。 - 如果你的代码必须保留预取功能,可以添加
-DEIGEN_PREFETCH_ALIGNMENT=64(根据你的内存对齐需求调整数值),同时确保代码中传递给预取的指针显式转为const void*——不过前者一般足够用了。
2. 解决x86_64链接错误
这部分需要针对PGI的特性调整链接选项:
- 编译时明确指定C标准,比如
-std=c++11(或你代码用的更高标准),同时用PGI的C前端pgcpp(而非pgcc)编译,确保正确处理Eigen的模板代码。 - 如果用到了Eigen的LAPACK/BLAS相关模块,必须链接PGI自己的数学库,比如添加
-lacml(PGI的ACML线性代数库),别混用GCC的liblapack/libblas,否则会出现ABI不兼容的链接错误。 - 针对macOS平台,如果依赖系统加速框架,可以尝试添加
-framework Accelerate,但要注意PGI和Accelerate的兼容性,优先用PGI自带的ACML更稳妥。 - 编译时加上
-fPIC选项(生成位置无关代码),尤其是在编译动态库或者混合GCC/PGI编译单元时,能避免很多符号解析的坑。
3. 混合GCC+PGI编译的注意事项
因为你需要结合OpenACC(只有PGI支持)和Eigen(GCC编译正常),建议分开编译再链接:
- 确保GCC和PGI使用相同的C标准(比如都用C11),ABI版本尽量匹配(PGI在macOS上的ABI和GCC基本兼容,但别跨太大版本)。
- 用GCC编译不含OpenACC的Eigen相关代码,生成静态库或目标文件(比如
g++ -c eigen_part.cpp -o eigen_part.o -std=c++11)。 - 用PGI编译带OpenACC的核心代码,链接时指定GCC生成的目标文件/库,同时添加
-lgcc确保GCC的标准库被正确链接(比如pgcpp -acc openacc_part.cpp eigen_part.o -o app -std=c++11 -lgcc)。 - 尽量不要在同一个编译单元中混合GCC和PGI的特性,分开编译能减少很多兼容性问题。
测试验证
拿最简单的Eigen示例代码测试:
#include <Eigen/Eigen> #include <iostream> int main() { Eigen::MatrixXd m(2,2); m(0,0) = 3; m(1,0) = 2.5; m(0,1) = -1; m(1,1) = m(1,0) + m(0,1); std::cout << m << std::endl; return 0; }
用PGI编译:
pgcpp -DEIGEN_HAS_MM_PREFETCH=0 -std=c++11 test.cpp -o test
如果需要链接BLAS/LAPACK:
pgcpp -DEIGEN_HAS_MM_PREFETCH=0 -std=c++11 test.cpp -o test -lacml
运行./test,如果正常输出矩阵,说明基础问题解决了。
额外小贴士
- 如果可以的话,尽量升级到较新的PGI版本,新版本对C++标准和第三方库的兼容性更好,很多旧版本的坑已经被修复了。
- 可以去Eigen官方文档的编译器兼容章节看看,里面有针对PGI的特定编译宏说明,能帮你更精准地调整。
- 如果链接错误还存在,用
nm -u test.o查看目标文件中的未定义符号,定位是哪个Eigen模块或函数出的问题,再针对性调整编译选项。
内容的提问来源于stack exchange,提问作者WoodenChain
相关产品推荐
相关产品推荐

