gpt4 book ai didi

c++ - 使用位运算符消除分支

转载 作者:可可西里 更新时间:2023-11-01 17:37:13 25 4
gpt4 key购买 nike

我在一个运行了大约 2^26 次的循环中有一些关键的分支代码。分支预测不是最优的,因为 m 是随机的。我将如何删除分支,可能使用按位运算符?

bool m;
unsigned int a;
const unsigned int k = ...; // k >= 7
if(a == 0)
a = (m ? (a+1) : (k));
else if(a == k)
a = (m ? 0 : (a-1));
else
a = (m ? (a+1) : (a-1));

这里是 gcc -O3 生成的相关程序集:

.cfi_startproc
movl 4(%esp), %edx
movb 8(%esp), %cl
movl (%edx), %eax
testl %eax, %eax
jne L15
cmpb $1, %cl
sbbl %eax, %eax
andl $638, %eax
incl %eax
movl %eax, (%edx)
ret
L15:
cmpl $639, %eax
je L23
testb %cl, %cl
jne L24
decl %eax
movl %eax, (%edx)
ret
L23:
cmpb $1, %cl
sbbl %eax, %eax
andl $638, %eax
movl %eax, (%edx)
ret
L24:
incl %eax
movl %eax, (%edx)
ret
.cfi_endproc

最佳答案

无分支无除法模可能很有用,但测试表明在实践中没有用。

const unsigned int k = 639;
void f(bool m, unsigned int &a)
{
a += m * 2 - 1;
if (a == -1u)
a = k;
else if (a == k + 1)
a = 0;
}

测试用例:

unsigned a = 0;
f(false, a);
assert(a == 639);
f(false, a);
assert(a == 638);
f(true, a);
assert(a == 639);
f(true, a);
assert(a == 0);
f(true, a);
assert(a == 1);
f(false, a);
assert(a == 0);

实际计时,使用测试程序:

int main()
{
for (int i = 0; i != 10000; i++)
{
unsigned int a = k / 2;
while (a != 0) f(rand() & 1, a);
}
}

(注意:没有srand,所以结果是确定的。)

我的原答案:5.3s

题中代码:4.8s

查找表:4.5s (static unsigned lookup[2][k+1];)

查找表:4.3s (static unsigned lookup[k+1][2];)

Eric 的回答:4.2s

本版本:4.0s

关于c++ - 使用位运算符消除分支,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12030022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com