【问题标题】:What is the fastest way for bit operations to calculate a parity?位运算计算奇偶校验的最快方法是什么?
【发布时间】:2011-05-11 15:41:42
【问题描述】:

我的解决方案:(对于输入块的每一位,都有这样一行)

*parity ^= (((x[0] >> 30) & 0x00000001) * 0xc3e0d69f);

所有类型都是 uint32。此行获取输入 x 的第二位,将其移至 LSB 并将所有其他位设置为零。然后,将 32 位奇偶校验与为该位设置的相应奇偶校验进行异或。

我发现这种乘法解决方案是执行此条件异或的最快方法。有更快的方法吗?

【问题讨论】:

  • 你在说什么语言/处理器?
  • 您要计算奇偶校验的块有多大?乘以 0xc3e0d69f 的意义何在?
  • 我说的是 C++。数据块是 256 位(因此 uint32 x[0..7]。奇偶校验是 32 位(存储在 uint32 中)。对于输入的每个设置位,奇偶校验字段都会应用一个特定的 XOR-Mask(并行实现) LFSR)。

标签: c bit-manipulation parity


【解决方案1】:

See here 用于计算单词、字节等奇偶校验的一些巧妙技巧

【讨论】:

  • 谢谢 - 我已经尝试了页面上的提示。但尤其是“有条件地设置或清除位而不分支”比乘法解决方案要慢。
【解决方案2】:

我不完全明白你的意思是什么奇偶校验,但是如果这行代码做你想要的,它可能会得到改进。

一般规则:对于 x in {0, 1} x * N == -x & N

这是因为 -x 表示 0 表示所有位都重置,而 1 表示 -1 表示所有位都已设置。

所以原来的代码行可以改写为:

*parity ^= (-((x[0] >> 30) & 0x00000001) & 0xc3e0d69f);

在许多微处理器上,哪两个运算的计算时间比乘法要短,但您应该检查一下。

代码也可以利用带符号的右移

*parity ^= (((int32_t)x[0] << 1 >> 31) & 0xc3e0d69f);

首先将第 30 位移位到第 31 位,即符号位,然后在所有其他位上扩展符号位,因为大多数机器上的右移充当地板(x / 2N),因此用符号位(abc...yz&gt;&gt;3 == aaaabc...yz)填充移位的位。

但这些技巧在 C 标准中被描述为 未定义的行为,因此不可移植。小心使用它们。

【讨论】:

  • 听起来不错 - 非常感谢,我明天试试!
【解决方案3】:

某些处理器会为您执行此操作。请参阅 x86 的 parity flag

【讨论】:

  • 不只是奇偶校验,它有 32 位。
【解决方案4】:

如果我正确理解了这个问题,那么你就是在做

for (i = 0; i < 32; i++)
    *parity ^= (((x[0] >> i) & 1) * SOME_CONST[i]); 

如果是这样,最好使用查找表:

for (i = 0; i < 4; i++)
    *parity ^= PARITY_LUT[i][ (x[0] >> (i*8)) & 0xFF];

它将花费 256kb,但会更快。

【讨论】:

    【解决方案5】:

    奇偶校验计算任务相当于一个计数。它也称为“计数集位”、“人口连续”或简称为人口计数。一些处理器有有效的指令来计算它(POPCNT,VCNT)。

    我会建议使用最低的 popcount。

    它可以通过内联汇编器或使用内置函数来访问: __builtin_popcount()/ __popcnt()/ std::bitset::count() 用于 GCC/VS/C++

    我个人更喜欢使用 __builtin_parity()

    将这项工作交给编译器

    【讨论】:

      猜你喜欢
      • 2013-06-25
      • 1970-01-01
      • 2016-01-31
      • 2017-06-22
      • 2013-03-13
      • 2015-06-05
      • 2010-11-09
      • 2014-05-11
      • 1970-01-01
      相关资源
      最近更新 更多