【问题标题】: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 汇编和/或低级编程。在现代处理器上,函数调用比未对齐的负载要糟糕得多。

标签: c++ simd intrinsics


【解决方案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,因此将寄存器存储在堆栈上,很可能会经历一些缓存未命中等。

【讨论】:

    猜你喜欢
    • 2016-06-14
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    相关资源
    最近更新 更多