测试固定集是否相等且无分支
我有一组整数 (x, y, z)
和一个采用 3 个整数 (u, v, w)
的函数。如何测试 (x,y,z) == (u,v,w)
?天真的方法是:
bool match = (x == u || x == v || x == w) && (y == u || y == v || y == w) && (z == u || z == v || z == w);
有人知道一些智能位运算/算术可以做同样的事情吗?
我可以假设 (x, y, z)
或 (u, v, w)
都不包含重复项。
I have a set of integers (x, y, z)
and a function that takes 3 integers (u, v, w)
. How can I test if (x,y,z) == (u,v,w)
? The naive way is:
bool match = (x == u || x == v || x == w) && (y == u || y == v || y == w) && (z == u || z == v || z == w);
Does anyone know of some smart bit operations/arithmetic to do the same thing?
I can assume that neither (x, y, z)
or (u, v, w)
contain duplicates.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在这种情况下,您可以用按位运算替换逻辑运算以消除分支:
但是,您必须测量性能影响以确定这是更快还是更慢。
In this case, you can replace the logical operations by bitwise operations to eliminate the branching:
However, you would have to measure the performance effect to see if this is faster or slower.
您可以通过在进行实际测试之前转换为无符号并比较总和来预先消除一堆不相等的向量。
You can eliminate a bunch of unequal vectors up front by converting to unsigned and comparing the sums before doing the real test.
如果 a 和 b 相同,则 a^b 为零。因此,仅当 a 和 b 相同时
!(a^b)
才非零。假设您的平台可以在没有分支的情况下执行逻辑“not”,因此您可以使用单个分支测试 a 是否是 (u, v, w) 的成员:因此是否所有 (x, y, z) 都是成员(u, v, w) 的使用:
即仅对各种结果执行按位与操作,并且再次仅执行单个分支。
如果您的平台需要一个分支来执行
!
,例如,如果它本质上是作为a 执行的? 0 : -1
,那么这就是十个条件,并不比简单的解决方案更好。If a and b are the same then
a^b
is zero. So!(a^b)
is non-zero only when a and b are the same. Supposing your platform can do logical 'not' without a branch, you can therefore test whether a is a member of (u, v, w) with a single branch using:And hence whether all of (x, y, z) are members of (u, v, w) using:
i.e. just doing a bitwise and on the various results, and again only a single branch.
If your platform needs a branch to perform
!
, e.g. if it's performed essentially asa ? 0 : -1
, then that's ten conditionals and no better than the naive solution.在 C 语言中,没有分支就无法做到这一点。
如果您愿意内联汇编,可以使用一些 CMPXCHG 指令来完成此操作。
In C there is no way to do this without branching.
If you are willing to inline-assembly you can do this with some
CMPXCHG
instructions.正如评论中所指出的,只要 (x,y,z) 中的所有元素都包含在集合 (u,v,w) 中,你的“天真的”方式就会匹配。如果您确实想测试这些集合是否相等,您可能需要您可以快速过滤掉许多不匹配的情况,
某些处理器具有非分支“最小”和“最大”指令,这将允许您执行以下操作:
As pointed out in the comments, your 'naive' way matches whenever all the elements in (x,y,z) are contained in the set (u,v,w). If you really want to test if the sets are equivalent, you probably wantYou can quickly filter out many mismatches with
Some processors have a non-branching 'min' and 'max' instructions, which would allow you to do