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

时间:2019-04-03 14:44:54

标签: c++ linker shared-libraries eigen

我正在开发一个大型软件包,其中包含许多编译为共享库的软件包。出于性能原因,我想使用矢量指令编译Eigen 3(仅标头的库),但是模板化的方法正在各处编译。如何确保将Eigen函数编译到特定的目标文件中?

该软件由〜2000个独立软件包组成。为了使开发保持合理的进度,建议的程序编译方法是稀疏地检出一些软件包并进行编译,然后可以使用预编译(由某些CI系统)共享库执行该程序。

问题是我的部分责任是优化程序的CPU时间。为此,我想使用A.so标志编译我正在处理的程序包(我们将其称为-march),以便Eigen可以利用现代SIMD处理器扩展。

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

当然,一种可能的解决方案是将包BCD等包含在我自己的稀疏编译中,但这否定了仅编译部分程序包的优点。项目。此外,如果我真的想对软件包A的代码中的所有线性代数运算进行矢量化处理,那么我将包括越来越多的软件包。

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

2 个答案:

答案 0 :(得分:4)

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

在构建库并针对其他库进行链接时,链接器将重用它所能使用的。还有旧的软件包。我希望您不需要自己构建的这些库吗?

有两个选择:

  • 强制在其他库之前加载A(但如果您需要其他库,我认为这是不可能的),
  • 告诉链接器这些功能对其他库不可见(默认为visibility=hidden)。

我看到编译错误的第三方库也发生了类似的情况。它是在调试模式下构建的,并随产品一起提供,突然间,我们的一个库的速度变慢了。映射文件确定了罪魁祸首调试功能的来源,因为它默认情况下会导出其所有符号。

答案 1 :(得分:1)

不更改代码即可更改可见性的另一种方法是在链接阶段使用版本脚本-> https://sourceware.org/binutils/docs/ld/VERSION.html来过滤符号。您需要类似 { global: *; local: extern "C++" { Eigen::*; *Eigen::internal::*; }; };