11

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

  1. __popcnt()
  2. _mm_popcnt_u32()

我发现的唯一区别是文档__popcnt()被标记为“Microsoft 特定”,并且_mm_popcnt_u32() 似乎是一个内在命令名称(非 MS 特定)。

这是唯一的区别,MS__popcnt()只调用 HW_mm_popcnt_u32()吗?

4

1 回答 1

14

多亏了 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,这两种实现都是二进制兼容的,尽管它们的内在名称不同。

英特尔的架构手册指出:

在应用程序尝试使用 POPCNT 指令之前,它必须检查处理器是否支持 SSE4.2(如果 CPUID.01H:ECX.SSE4_2[bit 20] = 1)和 POPCNT(如果 CPUID.01H:ECX.POPCNT[bit 23 ] = 1)。

AMD 的AMD64 架构程序员手册第 3 卷:通用和系统说明

CPUID 函数 0000_0001h 返回的 ECX 位 23 (POPCNT) 指示对 POPCNT 指令的支持。在使用 POPCNT 指令之前,软件必须在每个程序或库初始化时检查一次 CPUID 位,否则可能会导致不一致的行为。

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


AMD 的巴塞罗那,第一个拥有 popcnt 的 AMD CPU,没有完全实现 SSE4,所以英特尔的架构手册有可能提出了一种确定存在的方法,该方法适用于英特尔 CPU,但即使在合格的 AMD CPU 上也会失败。

英特尔在其第 2 卷指令集参考手册中的当前文档popcnt#UD If CPUID.01H:ECX.POPCNT [Bit 23] = 0popcnt仅说明了导致软件无法在没有 SSE4.2 的某些 AMD CPU 上利用的反竞争建议已不复存在。

于 2012-06-21T02:07:10.130 回答