【问题标题】:Are bitwise operations still practical?按位运算仍然实用吗?
【发布时间】:2011-09-27 10:17:39
【问题描述】:

维基百科,唯一的知识来源,指出:

在大多数较旧的微处理器上,按位 操作略快于 加法和减法运算 并且通常明显快于 乘法和除法 操作。在现代建筑中, 情况并非如此:按位 操作大致相同 速度作为加法(虽然仍然更快 比乘法)。

学习按位运算技巧是否有实际的理由,或者现在只是为了理论和好奇心而学习的东西?

【问题讨论】:

  • 维基百科“真正的知识来源”?好像有点夸张了……
  • @ShinTakezou:这叫讽刺。
  • 除了我认为这种说法被夸大了,而且我认识一些人认为维基百科确实是一个伟大的知识来源而且它是总是对的,因为我不知道 OP 的真实观点和 PoV,所以我必须认真对待这个说法。很高兴知道这是讽刺。
  • 在这种情况下,我们真正的知识来源对于现代 CPU 来说甚至是完全正确的。有关 Intel 的指令表,请参阅 here。 ADD/SUB 和 AND/OR/XOR 的倒数吞吐量是完全相同的 ;)
  • 你竟敢玷污维基媒体基金会的名誉! For a GNU dawn!

标签: c bit-manipulation bitwise-operators


【解决方案1】:

当然(对我来说)答案是肯定的:学习它们可能有实际的理由。如今,例如,add 指令在典型处理器上or/xorand 一样快,这仅意味着:add 一样快例如,那些处理器上的or

诸如加法、除法等指令速度的提高,只是意味着现在在这些处理器上您可以使用它们,而不必担心性能影响;但现在和过去一样,您通常不会将每个adds 更改为按位运算来实现add。也就是说,在某些情况下,它可能取决于哪些 hack:现在可能某些 hack 必须被视为具有教育意义,不再实用;其他人可能仍然有实际应用。

【讨论】:

    【解决方案2】:

    有趣的是,没有人认为在 C/C++ 中提及 ctype[] 数组是合适的——也是用 Java 实现的。这个概念在语言处理中非常有用,尤其是在使用不同的字母表或解析句子时。

    ctype[] 是一个由 256 个短整数组成的数组,每个整数中都有代表不同字符类型的位。例如, ctype[;A'] - ctype['Z'] 设置了位以显示它们是字母表的大写字母; ctype['0']-ctype['9'] 设置了位以显示它们是数字的。要查看字符 x 是否为字母数字,您可以编写类似 'if (ctype[x] & (UC | LC | NUM))' 的内容,这比编写 'if ('A' = x

    一旦您开始按位思考,您就会发现很多地方都可以使用它。例如,我有两个文本缓冲区。我写了一个到另一个,在我去的时候用 REPLACEstring 替换了所有出现的 FINDstring。然后对于下一个查找-替换对,我只是切换了缓冲区索引,所以我总是从缓冲区 [in] 写入缓冲区 [out]。 'in' 从 0 开始,'out' 从 1 开始。完成副本后,我简单地写了 'in ^= 1;出^= 1;'。在处理完所有替换之后,我只是将 buffer[out] 写入磁盘,不需要知道当时的“out”是什么。

    如果您认为这是低级的,请考虑某些心理错误,例如似曾相识及其孪生似曾相识,是由脑位错误引起的!

    【讨论】:

      【解决方案3】:

      按位运算仍然有用。例如,它们可用于使用单个变量创建“标志”,并节省用于指示各种条件的变量数量。关于算术运算的性能,最好让编译器进行优化(除非您是某种大师)。

      【讨论】:

      • 这对于诸如协议或硬件配置之类的东西是必不可少的,并且是比操作周期计数所暗示的更大的性能改进的潜在来源,因为它可以显着降低代码的内存带宽需求。
      • “最好让编译器进行优化(除非你是某种大师)” - 或者编写编译器,或者使用垃圾编译器......学习所有的黑客可能不会是必不可少的,但学习如何使用按位运算应该被视为与学习如何正确使用“+”和“,”一样重要。
      • @James 不确定。正如此处较早的帖子(现在很遗憾已删除)表明,弄错这些东西太容易了。此外,bitstuff 作为对数学重的东西的性能优化最有用,这些东西应该在一些不错的库中。对于空间优化(其中有一些陷阱),您可以使用位域再次很好地隐藏这些东西。所以基本上你只需要这样做来编写一些低级协议的东西,因为 C 再次未定义位域的顺序..
      【解决方案4】:

      使用 IPv4 地址经常需要位操作来发现对等点的地址是否在可路由网络内或必须转发到网关,或者对等点是否属于防火墙规则允许或拒绝的网络的一部分。需要进行位操作才能发现网络的广播地址。

      使用 IPv6 地址需要相同的基本位级操作,但由于它们很长,我不确定它们是如何实现的。我敢打赌,它们仍然是在片段数据上使用位运算符实现的,大小适合架构。

      【讨论】:

        【解决方案5】:

        位运算值得研究,因为它们有很多应用。 不是它们的主要用途是替代算术运算。密码学、计算机图形学、哈希函数、压缩算法和网络协议只是位运算非常有用的一些示例。

        您从 Wikipedia 文章中引用的行只是试图提供一些有关按位运算的 速度 的线索。遗憾的是,该文章未能提供一些很好的应用示例。

        【讨论】:

          【解决方案6】:

          确实,在大多数情况下,当您将整数乘以恰好是 2 的幂的常量时,编译器会对其进行优化以使用位移。但是当shift也是一个变量的时候,编译器是不能推导出来的,除非你显式的使用了shift操作。

          【讨论】:

          • 是的。另一方面,一些处理器的倍增速度超过了它们执行可变位数移位的速度。只写可读的。很有可能你的代码的关键 10% 无论如何都在其他地方......
          【解决方案7】:

          取决于你的问题是什么。如果您正在控制硬件,则需要在整数中设置单个位的方法。

          购买一块 OGD1 PCI 板卡(开放显卡)并使用 libpci 与它对话。 http://en.wikipedia.org/wiki/Open_Graphics_Project

          【讨论】:

            【解决方案8】:

            使用它们有意义的唯一情况是,如果您实际上将数字用作位向量。例如,如果您正在对某种硬件进行建模,并且变量代表寄存器。

            如果要进行算术运算,请使用算术运算符。

            【讨论】:

              【解决方案9】:

              它们有助于理解二进制“工作”的原理;否则,不。事实上,我想说的是,即使在给定架构上按位 hack 更快,利用这一事实是编译器的工作——而不是你的工作。写下你的意思。

              【讨论】:

              • +1 表示“这是编译器的工作”。也就是说,有时你的意思是|将一堆位掩码放在一起,然后将结果与一个值一起查看是否设置了各种标志。
              • @Sherm:当然——但是你不是“意思”加法或减法,所以按位运算在语义上是正确的(同样,编译器的工作是找出最好的方法来做到这一点)。
              • 代码并不总是被编译,取决于平台和语言,所以如果性能仍然是一个问题,按位运算可以很方便地了解和使用
              • 我不会把它放在现代解释器之外来优化一些琐碎的技巧——即使不是。严格的数学循环很少在解释性语言上运行 - 结果不会特别好(50+ 或 numpy 和常规 python 实现之间的什么?)
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-09-13
              • 2011-07-14
              • 1970-01-01
              • 1970-01-01
              • 2020-02-11
              • 2020-01-23
              相关资源
              最近更新 更多