java - 执行乘法最有效的方法是什么?

标签 java performance optimization

假设我们必须在一个循环中执行此计算 10000 次。

案例一

double answer = i * 1.6712 * 1000 * 60;

案例二

double answer = i * 100272; // 1.6712 * 1000 * 60 = 100272

其中 i 是循环索引。

问题

情况 1 或 2 中最有效的方法是什么(就 CPU 周期而言),为什么?

最佳答案

这是一个 JMH 基准:

@OutputTimeUnit(TimeUnit.SECONDS)
@BenchmarkMode({ Mode.Throughput })
@Warmup(iterations = 10)
@Fork(value = 1)
@State(Scope.Benchmark)
public class MyBenchmark {
    private static final double CONSTANT = 1.6712 * 1000 * 60;
    private double x = 0;

    @Benchmark
    public void testCaseOne() {
        for (double i = 1; i < 1000_000; i++) {
            x += i * 1.6712 * 1000 * 60;
        }
    }

    @Benchmark
    public void testCaseTwo() {
        for (double i = 1; i < 1000_000; i++) {
            x += i * (1.6712 * 1000 * 60);
        }
    }

    @Benchmark
    public void testCaseThree() {
        for (double i = 1; i < 1000_000; i++) {
            x += i * 100272;
        }
    }

    @Benchmark
    public void testCaseFour() {
        final double constant = 1.6712 * 1000 * 60;
        for (double i = 1; i < 1000_000; i++) {
            x += i * constant;
        }
    }

    @Benchmark
    public void testCaseFive() {
        for (double i = 1; i < 1000_000; i++) {
            x += i * CONSTANT;
        }
    }
}

结果:

Benchmark                   Mode  Cnt    Score    Error  Units

MyBenchmark.testCaseOne    thrpt   20  680,452 ± 15,700  ops/s
MyBenchmark.testCaseTwo    thrpt   20  721,542 ± 14,131  ops/s
MyBenchmark.testCaseThree  thrpt   20  729,411 ± 17,031  ops/s
MyBenchmark.testCaseFour   thrpt   20  735,255 ± 16,001  ops/s
MyBenchmark.testCaseFive   thrpt   20  719,481 ±  5,338  ops/s

Java 版本:

openjdk version "1.8.0_45-internal"
OpenJDK Runtime Environment (build 1.8.0_45-internal-b14)
OpenJDK 64-Bit Server VM (build 25.45-b02, mixed mode)

正如你所看到的,吞吐量没有显着差异,所以你可以用最清晰易懂的方式来写。


关于我之前的基准测试结果:

Benchmark                   Mode  Cnt     Score    Error  Units
MyBenchmark.testCaseOne    thrpt   20   228,285 ±  2,232  ops/s
MyBenchmark.testCaseTwo    thrpt   20   593,755 ±  8,165  ops/s
MyBenchmark.testCaseThree  thrpt   20  1035,549 ± 20,908  ops/s

之前的基准测试被打破了 - for 循环中的计数器是 int 类型,而在 testCaseThree 中它正在做整数乘法,这就是它快得多的原因.其他结果也受到基准测试中这个错误的影响。

尽管混合整数-双倍乘法比纯 int-int 和 double-double 乘法慢得多,但仍然很有趣。可能是因为类型转换?

关于java - 执行乘法最有效的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30556137/

相关文章:

java - 传递枚举参数

java - android中通过service实现sip

java - 如何加快文本转语音的初始化速度

c++ - 为什么将 return 移动到函数末尾效率较低?

c++ - libc++ 中的短字符串优化机制是什么?

java - 某些 Android 设备上应用程序崩溃的原因是什么

java - Java 语法的访问者方法在 ANTLR 4.4 中不起作用

c# - 如何编码以获得适当的 CPU 使用率?

c# - LINQ join Entities from HashSet's, Join vs Dictionary vs HashSet性能

c# - 用单个值填充数组的最快方法