我想使用著名的 MIT 位计数算法的一个版本,使用 SSE2 指令计算康威生命游戏中的邻居。
这是 c 中的 MIT 位计数,扩展到计数位计数 > 63 位。
int bitCount(unsigned long long n)
{
unsigned long long uCount;
uCount = n – ((n >> 1) & 0×7777777777777777)
- ((n >> 2) & 0×3333333333333333)
- ((n >> 3) & 0×1111111111111111);
return ((uCount + (uCount >> 4))
& 0x0F0F0F0F0F0F0F0F) % 255;
}
这是帕斯卡的一个版本
function bitcount(n: uint64): cardinal;
var ucount: uint64;
begin
ucount:= n - ((n shr 1) and $7777777777777777)
- ((n shr 2) and $3333333333333333)
- ((n shr 3) and $1111111111111111);
Result:= ((ucount + (count shr 4))
and $0F0F0F0F0F0F0F0F) mod 255;
end;
我正在寻找并行计算此结构中的位。
32-bit word where the pixels are laid out as follows.
lo-byte lo-byte neighbor
0 4 8 C 048C 0 4 8 C
+---------------+
1|5 9 D 159D 1|5 9 D
| |
2|6 A E 26AE 2|6 A E
+---------------+
3 7 B F 37BF 3 7 B F
|-------------| << slice A
|---------------| << slice B
|---------------| << slice C
注意这个结构中间有 16 位需要查找。我想使用 SSE2计算中间 16 位中的每一位的邻居计数。为了做到这一点,我将切片 A 放入 XMM0 低位双字中,切片 B 放入 XXM0-dword1 等。
我将 XMM0 复制到 XMM1 并屏蔽XMM0 的低位字中的012-456-89A
位5
,对 XMM0 的字1 执行相同操作,等等。使用不同的切片和掩码来确保 XMM0 和 XMM1 中的每个单词都包含不同像素的邻居。
问题
如何调整 MIT-bitcount 以在每个 XMM 字中得到每个字/像素的位计数?
备注
我不想使用查找表,因为我已经有了这种方法,我想测试一下 SSE2 是否会通过不需要对查找表进行内存访问来加快进程。
使用 SSE 汇编的答案将是最佳的,因为我在 Delphi 中对此进行了编程,因此我使用的是 x86+SSE2 汇编代码。