我有这个函数,给定一个格雷码,返回下一个格雷码。您可以在此处找到有关其工作原理的更完整说明。问题是我想让这个增量函数模块化,以便递增对应的格雷码UINT_MAX
返回对应的格雷码0
(分别是最高有效位和0
)。由于这不是默认行为,因此我为这种特殊情况添加了检查。这是完整的算法:
unsigned next_gray(unsigned gray)
{
static const unsigned msb
= 1u << (CHAR_BITS - sizeof(unsigned) - 1u);
// gray is odd
if (__builtin_parity(gray))
{
if (__builtin_expect(gray == msb, false))
{
return 0u;
}
else
{
unsigned y = gray & -gray;
return gray ^ (y << 1u);
}
}
// gray is even
return gray ^ 1;
}
所以,实际的问题实际上是关于分支预测的。我经常读到__builtin_expect
只有当一个分支真的很可能被选中或不太可能被选中时才使用它,常见的例子是在没有错误的情况下加速程序。
考虑到我没有处理错误情况,我不确定使用__builtin_expect
这样的边界检查是否是一个好主意。这是一个使用的好地方__builtin_expect
还是增加最大值是一个足够常见的操作来欺骗分支预测?
注意:与往常一样,评论和答案会突出显示我的问题中不清楚的事情:)
我将提供更多背景信息:此函数旨在成为库的一部分,为了成为库而开发,并且不被任何已知的实际项目使用。因此,添加__builtin_expect
意味着我希望人们主要增加其他值而不是最大值;手头没有任何实际项目,我想知道这是否是一个安全的假设。