【问题标题】:Fastest way of checking the condition l+1<r for int l,r in Java在 Java 中检查条件 l+1<r for int l,r 的最快方法
【发布时间】:2009-06-19 11:33:09
【问题描述】:

检查条件的最快方法是什么

l + 1 < r

int l,r 在 Java 中?

lr 不是恒定的,我知道 l &lt;= r。比较是二分搜索实现中while 循环的停止条件。我当然会在单独的测试(搜索大型数组)和使用它的代码中对我的代码进行基准测试。

我想,我正在寻找的是某种比目前情况更快的位操作。但我不知道。

【问题讨论】:

  • l,r 中的任何一个都是常数吗?您要在这里解决的实际问题是什么?
  • 当你说java的时候,所有的赌注都已经结束了
  • MAte 这是两个数字的比较,包括一个加法。你真的认为通过做一些魔术你的程序会变得快一百万倍吗?你有没有想过,还有一百万件事发生了,而你的无意义优化毫无意义。
  • 我删除了“白痴”标签。这里没有必要滥用
  • @harshath.jr - 是的,我觉得在 Java 中这需要超过 2 秒。

标签: java performance integer


【解决方案1】:

这种微优化几乎总是一个坏主意;你的表现将完全取决于热点编译器如何优化你的代码,以及与周围代码有关的微妙缓存效果。

【讨论】:

  • 我之前在Java中做过这样的微优化,效果不错。
【解决方案2】:

我认为这可能会很快。这将简化为非常简单的字节码,而 JIT(即时编译器)可能会将其简化为非常简单的本机实现。

(不相关:有趣的是看到“量化开发人员”使用 Java 顺便说一句。不经常发生)

【讨论】:

  • 是的,与 C++ 相比,我们损失了一些性能,但我们不喜欢算法交易,Java 比 C++ 有很多好处。无论如何,性能通常是受数据库限制的......
【解决方案3】:

那么基础比较必须:

l 加 1,与 r 比较结果

从 r 中减去 1 并将结果与​​ l 进行比较

所有现代硬件对于任一操作都将具有相同的原始性能(任何本机数据类型的加法和减法在完成周期和流水线副作用方面具有相同的性能)。

这会产生任何影响的唯一方法是:

l 或 r 之一是编译时已知的常量。例如。

l + 1 < 5
5 + 1 < r

在这种情况下,一个糟糕的优化编译器可能没有意识到它可以将第一个转换为l &lt; 4

但是所有 java 编译器都需要发现第二种情况是6 &lt; r

另一个是l和r的数据类型是否不同。

的操作:

  1. 浮点加法/减法然后与 int 比较
    诗句
  2. 积分加/减然后与双精度比较可能会有所不同。

公平地说,这在您的应用程序中成为严重问题的可能性可以忽略不计,因为与与决策相关的任何分支错误预测的管道命中相比,任何这些问题的周期成本都很小。

此外,一个体面的 JIT 可能会针对周围的代码进行各种优化,这些优化超过了所执行的微优化。

【讨论】:

  • 这个比较是在一个循环中,这是一个在我的代码中运行很多次的方法的主要部分。
  • 再次 - 减速不是比较,而是以下因素的组合:将 l 和 r(或其中之一)拉入缓存以及此类搜索的不良分支预测行为。
  • 仅仅因为采样/仪器分析器说您将大部分时间都花在“那条线上”并不意味着您花时间执行该代码。我建议投资一个分析器,它可以让您对缓存未命中或分支错误预测进行采样。你的工作应该允许这种投资(如果不需要,你需要一个打击雇主)
  • 我明白了关于分支预测的观点,但不幸的是,大多数时候我对长度 >20 的数组进行二进制搜索,所以我怀疑线性搜索(没有分支预测问题)会更快.我的雇主不喜欢花钱,但多亏了这一点,尽管有危机,我们现在没有现金流问题:D
  • 如果我是你,我会对其进行基准测试,你可能会发现你可以超过 20 并且仍然更快。另请注意,编写 BinarySearch 的 Binary 部分的方式会影响性能(因为要检查的下一个索引的计算可以做得很好(没有分支)或很差(有分支)
【解决方案4】:

有一个变量lr1,它总是等于(l - r + 1)。每当您增加或减少l 时,对lr1 执行相同的操作。 r 也是如此。

那么你的测试变成了(lr1 &lt; 0),修改lr1的指令不经常执行。

我觉得给你一个微优化有点傻,这在大多数情况下是一分钱一分货,一分钱一分货。就像你在比较字符串一样,它会完全淹没那个测试。

添加:由于您正在进行二进制搜索,我会提到 Jon Bentley 对二进制搜索的酷展开。首先,将表格A 填充到 2 的幂,例如 1024。然后编写如下内容:

i = 0;
if (X >= A[i+512]) i += 512;
if (X >= A[i+256]) i += 256;
   . . .
if (X >= A[i+  1]) i +=   1;

最后测试是否(X == A[i])。或者,如果您不想填充它,让 if 语句类似于
if (i+512 &lt; N &amp;&amp; X &gt;= A[i+512]) i += 512;

【讨论】:

    【解决方案5】:

    所有这些人都说了什么。编译器将为您优化它。编写它,使其看起来和阅读正确,然后继续。

    【讨论】:

      【解决方案6】:

      最好的办法是调整 JVM 而不是代码——因为这是你的瓶颈。

      尝试使用参数-server -XX:+AggressiveOpts 启动jvm。

      【讨论】:

      • 我几乎无法控制用于运行生产代码的 JVM 参数。
      【解决方案7】:

      如何将相等性测试移到 while 循环之外,以便仅在终止后检查 .equals()。顺便说一句,我找不到任何可以测试 l+1

      【讨论】:

        猜你喜欢
        • 2021-09-21
        • 2011-01-30
        • 2014-04-07
        • 1970-01-01
        • 1970-01-01
        • 2011-12-23
        • 1970-01-01
        • 2014-11-25
        • 2019-07-09
        相关资源
        最近更新 更多