Java Otherlo(比特板)中移动计算的优化

Java Otherlo(比特板)中移动计算的优化,java,optimization,Java,Optimization,我一直在用Java开发一个游戏Otherlo的实现,我将用于研究目的,我需要一个快速的实现来运行尽可能多的游戏,所以我就是这么做的: 董事会[][]实施 我的第一种方法是使用board[]]多维数组来表示board,只是为了让它工作,并确保它工作正常。我完成了,我很高兴。但是,正如大多数人所知,这并不是很快,因为我每秒只能玩1500场游戏(随机移动,只是为了测试) 比特板 然后,我将该板实现为一个位板,这大大加快了移动计算的速度,并且与以前的实现相比速度非常快。通过这种实现,它每秒可以玩多达20

我一直在用Java开发一个游戏Otherlo的实现,我将用于研究目的,我需要一个快速的实现来运行尽可能多的游戏,所以我就是这么做的:

董事会[][]实施

我的第一种方法是使用board[]]多维数组来表示board,只是为了让它工作,并确保它工作正常。我完成了,我很高兴。但是,正如大多数人所知,这并不是很快,因为我每秒只能玩1500场游戏(随机移动,只是为了测试)

比特板

然后,我将该板实现为一个位板,这大大加快了移动计算的速度,并且与以前的实现相比速度非常快。通过这种实现,它每秒可以玩多达20k个游戏。这是我用于移动计算的代码,它工作得很好,但重复:

private void calculateMoves() {
    legal = 0L;
    long potentialMoves;
    long currentBoard = getCurrentBoard();
    long opponentBoard = getOpponentBoard();
    long emptyBoard = emptyBoard();
    // UP
    potentialMoves = (currentBoard >> SIZE) & DOWN_MASK & opponentBoard;
    while (potentialMoves != 0L) {
        long tmp = (potentialMoves >> SIZE) & DOWN_MASK;
        legal |= tmp & emptyBoard;
        potentialMoves = tmp & opponentBoard;
    }
    // DOWN
    potentialMoves = (currentBoard << SIZE) & UP_MASK & opponentBoard;
    while (potentialMoves != 0L) {
        long tmp = (potentialMoves << SIZE) & UP_MASK;
        legal |= tmp & emptyBoard;
        potentialMoves = tmp & opponentBoard;
    }
    // LEFT
    potentialMoves = (currentBoard >> 1L) & RIGHT_MASK & opponentBoard;
    while (potentialMoves != 0L) {
        long tmp = (potentialMoves >> 1L) & RIGHT_MASK;
        legal |= tmp & emptyBoard;
        potentialMoves = tmp & opponentBoard;
    }
    // RIGHT
    potentialMoves = (currentBoard << 1L) & LEFT_MASK & opponentBoard;
    while (potentialMoves != 0L) {
        long tmp = (potentialMoves << 1L) & LEFT_MASK;
        legal |= tmp & emptyBoard;
        potentialMoves = tmp & opponentBoard;
    }
    // UP LEFT
    potentialMoves = (currentBoard >> (SIZE + 1L)) & RIGHT_MASK & DOWN_MASK & opponentBoard;
    while (potentialMoves != 0L) {
        long tmp = (potentialMoves >> (SIZE + 1L)) & RIGHT_MASK & DOWN_MASK;
        legal |= tmp & emptyBoard;
        potentialMoves = tmp & opponentBoard;
    }
    // UP RIGHT
    potentialMoves = (currentBoard >> (SIZE - 1L)) & LEFT_MASK & DOWN_MASK & opponentBoard;
    while (potentialMoves != 0L) {
        long tmp = (potentialMoves >> (SIZE - 1L)) & LEFT_MASK & DOWN_MASK;
        legal |= tmp & emptyBoard;
        potentialMoves = tmp & opponentBoard;
    }
    // DOWN LEFT
    potentialMoves = (currentBoard << (SIZE - 1L)) & RIGHT_MASK & UP_MASK & opponentBoard;
    while (potentialMoves != 0L) {
        long tmp = (potentialMoves << (SIZE - 1L)) & RIGHT_MASK & UP_MASK;
        legal |= tmp & emptyBoard;
        potentialMoves = tmp & opponentBoard;
    }
    // DOWN RIGHT
    potentialMoves = (currentBoard << (SIZE + 1L)) & LEFT_MASK & UP_MASK & opponentBoard;
    while (potentialMoves != 0L) {
        long tmp = (potentialMoves << (SIZE + 1L)) & LEFT_MASK & UP_MASK;
        legal |= tmp & emptyBoard;
        potentialMoves = tmp & opponentBoard;
    }
    moves.clear();
}
private void calculateMoves(){
合法=0升;
长电位动作;
长电流板=getCurrentBoard();
长对位板=getOpponentBoard();
长清空板=清空板();
//向上
电位移动=(电流板>>尺寸)&下掩模和对置板;
while(潜在移动量!=0L){
长tmp=(潜在移动>>大小)&向下屏蔽;
法律|=tmp和清空板;
潜在移动=tmp和对位板;
}
//向下
电位移动=(电流板1L)和右屏蔽和对面板;
while(潜在移动量!=0L){
长tmp=(潜在移动>>1L)和右屏蔽;
法律|=tmp和清空板;
潜在移动=tmp和对位板;
}
//对
电位移动=(电流板(尺寸+1L))&右屏蔽和下屏蔽和对面板;
while(潜在移动量!=0L){
长tmp=(潜在移动>>(大小+1L))&右下遮罩;
法律|=tmp和清空板;
潜在移动=tmp和对位板;
}
//向右转
电位移动=(电流板>>(尺寸-1L))&左屏蔽和下屏蔽和对面板;
while(潜在移动量!=0L){
长tmp=(潜在移动>>(大小-1L))&左下遮罩;
法律|=tmp和清空板;
潜在移动=tmp和对位板;
}
//左下角

potentialMoves=(currentBoardJava字节码与本机asm代码完全不同。当您使用接口和多态性时,它的执行方式与代码中的执行方式相同。方法调用也是如此

java字节码生成中没有进行优化,因此速度较慢。函数调用比重复内联代码慢,后期绑定比静态绑定慢


但是,我更喜欢第二个代码而不是第一个代码,我相信它应该保持这种状态。

使用数组不应该增加那么多开销

我认为方法调用可能会增加最大的开销,特别是如果它们没有得到优化的话


您可以尝试类似于原始代码的方法,在不使用类包装的情况下使用方法调用,看看性能是否更好;我似乎还记得Java优化getter和setter,因此可能将调用的方法放在类中会阻止它进行类似的优化。

我使用了JProfiler和50%的ime用于移动计算,但我不明白为什么调用方法会比较慢,我在分析器中看不到。有什么想法吗?你应该对你的结果有极大的怀疑。你看到了吗?没有,我没有看到,我会读的,谢谢!是的,我也喜欢第二种方法。但这正是我所需要的要做(模拟),我需要它尽可能快。:S
private MoveFinder[] finders = new MoveFinder[] {new UpFinder(), new DownFinder(), new LeftFinder(),
        new RightFinder(), new UpLeftFinder(), new UpRightFinder(), new DownLeftFinder(), new DownRightFinder()};

private void calculateMoves() {
    legal = 0L;
    long potentialMoves;
    long currentBoard = getCurrentBoard();
    long opponentBoard = getOpponentBoard();
    long emptyBoard = emptyBoard();
    for (MoveFinder finder : finders) {
        potentialMoves = finder.next(currentBoard) & opponentBoard;
        while (potentialMoves != 0L) {
            long tmp = finder.next(potentialMoves);
            legal |= tmp & emptyBoard;
            potentialMoves = tmp & opponentBoard;
        }
    }
    moves.clear();
}

private interface MoveFinder {
    long next(long next);
}

private class UpFinder implements MoveFinder {
    @Override
    public long next(long n) {
        return (n >> SIZE) & DOWN_MASK;
    }
}

private class DownFinder implements MoveFinder {
    @Override
    public long next(long n) {
        return (n << SIZE) & UP_MASK;
    }
}

// and so on for the rest of the moves (LeftFinder, RightFinder, etc).