简体   繁体   English

Math.abs(a - b)的更快实现 - Math.abs(c - d)?

[英]A faster implementation for Math.abs(a - b) - Math.abs(c - d)?

I have a Java method that repeatedly evaluates the following expression in a very tight loop with a large number of repetitions: 我有一个Java方法,它在一个非常紧凑的循环中重复计算以下表达式,并且重复次数很多:

Math.abs(a - b) - Math.abs(c - d)

a , b , c and d are long values that can span the whole range of their type. abcd是可以跨越其整个范围的long值。 They are different in each loop iteration and they do not satisfy any invariant that I know of. 它们在每个循环迭代中是不同的,并且它们不满足我所知的任何不变量。

The profiler indicates that a significant portion of the processor time is spent in this method. 分析器指示在此方法中花费了大部分处理器时间。 While I will pursue other avenues of optimization first, I was wondering if there is a smarter way to calculate the aforementioned expression. 虽然我将首先寻求其他优化途径,但我想知道是否有更聪明的方法来计算上述表达式。

Apart from inlining the Math.abs() calls manually for a very slight (if any) performance gain, is there any mathematical trick that I could use to speed-up the evaluation of this expression? 除了手动内联Math.abs()调用以获得非常小的(如果有的话)性能增益之外,还有什么数学技巧可以用来加速对这个表达式的评估吗?

I suspect the profiler isn't giving you a true result as it trying to profile (and thus adding over head to) such a trivial "method". 我怀疑分析器没有给你一个真实的结果,因为它试图分析(并因此添加头部)这样一个简单的“方法”。 Without the profile Math.abs can be turned into a small number of machine code instructions, and you won't be able to make it faster than that. 如果没有配置文件Math.abs可以转换为少量的机器代码指令,你将无法使它更快。

I suggest you do a micro-benchmark to confirm this. 我建议你做一个微基准来证实这一点。 I would expect loading the data to be an order of magnitude more expensive. 我希望加载数据要贵一个数量级。

long a = 10, b = 6, c = -2, d = 3;

int runs = 1000 * 1000 * 1000;
long start = System.nanoTime();
for (int i = 0; i < runs; i += 2) {
    long r = Math.abs(i - a) - Math.abs(c - i);
    long r2 = Math.abs(i - b) - Math.abs(d - i);
    if (r + r2 < Integer.MIN_VALUE) throw new AssertionError();
}
long time = System.nanoTime() - start;
System.out.printf("Took an average of %.1f ns per abs-abs. %n", (double) time / runs);

prints 版画

Took an average of 0.9 ns per abs-abs. 

I ended up using this little method: 我最终使用这个小方法:

public static long diff(final long a, final long b, final long c, final long d) {
    final long a0 = (a < b)?(b - a):(a - b);
    final long a1 = (c < d)?(d - c):(c - d);

    return a0 - a1;
}

I experienced a measurable performance increase - about 10-15% for the whole application. 我经历了可测量的性能提升 - 整个应用程序大约10-15%。 I believe this is mostly due to: 我相信这主要是由于:

  • The elimination of a method call: Rather than calling Math.abs() twice, I call this method once. 消除方法调用:我调用此方法一次,而不是两次调用Math.abs() Sure, static method calls are not inordinately expensive, but they still have an impact. 当然,静态方法调用并不是非常昂贵,但它们仍然会产生影响。

  • The elimination of a couple of negation operations: This may be offset by the slightly increased size of the code, but I'll happily fool myself into believing that it actually made a difference. 消除了几个否定操作:这可能会被稍微增加的代码大小所抵消,但我会高兴地自欺欺人地相信它实际上有所作为。

EDIT: 编辑:

It seems that it's actually the other way around. 看起来它实际上是另一种方式。 Explicitly inlining the code does not seem to impact the performance in my micro-benchmark. 明确地内联代码似乎不会影响我的微基准测试中的性能。 Changing the way the absolute values are calculated does... 改变计算绝对值的方式是......

You can always try to unroll the functions and hand optimize, if you don't get more cache misses it might be faster. 您可以随时尝试展开函数并进行手动优化,如果您没有获得更多缓存未命中,则可能会更快。

If I got the unrolling right it could be something like this: 如果我得到正确的展开,它可能是这样的:

    if(a<b)
{
    if(c<d)
    {
        r=b-a-d+c;
    }
    else
    {
        r=b-a+d-c;
    }
}
else
{
    if(c<d)
    {
        r=a-b-d+c;
    }
    else
    {
        r=a-b+d-c;
    }
}

are you sure its the method itself causes the problem? 你确定它的方法本身会导致问题吗? Maybe its an enormous amount of invocation of this method and you just see the aggregated results (like TIME_OF_METHOD_EXECUTION X NUMBER_OF_INVOCATIONS) in your profiler? 也许它是对这种方法的大量调用,你只是在你的探查器中看到聚合结果(如TIME_OF_METHOD_EXECUTION X NUMBER_OF_INVOCATIONS)?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM