我正在开发一个包含许多软件包的大型软件包,这些软件包被编译为共享对象。出于性能原因,我想用向量指令编译Eigen 3(一个只有头的库),但模板化的方法正在整个地方进行编译。如何确保将特征函数编译为特定的目标文件?
该软件包含约2000个独立包。为了使开发保持合理的速度,编译程序的推荐方法是稀疏地检查一些包并编译它们,之后可以使用预编译(通过某些CI系统)共享库来执行程序。
问题是我的部分职责是优化程序的CPU时间。为了做到这一点,我想用A.so
标志编译我正在处理的包(让我们称之为-march
),以便Eigen可以利用现代SIMD处理器扩展。
不幸的是,因为Eigen是一个只有头的库,所以Eigen函数被编译成许多不同的共享对象。例如,在A.so
中调用的最耗费CPU的方法之一是矩阵多平面内核,它是在B.so
中编译的。许多其他的特征函数被编译成C.so
,D.so
等。由于这些对象是为较旧的,更广泛实现的指令集扩展编译的,因此它们不是用AVX,AVX2等编译的。
当然,一种可能的解决方案是将包B
,C
,D
等包含在我自己的稀疏编译中,但这否定了仅编译项目的一部分的优点。另外,如果我真的想要在包A
的代码中矢量化所有线性代数运算,它会让我包含越来越多的包。
我正在寻找的是一种方法来编译A
使用的所有特征函数到A.so
,就像使用static关键字定义了特征函数一样。这可能吗?我可以利用编译器/链接器中的某些机制来实现这一点吗?
一个明显的解决方案是隐藏这些符号。发生这种情况(如果我理解正确的话),因为这些函数被导出并且可以被其他后续加载的库使用。
当您构建库并链接到其他库时,链接器会重用它所能提供的功能。还有旧套餐。我希望你不需要这些库用于你自己的构建?
所以有两个选择:
A
(但如果你需要其他库,我认为这不可行),visibility=hidden
)不应该看到这些函数。我看到一个类似于编译错误的第三方库的类似事情。它是在调试模式下构建的,在产品中提供,突然之间我们的一个库经历了一个减速。确定罪魁祸首调试功能来自的地图文件,因为它默认导出了所有符号。
在不修改代码的情况下更改可见性的另一种方法是使用版本脚本 - > https://sourceware.org/binutils/docs/ld/VERSION.html在链接阶段过滤符号。你需要像
{
global: *;
local:
extern "C++"
{
Eigen::*;
*Eigen::internal::*;
};
};
这样的东西