我为多个 CPU 编写了性能关键的代码。我在运行时检测 CPU,并基于此为检测到的 CPU 使用适当的函数。所以,现在我必须使用函数指针并使用这些函数指针调用函数:
void do_something_neon(void);
void do_something_armv6(void);
void (*do_something)(void);
if(cpu == NEON) {
do_something = do_something_neon;
}else{
do_something = do_something_armv6;
}
//Use function pointer:
do_something();
...
这并不重要,但我要提到的是,我针对不同的 cpu 优化了功能:支持 NEON 的 armv6 和 armv7。问题是,通过在许多地方使用函数指针,代码会变得更慢,我想避免这个问题。
基本上,在加载时链接器会使用函数地址解析重新定位和修补代码。有没有办法更好地控制这种行为?
就个人而言,我建议两种不同的方法来避免函数指针:为 cpu 相关函数创建两个单独的 .so (或 .dll),将它们放在不同的文件夹中,并根据检测到的 CPU 将这些文件夹之一添加到搜索路径(或LD_LIB_路径)。加载主代码和动态链接器将从搜索路径中选取所需的dll。另一种方法是编译两个单独的库副本:)
第一种方法的缺点是它迫使我至少拥有 3 个共享对象 (dll):两个用于 cpu 相关函数,一个用于使用它们的主代码。我需要 3 个,因为我必须能够在加载使用这些 cpu 相关函数的代码之前进行 CPU 检测。第一种方法的优点是应用程序不需要为多个 CPU 加载相同代码的多个副本,它只会加载将要使用的副本。第二种方法的缺点相当明显,无需多言。
我想知道是否有一种方法可以在不使用共享对象并在运行时手动加载它们的情况下做到这一点。其中一种方法是一些涉及在运行时修补代码的黑客技术,它可能太复杂而无法正确完成)。有没有更好的方法来控制加载时的重定位?也许将与 cpu 相关的函数放在不同的部分中,然后以某种方式指定哪个部分具有优先级?我觉得MAC的男子气概也有类似的东西。
仅 ELF(针对arm目标)解决方案对我来说就足够了,我并不真正关心PE(dll)。
thanks
您可能想要查找 GNU 动态链接器扩展STT_GNU_IFUNC
。添加时来自 Drepper 的博客:
因此,我设计了一个 ELF 扩展,它允许决定每个进程运行一次使用哪个实现。它是使用新的 ELF 符号类型 (STT_GNU_IFUNC) 实现的。每当符号查找解析为这种类型的符号时,动态链接器不会立即返回找到的值。相反,它将值解释为指向函数的函数指针,该函数不带参数并返回要使用的实际函数指针。所调用的代码可以在实现者的控制之下,并且可以基于实现者想要使用的任何信息来选择使用两个或更多个实现中的哪一个。
Source: http://udrepper.livejournal.com/20948.html http://udrepper.livejournal.com/20948.html
尽管如此,正如其他人所说,我认为您对间接调用对性能的影响是错误的。共享库中的所有代码都将通过 GOT 中的(隐藏)函数指针和加载/调用该函数指针的 PLT 条目来调用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)