迭代2D数组的偏移量

时间:2017-09-14 15:13:36

标签: java performance for-loop if-statement

我想迭代2D数组中单元格的邻居。所以我用:

for(var i=0; i<list.length; i++){
    console.log(list[i].main.temp);
}

我的问题是,如果这是最有效的方式,还是更好地使用if电话?如果有一个比使用它更好的方法,如果在循环内摆脱零零情况?

3 个答案:

答案 0 :(得分:2)

尚未对其进行测试,但以下是基于@ Zefick的答案,应该更高效:

int dirs[] = { -1, -1, -1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 0, 1, 1 };

for (int i = 0; i < dirs.length; i += 2) {
    int xOffset = dirs[i];
    int yOffset = dirs[i + 1];
    // my code
}       

答案 1 :(得分:2)

我运行了一个JMH基准测试,提供了各种解决方案。我总是在黑洞中消耗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的2D阵列比你的解决方案更慢。

就像演示一样,这是测试的样子:

@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 

你应该能够避免进行乘法运算。

(这是我第一次使用JMH运行基准测试,所以请告诉我是否使用它完全错误...)

答案 2 :(得分:1)

我通常使用以下方法:

int dirs[][] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};

for (int dir[] : dirs) {
    int xOffset = dir[0];
    int yOffset = dir[1];
    // my code
}