通过函数指针使用内部函数时的链接器错误
Posted
技术标签:
【中文标题】通过函数指针使用内部函数时的链接器错误【英文标题】:Linker errors when using intrinsic function via function pointer 【发布时间】:2015-08-26 06:47:10 【问题描述】:下面的代码不能用 Visual Studio 2013 编译。我得到 mm 函数的链接器错误未解析的外部符号(LNK 2019)。如果我直接使用这些功能,一切都很好。 为什么它不编译?有没有解决办法
#include "emmintrin.h"
#include <smmintrin.h>
#include <intrin.h>
__m128i (*load)(const __m128i*) = NULL;
if (it::isAligned<16>(ucpSrc, iXOffset * sizeof(unsigned char)) )
load = &_mm_load_si128;
else
load = &_mm_lddqu_si128;
【问题讨论】:
sizeof(unsigned char)
是 1
确定这些是普通函数而不是仿函数类?
这些内在函数不是函数,而是编译器插入的单个机器指令。
在循环中使用加载,如果我将 mm - 指令包装到函数中,是否会产生任何重大开销
如果您真的要问这个问题,我怀疑您可能不了解基本的 x86 汇编和/或低级编程。在现代处理器上,函数调用比未对齐的负载要糟糕得多。
【参考方案1】:
gcc 和 clang 等一些编译器在这些方法上使用了一些特殊的注解(static extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__))
用于 gcc,或 static __inline__ __attribute__((__always_inline__, __nodebug__))
用于 clang),而其他编译器(如 Windows 和 cl 上的 Intel,则不这样做并且可能会做一些特别的事情在引擎盖下。
关键是这些函数并不意味着被视为函数。他们不会显示任何序言,实施标准 ABI。这些只是调用一些汇编指令的 C 语法方式,比 __asm (...)
更具可读性
我相信你可以通过以下方式完成这个函数指针的事情:
__m128i load_aligned (const __m128i* p)
return _mm_load_si128(p);
__m128i load_unaligned (const __m128i* p)
return _mm_lddqu_si128(p);
__m128i (*load)(const __m128i*) = NULL;
void f(bool a)
if (a)
load = load_aligned;
else
load = load_unaligned;
int main()
__m128i a, b ;
f(argc != 0);
return 0;
不过,我要强调一个性能说明:使用函数指针将比一直使用未对齐的负载要昂贵得多。当内存对齐时,未对齐加载的开销约为百分之几,调用函数指针将强制您尊重 ABI,因此将寄存器存储在堆栈上,很可能会经历一些缓存未命中等。
【讨论】:
以上是关于通过函数指针使用内部函数时的链接器错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 jOOQ 执行 PL/SQL 函数时的 Java 空指针