As any further pruning (I already have null move, LMR, futility, delta) is not going to make the pure speed faster, and I have seen many many engines faster than 2mnps on here, there must be something wrong with the speed of my engine. However, the most surprising functions in the profiling report are:
1. make_move() - 12.61%
2. undo_move() - 9.6%
As my engine uses bitboards, I was not expecting make_move to take such a big portion of the running time. Even though make_move was called 102.6 million times, quiescence was called the same number of times and only took up around 3% of the time. A possible explanation is that I do incremental PST's in make_move which might slow it down. Full 20% of the time used for making moves is suspicious
For reference here is the make_move function, undo_move is similar
Code: Select all
void Position::make_move(Move move) {
hash ^= castling_rights.back() ^ zobrist_enpassant[enpassant_square.back()];
hash ^= zobrist_black;
side_to_move = !side_to_move;
switch (move.flag()) {
case none:
fill_sq(move.start(), empty_square);
fill_sq(move.end(), move.piece());
break;
case knight_pr:
fill_sq(move.start(), empty_square);
fill_sq(move.end(), move.piece() + 2);
break;
case bishop_pr:
fill_sq(move.start(), empty_square);
fill_sq(move.end(), move.piece() + 4);
break;
case rook_pr:
fill_sq(move.start(), empty_square);
fill_sq(move.end(), move.piece() + 6);
break;
case queen_pr:
fill_sq(move.start(), empty_square);
fill_sq(move.end(), move.piece() + 8);
break;
case k_castling:
fill_sq(move.start(), empty_square);
fill_sq(move.start() + 3, empty_square);
fill_sq(move.end(), move.piece());
fill_sq(move.start() + 1, move.piece() - 4);
break;
case q_castling:
fill_sq(move.start(), empty_square);
fill_sq(move.start() - 4, empty_square);
fill_sq(move.end(), move.piece());
fill_sq(move.start() - 1, move.piece() - 4);
break;
case enpassant:
fill_sq(move.start(), empty_square);
fill_sq(move.end() ^ 8, empty_square);//ep square
fill_sq(move.end(), move.piece());
break;
}
enpassant_square.push_back((!(move.piece() & ~1) && move.end() == (move.start() ^ 16)) ? ((move.start() + move.end()) >> 1) : 64);
castling_rights.push_back(castling_rights.back() & ~((1ull << move.start()) | (1ull << move.end())));
hash ^= castling_rights.back() ^ zobrist_enpassant[enpassant_square.back()];
}
castling rights is a bitboard with up to 6 bits filled for the unmoved kings and rooks
fill_sq flips a bit in two bitboards, does 2 xors on the hash, and updates 2 sets of PSTs and a phase variable
Any suggestions would be very helpful !