首页 > 解决方案 > 非 simd intel 内在的隐式定义

问题描述

在以下链接中有一个非 simd 英特尔内在函数的部分: https ://software.intel.com/sites/landingpage/IntrinsicsGuide/

其中包括汇编指令,如 bsf 和 bsr。对于 SIMD 指令,我可以复制 c 函数并在包含正确的标头后运行它。

对于非 simd 函数,比如_bit_scan_reverse(bsr),我知道这个函数对于 gcc 是未定义的(隐式定义)。GCC 有类似的“内置函数”,例如__builtin_ctz,但没有_bit_scan_reverseor _mm_popcnt_u32。为什么这些内在函数不可用?

#include <stdio.h>
#include <immintrin.h>

int main(void) {
  int x = 5;
  int y = _bit_scan_reverse (x);
  printf("%d\n",y);
  return 0;
}

标签: cgccintrinsics

解决方案


看来我需要进行两项更改:

x86intrin.h首先,包含而不是更具体的包含似乎是最佳实践。这似乎是特定于编译器的,并且在以下内容中有更详细的介绍:

x86 SIMD 内部函数的头文件

重要的是,如果不使用 gcc,您将拥有不同的包含。

其次,还需要启用编译器选项。对于 gcc,这些在以下中有详细说明:

https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html

尽管缺少许多标志的文档。

由于我的目标是分发已编译的二进制文件,因此我想尽量避免-march=native

我感兴趣的大多数“其他”内在函数都与位操作相关。Ye Olde Wikipedia 对 bmi2 等重要的位操作内在组有很好的描述: https ://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets

我需要 bmi2 用于BZHI(指令)或_bzhi_u32(c)

因此,我可以通过以下方式获得我想要的东西:

-mavx2 -mbmi2

使用-mbmi2似乎足以获得 bmi1 和 abm 之类的东西(有关定义,请参见链接的 Wikipedia 页面),尽管我在链接的 gcc 页面中没有看到任何提及这一点,所以我可能对此有误...... 编辑:似乎添加 bmi2 支持不会添加 bmi1 和 abm,我可能一直在使用 __builtin 调用....我后来需要添加-mabm-mbmi明确获得我想要的指令。正如 Peter Cordes 建议的那样,最好将 Haswell-march=haswell作为起点,然后根据需要添加其他标志。Haswell 是 2013 年以来第一个配备 AVX2 的处理器,所以在我看来-march=haswell基本上是在说,我希望您拥有 2013 年或更新的计算机。

此外,根据一些快速阅读,听起来 __builtin 的使用启用了必要的标志(SO 的未来问题),尽管内在函数和内置函数之间似乎没有 1:1 的对应关系。更具体地说,并非所有内在函数似乎都包含在内置函数中,这意味着标志设置方法似乎是必要的,而不是总是使用内置函数而不担心设置标志。此外,出于分发目的,了解正在使用的内在函数也很有用,因为似乎大部分计算机上仍然缺少 bmi2(例如,我认为从 2015 年起需要 AMD)。

我仍然不清楚为什么只使用英特尔文档中指定的包含不起作用,但这个信息让我 99% 到达我想去的地方。


推荐阅读