相关疑难解决方法(0)

为什么破坏LZCNT的"输出依赖性"很重要?

在测量某些东西的同时,我测量的吞吐量比我计算的要低得多,我将其缩小到LZCNT指令(它也发生在TZCNT中),如以下基准所示:

  xor ecx, ecx
_benchloop:
  lzcnt eax, edx
  add ecx, 1
  jnz _benchloop
Run Code Online (Sandbox Code Playgroud)

和:

  xor ecx, ecx
_benchloop:
  xor eax, eax  ; this shouldn't help, but it does
  lzcnt eax, edx
  add ecx, 1
  jnz _benchloop
Run Code Online (Sandbox Code Playgroud)

第二个版本要快得多.它不应该.LZCNT没有理由对其输出有输入依赖性.与BSR/BSF不同,xZCNT指令总是覆盖其输出.

我在4770K上运行它,所以LZCNT和TZCNT没有被执行为BSR/BSF.

这里发生了什么?

x86 assembly

22
推荐指数
1
解决办法
1339
查看次数

除非Haswell指定,否则GCC会很难编制前导零计数

GCC支持__builtin_clz(int x)内置,它计算参数中前导零(连续最重要的零)的数量.

除了其他东西0之外,这对于有效地实现lg(unsigned int x)函数非常有用,该函数采用基数2的对数x,舍入为1:

/** return the base-2 log of x, where x > 0 */
unsigned lg(unsigned x) {
  return 31U - (unsigned)__builtin_clz(x);
}
Run Code Online (Sandbox Code Playgroud)

这部作品在简单的方式-尤其是考虑的情况下x == 1,并clz(x) == 31-再x == 2^0这样lg(x) == 031 - 31 == 0我们得到正确的结果.更高的x工作价值.

假设内置程序有效实现,这比备用纯C解决方案更好.

现在,它发生了,计数前导零操作基本上是bsrx86中指令的双重.返回参数中最重要的1位2的索引.因此,如果有10个前导零,则第一个1位位于参数的第21位.一般来说,我们有31 - clz(x) == bsr(x),并在这样bsr …

c performance x86 gcc intel

9
推荐指数
1
解决办法
668
查看次数

标签 统计

x86 ×2

assembly ×1

c ×1

gcc ×1

intel ×1

performance ×1