Merge commit 'c467fe5ba42545827d769c360aa404767308ac18' into cluster

This commit is contained in:
Steinar H. Gunderson
2025-12-25 20:22:33 +01:00
19 changed files with 137 additions and 182 deletions
+12 -12
View File
@@ -20,8 +20,8 @@
"archive_ext": "tar"
},
{
"name": "macOS 14 Apple Clang M1",
"os": "macos-14",
"name": "macOS 15 Apple Clang M1",
"os": "macos-15",
"simple_name": "macos-m1",
"compiler": "clang++",
"comp": "clang",
@@ -71,49 +71,49 @@
{
"binaries": "x86-64",
"config": {
"os": "macos-14"
"os": "macos-15"
}
},
{
"binaries": "x86-64-sse41-popcnt",
"config": {
"os": "macos-14"
"os": "macos-15"
}
},
{
"binaries": "x86-64-avx2",
"config": {
"os": "macos-14"
"os": "macos-15"
}
},
{
"binaries": "x86-64-bmi2",
"config": {
"os": "macos-14"
"os": "macos-15"
}
},
{
"binaries": "x86-64-avxvnni",
"config": {
"os": "macos-14"
"os": "macos-15"
}
},
{
"binaries": "x86-64-avx512",
"config": {
"os": "macos-14"
"os": "macos-15"
}
},
{
"binaries": "x86-64-vnni512",
"config": {
"os": "macos-14"
"os": "macos-15"
}
},
{
"binaries": "x86-64-avx512icl",
"config": {
"os": "macos-14"
"os": "macos-15"
}
},
{
@@ -245,7 +245,7 @@
{
"binaries": "armv8",
"config": {
"os": "macos-14"
"os": "macos-15"
}
},
{
@@ -275,7 +275,7 @@
{
"binaries": "armv8-dotprod",
"config": {
"os": "macos-14"
"os": "macos-15"
}
}
]
+2 -2
View File
@@ -62,8 +62,8 @@ jobs:
comp: clang
run_64bit_tests: true
shell: bash
- name: macOS 14 Apple Clang M1
os: macos-14
- name: macOS 15 Apple Clang M1
os: macos-15
compiler: clang++
comp: clang
run_64bit_tests: false
+2 -2
View File
@@ -454,7 +454,7 @@ BenchmarkSetup setup_benchmark(std::istream& is) {
int desiredTimeS;
if (!(is >> setup.threads))
setup.threads = get_hardware_concurrency();
setup.threads = int(get_hardware_concurrency());
else
setup.originalInvocation += std::to_string(setup.threads);
@@ -486,7 +486,7 @@ BenchmarkSetup setup_benchmark(std::istream& is) {
int ply = 1;
for (int i = 0; i < static_cast<int>(game.size()); ++i)
{
const float correctedTime = getCorrectedTime(ply);
const float correctedTime = float(getCorrectedTime(ply));
totalTime += correctedTime;
ply += 1;
}
+1 -1
View File
@@ -33,7 +33,7 @@ namespace Eval {
// for the build process (profile-build and fishtest) to work. Do not change the
// name of the macro or the location where this macro is defined, as it is used
// in the Makefile/Fishtest.
#define EvalFileDefaultNameBig "nn-2962dca31855.nnue"
#define EvalFileDefaultNameBig "nn-c288c895ea92.nnue"
#define EvalFileDefaultNameSmall "nn-37f18f62d772.nnue"
namespace NNUE {
+6 -4
View File
@@ -48,13 +48,15 @@ inline int pawn_history_index(const Position& pos) {
return pos.pawn_key() & (PAWN_HISTORY_SIZE - 1);
}
inline uint16_t pawn_correction_history_index(const Position& pos) { return pos.pawn_key(); }
inline uint16_t pawn_correction_history_index(const Position& pos) {
return uint16_t(pos.pawn_key());
}
inline uint16_t minor_piece_index(const Position& pos) { return pos.minor_piece_key(); }
inline uint16_t minor_piece_index(const Position& pos) { return uint16_t(pos.minor_piece_key()); }
template<Color c>
inline uint16_t non_pawn_index(const Position& pos) {
return pos.non_pawn_key(c);
return uint16_t(pos.non_pawn_key(c));
}
// StatsEntry is the container of various numerical statistics. We use a class
@@ -100,7 +102,7 @@ using Stats = MultiArray<StatsEntry<T, D>, Sizes...>;
// see https://www.chessprogramming.org/Butterfly_Boards
using ButterflyHistory = Stats<std::int16_t, 7183, COLOR_NB, UINT_16_HISTORY_SIZE>;
// LowPlyHistory is addressed by play and move's from and to squares, used
// LowPlyHistory is addressed by ply and move's from and to squares, used
// to improve move ordering near the root
using LowPlyHistory = Stats<std::int16_t, 7183, LOW_PLY_HISTORY_SIZE, UINT_16_HISTORY_SIZE>;
+1 -1
View File
@@ -44,7 +44,7 @@ constexpr std::string_view version = "dev";
// Our fancy logging facility. The trick here is to replace cin.rdbuf() and
// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We
// can toggle the logging of std::cout and std:cin at runtime whilst preserving
// can toggle the logging of std::cout and std::cin at runtime whilst preserving
// usual I/O functionality, all without changing a single line of code!
// Idea from http://groups.google.com/group/comp.lang.c++/msg/1d941c0f26ea0d81
+2 -1
View File
@@ -134,6 +134,7 @@ class ValueList {
public:
std::size_t size() const { return size_; }
int ssize() const { return int(size_); }
void push_back(const T& value) {
assert(size_ < MaxSize);
values_[size_++] = value;
@@ -424,7 +425,7 @@ void move_to_front(std::vector<T>& vec, Predicate pred) {
#elif defined(_MSC_VER)
#define sf_always_inline __forceinline
#else
// do nothign for other compilers
// do nothing for other compilers
#define sf_always_inline
#endif
+61 -52
View File
@@ -360,6 +360,8 @@ struct AccumulatorUpdateContext {
vec_t acc[Tiling::NumRegs];
psqt_vec_t psqt[Tiling::NumPsqtRegs];
const auto* threatWeights = &featureTransformer.threatWeights[0];
for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j)
{
auto* fromTile = reinterpret_cast<const vec_t*>(&fromAcc[j * Tiling::TileHeight]);
@@ -368,12 +370,11 @@ struct AccumulatorUpdateContext {
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = fromTile[k];
for (IndexType i = 0; i < removed.size(); ++i)
for (int i = 0; i < removed.ssize(); ++i)
{
IndexType index = removed[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight;
auto* column =
reinterpret_cast<const vec_i8_t*>(&featureTransformer.threatWeights[offset]);
size_t index = removed[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
#ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
@@ -387,12 +388,11 @@ struct AccumulatorUpdateContext {
#endif
}
for (IndexType i = 0; i < added.size(); ++i)
for (int i = 0; i < added.ssize(); ++i)
{
IndexType index = added[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight;
auto* column =
reinterpret_cast<const vec_i8_t*>(&featureTransformer.threatWeights[offset]);
size_t index = added[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
#ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
@@ -408,6 +408,8 @@ struct AccumulatorUpdateContext {
for (IndexType k = 0; k < Tiling::NumRegs; k++)
vec_store(&toTile[k], acc[k]);
threatWeights += Tiling::TileHeight;
}
for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j)
@@ -420,22 +422,22 @@ struct AccumulatorUpdateContext {
for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = fromTilePsqt[k];
for (IndexType i = 0; i < removed.size(); ++i)
for (int i = 0; i < removed.ssize(); ++i)
{
IndexType index = removed[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
size_t index = removed[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
&featureTransformer.threatPsqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]);
}
for (IndexType i = 0; i < added.size(); ++i)
for (int i = 0; i < added.ssize(); ++i)
{
IndexType index = added[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
size_t index = added[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
&featureTransformer.threatPsqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
@@ -691,6 +693,8 @@ void update_accumulator_refresh_cache(Color pers
vec_t acc[Tiling::NumRegs];
psqt_vec_t psqt[Tiling::NumPsqtRegs];
const auto* weights = &featureTransformer.weights[0];
for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j)
{
auto* accTile =
@@ -700,33 +704,33 @@ void update_accumulator_refresh_cache(Color pers
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = entryTile[k];
IndexType i = 0;
for (; i < std::min(removed.size(), added.size()); ++i)
int i = 0;
for (; i < std::min(removed.ssize(), added.ssize()); ++i)
{
IndexType indexR = removed[i];
const IndexType offsetR = Dimensions * indexR + j * Tiling::TileHeight;
auto* columnR = reinterpret_cast<const vec_t*>(&featureTransformer.weights[offsetR]);
IndexType indexA = added[i];
const IndexType offsetA = Dimensions * indexA + j * Tiling::TileHeight;
auto* columnA = reinterpret_cast<const vec_t*>(&featureTransformer.weights[offsetA]);
size_t indexR = removed[i];
const size_t offsetR = Dimensions * indexR;
auto* columnR = reinterpret_cast<const vec_t*>(&weights[offsetR]);
size_t indexA = added[i];
const size_t offsetA = Dimensions * indexA;
auto* columnA = reinterpret_cast<const vec_t*>(&weights[offsetA]);
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = fused<Vec16Wrapper, Add, Sub>(acc[k], columnA[k], columnR[k]);
}
for (; i < removed.size(); ++i)
for (; i < removed.ssize(); ++i)
{
IndexType index = removed[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight;
auto* column = reinterpret_cast<const vec_t*>(&featureTransformer.weights[offset]);
size_t index = removed[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_t*>(&weights[offset]);
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = vec_sub_16(acc[k], column[k]);
}
for (; i < added.size(); ++i)
for (; i < added.ssize(); ++i)
{
IndexType index = added[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight;
auto* column = reinterpret_cast<const vec_t*>(&featureTransformer.weights[offset]);
size_t index = added[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_t*>(&weights[offset]);
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = vec_add_16(acc[k], column[k]);
@@ -736,6 +740,8 @@ void update_accumulator_refresh_cache(Color pers
vec_store(&entryTile[k], acc[k]);
for (IndexType k = 0; k < Tiling::NumRegs; k++)
vec_store(&accTile[k], acc[k]);
weights += Tiling::TileHeight;
}
for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j)
@@ -748,21 +754,21 @@ void update_accumulator_refresh_cache(Color pers
for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = entryTilePsqt[k];
for (IndexType i = 0; i < removed.size(); ++i)
for (int i = 0; i < removed.ssize(); ++i)
{
IndexType index = removed[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
size_t index = removed[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
reinterpret_cast<const psqt_vec_t*>(&featureTransformer.psqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]);
}
for (IndexType i = 0; i < added.size(); ++i)
for (int i = 0; i < added.ssize(); ++i)
{
IndexType index = added[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
size_t index = added[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
reinterpret_cast<const psqt_vec_t*>(&featureTransformer.psqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
@@ -820,6 +826,8 @@ void update_threats_accumulator_full(Color persp
vec_t acc[Tiling::NumRegs];
psqt_vec_t psqt[Tiling::NumPsqtRegs];
const auto* threatWeights = &featureTransformer.threatWeights[0];
for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j)
{
auto* accTile =
@@ -828,14 +836,13 @@ void update_threats_accumulator_full(Color persp
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = vec_zero();
IndexType i = 0;
int i = 0;
for (; i < active.size(); ++i)
for (; i < active.ssize(); ++i)
{
IndexType index = active[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight;
auto* column =
reinterpret_cast<const vec_i8_t*>(&featureTransformer.threatWeights[offset]);
size_t index = active[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
#ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
@@ -851,6 +858,8 @@ void update_threats_accumulator_full(Color persp
for (IndexType k = 0; k < Tiling::NumRegs; k++)
vec_store(&accTile[k], acc[k]);
threatWeights += Tiling::TileHeight;
}
for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j)
@@ -861,11 +870,11 @@ void update_threats_accumulator_full(Color persp
for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_zero_psqt();
for (IndexType i = 0; i < active.size(); ++i)
for (int i = 0; i < active.ssize(); ++i)
{
IndexType index = active[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
size_t index = active[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
reinterpret_cast<const psqt_vec_t*>(&featureTransformer.threatPsqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
-1
View File
@@ -157,7 +157,6 @@ class AccumulatorStack {
[[nodiscard]] const AccumulatorState<T>& latest() const noexcept;
void reset() noexcept;
void push(const DirtyBoardData& dirtyBoardData) noexcept;
std::pair<DirtyPiece&, DirtyThreats&> push() noexcept;
void pop() noexcept;
+8 -25
View File
@@ -164,22 +164,13 @@ class FeatureTransformer {
if (UseThreats)
{
auto combinedWeights =
std::make_unique<std::array<WeightType, HalfDimensions * TotalInputDimensions>>();
read_little_endian<ThreatWeightType>(stream, threatWeights.data(),
ThreatInputDimensions * HalfDimensions);
read_leb_128<WeightType>(stream, weights);
auto combinedPsqtWeights =
std::make_unique<std::array<PSQTWeightType, TotalInputDimensions * PSQTBuckets>>();
read_leb_128<WeightType>(stream, *combinedWeights);
std::copy(combinedWeights->begin(),
combinedWeights->begin() + ThreatInputDimensions * HalfDimensions,
std::begin(threatWeights));
std::copy(combinedWeights->begin() + ThreatInputDimensions * HalfDimensions,
combinedWeights->begin()
+ (ThreatInputDimensions + InputDimensions) * HalfDimensions,
std::begin(weights));
read_leb_128<PSQTWeightType>(stream, *combinedPsqtWeights);
std::copy(combinedPsqtWeights->begin(),
@@ -218,21 +209,13 @@ class FeatureTransformer {
if (UseThreats)
{
auto combinedWeights =
std::make_unique<std::array<WeightType, HalfDimensions * TotalInputDimensions>>();
write_little_endian<ThreatWeightType>(stream, copy->threatWeights.data(),
ThreatInputDimensions * HalfDimensions);
write_leb_128<WeightType>(stream, copy->weights);
auto combinedPsqtWeights =
std::make_unique<std::array<PSQTWeightType, TotalInputDimensions * PSQTBuckets>>();
std::copy(std::begin(copy->threatWeights),
std::begin(copy->threatWeights) + ThreatInputDimensions * HalfDimensions,
combinedWeights->begin());
std::copy(std::begin(copy->weights),
std::begin(copy->weights) + InputDimensions * HalfDimensions,
combinedWeights->begin() + ThreatInputDimensions * HalfDimensions);
write_leb_128<WeightType>(stream, *combinedWeights);
std::copy(std::begin(copy->threatPsqtWeights),
std::begin(copy->threatPsqtWeights) + ThreatInputDimensions * PSQTBuckets,
combinedPsqtWeights->begin());
+13 -39
View File
@@ -911,7 +911,7 @@ void Position::do_move(Move m,
if (more_than_one(pawns))
{
// If there are two pawns potentially being abled to capture and at least one
// If there are two pawns potentially being able to capture and at least one
// is not pinned, ep is legal as there are no horizontal exposed checks
if (!more_than_one(blockers_for_king(them) & pawns))
{
@@ -1093,10 +1093,10 @@ void write_multiple_dirties(const Position& p,
#endif
template<bool PutPiece, bool ComputeRay>
void Position::update_piece_threats(Piece pc,
Square s,
DirtyThreats* const dts,
Bitboard noRaysContaining) {
void Position::update_piece_threats(Piece pc,
Square s,
DirtyThreats* const dts,
[[maybe_unused]] Bitboard noRaysContaining) const {
const Bitboard occupied = pieces();
const Bitboard rookQueens = pieces(ROOK, QUEEN);
const Bitboard bishopQueens = pieces(BISHOP, QUEEN);
@@ -1108,35 +1108,8 @@ void Position::update_piece_threats(Piece pc,
const Bitboard rAttacks = attacks_bb<ROOK>(s, occupied);
const Bitboard bAttacks = attacks_bb<BISHOP>(s, occupied);
Bitboard qAttacks = Bitboard(0);
if constexpr (ComputeRay)
qAttacks = rAttacks | bAttacks;
else if (type_of(pc) == QUEEN)
qAttacks = rAttacks | bAttacks;
Bitboard threatened;
switch (type_of(pc))
{
case PAWN :
threatened = PseudoAttacks[color_of(pc)][s];
break;
case BISHOP :
threatened = bAttacks;
break;
case ROOK :
threatened = rAttacks;
break;
case QUEEN :
threatened = qAttacks;
break;
default :
threatened = PseudoAttacks[type_of(pc)][s];
}
threatened &= occupied;
Bitboard sliders = (rookQueens & rAttacks) | (bishopQueens & bAttacks);
Bitboard threatened = attacks_bb(pc, s, occupied) & occupied;
Bitboard sliders = (rookQueens & rAttacks) | (bishopQueens & bAttacks);
Bitboard incoming_threats =
(PseudoAttacks[KNIGHT][s] & knights) | (attacks_bb<PAWN>(s, WHITE) & blackPawns)
| (attacks_bb<PAWN>(s, BLACK) & whitePawns) | (PseudoAttacks[KING][s] & kings);
@@ -1159,8 +1132,11 @@ void Position::update_piece_threats(Piece pc,
if (!all_attackers)
return; // Square s is threatened iff there's at least one attacker
dts->threatenedSqs |= square_bb(s);
dts->threateningSqs |= all_attackers;
if constexpr (PutPiece)
{
dts->threatenedSqs |= square_bb(s);
dts->threateningSqs |= all_attackers;
}
DirtyThreat dt_template{NO_PIECE, pc, Square(0), s, PutPiece};
write_multiple_dirties<DirtyThreat::PcSqOffset, DirtyThreat::PcOffset>(*this, all_attackers,
@@ -1186,7 +1162,7 @@ void Position::update_piece_threats(Piece pc,
Piece slider = piece_on(sliderSq);
const Bitboard ray = RayPassBB[sliderSq][s] & ~BetweenBB[sliderSq][s];
const Bitboard discovered = ray & qAttacks & occupied;
const Bitboard discovered = ray & (rAttacks | bAttacks) & occupied;
assert(!more_than_one(discovered));
if (discovered && (RayPassBB[sliderSq][s] & noRaysContaining) != noRaysContaining)
@@ -1249,8 +1225,6 @@ void Position::do_castling(Color us,
// Remove both pieces first since squares could overlap in Chess960
remove_piece(Do ? from : to, dts);
remove_piece(Do ? rfrom : rto, dts);
board[Do ? from : to] = board[Do ? rfrom : rto] =
NO_PIECE; // remove_piece does not do this for us
put_piece(make_piece(us, KING), Do ? to : from, dts);
put_piece(make_piece(us, ROOK), Do ? rto : rfrom, dts);
}
+1 -1
View File
@@ -190,7 +190,7 @@ class Position {
void update_piece_threats(Piece pc,
Square s,
DirtyThreats* const dts,
Bitboard noRaysContaining = -1ULL);
Bitboard noRaysContaining = -1ULL) const;
void move_piece(Square from, Square to, DirtyThreats* const dts = nullptr);
template<bool Do>
void do_castling(Color us,
+7 -15
View File
@@ -142,9 +142,8 @@ void update_all_stats(const Position& pos,
Move TTMove,
int moveCount);
bool isShuffling(Move move, Stack* const ss, const Position& pos) {
if (type_of(pos.moved_piece(move)) == PAWN || pos.capture_stage(move)
|| pos.rule50_count() < 10)
bool is_shuffling(Move move, Stack* const ss, const Position& pos) {
if (pos.capture_stage(move) || pos.rule50_count() < 10)
return false;
if (pos.state()->pliesFromNull <= 6 || ss->ply < 20)
return false;
@@ -747,18 +746,12 @@ Value Search::Worker::search(
ss->ttPv = excludedMove ? ss->ttPv : PvNode || (ttHit && ttData.is_pv);
ttCapture = ttData.move && pos.capture_stage(ttData.move);
// At this point, if excluded, skip straight to step 6, static eval. However,
// to save indentation, we list the condition in all code between here and there.
// Step 6. Static evaluation of the position
Value unadjustedStaticEval = VALUE_NONE;
const auto correctionValue = correction_value(*this, pos, ss);
// Skip early pruning when in check
if (ss->inCheck)
{
// Skip early pruning when in check
ss->staticEval = eval = (ss - 2)->staticEval;
improving = false;
}
else if (excludedMove)
unadjustedStaticEval = eval = ss->staticEval;
else if (ss->ttHit)
@@ -923,9 +916,8 @@ Value Search::Worker::search(
auto futility_margin = [&](Depth d) {
Value futilityMult = 76 - 23 * !ss->ttHit;
return futilityMult * d //
- 2474 * improving * futilityMult / 1024 //
- 331 * opponentWorsening * futilityMult / 1024 //
return futilityMult * d
- (2474 * improving + 331 * opponentWorsening) * futilityMult / 1024 //
+ std::abs(correctionValue) / 174665;
};
@@ -1174,7 +1166,7 @@ moves_loop: // When in check, search starts here
// and lower extension margins scale well.
if (!rootNode && move == ttData.move && !excludedMove && depth >= 6 + ss->ttPv
&& is_valid(ttData.value) && !is_decisive(ttData.value) && (ttData.bound & BOUND_LOWER)
&& ttData.depth >= depth - 3 && !isShuffling(move, ss, pos))
&& ttData.depth >= depth - 3 && !is_shuffling(move, ss, pos))
{
Value singularBeta = ttData.value - (53 + 75 * (ss->ttPv && !PvNode)) * depth / 60;
Depth singularDepth = newDepth / 2;
@@ -1325,7 +1317,7 @@ moves_loop: // When in check, search starts here
// decisive score handling improves mate finding and retrograde analysis.
if (move == ttData.move
&& ((is_valid(ttData.value) && is_decisive(ttData.value) && ttData.depth > 0)
|| (ttData.depth > 1 && rootDepth > 8)))
|| ttData.depth > 1))
newDepth = std::max(newDepth, 1);
value = -search<PV>(pos, ss + 1, -beta, -alpha, newDepth, false);
+2 -2
View File
@@ -586,7 +586,7 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
// idx = k * d->span + idx % d->span (2)
//
// So from (1) and (2) we can compute idx - I(K):
int diff = idx % d->span - d->span / 2;
int diff = int(idx % d->span - d->span / 2);
// Sum the above to offset to find the offset corresponding to our idx
offset += diff;
@@ -1094,7 +1094,7 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) {
// See https://web.archive.org/web/20201106232444/http://www.larsson.dogma.net/dcc99.pdf
std::vector<bool> visited(d->symlen.size());
for (std::size_t sym = 0; sym < d->symlen.size(); ++sym)
for (Sym sym = 0; sym < d->symlen.size(); ++sym)
if (!visited[sym])
d->symlen[sym] = set_symlen(d, sym, visited);
+2 -2
View File
@@ -286,8 +286,8 @@ void ThreadPool::start_thinking(const OptionsMap& options,
{
th->run_custom_job([&]() {
th->worker->limits = limits;
th->worker->nodes = th->worker->tbHits = th->worker->nmpMinPly =
th->worker->bestMoveChanges = 0;
th->worker->nodes = th->worker->tbHits = th->worker->bestMoveChanges = 0;
th->worker->nmpMinPly = 0;
th->worker->rootDepth = th->worker->completedDepth = 0;
th->worker->rootMoves = rootMoves;
th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState);
+1 -1
View File
@@ -91,7 +91,7 @@ void TimeManagement::init(Search::LimitsType& limits,
// If less than one second, gradually reduce mtg
if (scaledTime < 1000)
centiMTG = scaledTime * 5.051;
centiMTG = int(scaledTime * 5.051);
// Make sure timeLeft is > 0 since we may use it as a divisor
TimePoint timeLeft =
-2
View File
@@ -110,8 +110,6 @@ void TTEntry::save(
value16 = int16_t(v);
eval16 = int16_t(ev);
}
else if (depth8 + DEPTH_ENTRY_OFFSET >= 5 && Bound(genBound8 & 0x3) != BOUND_EXACT)
depth8--;
}
+9 -13
View File
@@ -306,24 +306,25 @@ struct DirtyThreat {
| (threatened_sq << ThreatenedSqOffset) | (pc_sq << PcSqOffset);
}
Piece pc() const { return static_cast<Piece>(data >> 20 & 0xf); }
Piece threatened_pc() const { return static_cast<Piece>(data >> 16 & 0xf); }
Square threatened_sq() const { return static_cast<Square>(data >> 8 & 0xff); }
Square pc_sq() const { return static_cast<Square>(data & 0xff); }
bool add() const { return data >> 31; }
Piece pc() const { return static_cast<Piece>(data >> PcOffset & 0xf); }
Piece threatened_pc() const { return static_cast<Piece>(data >> ThreatenedPcOffset & 0xf); }
Square threatened_sq() const { return static_cast<Square>(data >> ThreatenedSqOffset & 0xff); }
Square pc_sq() const { return static_cast<Square>(data >> PcSqOffset & 0xff); }
bool add() const { return data >> 31; }
uint32_t raw() const { return data; }
private:
uint32_t data;
};
using DirtyThreatList = ValueList<DirtyThreat, 96>;
// A piece can be involved in at most 8 outgoing attacks and 16 incoming attacks.
// Moving a piece also can reveal at most 8 discovered attacks.
// This implies that a non-castling move can change at most (8 + 16) * 3 + 8 = 80 features.
// By similar logic, a castling move can change at most (5 + 1 + 3 + 9) * 2 = 36 features.
// Thus, 80 should work as an upper bound.
// Thus, 80 should work as an upper bound. Finally, 16 entries are added to accommodate
// unmasked vector stores near the end of the list.
using DirtyThreatList = ValueList<DirtyThreat, 96>;
struct DirtyThreats {
DirtyThreatList list;
@@ -333,11 +334,6 @@ struct DirtyThreats {
Bitboard threatenedSqs, threateningSqs;
};
struct DirtyBoardData {
DirtyPiece dp;
DirtyThreats dts;
};
#define ENABLE_INCR_OPERATORS_ON(T) \
constexpr T& operator++(T& d) { return d = T(int(d) + 1); } \
constexpr T& operator--(T& d) { return d = T(int(d) - 1); }
+7 -6
View File
@@ -319,8 +319,8 @@ void UCIEngine::benchmark(std::istream& args) {
Benchmark::BenchmarkSetup setup = Benchmark::setup_benchmark(args);
const int numGoCommands = count_if(setup.commands.begin(), setup.commands.end(),
[](const std::string& s) { return s.find("go ") == 0; });
const auto numGoCommands = count_if(setup.commands.begin(), setup.commands.end(),
[](const std::string& s) { return s.find("go ") == 0; });
TimePoint totalTime = 0;
@@ -367,13 +367,14 @@ void UCIEngine::benchmark(std::istream& args) {
int numHashfullReadings = 0;
constexpr int hashfullAges[] = {0, 999}; // Only normal hashfull and touched hash.
int totalHashfull[std::size(hashfullAges)] = {0};
int maxHashfull[std::size(hashfullAges)] = {0};
constexpr int hashfullAgeCount = std::size(hashfullAges);
int totalHashfull[hashfullAgeCount] = {0};
int maxHashfull[hashfullAgeCount] = {0};
auto updateHashfullReadings = [&]() {
numHashfullReadings += 1;
for (int i = 0; i < static_cast<int>(std::size(hashfullAges)); ++i)
for (int i = 0; i < hashfullAgeCount; ++i)
{
const int hashfull = engine.get_hashfull(hashfullAges[i]);
maxHashfull[i] = std::max(maxHashfull[i], hashfull);
@@ -561,7 +562,7 @@ int UCIEngine::to_cp(Value v, const Position& pos) {
auto [a, b] = win_rate_params(pos);
return std::round(100 * int(v) / a);
return int(std::round(100 * int(v) / a));
}
std::string UCIEngine::wdl(Value v, const Position& pos) {