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
Tord Romstad (romstad)

View File

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

View File

@ -54,7 +54,6 @@
using namespace std;
using namespace Stockfish::Eval::NNUE;
namespace Stockfish {
@ -396,7 +395,8 @@ namespace {
attackedBy[Us][Pt] = 0;
while (b1) {
while (b1)
{
Square s = pop_lsb(b1);
// Find attacked squares, including x-ray attacks for bishops and rooks
@ -1038,46 +1038,51 @@ make_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 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();
if ( (pos.pieces(Us, BISHOP) & relative_square(Us, SQ_A1))
&& (pos.pieces(Us, PAWN) & relative_square(Us, SQ_B2)))
{
bAdjust -= !pos.empty(relative_square(Us,SQ_B3)) ? p1
: pos.piece_on(relative_square(Us,SQ_C3)) == make_piece(Us, PAWN) ? p2
: p3;
}
if ( (pos.pieces(Us, BISHOP) & relative_square(Us, SQ_H1))
&& (pos.pieces(Us, PAWN) & relative_square(Us, SQ_G2)))
{
bAdjust -= !pos.empty(relative_square(Us,SQ_G3)) ? p1
: pos.piece_on(relative_square(Us,SQ_F3)) == make_piece(Us, PAWN) ? p2
: p3;
}
if ( (pos.pieces(~Us, BISHOP) & relative_square(Us, SQ_A8))
&& (pos.pieces(~Us, PAWN) & relative_square(Us, SQ_B7)))
{
bAdjust += !pos.empty(relative_square(Us,SQ_B6)) ? p1
: pos.piece_on(relative_square(Us,SQ_C6)) == make_piece(~Us, PAWN) ? p2
: p3;
}
if ( (pos.pieces(~Us, BISHOP) & relative_square(Us, SQ_H8))
&& (pos.pieces(~Us, PAWN) & relative_square(Us, SQ_G7)))
{
bAdjust += !pos.empty(relative_square(Us,SQ_G6)) ? p1
: pos.piece_on(relative_square(Us,SQ_F6)) == make_piece(~Us, PAWN) ? p2
: p3;
}
return bAdjust;
constexpr int penalty1 = -209;
constexpr int penalty2 = -136;
constexpr int penalty3 = -148;
int correction = 0;
if ( pos.piece_on(SQ_A1) == W_BISHOP
&& pos.piece_on(SQ_B2) == W_PAWN)
correction += !pos.empty(SQ_B3) ? penalty1
: pos.piece_on(SQ_C3) == W_PAWN ? penalty2
: penalty3;
if ( pos.piece_on(SQ_H1) == W_BISHOP
&& pos.piece_on(SQ_G2) == W_PAWN)
correction += !pos.empty(SQ_G3) ? penalty1
: pos.piece_on(SQ_F3) == W_PAWN ? penalty2
: penalty3;
if ( pos.piece_on(SQ_A8) == B_BISHOP
&& pos.piece_on(SQ_B7) == B_PAWN)
correction += !pos.empty(SQ_B6) ? -penalty1
: pos.piece_on(SQ_C6) == B_PAWN ? -penalty2
: -penalty3;
if ( pos.piece_on(SQ_H8) == B_BISHOP
&& pos.piece_on(SQ_G7) == B_PAWN)
correction += !pos.empty(SQ_G6) ? -penalty1
: pos.piece_on(SQ_F6) == B_PAWN ? -penalty2
: -penalty3;
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
@ -1092,14 +1097,19 @@ Value Eval::evaluate(const Position& pos) {
else
{
// Scale and shift NNUE for compatibility with search and classical evaluation
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;
auto adjusted_NNUE = [&]()
{
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())
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

View File

@ -74,7 +74,7 @@ namespace {
bool is_KBPsK(const Position& pos, Color us) {
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) {

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.
#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 { };
LUID luid { };
@ -406,21 +410,18 @@ static void* aligned_large_pages_alloc_win(size_t allocSize) {
CloseHandle(hProcessToken);
return mem;
#endif
}
#endif
void* aligned_large_pages_alloc(size_t allocSize) {
#if defined(_WIN64)
// 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
if (!mem)
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;
}
@ -456,8 +457,9 @@ void aligned_large_pages_free(void* mem) {
if (mem && !VirtualFree(mem, 0, MEM_RELEASE))
{
DWORD err = GetLastError();
std::cerr << "Failed to free transposition table. Error code: 0x" <<
std::hex << err << std::dec << std::endl;
std::cerr << "Failed to free large page memory. Error code: 0x"
<< std::hex << err
<< std::dec << std::endl;
exit(EXIT_FAILURE);
}
}

View File

@ -182,7 +182,8 @@ namespace {
Bitboard bb = piecesToMove & pos.pieces(Pt);
while (bb) {
while (bb)
{
Square from = pop_lsb(bb);
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));
Bitboard bb = pos.pieces() & ~pos.pieces(KING);
while (bb) {
while (bb)
{
Square s = pop_lsb(bb);
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;
sum[w[idx] < 0] += w[idx];
}
for (int sign : {-1, 1})
for (int sign : { -1, 1 })
while (sign * sum[sign == -1] > 258)
{
int maxK = 0, maxW = 0;
@ -234,9 +234,9 @@ namespace Stockfish::Eval::NNUE::Layers {
__m128i product1 = _mm_maddubs_epi16(a1, b1);
__m128i product2 = _mm_maddubs_epi16(a2, b2);
__m128i product3 = _mm_maddubs_epi16(a3, b3);
product0 = _mm_adds_epi16(product0, product1);
product2 = _mm_adds_epi16(product2, product3);
product0 = _mm_adds_epi16(product0, product2);
product0 = _mm_add_epi16(product0, product1);
product2 = _mm_add_epi16(product2, product3);
product0 = _mm_add_epi16(product0, product2);
product0 = _mm_madd_epi16(product0, kOnes128);
acc = _mm_add_epi32(acc, product0);
};

View File

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

View File

@ -612,12 +612,12 @@ namespace {
// Step 1. Initialize node
Thread* thisThread = pos.this_thread();
ss->inCheck = pos.checkers();
priorCapture = pos.captured_piece();
Color us = pos.side_to_move();
moveCount = captureCount = quietCount = ss->moveCount = 0;
bestValue = -VALUE_INFINITE;
maxValue = VALUE_INFINITE;
ss->inCheck = pos.checkers();
priorCapture = pos.captured_piece();
Color us = pos.side_to_move();
moveCount = captureCount = quietCount = ss->moveCount = 0;
bestValue = -VALUE_INFINITE;
maxValue = VALUE_INFINITE;
ss->distanceFromPv = (PvNode ? 0 : ss->distanceFromPv);
// Check for the available remaining time
@ -917,6 +917,7 @@ namespace {
return probCutBeta;
assert(probCutBeta < VALUE_INFINITE);
MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory);
int probCutCount = 0;
bool ttPv = ss->ttPv;
@ -1121,6 +1122,7 @@ moves_loop: // When in check, search starts from here
{
Value singularBeta = ttValue - ((formerPv + 4) * depth) / 2;
Depth singularDepth = (depth - 1 + 3 * formerPv) / 2;
ss->excludedMove = move;
value = search<NonPV>(pos, ss, singularBeta - 1, singularBeta, singularDepth, cutNode);
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
// and node is not likely to fail low. (~10 Elo)
if (ss->ttPv && !likelyFailLow)
if ( ss->ttPv
&& !likelyFailLow)
r -= 2;
// 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++;
// More reductions for late moves if position was not in previous PV
if (moveCountPruning && !formerPv)
if ( moveCountPruning
&& !formerPv)
r++;
// 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)
{
// Unless giving check, this capture is likely bad
// Increase reduction for non-checking captures likely to be bad
if ( !givesCheck
&& ss->staticEval + PieceValue[EG][pos.captured_piece()] + 210 * depth <= alpha)
r++;
@ -1246,7 +1252,7 @@ moves_loop: // When in check, search starts from here
// Decrease reduction for moves that escape a capture. Filter out
// 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
&& !pos.see_ge(reverse_move(move)))
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());
if (!moveCount)
bestValue = excludedMove ? alpha
: ss->inCheck ? mated_in(ss->ply) : VALUE_DRAW;
bestValue = excludedMove ? alpha :
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
else if (bestMove)

View File

@ -192,7 +192,8 @@ public:
std::stringstream ss(Paths);
std::string path;
while (std::getline(ss, path, SepChar)) {
while (std::getline(ss, path, SepChar))
{
fname = path + "/" + f;
std::ifstream::open(fname);
if (is_open())
@ -567,7 +568,8 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
int buf64Size = 64;
Sym sym;
while (true) {
while (true)
{
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
@ -605,8 +607,8 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
// 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
// that will store the value we need.
while (d->symlen[sym]) {
while (d->symlen[sym])
{
Sym left = d->btree[sym].get<LR::Left>();
// 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) {
if (size() > 0) { // destroy any existing thread(s)
if (size() > 0) // destroy any existing thread(s)
{
main()->wait_for_search_finished();
while (size() > 0)
delete back(), pop_back();
}
if (requested > 0) { // create new thread(s)
if (requested > 0) // create new thread(s)
{
push_back(new MainThread(0));
while (size() < requested)