mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 08:43:09 +00:00
Only evaluate the PSQT part of the small net for large evals.
Thanks to Viren6 for suggesting to set complexity to 0. STC https://tests.stockfishchess.org/tests/view/65d7d6709b2da0226a5a203f LLR: 2.92 (-2.94,2.94) <0.00,2.00> Total: 328384 W: 85316 L: 84554 D: 158514 Ptnml(0-2): 1414, 39076, 82486, 39766, 1450 LTC https://tests.stockfishchess.org/tests/view/65dce6d290f639b028a54d2e LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 165162 W: 41918 L: 41330 D: 81914 Ptnml(0-2): 102, 18332, 45124, 18922, 101 closes https://github.com/official-stockfish/Stockfish/pull/5083 bench: 1504003
This commit is contained in:
parent
0a3eb1d8fa
commit
7831131591
6 changed files with 193 additions and 148 deletions
|
@ -194,11 +194,12 @@ Value Eval::evaluate(const Position& pos, int optimism) {
|
||||||
|
|
||||||
int simpleEval = simple_eval(pos, pos.side_to_move());
|
int simpleEval = simple_eval(pos, pos.side_to_move());
|
||||||
bool smallNet = std::abs(simpleEval) > 1050;
|
bool smallNet = std::abs(simpleEval) > 1050;
|
||||||
|
bool psqtOnly = std::abs(simpleEval) > 2500;
|
||||||
|
|
||||||
int nnueComplexity;
|
int nnueComplexity;
|
||||||
|
|
||||||
Value nnue = smallNet ? NNUE::evaluate<NNUE::Small>(pos, true, &nnueComplexity)
|
Value nnue = smallNet ? NNUE::evaluate<NNUE::Small>(pos, true, &nnueComplexity, psqtOnly)
|
||||||
: NNUE::evaluate<NNUE::Big>(pos, true, &nnueComplexity);
|
: NNUE::evaluate<NNUE::Big>(pos, true, &nnueComplexity, false);
|
||||||
|
|
||||||
// Blend optimism and eval with nnue complexity and material imbalance
|
// Blend optimism and eval with nnue complexity and material imbalance
|
||||||
optimism += optimism * (nnueComplexity + std::abs(simpleEval - nnue)) / 512;
|
optimism += optimism * (nnueComplexity + std::abs(simpleEval - nnue)) / 512;
|
||||||
|
|
|
@ -179,16 +179,16 @@ write_parameters(std::ostream& stream, NetSize netSize, const std::string& netDe
|
||||||
|
|
||||||
void hint_common_parent_position(const Position& pos) {
|
void hint_common_parent_position(const Position& pos) {
|
||||||
|
|
||||||
int simpleEval = simple_eval(pos, pos.side_to_move());
|
int simpleEvalAbs = std::abs(simple_eval(pos, pos.side_to_move()));
|
||||||
if (std::abs(simpleEval) > 1050)
|
if (simpleEvalAbs > 1050)
|
||||||
featureTransformerSmall->hint_common_access(pos);
|
featureTransformerSmall->hint_common_access(pos, simpleEvalAbs > 2500);
|
||||||
else
|
else
|
||||||
featureTransformerBig->hint_common_access(pos);
|
featureTransformerBig->hint_common_access(pos, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluation function. Perform differential calculation.
|
// Evaluation function. Perform differential calculation.
|
||||||
template<NetSize Net_Size>
|
template<NetSize Net_Size>
|
||||||
Value evaluate(const Position& pos, bool adjusted, int* complexity) {
|
Value evaluate(const Position& pos, bool adjusted, int* complexity, bool psqtOnly) {
|
||||||
|
|
||||||
// We manually align the arrays on the stack because with gcc < 9.3
|
// We manually align the arrays on the stack because with gcc < 9.3
|
||||||
// overaligning stack variables with alignas() doesn't work correctly.
|
// overaligning stack variables with alignas() doesn't work correctly.
|
||||||
|
@ -214,14 +214,18 @@ Value evaluate(const Position& pos, bool adjusted, int* complexity) {
|
||||||
ASSERT_ALIGNED(transformedFeatures, alignment);
|
ASSERT_ALIGNED(transformedFeatures, alignment);
|
||||||
|
|
||||||
const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
|
const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
|
||||||
const auto psqt = Net_Size == Small
|
const auto psqt =
|
||||||
? featureTransformerSmall->transform(pos, transformedFeatures, bucket)
|
Net_Size == Small
|
||||||
: featureTransformerBig->transform(pos, transformedFeatures, bucket);
|
? featureTransformerSmall->transform(pos, transformedFeatures, bucket, psqtOnly)
|
||||||
const auto positional = Net_Size == Small ? networkSmall[bucket]->propagate(transformedFeatures)
|
: featureTransformerBig->transform(pos, transformedFeatures, bucket, psqtOnly);
|
||||||
: networkBig[bucket]->propagate(transformedFeatures);
|
|
||||||
|
const auto positional =
|
||||||
|
!psqtOnly ? (Net_Size == Small ? networkSmall[bucket]->propagate(transformedFeatures)
|
||||||
|
: networkBig[bucket]->propagate(transformedFeatures))
|
||||||
|
: 0;
|
||||||
|
|
||||||
if (complexity)
|
if (complexity)
|
||||||
*complexity = std::abs(psqt - positional) / OutputScale;
|
*complexity = !psqtOnly ? std::abs(psqt - positional) / OutputScale : 0;
|
||||||
|
|
||||||
// Give more value to positional evaluation when adjusted flag is set
|
// Give more value to positional evaluation when adjusted flag is set
|
||||||
if (adjusted)
|
if (adjusted)
|
||||||
|
@ -231,8 +235,8 @@ Value evaluate(const Position& pos, bool adjusted, int* complexity) {
|
||||||
return static_cast<Value>((psqt + positional) / OutputScale);
|
return static_cast<Value>((psqt + positional) / OutputScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
template Value evaluate<Big>(const Position& pos, bool adjusted, int* complexity);
|
template Value evaluate<Big>(const Position& pos, bool adjusted, int* complexity, bool psqtOnly);
|
||||||
template Value evaluate<Small>(const Position& pos, bool adjusted, int* complexity);
|
template Value evaluate<Small>(const Position& pos, bool adjusted, int* complexity, bool psqtOnly);
|
||||||
|
|
||||||
struct NnueEvalTrace {
|
struct NnueEvalTrace {
|
||||||
static_assert(LayerStacks == PSQTBuckets);
|
static_assert(LayerStacks == PSQTBuckets);
|
||||||
|
@ -265,7 +269,8 @@ static NnueEvalTrace trace_evaluate(const Position& pos) {
|
||||||
t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4;
|
t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4;
|
||||||
for (IndexType bucket = 0; bucket < LayerStacks; ++bucket)
|
for (IndexType bucket = 0; bucket < LayerStacks; ++bucket)
|
||||||
{
|
{
|
||||||
const auto materialist = featureTransformerBig->transform(pos, transformedFeatures, bucket);
|
const auto materialist =
|
||||||
|
featureTransformerBig->transform(pos, transformedFeatures, bucket, false);
|
||||||
const auto positional = networkBig[bucket]->propagate(transformedFeatures);
|
const auto positional = networkBig[bucket]->propagate(transformedFeatures);
|
||||||
|
|
||||||
t.psqt[bucket] = static_cast<Value>(materialist / OutputScale);
|
t.psqt[bucket] = static_cast<Value>(materialist / OutputScale);
|
||||||
|
@ -370,16 +375,18 @@ std::string trace(Position& pos) {
|
||||||
auto st = pos.state();
|
auto st = pos.state();
|
||||||
|
|
||||||
pos.remove_piece(sq);
|
pos.remove_piece(sq);
|
||||||
st->accumulatorBig.computed[WHITE] = false;
|
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||||
st->accumulatorBig.computed[BLACK] = false;
|
st->accumulatorBig.computedPSQT[WHITE] = st->accumulatorBig.computedPSQT[BLACK] =
|
||||||
|
false;
|
||||||
|
|
||||||
Value eval = evaluate<NNUE::Big>(pos);
|
Value eval = evaluate<NNUE::Big>(pos);
|
||||||
eval = pos.side_to_move() == WHITE ? eval : -eval;
|
eval = pos.side_to_move() == WHITE ? eval : -eval;
|
||||||
v = base - eval;
|
v = base - eval;
|
||||||
|
|
||||||
pos.put_piece(pc, sq);
|
pos.put_piece(pc, sq);
|
||||||
st->accumulatorBig.computed[WHITE] = false;
|
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||||
st->accumulatorBig.computed[BLACK] = false;
|
st->accumulatorBig.computedPSQT[WHITE] = st->accumulatorBig.computedPSQT[BLACK] =
|
||||||
|
false;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSquare(f, r, pc, v);
|
writeSquare(f, r, pc, v);
|
||||||
|
|
|
@ -76,7 +76,10 @@ using LargePagePtr = std::unique_ptr<T, LargePageDeleter<T>>;
|
||||||
|
|
||||||
std::string trace(Position& pos);
|
std::string trace(Position& pos);
|
||||||
template<NetSize Net_Size>
|
template<NetSize Net_Size>
|
||||||
Value evaluate(const Position& pos, bool adjusted = false, int* complexity = nullptr);
|
Value evaluate(const Position& pos,
|
||||||
|
bool adjusted = false,
|
||||||
|
int* complexity = nullptr,
|
||||||
|
bool psqtOnly = false);
|
||||||
void hint_common_parent_position(const Position& pos);
|
void hint_common_parent_position(const Position& pos);
|
||||||
|
|
||||||
std::optional<std::string> load_eval(std::istream& stream, NetSize netSize);
|
std::optional<std::string> load_eval(std::istream& stream, NetSize netSize);
|
||||||
|
|
|
@ -34,6 +34,7 @@ struct alignas(CacheLineSize) Accumulator {
|
||||||
std::int16_t accumulation[2][Size];
|
std::int16_t accumulation[2][Size];
|
||||||
std::int32_t psqtAccumulation[2][PSQTBuckets];
|
std::int32_t psqtAccumulation[2][PSQTBuckets];
|
||||||
bool computed[2];
|
bool computed[2];
|
||||||
|
bool computedPSQT[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Stockfish::Eval::NNUE
|
} // namespace Stockfish::Eval::NNUE
|
||||||
|
|
|
@ -250,18 +250,21 @@ class FeatureTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert input features
|
// Convert input features
|
||||||
std::int32_t transform(const Position& pos, OutputType* output, int bucket) const {
|
std::int32_t
|
||||||
update_accumulator<WHITE>(pos);
|
transform(const Position& pos, OutputType* output, int bucket, bool psqtOnly) const {
|
||||||
update_accumulator<BLACK>(pos);
|
update_accumulator<WHITE>(pos, psqtOnly);
|
||||||
|
update_accumulator<BLACK>(pos, psqtOnly);
|
||||||
|
|
||||||
const Color perspectives[2] = {pos.side_to_move(), ~pos.side_to_move()};
|
const Color perspectives[2] = {pos.side_to_move(), ~pos.side_to_move()};
|
||||||
const auto& accumulation = (pos.state()->*accPtr).accumulation;
|
|
||||||
const auto& psqtAccumulation = (pos.state()->*accPtr).psqtAccumulation;
|
const auto& psqtAccumulation = (pos.state()->*accPtr).psqtAccumulation;
|
||||||
|
|
||||||
const auto psqt =
|
const auto psqt =
|
||||||
(psqtAccumulation[perspectives[0]][bucket] - psqtAccumulation[perspectives[1]][bucket])
|
(psqtAccumulation[perspectives[0]][bucket] - psqtAccumulation[perspectives[1]][bucket])
|
||||||
/ 2;
|
/ 2;
|
||||||
|
|
||||||
|
if (psqtOnly)
|
||||||
|
return psqt;
|
||||||
|
|
||||||
|
const auto& accumulation = (pos.state()->*accPtr).accumulation;
|
||||||
|
|
||||||
for (IndexType p = 0; p < 2; ++p)
|
for (IndexType p = 0; p < 2; ++p)
|
||||||
{
|
{
|
||||||
|
@ -312,20 +315,22 @@ class FeatureTransformer {
|
||||||
return psqt;
|
return psqt;
|
||||||
} // end of function transform()
|
} // end of function transform()
|
||||||
|
|
||||||
void hint_common_access(const Position& pos) const {
|
void hint_common_access(const Position& pos, bool psqtOnly) const {
|
||||||
hint_common_access_for_perspective<WHITE>(pos);
|
hint_common_access_for_perspective<WHITE>(pos, psqtOnly);
|
||||||
hint_common_access_for_perspective<BLACK>(pos);
|
hint_common_access_for_perspective<BLACK>(pos, psqtOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<Color Perspective>
|
template<Color Perspective>
|
||||||
[[nodiscard]] std::pair<StateInfo*, StateInfo*>
|
[[nodiscard]] std::pair<StateInfo*, StateInfo*>
|
||||||
try_find_computed_accumulator(const Position& pos) const {
|
try_find_computed_accumulator(const Position& pos, bool psqtOnly) const {
|
||||||
// Look for a usable accumulator of an earlier position. We keep track
|
// Look for a usable accumulator of an earlier position. We keep track
|
||||||
// of the estimated gain in terms of features to be added/subtracted.
|
// of the estimated gain in terms of features to be added/subtracted.
|
||||||
StateInfo *st = pos.state(), *next = nullptr;
|
StateInfo *st = pos.state(), *next = nullptr;
|
||||||
int gain = FeatureSet::refresh_cost(pos);
|
int gain = FeatureSet::refresh_cost(pos);
|
||||||
while (st->previous && !(st->*accPtr).computed[Perspective])
|
while (st->previous
|
||||||
|
&& (!(st->*accPtr).computedPSQT[Perspective]
|
||||||
|
|| (!psqtOnly && !(st->*accPtr).computed[Perspective])))
|
||||||
{
|
{
|
||||||
// This governs when a full feature refresh is needed and how many
|
// This governs when a full feature refresh is needed and how many
|
||||||
// updates are better than just one full refresh.
|
// updates are better than just one full refresh.
|
||||||
|
@ -347,7 +352,8 @@ class FeatureTransformer {
|
||||||
template<Color Perspective, size_t N>
|
template<Color Perspective, size_t N>
|
||||||
void update_accumulator_incremental(const Position& pos,
|
void update_accumulator_incremental(const Position& pos,
|
||||||
StateInfo* computed_st,
|
StateInfo* computed_st,
|
||||||
StateInfo* states_to_update[N]) const {
|
StateInfo* states_to_update[N],
|
||||||
|
bool psqtOnly) const {
|
||||||
static_assert(N > 0);
|
static_assert(N > 0);
|
||||||
assert(states_to_update[N - 1] == nullptr);
|
assert(states_to_update[N - 1] == nullptr);
|
||||||
|
|
||||||
|
@ -383,7 +389,8 @@ class FeatureTransformer {
|
||||||
|
|
||||||
for (; i >= 0; --i)
|
for (; i >= 0; --i)
|
||||||
{
|
{
|
||||||
(states_to_update[i]->*accPtr).computed[Perspective] = true;
|
(states_to_update[i]->*accPtr).computed[Perspective] = !psqtOnly;
|
||||||
|
(states_to_update[i]->*accPtr).computedPSQT[Perspective] = true;
|
||||||
|
|
||||||
const StateInfo* end_state = i == 0 ? computed_st : states_to_update[i - 1];
|
const StateInfo* end_state = i == 0 ? computed_st : states_to_update[i - 1];
|
||||||
|
|
||||||
|
@ -403,6 +410,8 @@ class FeatureTransformer {
|
||||||
{
|
{
|
||||||
assert(states_to_update[0]);
|
assert(states_to_update[0]);
|
||||||
|
|
||||||
|
if (!psqtOnly)
|
||||||
|
{
|
||||||
auto accIn =
|
auto accIn =
|
||||||
reinterpret_cast<const vec_t*>(&(st->*accPtr).accumulation[Perspective][0]);
|
reinterpret_cast<const vec_t*>(&(st->*accPtr).accumulation[Perspective][0]);
|
||||||
auto accOut = reinterpret_cast<vec_t*>(
|
auto accOut = reinterpret_cast<vec_t*>(
|
||||||
|
@ -429,6 +438,7 @@ class FeatureTransformer {
|
||||||
accOut[k] = vec_sub_16(vec_add_16(accIn[k], columnA[k]),
|
accOut[k] = vec_sub_16(vec_add_16(accIn[k], columnA[k]),
|
||||||
vec_add_16(columnR0[k], columnR1[k]));
|
vec_add_16(columnR0[k], columnR1[k]));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto accPsqtIn =
|
auto accPsqtIn =
|
||||||
reinterpret_cast<const psqt_vec_t*>(&(st->*accPtr).psqtAccumulation[Perspective][0]);
|
reinterpret_cast<const psqt_vec_t*>(&(st->*accPtr).psqtAccumulation[Perspective][0]);
|
||||||
|
@ -461,6 +471,7 @@ class FeatureTransformer {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!psqtOnly)
|
||||||
for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
|
for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
|
||||||
{
|
{
|
||||||
// Load accumulator
|
// Load accumulator
|
||||||
|
@ -490,8 +501,9 @@ class FeatureTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store accumulator
|
// Store accumulator
|
||||||
auto accTileOut = reinterpret_cast<vec_t*>(
|
auto accTileOut =
|
||||||
&(states_to_update[i]->*accPtr).accumulation[Perspective][j * TileHeight]);
|
reinterpret_cast<vec_t*>(&(states_to_update[i]->*accPtr)
|
||||||
|
.accumulation[Perspective][j * TileHeight]);
|
||||||
for (IndexType k = 0; k < NumRegs; ++k)
|
for (IndexType k = 0; k < NumRegs; ++k)
|
||||||
vec_store(&accTileOut[k], acc[k]);
|
vec_store(&accTileOut[k], acc[k]);
|
||||||
}
|
}
|
||||||
|
@ -537,8 +549,10 @@ class FeatureTransformer {
|
||||||
#else
|
#else
|
||||||
for (IndexType i = 0; states_to_update[i]; ++i)
|
for (IndexType i = 0; states_to_update[i]; ++i)
|
||||||
{
|
{
|
||||||
|
if (!psqtOnly)
|
||||||
std::memcpy((states_to_update[i]->*accPtr).accumulation[Perspective],
|
std::memcpy((states_to_update[i]->*accPtr).accumulation[Perspective],
|
||||||
(st->*accPtr).accumulation[Perspective], HalfDimensions * sizeof(BiasType));
|
(st->*accPtr).accumulation[Perspective],
|
||||||
|
HalfDimensions * sizeof(BiasType));
|
||||||
|
|
||||||
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
||||||
(states_to_update[i]->*accPtr).psqtAccumulation[Perspective][k] =
|
(states_to_update[i]->*accPtr).psqtAccumulation[Perspective][k] =
|
||||||
|
@ -548,11 +562,13 @@ class FeatureTransformer {
|
||||||
|
|
||||||
// Difference calculation for the deactivated features
|
// Difference calculation for the deactivated features
|
||||||
for (const auto index : removed[i])
|
for (const auto index : removed[i])
|
||||||
|
{
|
||||||
|
if (!psqtOnly)
|
||||||
{
|
{
|
||||||
const IndexType offset = HalfDimensions * index;
|
const IndexType offset = HalfDimensions * index;
|
||||||
|
|
||||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||||
(st->*accPtr).accumulation[Perspective][j] -= weights[offset + j];
|
(st->*accPtr).accumulation[Perspective][j] -= weights[offset + j];
|
||||||
|
}
|
||||||
|
|
||||||
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
||||||
(st->*accPtr).psqtAccumulation[Perspective][k] -=
|
(st->*accPtr).psqtAccumulation[Perspective][k] -=
|
||||||
|
@ -561,11 +577,13 @@ class FeatureTransformer {
|
||||||
|
|
||||||
// Difference calculation for the activated features
|
// Difference calculation for the activated features
|
||||||
for (const auto index : added[i])
|
for (const auto index : added[i])
|
||||||
|
{
|
||||||
|
if (!psqtOnly)
|
||||||
{
|
{
|
||||||
const IndexType offset = HalfDimensions * index;
|
const IndexType offset = HalfDimensions * index;
|
||||||
|
|
||||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||||
(st->*accPtr).accumulation[Perspective][j] += weights[offset + j];
|
(st->*accPtr).accumulation[Perspective][j] += weights[offset + j];
|
||||||
|
}
|
||||||
|
|
||||||
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
||||||
(st->*accPtr).psqtAccumulation[Perspective][k] +=
|
(st->*accPtr).psqtAccumulation[Perspective][k] +=
|
||||||
|
@ -576,7 +594,7 @@ class FeatureTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Color Perspective>
|
template<Color Perspective>
|
||||||
void update_accumulator_refresh(const Position& pos) const {
|
void update_accumulator_refresh(const Position& pos, bool psqtOnly) const {
|
||||||
#ifdef VECTOR
|
#ifdef VECTOR
|
||||||
// Gcc-10.2 unnecessarily spills AVX2 registers if this array
|
// Gcc-10.2 unnecessarily spills AVX2 registers if this array
|
||||||
// is defined in the VECTOR code below, once in each branch
|
// is defined in the VECTOR code below, once in each branch
|
||||||
|
@ -588,11 +606,13 @@ class FeatureTransformer {
|
||||||
// Could be extracted to a separate function because it's done in 2 places,
|
// Could be extracted to a separate function because it's done in 2 places,
|
||||||
// but it's unclear if compilers would correctly handle register allocation.
|
// but it's unclear if compilers would correctly handle register allocation.
|
||||||
auto& accumulator = pos.state()->*accPtr;
|
auto& accumulator = pos.state()->*accPtr;
|
||||||
accumulator.computed[Perspective] = true;
|
accumulator.computed[Perspective] = !psqtOnly;
|
||||||
|
accumulator.computedPSQT[Perspective] = true;
|
||||||
FeatureSet::IndexList active;
|
FeatureSet::IndexList active;
|
||||||
FeatureSet::append_active_indices<Perspective>(pos, active);
|
FeatureSet::append_active_indices<Perspective>(pos, active);
|
||||||
|
|
||||||
#ifdef VECTOR
|
#ifdef VECTOR
|
||||||
|
if (!psqtOnly)
|
||||||
for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
|
for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
|
||||||
{
|
{
|
||||||
auto biasesTile = reinterpret_cast<const vec_t*>(&biases[j * TileHeight]);
|
auto biasesTile = reinterpret_cast<const vec_t*>(&biases[j * TileHeight]);
|
||||||
|
@ -635,6 +655,7 @@ class FeatureTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
if (!psqtOnly)
|
||||||
std::memcpy(accumulator.accumulation[Perspective], biases,
|
std::memcpy(accumulator.accumulation[Perspective], biases,
|
||||||
HalfDimensions * sizeof(BiasType));
|
HalfDimensions * sizeof(BiasType));
|
||||||
|
|
||||||
|
@ -642,11 +663,13 @@ class FeatureTransformer {
|
||||||
accumulator.psqtAccumulation[Perspective][k] = 0;
|
accumulator.psqtAccumulation[Perspective][k] = 0;
|
||||||
|
|
||||||
for (const auto index : active)
|
for (const auto index : active)
|
||||||
|
{
|
||||||
|
if (!psqtOnly)
|
||||||
{
|
{
|
||||||
const IndexType offset = HalfDimensions * index;
|
const IndexType offset = HalfDimensions * index;
|
||||||
|
|
||||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||||
accumulator.accumulation[Perspective][j] += weights[offset + j];
|
accumulator.accumulation[Perspective][j] += weights[offset + j];
|
||||||
|
}
|
||||||
|
|
||||||
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
||||||
accumulator.psqtAccumulation[Perspective][k] +=
|
accumulator.psqtAccumulation[Perspective][k] +=
|
||||||
|
@ -656,7 +679,7 @@ class FeatureTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Color Perspective>
|
template<Color Perspective>
|
||||||
void hint_common_access_for_perspective(const Position& pos) const {
|
void hint_common_access_for_perspective(const Position& pos, bool psqtOnly) const {
|
||||||
|
|
||||||
// Works like update_accumulator, but performs less work.
|
// Works like update_accumulator, but performs less work.
|
||||||
// Updates ONLY the accumulator for pos.
|
// Updates ONLY the accumulator for pos.
|
||||||
|
@ -664,27 +687,31 @@ class FeatureTransformer {
|
||||||
// Look for a usable accumulator of an earlier position. We keep track
|
// Look for a usable accumulator of an earlier position. We keep track
|
||||||
// of the estimated gain in terms of features to be added/subtracted.
|
// of the estimated gain in terms of features to be added/subtracted.
|
||||||
// Fast early exit.
|
// Fast early exit.
|
||||||
if ((pos.state()->*accPtr).computed[Perspective])
|
if ((pos.state()->*accPtr).computed[Perspective]
|
||||||
|
|| (psqtOnly && (pos.state()->*accPtr).computedPSQT[Perspective]))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto [oldest_st, _] = try_find_computed_accumulator<Perspective>(pos);
|
auto [oldest_st, _] = try_find_computed_accumulator<Perspective>(pos, psqtOnly);
|
||||||
|
|
||||||
if ((oldest_st->*accPtr).computed[Perspective])
|
if ((oldest_st->*accPtr).computed[Perspective]
|
||||||
|
|| (psqtOnly && (oldest_st->*accPtr).computedPSQT[Perspective]))
|
||||||
{
|
{
|
||||||
// Only update current position accumulator to minimize work.
|
// Only update current position accumulator to minimize work.
|
||||||
StateInfo* states_to_update[2] = {pos.state(), nullptr};
|
StateInfo* states_to_update[2] = {pos.state(), nullptr};
|
||||||
update_accumulator_incremental<Perspective, 2>(pos, oldest_st, states_to_update);
|
update_accumulator_incremental<Perspective, 2>(pos, oldest_st, states_to_update,
|
||||||
|
psqtOnly);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
update_accumulator_refresh<Perspective>(pos);
|
update_accumulator_refresh<Perspective>(pos, psqtOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Color Perspective>
|
template<Color Perspective>
|
||||||
void update_accumulator(const Position& pos) const {
|
void update_accumulator(const Position& pos, bool psqtOnly) const {
|
||||||
|
|
||||||
auto [oldest_st, next] = try_find_computed_accumulator<Perspective>(pos);
|
auto [oldest_st, next] = try_find_computed_accumulator<Perspective>(pos, psqtOnly);
|
||||||
|
|
||||||
if ((oldest_st->*accPtr).computed[Perspective])
|
if ((oldest_st->*accPtr).computed[Perspective]
|
||||||
|
|| (psqtOnly && (oldest_st->*accPtr).computedPSQT[Perspective]))
|
||||||
{
|
{
|
||||||
if (next == nullptr)
|
if (next == nullptr)
|
||||||
return;
|
return;
|
||||||
|
@ -697,12 +724,11 @@ class FeatureTransformer {
|
||||||
StateInfo* states_to_update[3] = {next, next == pos.state() ? nullptr : pos.state(),
|
StateInfo* states_to_update[3] = {next, next == pos.state() ? nullptr : pos.state(),
|
||||||
nullptr};
|
nullptr};
|
||||||
|
|
||||||
update_accumulator_incremental<Perspective, 3>(pos, oldest_st, states_to_update);
|
update_accumulator_incremental<Perspective, 3>(pos, oldest_st, states_to_update,
|
||||||
|
psqtOnly);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
update_accumulator_refresh<Perspective>(pos, psqtOnly);
|
||||||
update_accumulator_refresh<Perspective>(pos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
alignas(CacheLineSize) BiasType biases[HalfDimensions];
|
alignas(CacheLineSize) BiasType biases[HalfDimensions];
|
||||||
|
|
|
@ -681,7 +681,11 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
||||||
|
|
||||||
// Used by NNUE
|
// Used by NNUE
|
||||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||||
st->accumulatorSmall.computed[WHITE] = st->accumulatorSmall.computed[BLACK] = false;
|
st->accumulatorBig.computedPSQT[WHITE] = st->accumulatorBig.computedPSQT[BLACK] =
|
||||||
|
st->accumulatorSmall.computed[WHITE] = st->accumulatorSmall.computed[BLACK] =
|
||||||
|
st->accumulatorSmall.computedPSQT[WHITE] = st->accumulatorSmall.computedPSQT[BLACK] =
|
||||||
|
false;
|
||||||
|
|
||||||
auto& dp = st->dirtyPiece;
|
auto& dp = st->dirtyPiece;
|
||||||
dp.dirty_num = 1;
|
dp.dirty_num = 1;
|
||||||
|
|
||||||
|
@ -968,7 +972,10 @@ void Position::do_null_move(StateInfo& newSt, TranspositionTable& tt) {
|
||||||
st->dirtyPiece.dirty_num = 0;
|
st->dirtyPiece.dirty_num = 0;
|
||||||
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
|
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
|
||||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||||
st->accumulatorSmall.computed[WHITE] = st->accumulatorSmall.computed[BLACK] = false;
|
st->accumulatorBig.computedPSQT[WHITE] = st->accumulatorBig.computedPSQT[BLACK] =
|
||||||
|
st->accumulatorSmall.computed[WHITE] = st->accumulatorSmall.computed[BLACK] =
|
||||||
|
st->accumulatorSmall.computedPSQT[WHITE] = st->accumulatorSmall.computedPSQT[BLACK] =
|
||||||
|
false;
|
||||||
|
|
||||||
if (st->epSquare != SQ_NONE)
|
if (st->epSquare != SQ_NONE)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue