【问题标题】:Branchless Binary Search无分支二分搜索
【发布时间】:2011-02-08 18:53:43
【问题描述】:

我很好奇是否有人可以向我解释无分支二进制搜索实现。我在最近的question 中看到了它,但我无法想象它会如何实现。如果项目数量很大,我认为避免分支可能很有用。

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    我将假设您正在谈论“在您想要支持的域中创建一个包含所有完美正方形的static const 数组,并对其执行快速无分支二进制搜索”这句话。发现于this answer

    “无分支”二分搜索基本上只是展开的二分搜索循环。这仅在您事先知道要搜索的数组中的项目数时才有效(就像您在 static const 时一样)。展开的代码如果太长,手工写不出来,你可以写一个程序来写。

    然后,您必须对您的解决方案进行基准测试,看看它是否真的比循环更快。如果您的无分支代码太大,它将无法放入 CPU 的快速指令缓存中,并且运行时间会比等效循环更长。

    【讨论】:

    • 嗯,好的,我现在明白了,谢谢。我认为有一些奇怪的操作来避免循环内的 if 语句。
    • +1 因为这确实是删除循环分支的有用方法,尽管从稍后对该问题的评论来看,R. 似乎打算使用“旋转位以避免条件分支”的含义。通过同时做这两件事,你实际上可以避免 all 分支。
    • Bentley 的“Programming Pearls”IIRC 中介绍了这种“无分支”展开搜索,他在其中彻底解释了该技术
    • @GWW:我创建了这种无分支二分搜索的实现,但它被常规搜索从水中吹走了。也许我在桌面上留下了一些优化? gist.github.com/3481295
    • 您将如何处理涉及代码大小的基准测试问题?听起来只有现实生活中的实现(完整的应用程序)才能描绘出真实的画面。
    【解决方案2】:

    如果有一个函数根据正确项目相对于当前项目的位置返回 +1、-1 或 0,则可以将位置初始化为列表大小/2,并将步长初始化为位置/2,然后每次比较后做位置+=方向*步长;步长=步长/2。迭代直到步长为零。

    【讨论】:

    • "迭代直到步长为零。"无分支是怎么回事,你做的分支不是零?
    • 如果知道起始值,就可以展开循环所需的次数。或者,某些硬件平台(尤其是 DSP)支持硬件中的 Fortran 风格的“DO”循环;当从与循环结束地址匹配的地址中取出指令时,循环计数器将递减,程序计数器将加载循环起始地址。循环的零周期开销。
    • 计算分支仍然是分支。循环展开是无分支的(或者至少可以),但它不使用“直到步长为零”之类的任何条件。
    • @rlibby:DSP 循环不是分支,因为执行单元看到连续的(非分支)指令流,循环中的指令重复了适当的次数。至于终止条件,如果知道起始值,则可以相当容易地确定可能需要的最大循环数。由于迭代次数超过必要次数将是无害的,如果需要,只需编写最大值即可。由于无法在 O(1) 时间内执行二分查找,因此只有针对特定的最大数组大小进行编码才能实现无分支。
    猜你喜欢
    • 1970-01-01
    • 2015-08-23
    • 2013-11-15
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    • 2021-03-23
    相关资源
    最近更新 更多