x86 - __popcnt() 和 _mm_popcnt_u32() 有什么区别?

标签 x86 sse intrinsics sse4

MS Visual C++ 在具有 SSE4.2 的 CPU 上支持 2 种类型的 popcnt 指令:

  1. __popcnt()
  2. _mm_popcnt_u32()

我发现的唯一区别是 __popcnt() 的文档被标记为“Microsoft Specific”,而 _mm_popcnt_u32() seems to be an intrinsic command name (非 MS 特定)。

这是唯一的区别吗,MS __popcnt() 仅调用 HW _mm_popcnt_u32()

最佳答案

感谢 Intel 和 AMD,这是同一机器指令的两个不同的内在名称。该指令在所有支持它的 CPU 上都是相同的,并且不同的内在函数在 C 中也没有区别或 C++。

<小时/>

__popcnt*() 内置函数用于 AMD 的高级位操作 (ABM) 指令。请参阅http://blogs.amd.com/developer/2007/09/26/barcelona-processor-feature-advanced-bit-manipulation-abm/

_mm_popcnt_u*() 内在函数用于 Intel 的实现,其本身不是 SSE4.2 的一部分,但大约在同一时间实现。请参阅http://en.wikipedia.org/wiki/SSE4#POPCNT_and_LZCNT

根据https://www.chessprogramming.org/Population_Count ,尽管它们的内在名称不同,但两种实现都是二进制兼容的。

英特尔的architecture manual指出:

Before an application attempts to use the POPCNT instruction, it must check that the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1) and POPCNT (if CPUID.01H:ECX.POPCNT[bit 23] = 1).

AMD 的 AMD64 Architecture Programmer's Manual Volume 3: General Purpose and System Instructions

Support for the POPCNT instruction is indicated by ECX bit 23 (POPCNT) as returned by CPUID function 0000_0001h. Software MUST check the CPUID bit once per program or library initialization before using the POPCNT instruction, or inconsistent behavior may result.

我看不出为什么 popcnt 需要 SSE4.2 的存在,因此我认为检查 ECX 的第 23 位足以确定 popcnt 的存在。

<小时/>

AMD 的巴塞罗那是第一个具有 popcnt 的 AMD CPU,没有完全实现 SSE4,因此英特尔的架构手册可能建议了一种确定存在的方法,该方法将在英特尔 CPU 上工作,但在合格的 AMD CPU 上却失败。

英特尔当前documentation for popcnt在他们的第 2 卷指令集引用手册中仅说 #UD If CPUID.01H:ECX.POPCNT [Bit 23] = 0 因此,反竞争建议将导致软件在某些没有 SSE4.2 的 AMD CPU 上不利用 popcnt 的情况已经消失了。

关于x86 - __popcnt() 和 _mm_popcnt_u32() 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11114017/

相关文章:

c++ - Qt 5.1 使用 QSerialPort 进行串口通信

sse - AVX2:U8绝对差

c++ - 这种使用 SSE 处理数组尾部的方法是否矫枉过正?

gcc - 如何在 ARMv8-a 上启用 Aarch32 指令集?

c++ - Add+Mul 使用 Intrinsics 变得更慢——我哪里错了?

从 x86 汇编语言调用 C 函数

assembly - 汇编 TEST 指令如何与这些跳转指令一起工作?

将 __m256d 转换为 __m256i

assembly - cmpl和cmp的区别

c++ - 如何使用 SSE 将 _m128i 转换为 unsigned int?