如何跨共享对象管理C ++标头库的编译

问题描述 投票:4回答:2

我正在开发一个包含许多软件包的大型软件包,这些软件包被编译为共享对象。出于性能原因,我想用向量指令编译Eigen 3(一个只有头的库),但模板化的方法正在整个地方进行编译。如何确保将特征函数编译为特定的目标文件?

该软件包含约2000个独立包。为了使开发保持合理的速度,编译程序的推荐方法是稀疏地检查一些包并编译它们,之后可以使用预编译(通过某些CI系统)共享库来执行程序。

问题是我的部分职责是优化程序的CPU时间。为了做到这一点,我想用A.so标志编译我正在处理的包(让我们称之为-march),以便Eigen可以利用现代SIMD处理器扩展。

不幸的是,因为Eigen是一个只有头的库,所以Eigen函数被编译成许多不同的共享对象。例如,在A.so中调用的最耗费CPU的方法之一是矩阵多平面内核,它是在B.so中编译的。许多其他的特征函数被编译成C.soD.so等。由于这些对象是为较旧的,更广泛实现的指令集扩展编译的,因此它们不是用AVX,AVX2等编译的。

当然,一种可能的解决方案是将包BCD等包含在我自己的稀疏编译中,但这否定了仅编译项目的一部分的优点。另外,如果我真的想要在包A的代码中矢量化所有线性代数运算,它会让我包含越来越多的包。

我正在寻找的是一种方法来编译A使用的所有特征函数到A.so,就像使用static关键字定义了特征函数一样。这可能吗?我可以利用编译器/链接器中的某些机制来实现这一点吗?

c++ linker shared-libraries eigen
2个回答
4
投票

一个明显的解决方案是隐藏这些符号。发生这种情况(如果我理解正确的话),因为这些函数被导出并且可以被其他后续加载的库使用。

当您构建库并链接到其他库时,链接器会重用它所能提供的功能。还有旧套餐。我希望你不需要这些库用于你自己的构建?

所以有两个选择:

  • 在其他库之前强制加载A(但如果你需要其他库,我认为这不可行),
  • 告诉链接器其他库(默认情况下为visibility=hidden)不应该看到这些函数。

我看到一个类似于编译错误的第三方库的类似事情。它是在调试模式下构建的,在产品中提供,突然之间我们的一个库经历了一个减速。确定罪魁祸首调试功能来自的地图文件,因为它默认导出了所有符号。


1
投票

在不修改代码的情况下更改可见性的另一种方法是使用版本脚本 - > https://sourceware.org/binutils/docs/ld/VERSION.html在链接阶段过滤符号。你需要像 { global: *; local: extern "C++" { Eigen::*; *Eigen::internal::*; }; };这样的东西

© www.soinside.com 2019 - 2024. All rights reserved.