我跑了江铃控股基准用这个问题的各种解决方案。我总是在黑洞中消耗2个偏移量的指标。结果如下:
Benchmark Mode Cnt Score Error Units
Offset2DBenchmark.doubleLoopWithIf thrpt 3 35425373,827 ± 4242716,439 ops/s
Offset2DBenchmark.loopOverFlatIndex thrpt 3 35929636,197 ± 935681,592 ops/s
Offset2DBenchmark.loopOverIndex thrpt 3 31438051,279 ± 3286314,668 ops/s
Offset2DBenchmark.unrolledLoop thrpt 3 40495297,238 ± 6423961,118 ops/s
Offset2DBenchmark.unrolledLoopWithLambda thrpt 3 27526581,417 ± 1712524,060 ops/s
doubleLoopWithIf = Nested Loops with If to filter 0,0 (TheSorm)
loopOverFlatIndex = Single loop with flattend indizes (Oleg)
loopOverIndex = Single Loop with 2d indizes (Zefick)
unrolledLoop = Completely Unrolled Loop
unrolledLoopWithLambda = Unrolled Loop consuming a Bifunction<Integer, Integer>
因此,展开的循环是最快的。稍微慢一点的是带有if语句和Oleg提出的扁平数组的双循环。 Zefick的二维数组比您的解决方案更慢。
就像一个演示,这里是一个测试看起来像什么:
@Fork(value = 1)
@Warmup(iterations = 3)
@Measurement(iterations = 3)
@Benchmark
public void unrolledLoopWithLambda(Blackhole bh) {
outerOffsets((x, y) -> {
bh.consume(x);
bh.consume(y);
});
}
private void outerOffsets(BiConsumer<Integer, Integer> consumer) {
consumer.accept(-1, -1);
consumer.accept(-1, 0);
consumer.accept(-1, 1);
consumer.accept(0, -1);
consumer.accept(0, 1);
consumer.accept(1, -1);
consumer.accept(1, 0);
consumer.accept(1, 1);
}
所以,除非你想手动展开你的循环,没有太多可以做,以提高性能。
不幸的是,你没有告诉使用循环内的代码是什么样的。如果它甚至有点费时,问题如何循环可能会被忽略...
但是你的标题说明你想要这个作为二维数组的偏移量。我怀疑你可能会在x和y以上的更大循环中使用它。您可以通过使用1d数组并获得更高性能并自行计算索引。
相反的:
array[x][y]
使用
array[xy] with xy = x + y * xsize
你应该能够避免做乘法的。
(这是我第一次跑了标杆与江铃控股,所以请告诉我,如果我用它完全错了...)
你认为什么是最可读性和可维护性的解决方案?这里是否存在实际的性能问题? – tnw
是的它是一种性能问题,我寻找所有我可以优化的东西。这是在数百万个对象的更新循环中运行的。 – TheSorm
因此,使用您当前的解决方案的性能是否存在实际问题? – tnw