我有一个二分搜索循环,它在执行路径中被多次命中。
探查器显示,搜索的除法部分(在给定搜索范围的高索引和低索引的情况下查找中间索引)实际上是搜索中成本最高的部分,大约是 4 倍。
(我认为)它不是对于有效的二分搜索找到精确的中间值至关重要,该值只是靠近中间且在任一方向上都没有偏差的值。
是否有一种比特旋转算法可以用更快的算法替换 mid = (low + high) / 2
?
编辑:语言是 C#,但等效的位操作在任何语言中都有效(尽管它可能没有性能优势),这就是我保留 C# 标记的原因。
I have a binary search loop which gets hit many times in the execution path.
A profiler shows that the division part of the search (finding the middle index given the high and low indices of the search range) is actually the most costly part of the search, by a factor of about 4.
(I think) it is not critical for efficient binary search to find the exact middle value, just a value near the middle which does not have bias in either direction.
Is there a bit-twiddling algorithm to replace mid = (low + high) / 2
with something much faster?
Edit: Language is C#, but the equivalent bit-operation is valid in any language (although it may be of no performance benefit), which is why I left the C# tag off.
发布评论
评论(6)
这是平均值的位黑客版本,不会遇到溢出问题:
Here is a bit-hack version of the average that does not suffer from the overflow problem:
请注意,使用“(low + high) / 2”进行中点计算 将无法正常工作。
Be advised that using "(low + high) / 2" for midpoint calculations won't work correctly when integer overflow becomes an issue.
您可以使用位移位并克服可能的溢出问题:
但是我必须承认我希望现代编译器和解释器将除以 2(或除以任何其他 2 的常数幂)作为位移位,所以不确定它是否会真的有帮助 - 尝试一下。
You can use bit shifting and also overcome a possible overflow issue:
However I must admit I expect modern compilers and interpreters to do division by 2 (or division by any other constant power of 2) as bit-shifting, so not sure if it will really help - try it out.
为了进一步扩展尼尔斯的答案,理查德·施罗佩尔发明了这个。
http://www.inwap.com/pdp10/hbaker/hakmem/boolean .html#item23
(A AND B) + (A OR B) = A + B
因为A AND B
给出了 2 的共享(A 和 B 之间)幂的总和,< code>A OR B 给出共享的和不共享的,因此:A XOR B
给出 A 和 B 之间不同的位的映射。因此,因此:
To further expand on Nils' answer Richard Schroeppel invented this.
http://www.inwap.com/pdp10/hbaker/hakmem/boolean.html#item23
(A AND B) + (A OR B) = A + B
becauseA AND B
gives the sum of the shared (between A and B) powers of two,A OR B
gives both those shared and those that aren't, hence:A XOR B
gives a map of those bits that differ between A and B. Hence,And thus:
如果我没记错的话,在某些情况下,使用数组的中间位置实际上会更慢。 解决方案是随机选择平分数组的索引。 确定数组中位数的算法同样如此。
我不记得确切的细节,但我记得在 iTunes 上的 MIT 算法系列。
If I recall correctly, there are some cases where using the exact middle of the array can actually be slower. The solution is to randomize the choice of the index where you bisect the array. Equally true of the algorithm for determining the median of an array.
I can't recall the precise details, but I remember hearing in lecture 6 of the MIT algorithms series on iTunes.
尝试低 + ((高 - 低) / 2))。 这应该有效,因为您只取两个数字的平均值。 如果二分搜索列表相当大,这将减少算法所花费的时间,因为高 - 低比高 + 低要小得多。
Try low + ((high - low) / 2)). This should work because you're only taking the average of two numbers. This would reduce the amount of time the algorithm is taking if the binary search list is fairly big, since high - low is much smaller than high + low.