1
0
Fork 0

Small cleanups (march 2021)

With help of @BM123499, @mstembera, @gvreuls, @noobpwnftw and @Fanael
Thanks!

Closes https://github.com/official-stockfish/Stockfish/pull/3405

No functional change
pull/3413/head
Stéphane Nicolet 2021-03-19 19:43:25 +01:00
parent ec42154ef2
commit 83eac08e75
12 changed files with 107 additions and 81 deletions

View File

@ -1,4 +1,4 @@
# List of authors for Stockfish, as of August 4, 2020 # List of authors for Stockfish, as of March 24, 2021
# Founders of the Stockfish project and fishtest infrastructure # Founders of the Stockfish project and fishtest infrastructure
Tord Romstad (romstad) Tord Romstad (romstad)

View File

@ -150,8 +150,8 @@ namespace {
Bitboard b = attacks_bb<KING>(ksq[stm]); Bitboard b = attacks_bb<KING>(ksq[stm]);
while (b) while (b)
r |= stm == WHITE ? db[index(BLACK, ksq[BLACK] , pop_lsb(b), psq)] r |= stm == WHITE ? db[index(BLACK, ksq[BLACK], pop_lsb(b), psq)]
: db[index(WHITE, pop_lsb(b), ksq[WHITE], psq)]; : db[index(WHITE, pop_lsb(b), ksq[WHITE], psq)];
if (stm == WHITE) if (stm == WHITE)
{ {

View File

@ -54,7 +54,6 @@
using namespace std; using namespace std;
using namespace Stockfish::Eval::NNUE;
namespace Stockfish { namespace Stockfish {
@ -396,7 +395,8 @@ namespace {
attackedBy[Us][Pt] = 0; attackedBy[Us][Pt] = 0;
while (b1) { while (b1)
{
Square s = pop_lsb(b1); Square s = pop_lsb(b1);
// Find attacked squares, including x-ray attacks for bishops and rooks // Find attacked squares, including x-ray attacks for bishops and rooks
@ -1038,46 +1038,51 @@ make_v:
return v; return v;
} }
// specifically correct for cornered bishops to fix FRC with NNUE.
/// Fisher Random Chess: correction for cornered bishops, to fix chess960 play with NNUE
Value fix_FRC(const Position& pos) { Value fix_FRC(const Position& pos) {
Value bAdjust = Value(0); constexpr Bitboard Corners = 1ULL << SQ_A1 | 1ULL << SQ_H1 | 1ULL << SQ_A8 | 1ULL << SQ_H8;
constexpr Value p1=Value(209), p2=Value(136), p3=Value(148); if (!(pos.pieces(BISHOP) & Corners))
return VALUE_ZERO;
Color Us = pos.side_to_move(); constexpr int penalty1 = -209;
if ( (pos.pieces(Us, BISHOP) & relative_square(Us, SQ_A1)) constexpr int penalty2 = -136;
&& (pos.pieces(Us, PAWN) & relative_square(Us, SQ_B2))) constexpr int penalty3 = -148;
{
bAdjust -= !pos.empty(relative_square(Us,SQ_B3)) ? p1 int correction = 0;
: pos.piece_on(relative_square(Us,SQ_C3)) == make_piece(Us, PAWN) ? p2
: p3; if ( pos.piece_on(SQ_A1) == W_BISHOP
} && pos.piece_on(SQ_B2) == W_PAWN)
if ( (pos.pieces(Us, BISHOP) & relative_square(Us, SQ_H1)) correction += !pos.empty(SQ_B3) ? penalty1
&& (pos.pieces(Us, PAWN) & relative_square(Us, SQ_G2))) : pos.piece_on(SQ_C3) == W_PAWN ? penalty2
{ : penalty3;
bAdjust -= !pos.empty(relative_square(Us,SQ_G3)) ? p1
: pos.piece_on(relative_square(Us,SQ_F3)) == make_piece(Us, PAWN) ? p2 if ( pos.piece_on(SQ_H1) == W_BISHOP
: p3; && pos.piece_on(SQ_G2) == W_PAWN)
} correction += !pos.empty(SQ_G3) ? penalty1
if ( (pos.pieces(~Us, BISHOP) & relative_square(Us, SQ_A8)) : pos.piece_on(SQ_F3) == W_PAWN ? penalty2
&& (pos.pieces(~Us, PAWN) & relative_square(Us, SQ_B7))) : penalty3;
{
bAdjust += !pos.empty(relative_square(Us,SQ_B6)) ? p1 if ( pos.piece_on(SQ_A8) == B_BISHOP
: pos.piece_on(relative_square(Us,SQ_C6)) == make_piece(~Us, PAWN) ? p2 && pos.piece_on(SQ_B7) == B_PAWN)
: p3; correction += !pos.empty(SQ_B6) ? -penalty1
} : pos.piece_on(SQ_C6) == B_PAWN ? -penalty2
if ( (pos.pieces(~Us, BISHOP) & relative_square(Us, SQ_H8)) : -penalty3;
&& (pos.pieces(~Us, PAWN) & relative_square(Us, SQ_G7)))
{ if ( pos.piece_on(SQ_H8) == B_BISHOP
bAdjust += !pos.empty(relative_square(Us,SQ_G6)) ? p1 && pos.piece_on(SQ_G7) == B_PAWN)
: pos.piece_on(relative_square(Us,SQ_F6)) == make_piece(~Us, PAWN) ? p2 correction += !pos.empty(SQ_G6) ? -penalty1
: p3; : pos.piece_on(SQ_F6) == B_PAWN ? -penalty2
} : -penalty3;
return bAdjust;
return pos.side_to_move() == WHITE ? Value(correction)
: -Value(correction);
} }
} // namespace } // namespace Eval
/// evaluate() is the evaluator for the outer world. It returns a static /// evaluate() is the evaluator for the outer world. It returns a static
@ -1092,14 +1097,19 @@ Value Eval::evaluate(const Position& pos) {
else else
{ {
// Scale and shift NNUE for compatibility with search and classical evaluation // Scale and shift NNUE for compatibility with search and classical evaluation
auto adjusted_NNUE = [&](){ auto adjusted_NNUE = [&]()
int mat = pos.non_pawn_material() + 2 * PawnValueMg * pos.count<PAWN>(); {
Value nnueValue = NNUE::evaluate(pos) * (641 + mat / 32 - 4 * pos.rule50_count()) / 1024 + Tempo; int material = pos.non_pawn_material() + 2 * PawnValueMg * pos.count<PAWN>();
int scale = 641
+ material / 32
- 4 * pos.rule50_count();
Value nnue = NNUE::evaluate(pos) * scale / 1024 + Tempo;
if (pos.is_chess960()) if (pos.is_chess960())
nnueValue += fix_FRC(pos); nnue += fix_FRC(pos);
return nnueValue; return nnue;
}; };
// If there is PSQ imbalance use classical eval, with small probability if it is small // If there is PSQ imbalance use classical eval, with small probability if it is small

View File

@ -74,7 +74,7 @@ namespace {
bool is_KBPsK(const Position& pos, Color us) { bool is_KBPsK(const Position& pos, Color us) {
return pos.non_pawn_material(us) == BishopValueMg return pos.non_pawn_material(us) == BishopValueMg
&& pos.count<PAWN >(us) >= 1; && pos.count<PAWN>(us) >= 1;
} }
bool is_KQKRPs(const Position& pos, Color us) { bool is_KQKRPs(const Position& pos, Color us) {

View File

@ -362,8 +362,12 @@ void std_aligned_free(void* ptr) {
/// aligned_large_pages_alloc() will return suitably aligned memory, if possible using large pages. /// aligned_large_pages_alloc() will return suitably aligned memory, if possible using large pages.
#if defined(_WIN32) #if defined(_WIN32)
#if defined(_WIN64)
static void* aligned_large_pages_alloc_win(size_t allocSize) { static void* aligned_large_pages_alloc_windows(size_t allocSize) {
#if !defined(_WIN64)
return nullptr;
#else
HANDLE hProcessToken { }; HANDLE hProcessToken { };
LUID luid { }; LUID luid { };
@ -406,21 +410,18 @@ static void* aligned_large_pages_alloc_win(size_t allocSize) {
CloseHandle(hProcessToken); CloseHandle(hProcessToken);
return mem; return mem;
#endif
} }
#endif
void* aligned_large_pages_alloc(size_t allocSize) { void* aligned_large_pages_alloc(size_t allocSize) {
#if defined(_WIN64)
// Try to allocate large pages // Try to allocate large pages
void* mem = aligned_large_pages_alloc_win(allocSize); void* mem = aligned_large_pages_alloc_windows(allocSize);
// Fall back to regular, page aligned, allocation if necessary // Fall back to regular, page aligned, allocation if necessary
if (!mem) if (!mem)
mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
#else
void* mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
#endif
return mem; return mem;
} }
@ -456,8 +457,9 @@ void aligned_large_pages_free(void* mem) {
if (mem && !VirtualFree(mem, 0, MEM_RELEASE)) if (mem && !VirtualFree(mem, 0, MEM_RELEASE))
{ {
DWORD err = GetLastError(); DWORD err = GetLastError();
std::cerr << "Failed to free transposition table. Error code: 0x" << std::cerr << "Failed to free large page memory. Error code: 0x"
std::hex << err << std::dec << std::endl; << std::hex << err
<< std::dec << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }

View File

@ -182,7 +182,8 @@ namespace {
Bitboard bb = piecesToMove & pos.pieces(Pt); Bitboard bb = piecesToMove & pos.pieces(Pt);
while (bb) { while (bb)
{
Square from = pop_lsb(bb); Square from = pop_lsb(bb);
Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target; Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;

View File

@ -40,7 +40,8 @@ namespace Stockfish::Eval::NNUE::Features {
Square ksq = orient(perspective, pos.square<KING>(perspective)); Square ksq = orient(perspective, pos.square<KING>(perspective));
Bitboard bb = pos.pieces() & ~pos.pieces(KING); Bitboard bb = pos.pieces() & ~pos.pieces(KING);
while (bb) { while (bb)
{
Square s = pop_lsb(bb); Square s = pop_lsb(bb);
active->push_back(make_index(perspective, s, pos.piece_on(s), ksq)); active->push_back(make_index(perspective, s, pos.piece_on(s), ksq));
} }

View File

@ -96,7 +96,7 @@ namespace Stockfish::Eval::NNUE::Layers {
IndexType idx = k / 2 * kOutputDimensions * 4 + k % 2; IndexType idx = k / 2 * kOutputDimensions * 4 + k % 2;
sum[w[idx] < 0] += w[idx]; sum[w[idx] < 0] += w[idx];
} }
for (int sign : {-1, 1}) for (int sign : { -1, 1 })
while (sign * sum[sign == -1] > 258) while (sign * sum[sign == -1] > 258)
{ {
int maxK = 0, maxW = 0; int maxK = 0, maxW = 0;
@ -234,9 +234,9 @@ namespace Stockfish::Eval::NNUE::Layers {
__m128i product1 = _mm_maddubs_epi16(a1, b1); __m128i product1 = _mm_maddubs_epi16(a1, b1);
__m128i product2 = _mm_maddubs_epi16(a2, b2); __m128i product2 = _mm_maddubs_epi16(a2, b2);
__m128i product3 = _mm_maddubs_epi16(a3, b3); __m128i product3 = _mm_maddubs_epi16(a3, b3);
product0 = _mm_adds_epi16(product0, product1); product0 = _mm_add_epi16(product0, product1);
product2 = _mm_adds_epi16(product2, product3); product2 = _mm_add_epi16(product2, product3);
product0 = _mm_adds_epi16(product0, product2); product0 = _mm_add_epi16(product0, product2);
product0 = _mm_madd_epi16(product0, kOnes128); product0 = _mm_madd_epi16(product0, kOnes128);
acc = _mm_add_epi32(acc, product0); acc = _mm_add_epi32(acc, product0);
}; };

View File

@ -109,7 +109,8 @@ namespace {
e->blockedCount += popcount(shift<Up>(ourPawns) & (theirPawns | doubleAttackThem)); e->blockedCount += popcount(shift<Up>(ourPawns) & (theirPawns | doubleAttackThem));
// Loop through all pawns of the current color and score each pawn // Loop through all pawns of the current color and score each pawn
while (b) { while (b)
{
s = pop_lsb(b); s = pop_lsb(b);
assert(pos.piece_on(s) == make_piece(Us, PAWN)); assert(pos.piece_on(s) == make_piece(Us, PAWN));

View File

@ -612,12 +612,12 @@ namespace {
// Step 1. Initialize node // Step 1. Initialize node
Thread* thisThread = pos.this_thread(); Thread* thisThread = pos.this_thread();
ss->inCheck = pos.checkers(); ss->inCheck = pos.checkers();
priorCapture = pos.captured_piece(); priorCapture = pos.captured_piece();
Color us = pos.side_to_move(); Color us = pos.side_to_move();
moveCount = captureCount = quietCount = ss->moveCount = 0; moveCount = captureCount = quietCount = ss->moveCount = 0;
bestValue = -VALUE_INFINITE; bestValue = -VALUE_INFINITE;
maxValue = VALUE_INFINITE; maxValue = VALUE_INFINITE;
ss->distanceFromPv = (PvNode ? 0 : ss->distanceFromPv); ss->distanceFromPv = (PvNode ? 0 : ss->distanceFromPv);
// Check for the available remaining time // Check for the available remaining time
@ -917,6 +917,7 @@ namespace {
return probCutBeta; return probCutBeta;
assert(probCutBeta < VALUE_INFINITE); assert(probCutBeta < VALUE_INFINITE);
MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory); MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory);
int probCutCount = 0; int probCutCount = 0;
bool ttPv = ss->ttPv; bool ttPv = ss->ttPv;
@ -1121,6 +1122,7 @@ moves_loop: // When in check, search starts from here
{ {
Value singularBeta = ttValue - ((formerPv + 4) * depth) / 2; Value singularBeta = ttValue - ((formerPv + 4) * depth) / 2;
Depth singularDepth = (depth - 1 + 3 * formerPv) / 2; Depth singularDepth = (depth - 1 + 3 * formerPv) / 2;
ss->excludedMove = move; ss->excludedMove = move;
value = search<NonPV>(pos, ss, singularBeta - 1, singularBeta, singularDepth, cutNode); value = search<NonPV>(pos, ss, singularBeta - 1, singularBeta, singularDepth, cutNode);
ss->excludedMove = MOVE_NONE; ss->excludedMove = MOVE_NONE;
@ -1205,15 +1207,19 @@ moves_loop: // When in check, search starts from here
// Decrease reduction if position is or has been on the PV // Decrease reduction if position is or has been on the PV
// and node is not likely to fail low. (~10 Elo) // and node is not likely to fail low. (~10 Elo)
if (ss->ttPv && !likelyFailLow) if ( ss->ttPv
&& !likelyFailLow)
r -= 2; r -= 2;
// Increase reduction at root and non-PV nodes when the best move does not change frequently // Increase reduction at root and non-PV nodes when the best move does not change frequently
if ((rootNode || !PvNode) && thisThread->rootDepth > 10 && thisThread->bestMoveChanges <= 2) if ( (rootNode || !PvNode)
&& thisThread->rootDepth > 10
&& thisThread->bestMoveChanges <= 2)
r++; r++;
// More reductions for late moves if position was not in previous PV // More reductions for late moves if position was not in previous PV
if (moveCountPruning && !formerPv) if ( moveCountPruning
&& !formerPv)
r++; r++;
// Decrease reduction if opponent's move count is high (~5 Elo) // Decrease reduction if opponent's move count is high (~5 Elo)
@ -1226,7 +1232,7 @@ moves_loop: // When in check, search starts from here
if (captureOrPromotion) if (captureOrPromotion)
{ {
// Unless giving check, this capture is likely bad // Increase reduction for non-checking captures likely to be bad
if ( !givesCheck if ( !givesCheck
&& ss->staticEval + PieceValue[EG][pos.captured_piece()] + 210 * depth <= alpha) && ss->staticEval + PieceValue[EG][pos.captured_piece()] + 210 * depth <= alpha)
r++; r++;
@ -1246,7 +1252,7 @@ moves_loop: // When in check, search starts from here
// Decrease reduction for moves that escape a capture. Filter out // Decrease reduction for moves that escape a capture. Filter out
// castling moves, because they are coded as "king captures rook" and // castling moves, because they are coded as "king captures rook" and
// hence break make_move(). (~2 Elo) // hence break reverse_move() (~2 Elo)
else if ( type_of(move) == NORMAL else if ( type_of(move) == NORMAL
&& !pos.see_ge(reverse_move(move))) && !pos.see_ge(reverse_move(move)))
r -= 2 + ss->ttPv - (type_of(movedPiece) == PAWN); r -= 2 + ss->ttPv - (type_of(movedPiece) == PAWN);
@ -1408,8 +1414,9 @@ moves_loop: // When in check, search starts from here
assert(moveCount || !ss->inCheck || excludedMove || !MoveList<LEGAL>(pos).size()); assert(moveCount || !ss->inCheck || excludedMove || !MoveList<LEGAL>(pos).size());
if (!moveCount) if (!moveCount)
bestValue = excludedMove ? alpha bestValue = excludedMove ? alpha :
: ss->inCheck ? mated_in(ss->ply) : VALUE_DRAW; ss->inCheck ? mated_in(ss->ply)
: VALUE_DRAW;
// If there is a move which produces search value greater than alpha we update stats of searched moves // If there is a move which produces search value greater than alpha we update stats of searched moves
else if (bestMove) else if (bestMove)

View File

@ -192,7 +192,8 @@ public:
std::stringstream ss(Paths); std::stringstream ss(Paths);
std::string path; std::string path;
while (std::getline(ss, path, SepChar)) { while (std::getline(ss, path, SepChar))
{
fname = path + "/" + f; fname = path + "/" + f;
std::ifstream::open(fname); std::ifstream::open(fname);
if (is_open()) if (is_open())
@ -567,7 +568,8 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
int buf64Size = 64; int buf64Size = 64;
Sym sym; Sym sym;
while (true) { while (true)
{
int len = 0; // This is the symbol length - d->min_sym_len int len = 0; // This is the symbol length - d->min_sym_len
// Now get the symbol length. For any symbol s64 of length l right-padded // Now get the symbol length. For any symbol s64 of length l right-padded
@ -605,8 +607,8 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
// We binary-search for our value recursively expanding into the left and // We binary-search for our value recursively expanding into the left and
// right child symbols until we reach a leaf node where symlen[sym] + 1 == 1 // right child symbols until we reach a leaf node where symlen[sym] + 1 == 1
// that will store the value we need. // that will store the value we need.
while (d->symlen[sym]) { while (d->symlen[sym])
{
Sym left = d->btree[sym].get<LR::Left>(); Sym left = d->btree[sym].get<LR::Left>();
// If a symbol contains 36 sub-symbols (d->symlen[sym] + 1 = 36) and // If a symbol contains 36 sub-symbols (d->symlen[sym] + 1 = 36) and

View File

@ -128,14 +128,16 @@ void Thread::idle_loop() {
void ThreadPool::set(size_t requested) { void ThreadPool::set(size_t requested) {
if (size() > 0) { // destroy any existing thread(s) if (size() > 0) // destroy any existing thread(s)
{
main()->wait_for_search_finished(); main()->wait_for_search_finished();
while (size() > 0) while (size() > 0)
delete back(), pop_back(); delete back(), pop_back();
} }
if (requested > 0) { // create new thread(s) if (requested > 0) // create new thread(s)
{
push_back(new MainThread(0)); push_back(new MainThread(0));
while (size() < requested) while (size() < requested)