对于一个特定的项目,我坚持使用gcc和在i7 Core上运行的32位12.04 LTS Ubuntu,支持高达AVX SIMD指令。
由于 32 位操作系统,我显然无法使用在 256 位上运行的 AVX 指令。我可以使用 4.2 位访问 SSE128 指令,POPCNT 可以在 16、32 和 64 位数据上运行,所以看起来很有希望。但是我已经尝试了几种方法向POPCNT提供64位数据,但没有成功。GCC 4.6.3 返回
- R8 至 R15 的"未知寄存器名称",
- RAX-RDX 的"错误寄存器名称", 当尝试提供 MM 寄存器或
- 为我的内联程序集函数提供一些 uint64 或长 uint64 或长 在这样的寄存器中 受到影响时
道路:
uint64 a, b;
__asm__ volatile (“POPCNT %1, %0;”
:”=r”(b)
:”r”(a)
:
)
GCC 告诉"POPCNT 的操作数类型不匹配",
- 编写 POPCNTQ 会导致"POPCNT 的指令后缀无效"。
如果 POPCNT 支持 128 位 xmm 寄存器,那就太好了......
有什么解决方法可以对程序集中的 64 位数据应用 POPCNT 吗?
PS:关于使用随机播放的SSSE3流行计数与SSE4 POPCNT性能的讨论在这里找到了结论 http://danluu.com/assembly-intrinsics/这仅仅是因为使用内部函数并不总是提供有效的汇编代码。使用内联函数快速优化C/C++代码很好,如果这足以满足需求,那很好。但除此之外,与内部函数相比,我在汇编中使用随机排序获得了近 30% 的性能改进。
popcnt
是一个整数指令。因此,在 32 位模式下,不能将其与 64 位操作数一起使用。您需要计算两半的popcnt
并将它们相加。这就是我测试过的所有 clang 版本对内置版本所做的。但是,我无法获得任何 gcc 版本来使用 popcnt 指令。因此,虽然通常建议使用内置,但在这种情况下,内联 asm 可能会更好。
32 位系统上不支持 64 位 POPCOUNT,因为
REX 前缀仅在长模式下可用。(不在 32 位操作系统中)
因此
编写 POPCNTQ 会导致"POPCNT 的指令后缀无效"。
看这里:http://www.felixcloutier.com/x86/POPCNT.html(引用如下)
Opcode Instruction Op/En 64-Bit Mode Compat/Leg Mode Description
F3 0F B8 /r POPCNT r16, r/m16 RM Valid Valid POPCNT on r/m16
F3 0F B8 /r POPCNT r32, r/m32 RM Valid Valid POPCNT on r/m32
F3 REX.W 0F B8 /r POPCNT r64,r/m64 RM Valid N.E. POPCNT on r/m64
解决方法是将 64/128 位拆分为两个/四个 32 位指令:
; a=uint_64, 64 bit operand, little endian
popcount eax, dword ptr [a]
popcount edx, dword ptr [a+4]
add eax, edx
xor edx, edx ; for first mov below
mov dword ptr [b], edx ; not neccessary, only due to 64 target op (will there ever be 2^64 bits set???)
mov dword ptr [b+4], eax
编辑:MASM32代码中(二进制)汉明距离的64位操作数大小版本:
Hamming_64 PROC word1:QWORD , word2: QWORD
mov ecx, dword ptr [word1]
mov edx, dword ptr [word1+4]
xor ecx, dword ptr [word2]
xor edx, dword ptr [word2+4]
popcnt eax, ecx
popcnt ebx, edx
add eax, ebx ; returns distance in EAX
ret
Hamming_64 ENDP
是否有 32 位 popcnt 指令,但我敢打赌你不能在 64 位代码中使用 32 位 popcnt。尝试将 a 和 b 声明为 uint32_t。 顺便说一句,uint64_t是标准 C,uint64 不是。
使用汇编实现 32 位 POPCNT 后,与 SSSE3 随机汇编方法相比,看起来没有真正的改进。正如我所怀疑的那样,只有64位POPCNT版本才能使速度几乎翻倍。