在 Java 中检查 int l,r 的条件 l+1
条件的最快方法是什么
l + 1 < r
在 Java 中检查 int l,r
? l
和 r
不是常数,我知道 l <= r
。 比较是二分搜索实现中 while
循环的停止条件。 当然,我在单独的测试(搜索大数组)和使用它的代码中对我的代码进行基准测试。
我想,我正在寻找的是某种比目前情况更快的位操作。 但我不知道。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web
技术交流群。
条件的最快方法是什么
l + 1 < r
在 Java 中检查 int l,r
? l
和 r
不是常数,我知道 l <= r
。 比较是二分搜索实现中 while
循环的停止条件。 当然,我在单独的测试(搜索大数组)和使用它的代码中对我的代码进行基准测试。
我想,我正在寻找的是某种比目前情况更快的位操作。 但我不知道。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这种微观优化几乎总是一个坏主意。 这么小的一点的性能将完全取决于热点编译器如何优化您的代码,以及与周围代码有关的微妙缓存效果。
This kind of micro-optimization is almost always a bad idea; your performance for such a small bit will be entirely dependent on how the hotspot compiler optimizes your code, and subtle cache effects having to do with the surrounding code.
我认为这可能是最快的。 这将简化为非常简单的字节码,而 JIT(即时编译器)可能会将其简化为非常简单的本机实现。
(无关:顺便说一句,看到“定量开发”使用 Java 很有趣。这种情况并不经常发生)
I think that's probably as fast as it's going to get. That'll reduce to very simple bytecode, and the JIT (just-in-time compiler) will probably reduce that to a very simple native implementation.
(Unrelated: interesting to see a 'quant dev' use Java btw. Doesn't happen that often)
那么底层比较必须是:
将 l 加 1,将结果与 r 进行比较
,或者
从 r 中减去 1,并将结果与 l 进行比较
所有现代硬件对于任一操作都将具有相同的原始性能(其中任何本机数据类型的加法和减法)在完成周期和管道副作用方面具有相同的性能)。
唯一产生效果的方法是:
l 或 r 之一在编译时是已知常量。 例如。
在这种情况下,一个糟糕的优化编译器可能没有意识到它可以将第一个转换为
l <; 4
但所有 java 编译器都需要发现第二种情况是
6 < r
另一种情况是l和r的数据类型不同。
操作:
与
可以公平地说,这在您的应用程序中成为严重问题的可能性可以忽略不计,因为与与决策相关的任何分支错误预测的管道命中相比,其中任何一个的周期成本都很小。
此外,一个像样的 JIT 可以对周围的代码进行各种优化,这些优化比执行的微优化更重要。
Well the underlying comparison must either:
add 1 to l, compare the result to r
or
subtract 1 from r and compare the result to l
All modern hardware will have the same raw performance for either operation (where addition and subtraction of any native data type has identical performance in terms of cycles to complete and pipeline side effects).
The only way this will have any effect is if:
one of l or r are known constants at compile time. eg.
in this case a poor optimizing compiler may not realise it can convert the first into
l < 4
but all java compilers are required to spot that the second case is
6 < r
The other is if the data types of l and r are different.
The operation of :
verses
It is fair to say that the chances of this being a serious issue in your application are negligible since the cycle cost of any of these is tiny compared to the pipeline hit of any branch mispredictions associated with the decision.
Also a decent JIT may do all sorts of optimizations in relation to the surrounding code that outweigh the micro optimization performed.
有一个变量
lr1
,它始终等于(l - r + 1)
。 每当您递增或递减l
时,请对lr1
执行相同的操作。 对于r
也是如此。然后,您的测试将变为
(lr1 < 0)
,并且修改lr1
的指令的执行次数不会超过必要的次数。我觉得给你一个微观优化有点愚蠢,在大多数情况下这是小聪明,大笨蛋。 就像如果您正在比较字符串一样,它将完全淹没该测试。
添加:既然你正在进行二分搜索,我会提到乔恩·本特利(Jon Bentley)对二分搜索的精彩展开。 首先,将表
A
填充到 2 的幂,例如 1024。然后编写如下内容:最后测试 if
(X == A[i])
。 或者,如果您不想填充它,请让if
语句类似于if (i+512 < N && X >= A[ i+512]) i += 512;
Have a variable
lr1
which always equals(l - r + 1)
. Whenever you increment or decrementl
, do the same tolr1
. Similarly forr
.Then your test becomes
(lr1 < 0)
, and the instructions to modifylr1
are executed no more often than necessary.I feel a little silly giving you a micro-optimization, which in most cases is penny-wise, pound-foolish. Like if you're comparing strings, it will totally swamp that test.
ADDED: Since you're doing binary search, I would mention Jon Bentley's cool unrolling of binary search. First you pad the table
A
up to a power of 2, like 1024. Then you write something like this:and finally test if
(X == A[i])
. Or, if you don't want to pad it, let theif
statements be something likeif (i+512 < N && X >= A[i+512]) i += 512;
这些人都说了什么。 编译器将为您优化它。 写下来,让你看起来和读起来都正确,然后继续。
What all these guys said. The compiler is going to optimize that away for you. Write it so it looks and reads properly to you and move on.
最好的选择是调整 JVM 而不是代码 - 考虑到这是您的瓶颈。
尝试使用参数
-server -XX:+AggressiveOpts
启动 jvm。Your best bet is to tweak the JVM rather than the code - given that this is your bottleneck.
Try starting the jvm with the arguments
-server -XX:+AggressiveOpts
.如何将相等测试移到 while 循环之外,以便仅在终止后检查 .equals() 。 顺便说一句,我找不到任何有点麻烦的方法来测试是否 l+1
How about moving your equality test outside of the while loop, so you check .equals() only after termination. btw I couldn't find any bit twiddling ways to test whether l+1<r. If your array lengths are known to be less than certain sizes, what if you use a different datatype for indices? char/short/byte?