From fa1a2a0667ff81f04e94cab078c50c2d51f4cb5e Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Thu, 11 Jul 2019 09:12:54 +1000 Subject: [PATCH 1/5] Enable popcount and prefetch for ppc-64 PowerPC has had popcount instructions for a long time, at least as far back as POWER5 (released 2004). Enable them via a gcc builtin. Using a gcc builtin has the added bonus that if compiled for a processor that lacks a hardware instruction, gcc will include a software popcount implementation that does not use the instruction. It might be slower than the table lookups (or it might be faster) but it will certainly work. So this isn't going to break anything. On my POWER8 VM, this leads to a ~4.27% speedup. Fir prefetch, the gcc builtin generates a 'dcbt' instruction, which is supported at least as far back as the G5 (2002) and POWER4 (2001). This leads to a ~5% speedup on my POWER8 VM. No functional change --- src/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 2d6042e2..285d314e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -136,6 +136,8 @@ endif ifeq ($(ARCH),ppc-64) arch = ppc64 bits = 64 + popcnt = yes + prefetch = yes endif @@ -313,7 +315,9 @@ endif ### 3.6 popcnt ifeq ($(popcnt),yes) - ifeq ($(comp),icc) + ifeq ($(arch),ppc64) + CXXFLAGS += -DUSE_POPCNT + else ifeq ($(comp),icc) CXXFLAGS += -msse3 -DUSE_POPCNT else CXXFLAGS += -msse3 -mpopcnt -DUSE_POPCNT From 93349d0dbd22f063b39e6815c02835a4748fffbc Mon Sep 17 00:00:00 2001 From: protonspring Date: Tue, 9 Jul 2019 14:03:00 -0600 Subject: [PATCH 2/5] Use score instead of array to evaluate shelter This is a non-functional simplification. Instead of an array of values, just use a Score. STC LLR: 2.95 (-2.94,2.94) [-3.00,1.00] Total: 16309 W: 3673 L: 3541 D: 9095 http://tests.stockfishchess.org/tests/view/5d24f3b80ebc5925cf0ceb5b No functional change --- src/pawns.cpp | 14 +++++++------- src/search.cpp | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/pawns.cpp b/src/pawns.cpp index c85d4fd9..acc3d770 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -181,13 +181,13 @@ Entry* probe(const Position& pos) { template void Entry::evaluate_shelter(const Position& pos, Square ksq, Score& shelter) { - constexpr Color Them = (Us == WHITE ? BLACK : WHITE); + constexpr Color Them = (Us == WHITE ? BLACK : WHITE); Bitboard b = pos.pieces(PAWN) & ~forward_ranks_bb(Them, ksq); Bitboard ourPawns = b & pos.pieces(Us); Bitboard theirPawns = b & pos.pieces(Them); - Value bonus[] = { Value(5), Value(5) }; + Score bonus = make_score(5, 5); File center = clamp(file_of(ksq), FILE_B, FILE_G); for (File f = File(center - 1); f <= File(center + 1); ++f) @@ -199,16 +199,16 @@ void Entry::evaluate_shelter(const Position& pos, Square ksq, Score& shelter) { Rank theirRank = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1; int d = std::min(f, ~f); - bonus[MG] += ShelterStrength[d][ourRank]; + bonus += make_score(ShelterStrength[d][ourRank], 0); if (ourRank && (ourRank == theirRank - 1)) - bonus[MG] -= 82 * (theirRank == RANK_3), bonus[EG] -= 82 * (theirRank == RANK_3); + bonus -= make_score(82 * (theirRank == RANK_3), 82 * (theirRank == RANK_3)); else - bonus[MG] -= UnblockedStorm[d][theirRank]; + bonus -= make_score(UnblockedStorm[d][theirRank], 0); } - if (bonus[MG] > mg_value(shelter)) - shelter = make_score(bonus[MG], bonus[EG]); + if (mg_value(bonus) > mg_value(shelter)) + shelter = bonus; } diff --git a/src/search.cpp b/src/search.cpp index b4a69092..8993a4b0 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1070,7 +1070,7 @@ moves_loop: // When in check, search starts from here Depth r = reduction(improving, depth, moveCount); // Reduction if other threads are searching this position. - if (th.marked()) + if (th.marked()) r += ONE_PLY; // Decrease reduction if position is or has been on the PV From 5a7827d59de5e3dea0d90bdb3e7c57153c0a9f1f Mon Sep 17 00:00:00 2001 From: xoto10 Date: Sun, 7 Jul 2019 02:20:49 +0100 Subject: [PATCH 3/5] Combo of statscore divisor and pawn psqt changes Passed STC 10+0.1 th 1: LLR: 2.96 (-2.94,2.94) [0.00,4.00] Total: 13282 W: 3100 L: 2881 D: 7301 http://tests.stockfishchess.org/tests/view/5d21132e0ebc5925cf0c81f4 Passed LTC 60+0.6 th 1: LLR: 2.95 (-2.94,2.94) [0.00,4.00] Total: 44243 W: 7768 L: 7468 D: 29007 http://tests.stockfishchess.org/tests/view/5d2119050ebc5925cf0c832b Bench 3705891 --- src/psqt.cpp | 12 ++++++------ src/search.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/psqt.cpp b/src/psqt.cpp index cba6bb06..36d99feb 100644 --- a/src/psqt.cpp +++ b/src/psqt.cpp @@ -93,12 +93,12 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = { constexpr Score PBonus[RANK_NB][FILE_NB] = { // Pawn (asymmetric distribution) { }, - { S( 0,-10), S( -5,-3), S( 10, 7), S( 13,-1), S( 21, 7), S( 17, 6), S( 6, 1), S( -3,-20) }, - { S(-11, -6), S(-10,-6), S( 15,-1), S( 22,-1), S( 26, -1), S( 28, 2), S( 4,-2), S(-24, -5) }, - { S( -9, 4), S(-18,-5), S( 8,-4), S( 22,-5), S( 33, -6), S( 25,-13), S( -4,-3), S(-16, -7) }, - { S( 6, 18), S( -3, 2), S(-10, 2), S( 1,-9), S( 12,-13), S( 6, -8), S(-12,11), S( 1, 9) }, - { S( -6, 25), S( -8,17), S( 5,19), S( 11,29), S(-14, 29), S( 0, 8), S(-12, 4), S(-14, 12) }, - { S(-10, -1), S( 6,-6), S( -5,18), S(-11,22), S( -2, 22), S(-14, 17), S( 12, 2), S( -1, 9) } + { S( 3,-10), S( 3, -6), S( 10, 10), S( 19, 0), S( 16, 14), S( 19, 7), S( 7, -5), S( -5,-19) }, + { S( -9,-10), S(-15,-10), S( 11,-10), S( 15, 4), S( 32, 4), S( 22, 3), S( 5, -6), S(-22, -4) }, + { S( -8, 6), S(-23, -2), S( 6, -8), S( 20, -4), S( 40,-13), S( 17,-12), S( 4,-10), S(-12, -9) }, + { S( 13, 9), S( 0, 4), S(-13, 3), S( 1,-12), S( 11,-12), S( -2, -6), S(-13, 13), S( 5, 8) }, + { S( -5, 28), S(-12, 20), S( -7, 21), S( 22, 28), S( -8, 30), S( -5, 7), S(-15, 6), S(-18, 13) }, + { S( -7, 0), S( 7,-11), S( -3, 12), S(-13, 21), S( 5, 25), S(-16, 19), S( 10, 4), S( -8, 7) } }; #undef S diff --git a/src/search.cpp b/src/search.cpp index 8993a4b0..ff7a2c23 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1115,7 +1115,7 @@ moves_loop: // When in check, search starts from here r += ONE_PLY; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / 20000 * ONE_PLY; + r -= ss->statScore / 16384 * ONE_PLY; } Depth d = clamp(newDepth - r, ONE_PLY, newDepth); From c83cbe42f3a6c9b145a4557ef874222fe685a9bc Mon Sep 17 00:00:00 2001 From: VoyagerOne Date: Wed, 10 Jul 2019 19:59:33 -0400 Subject: [PATCH 4/5] Tweak capture scoring formula STC: LLR: 2.96 (-2.94,2.94) [0.00,4.00] Total: 20556 W: 4685 L: 4438 D: 11433 http://tests.stockfishchess.org/tests/view/5d25d26e0ebc5925cf0d0b4a LTC: LLR: 2.95 (-2.94,2.94) [0.00,4.00] Total: 14856 W: 2649 L: 2446 D: 9761 http://tests.stockfishchess.org/tests/view/5d25d8b20ebc5925cf0d0c6d bench: 3206912 --- src/movepick.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index b7f66178..64380da9 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -107,8 +107,8 @@ void MovePicker::score() { for (auto& m : *this) if (Type == CAPTURES) - m.value = PieceValue[MG][pos.piece_on(to_sq(m))] - + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))] / 8; + m.value = int(PieceValue[MG][pos.piece_on(to_sq(m))]) * 6 + + (*captureHistory)[pos.moved_piece(m)][to_sq(m)][type_of(pos.piece_on(to_sq(m)))]; else if (Type == QUIETS) m.value = (*mainHistory)[pos.side_to_move()][from_to(m)] From 4ae5a7b45a430aea5f4b21f9455b4db74ed1c44a Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sun, 9 Jun 2019 15:07:36 +0200 Subject: [PATCH 5/5] Assorted trivial cleanups June 2019 No functional change. --- src/evaluate.cpp | 10 +++++----- src/pawns.cpp | 18 ++++++++++-------- src/position.cpp | 6 +++--- src/position.h | 5 +++++ src/search.cpp | 12 ++++++------ 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/evaluate.cpp b/src/evaluate.cpp index f2e822d0..c4e02e4e 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -142,7 +142,7 @@ namespace { constexpr Score KnightOnQueen = S( 16, 12); constexpr Score LongDiagonalBishop = S( 45, 0); constexpr Score MinorBehindPawn = S( 18, 3); - constexpr Score Outpost = S( 36, 12); + constexpr Score Outpost = S( 18, 6); constexpr Score PawnlessFlank = S( 17, 95); constexpr Score RestrictedPiece = S( 7, 7); constexpr Score RookOnPawn = S( 10, 32); @@ -222,7 +222,7 @@ namespace { constexpr Color Them = (Us == WHITE ? BLACK : WHITE); constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH); constexpr Direction Down = (Us == WHITE ? SOUTH : NORTH); - constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB: Rank7BB | Rank6BB); + constexpr Bitboard LowRanks = (Us == WHITE ? Rank2BB | Rank3BB : Rank7BB | Rank6BB); const Square ksq = pos.square(Us); @@ -305,10 +305,10 @@ namespace { // Bonus if piece is on an outpost square or can reach one bb = OutpostRanks & attackedBy[Us][PAWN] & ~pe->pawn_attacks_span(Them); if (bb & s) - score += Outpost * (Pt == KNIGHT ? 2 : 1); + score += Outpost * (Pt == KNIGHT ? 4 : 2); else if (bb & b & ~pos.pieces(Us)) - score += Outpost / (Pt == KNIGHT ? 1 : 2); + score += Outpost * (Pt == KNIGHT ? 2 : 1); // Knight and Bishop bonus for being right behind a pawn if (shift(pos.pieces(PAWN)) & s) @@ -561,7 +561,7 @@ namespace { b &= ~attackedBy[Them][PAWN] & safe; // Bonus for safe pawn threats on the next move - b = pawn_attacks_bb(b) & pos.pieces(Them); + b = pawn_attacks_bb(b) & nonPawnEnemies; score += ThreatByPawnPush * popcount(b); // Our safe or protected pawns diff --git a/src/pawns.cpp b/src/pawns.cpp index acc3d770..45c40471 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -32,9 +32,9 @@ namespace { #define S(mg, eg) make_score(mg, eg) // Pawn penalties - constexpr Score Backward = S( 9, 24); - constexpr Score Doubled = S(11, 56); - constexpr Score Isolated = S( 5, 15); + constexpr Score Backward = S( 9, 24); + constexpr Score Doubled = S(11, 56); + constexpr Score Isolated = S( 5, 15); constexpr Score WeakUnopposed = S( 13, 27); constexpr Score Attacked2Unsupported = S( 0, 20); @@ -108,17 +108,18 @@ namespace { phalanx = neighbours & rank_bb(s); support = neighbours & rank_bb(s - Up); - // A pawn is backward when it is behind all pawns of the same color - // on the adjacent files and cannot be safely advanced. - backward = !(ourPawns & pawn_attack_span(Them, s + Up)) + // A pawn is backward when it is behind all pawns of the same color on + // the adjacent files and cannot safely advance. Phalanx and isolated + // pawns will be excluded when the pawn is scored. + backward = !(neighbours & forward_ranks_bb(Them, s)) && (stoppers & (leverPush | (s + Up))); // Passed pawns will be properly scored in evaluation because we need // full attack info to evaluate them. Include also not passed pawns // which could become passed after one or two pawn pushes when are // not attacked more times than defended. - if ( !(stoppers ^ lever) || - (!(stoppers ^ leverPush) && popcount(phalanx) >= popcount(leverPush))) + if ( !(stoppers ^ lever) || + (!(stoppers ^ leverPush) && popcount(phalanx) >= popcount(leverPush))) e->passedPawns[Us] |= s; else if (stoppers == square_bb(s + Up) && r >= RANK_5) @@ -137,6 +138,7 @@ namespace { score += make_score(v, v * (r - 2) / 4); } + else if (!neighbours) score -= Isolated + WeakUnopposed * int(!opposed); diff --git a/src/position.cpp b/src/position.cpp index 14121d47..9f06e174 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -55,13 +55,13 @@ constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING // valuable attacker for the side to move, remove the attacker we just found // from the bitboards and scan for new X-ray attacks behind it. -template +template PieceType min_attacker(const Bitboard* byTypeBB, Square to, Bitboard stmAttackers, Bitboard& occupied, Bitboard& attackers) { Bitboard b = stmAttackers & byTypeBB[Pt]; if (!b) - return min_attacker(byTypeBB, to, stmAttackers, occupied, attackers); + return min_attacker(byTypeBB, to, stmAttackers, occupied, attackers); occupied ^= lsb(b); // Remove the attacker from occupied @@ -77,7 +77,7 @@ PieceType min_attacker(const Bitboard* byTypeBB, Square to, Bitboard stmAttacker // X-ray may add already processed pieces because byTypeBB[] is constant: in // the rook example, now attackers contains _again_ rook in a7, so remove it. attackers &= occupied; - return (PieceType)Pt; + return Pt; } template<> diff --git a/src/position.h b/src/position.h index 343751ed..2106414b 100644 --- a/src/position.h +++ b/src/position.h @@ -108,6 +108,7 @@ public: Bitboard checkers() const; Bitboard blockers_for_king(Color c) const; Bitboard check_squares(PieceType pt) const; + bool is_discovery_check_on_king(Color c, Move m) const; // Attacks to/from a given square Bitboard attackers_to(Square s) const; @@ -316,6 +317,10 @@ inline Bitboard Position::check_squares(PieceType pt) const { return st->checkSquares[pt]; } +inline bool Position::is_discovery_check_on_king(Color c, Move m) const { + return st->blockersForKing[c] & from_sq(m); +} + inline bool Position::pawn_passed(Color c, Square s) const { return !(pieces(~c, PAWN) & passed_pawn_span(c, s)); } diff --git a/src/search.cpp b/src/search.cpp index ff7a2c23..e6446768 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -739,7 +739,7 @@ namespace { } else if (ttHit) { - // Never assume anything on values stored in TT + // Never assume anything about values stored in TT ss->staticEval = eval = tte->eval(); if (eval == VALUE_NONE) ss->staticEval = eval = evaluate(pos); @@ -978,7 +978,7 @@ moves_loop: // When in check, search starts from here // Check extension (~2 Elo) else if ( givesCheck - && (pos.blockers_for_king(~us) & from_sq(move) || pos.see_ge(move))) + && (pos.is_discovery_check_on_king(~us, move) || pos.see_ge(move))) extension = ONE_PLY; // Castling extension @@ -1013,7 +1013,7 @@ moves_loop: // When in check, search starts from here && !givesCheck && (!pos.advanced_pawn_push(move) || pos.non_pawn_material(~us) > BishopValueMg)) { - // Move count based pruning (~30 Elo) + // Move count based pruning if (moveCountPruning) continue; @@ -1037,8 +1037,8 @@ moves_loop: // When in check, search starts from here if (!pos.see_ge(move, Value(-29 * lmrDepth * lmrDepth))) continue; } - else if ((!givesCheck || !extension) - && !pos.see_ge(move, -PawnValueEg * (depth / ONE_PLY))) // (~20 Elo) + else if ( (!givesCheck || !extension) + && !pos.see_ge(move, -PawnValueEg * (depth / ONE_PLY))) // (~20 Elo) continue; } @@ -1341,7 +1341,7 @@ moves_loop: // When in check, search starts from here { if (ttHit) { - // Never assume anything on values stored in TT + // Never assume anything about values stored in TT if ((ss->staticEval = bestValue = tte->eval()) == VALUE_NONE) ss->staticEval = bestValue = evaluate(pos);