【问题标题】:Is there any difference in the efficiency of counting leading/trailing ones/zeros?计算前导/尾随 1/0 的效率有什么不同吗?
【发布时间】:2020-11-23 18:19:12
【问题描述】:

我正在设计一个带前缀的可变长度整数。

Rust 具有计算前导和尾随 1 和 0 的方法:https://doc.rust-lang.org/std/primitive.u64.html#method.leading_zeros

这些方法在 x86_64、arm32 和 arm64 上的效率有什么区别吗?

例如如果计算尾随 1 比尾随 0 快,我将使用 xxxx0111 而不是 xxxx1000 作为长度编码字节(在本例中为三个后续字节)。

【问题讨论】:

  • on x86_64, arm32 and arm64? 那么支持哪些指令集最好的和最简单的方法是编写一个小程序并检查这些体系结构上生成的程序集。请尝试一下。记住rules of optimization

标签: rust arm bit-manipulation x86-64 varint


【解决方案1】:

在所有 3 个 ISA:x86*、ARM、AArch64 上,计算尾随零的速度都比尾随的快。它们都提供零计数指令,例如 x86 bsf(查找最低设置位)或 x86 BMI1 tzcnt(尾随零计数)。计算运行时变量中的前导/尾随需要否定输入。

ARM / AArch64 提供前导零计数,但尾随零的最佳选择是 rbit / clz 到位反转(从 ARMv6t2 或 ARMv7 开始)。 https://godbolt.org/z/Yr7eac。在此之前,编译器必须用x & -x 隔离最低设置位,计算其中的前导零,然后取31-clz(x&-x)


(在 x86 上,使用 BMI1 计算前导零最有效。没有它,bsr 可以为您提供最高设置位的位置,因此编译器需要31-bsr(x) 来实现 clz。在 AMD CPU 上,bsf / bsr比它们的 tzcnt / lzcnt 对应物要慢得多,所以如果可能的话,最好使用 -march=native 或其他 Rust 等价物进行编译。)

【讨论】:

  • 谢谢,我之前没遇到过godbolt。
  • rbit 可从armv7获得
  • @Jake'Alquimista'LEE:我的 Godbolt 链接显示 GCC 使用 rbit-march=armv6t2。哦,但显然不是普通的 ARMv6。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 2021-12-05
相关资源
最近更新 更多