mirror of
https://github.com/sockspls/badfish
synced 2025-04-29 16:23:09 +00:00
Remove PSQT-only mode
Passed STC: LLR: 2.94 (-2.94,2.94) <-1.75,0.25> Total: 94208 W: 24270 L: 24112 D: 45826 Ptnml(0-2): 286, 11186, 24009, 11330, 293 https://tests.stockfishchess.org/tests/view/6635ddd773559a8aa8582826 Passed LTC: LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 114960 W: 29107 L: 28982 D: 56871 Ptnml(0-2): 37, 12683, 31924, 12790, 46 https://tests.stockfishchess.org/tests/view/663604a973559a8aa85881ed closes #5214 Bench 1653939
This commit is contained in:
parent
be026bdcb2
commit
8ee9905d8b
8 changed files with 172 additions and 244 deletions
|
@ -56,13 +56,11 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks,
|
|||
|
||||
int simpleEval = simple_eval(pos, pos.side_to_move());
|
||||
bool smallNet = std::abs(simpleEval) > SmallNetThreshold;
|
||||
bool psqtOnly = std::abs(simpleEval) > PsqtOnlyThreshold;
|
||||
int nnueComplexity;
|
||||
int v;
|
||||
|
||||
Value nnue = smallNet
|
||||
? networks.small.evaluate(pos, &caches.small, true, &nnueComplexity, psqtOnly)
|
||||
: networks.big.evaluate(pos, &caches.big, true, &nnueComplexity, false);
|
||||
Value nnue = smallNet ? networks.small.evaluate(pos, &caches.small, true, &nnueComplexity)
|
||||
: networks.big.evaluate(pos, &caches.big, true, &nnueComplexity);
|
||||
|
||||
const auto adjustEval = [&](int optDiv, int nnueDiv, int pawnCountConstant, int pawnCountMul,
|
||||
int npmConstant, int evalDiv, int shufflingConstant,
|
||||
|
@ -83,8 +81,6 @@ Value Eval::evaluate(const Eval::NNUE::Networks& networks,
|
|||
|
||||
if (!smallNet)
|
||||
adjustEval(524, 32395, 942, 11, 139, 1058, 178, 204);
|
||||
else if (psqtOnly)
|
||||
adjustEval(517, 32857, 908, 7, 155, 1006, 224, 238);
|
||||
else
|
||||
adjustEval(515, 32793, 944, 9, 140, 1067, 206, 206);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class Position;
|
|||
|
||||
namespace Eval {
|
||||
|
||||
constexpr inline int SmallNetThreshold = 1274, PsqtOnlyThreshold = 2389;
|
||||
constexpr inline int SmallNetThreshold = 1274;
|
||||
|
||||
// The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue
|
||||
// for the build process (profile-build and fishtest) to work. Do not change the
|
||||
|
|
|
@ -189,8 +189,7 @@ template<typename Arch, typename Transformer>
|
|||
Value Network<Arch, Transformer>::evaluate(const Position& pos,
|
||||
AccumulatorCaches::Cache<FTDimensions>* cache,
|
||||
bool adjusted,
|
||||
int* complexity,
|
||||
bool psqtOnly) const {
|
||||
int* complexity) const {
|
||||
// We manually align the arrays on the stack because with gcc < 9.3
|
||||
// overaligning stack variables with alignas() doesn't work correctly.
|
||||
|
||||
|
@ -210,13 +209,12 @@ Value Network<Arch, Transformer>::evaluate(const Position&
|
|||
|
||||
ASSERT_ALIGNED(transformedFeatures, alignment);
|
||||
|
||||
const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
|
||||
const auto psqt =
|
||||
featureTransformer->transform(pos, cache, transformedFeatures, bucket, psqtOnly);
|
||||
const auto positional = !psqtOnly ? (network[bucket]->propagate(transformedFeatures)) : 0;
|
||||
const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
|
||||
const auto psqt = featureTransformer->transform(pos, cache, transformedFeatures, bucket);
|
||||
const auto positional = network[bucket]->propagate(transformedFeatures);
|
||||
|
||||
if (complexity)
|
||||
*complexity = !psqtOnly ? std::abs(psqt - positional) / OutputScale : 0;
|
||||
*complexity = std::abs(psqt - positional) / OutputScale;
|
||||
|
||||
// Give more value to positional evaluation when adjusted flag is set
|
||||
if (adjusted)
|
||||
|
@ -261,10 +259,9 @@ void Network<Arch, Transformer>::verify(std::string evalfilePath) const {
|
|||
|
||||
|
||||
template<typename Arch, typename Transformer>
|
||||
void Network<Arch, Transformer>::hint_common_access(const Position& pos,
|
||||
AccumulatorCaches::Cache<FTDimensions>* cache,
|
||||
bool psqtOnly) const {
|
||||
featureTransformer->hint_common_access(pos, cache, psqtOnly);
|
||||
void Network<Arch, Transformer>::hint_common_access(
|
||||
const Position& pos, AccumulatorCaches::Cache<FTDimensions>* cache) const {
|
||||
featureTransformer->hint_common_access(pos, cache);
|
||||
}
|
||||
|
||||
template<typename Arch, typename Transformer>
|
||||
|
@ -293,7 +290,7 @@ Network<Arch, Transformer>::trace_evaluate(const Position&
|
|||
for (IndexType bucket = 0; bucket < LayerStacks; ++bucket)
|
||||
{
|
||||
const auto materialist =
|
||||
featureTransformer->transform(pos, cache, transformedFeatures, bucket, false);
|
||||
featureTransformer->transform(pos, cache, transformedFeatures, bucket);
|
||||
const auto positional = network[bucket]->propagate(transformedFeatures);
|
||||
|
||||
t.psqt[bucket] = static_cast<Value>(materialist / OutputScale);
|
||||
|
|
|
@ -56,13 +56,11 @@ class Network {
|
|||
Value evaluate(const Position& pos,
|
||||
AccumulatorCaches::Cache<FTDimensions>* cache,
|
||||
bool adjusted = false,
|
||||
int* complexity = nullptr,
|
||||
bool psqtOnly = false) const;
|
||||
int* complexity = nullptr) const;
|
||||
|
||||
|
||||
void hint_common_access(const Position& pos,
|
||||
AccumulatorCaches::Cache<FTDimensions>* cache,
|
||||
bool psqtOnly) const;
|
||||
AccumulatorCaches::Cache<FTDimensions>* cache) const;
|
||||
|
||||
void verify(std::string evalfilePath) const;
|
||||
NnueEvalTrace trace_evaluate(const Position& pos,
|
||||
|
|
|
@ -38,7 +38,6 @@ struct alignas(CacheLineSize) Accumulator {
|
|||
std::int16_t accumulation[COLOR_NB][Size];
|
||||
std::int32_t psqtAccumulation[COLOR_NB][PSQTBuckets];
|
||||
bool computed[COLOR_NB];
|
||||
bool computedPSQT[COLOR_NB];
|
||||
};
|
||||
|
||||
|
||||
|
@ -63,7 +62,6 @@ struct AccumulatorCaches {
|
|||
PSQTWeightType psqtAccumulation[PSQTBuckets];
|
||||
Bitboard byColorBB[COLOR_NB];
|
||||
Bitboard byTypeBB[PIECE_TYPE_NB];
|
||||
bool psqtOnly;
|
||||
|
||||
// To initialize a refresh entry, we set all its bitboards empty,
|
||||
// so we put the biases in the accumulation, without any weights on top
|
||||
|
|
|
@ -309,10 +309,9 @@ class FeatureTransformer {
|
|||
std::int32_t transform(const Position& pos,
|
||||
AccumulatorCaches::Cache<HalfDimensions>* cache,
|
||||
OutputType* output,
|
||||
int bucket,
|
||||
bool psqtOnly) const {
|
||||
update_accumulator<WHITE>(pos, cache, psqtOnly);
|
||||
update_accumulator<BLACK>(pos, cache, psqtOnly);
|
||||
int bucket) const {
|
||||
update_accumulator<WHITE>(pos, cache);
|
||||
update_accumulator<BLACK>(pos, cache);
|
||||
|
||||
const Color perspectives[2] = {pos.side_to_move(), ~pos.side_to_move()};
|
||||
const auto& psqtAccumulation = (pos.state()->*accPtr).psqtAccumulation;
|
||||
|
@ -320,9 +319,6 @@ class FeatureTransformer {
|
|||
(psqtAccumulation[perspectives[0]][bucket] - psqtAccumulation[perspectives[1]][bucket])
|
||||
/ 2;
|
||||
|
||||
if (psqtOnly)
|
||||
return psqt;
|
||||
|
||||
const auto& accumulation = (pos.state()->*accPtr).accumulation;
|
||||
|
||||
for (IndexType p = 0; p < 2; ++p)
|
||||
|
@ -375,23 +371,20 @@ class FeatureTransformer {
|
|||
} // end of function transform()
|
||||
|
||||
void hint_common_access(const Position& pos,
|
||||
AccumulatorCaches::Cache<HalfDimensions>* cache,
|
||||
bool psqtOnly) const {
|
||||
hint_common_access_for_perspective<WHITE>(pos, cache, psqtOnly);
|
||||
hint_common_access_for_perspective<BLACK>(pos, cache, psqtOnly);
|
||||
AccumulatorCaches::Cache<HalfDimensions>* cache) const {
|
||||
hint_common_access_for_perspective<WHITE>(pos, cache);
|
||||
hint_common_access_for_perspective<BLACK>(pos, cache);
|
||||
}
|
||||
|
||||
private:
|
||||
template<Color Perspective>
|
||||
[[nodiscard]] std::pair<StateInfo*, StateInfo*>
|
||||
try_find_computed_accumulator(const Position& pos, bool psqtOnly) const {
|
||||
try_find_computed_accumulator(const Position& pos) const {
|
||||
// Look for a usable accumulator of an earlier position. We keep track
|
||||
// of the estimated gain in terms of features to be added/subtracted.
|
||||
StateInfo *st = pos.state(), *next = nullptr;
|
||||
int gain = FeatureSet::refresh_cost(pos);
|
||||
while (st->previous
|
||||
&& (!(st->*accPtr).computedPSQT[Perspective]
|
||||
|| (!psqtOnly && !(st->*accPtr).computed[Perspective])))
|
||||
while (st->previous && !(st->*accPtr).computed[Perspective])
|
||||
{
|
||||
// This governs when a full feature refresh is needed and how many
|
||||
// updates are better than just one full refresh.
|
||||
|
@ -412,8 +405,7 @@ class FeatureTransformer {
|
|||
template<Color Perspective, size_t N>
|
||||
void update_accumulator_incremental(const Position& pos,
|
||||
StateInfo* computed_st,
|
||||
StateInfo* states_to_update[N],
|
||||
bool psqtOnly) const {
|
||||
StateInfo* states_to_update[N]) const {
|
||||
static_assert(N > 0);
|
||||
assert([&]() {
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
|
@ -443,8 +435,7 @@ class FeatureTransformer {
|
|||
|
||||
for (int i = N - 1; i >= 0; --i)
|
||||
{
|
||||
(states_to_update[i]->*accPtr).computed[Perspective] = !psqtOnly;
|
||||
(states_to_update[i]->*accPtr).computedPSQT[Perspective] = true;
|
||||
(states_to_update[i]->*accPtr).computed[Perspective] = true;
|
||||
|
||||
const StateInfo* end_state = i == 0 ? computed_st : states_to_update[i - 1];
|
||||
|
||||
|
@ -462,34 +453,31 @@ class FeatureTransformer {
|
|||
{
|
||||
assert(states_to_update[0]);
|
||||
|
||||
if (!psqtOnly)
|
||||
auto accIn =
|
||||
reinterpret_cast<const vec_t*>(&(st->*accPtr).accumulation[Perspective][0]);
|
||||
auto accOut = reinterpret_cast<vec_t*>(
|
||||
&(states_to_update[0]->*accPtr).accumulation[Perspective][0]);
|
||||
|
||||
const IndexType offsetR0 = HalfDimensions * removed[0][0];
|
||||
auto columnR0 = reinterpret_cast<const vec_t*>(&weights[offsetR0]);
|
||||
const IndexType offsetA = HalfDimensions * added[0][0];
|
||||
auto columnA = reinterpret_cast<const vec_t*>(&weights[offsetA]);
|
||||
|
||||
if (removed[0].size() == 1)
|
||||
{
|
||||
auto accIn =
|
||||
reinterpret_cast<const vec_t*>(&(st->*accPtr).accumulation[Perspective][0]);
|
||||
auto accOut = reinterpret_cast<vec_t*>(
|
||||
&(states_to_update[0]->*accPtr).accumulation[Perspective][0]);
|
||||
for (IndexType k = 0; k < HalfDimensions * sizeof(std::int16_t) / sizeof(vec_t);
|
||||
++k)
|
||||
accOut[k] = vec_add_16(vec_sub_16(accIn[k], columnR0[k]), columnA[k]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const IndexType offsetR1 = HalfDimensions * removed[0][1];
|
||||
auto columnR1 = reinterpret_cast<const vec_t*>(&weights[offsetR1]);
|
||||
|
||||
const IndexType offsetR0 = HalfDimensions * removed[0][0];
|
||||
auto columnR0 = reinterpret_cast<const vec_t*>(&weights[offsetR0]);
|
||||
const IndexType offsetA = HalfDimensions * added[0][0];
|
||||
auto columnA = reinterpret_cast<const vec_t*>(&weights[offsetA]);
|
||||
|
||||
if (removed[0].size() == 1)
|
||||
{
|
||||
for (IndexType k = 0; k < HalfDimensions * sizeof(std::int16_t) / sizeof(vec_t);
|
||||
++k)
|
||||
accOut[k] = vec_add_16(vec_sub_16(accIn[k], columnR0[k]), columnA[k]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const IndexType offsetR1 = HalfDimensions * removed[0][1];
|
||||
auto columnR1 = reinterpret_cast<const vec_t*>(&weights[offsetR1]);
|
||||
|
||||
for (IndexType k = 0; k < HalfDimensions * sizeof(std::int16_t) / sizeof(vec_t);
|
||||
++k)
|
||||
accOut[k] = vec_sub_16(vec_add_16(accIn[k], columnA[k]),
|
||||
vec_add_16(columnR0[k], columnR1[k]));
|
||||
}
|
||||
for (IndexType k = 0; k < HalfDimensions * sizeof(std::int16_t) / sizeof(vec_t);
|
||||
++k)
|
||||
accOut[k] = vec_sub_16(vec_add_16(accIn[k], columnA[k]),
|
||||
vec_add_16(columnR0[k], columnR1[k]));
|
||||
}
|
||||
|
||||
auto accPsqtIn =
|
||||
|
@ -523,43 +511,41 @@ class FeatureTransformer {
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!psqtOnly)
|
||||
for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
|
||||
for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
|
||||
{
|
||||
// Load accumulator
|
||||
auto accTileIn = reinterpret_cast<const vec_t*>(
|
||||
&(st->*accPtr).accumulation[Perspective][j * TileHeight]);
|
||||
for (IndexType k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_load(&accTileIn[k]);
|
||||
|
||||
for (IndexType i = 0; i < N; ++i)
|
||||
{
|
||||
// Load accumulator
|
||||
auto accTileIn = reinterpret_cast<const vec_t*>(
|
||||
&(st->*accPtr).accumulation[Perspective][j * TileHeight]);
|
||||
for (IndexType k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_load(&accTileIn[k]);
|
||||
|
||||
for (IndexType i = 0; i < N; ++i)
|
||||
// Difference calculation for the deactivated features
|
||||
for (const auto index : removed[i])
|
||||
{
|
||||
// Difference calculation for the deactivated features
|
||||
for (const auto index : removed[i])
|
||||
{
|
||||
const IndexType offset = HalfDimensions * index + j * TileHeight;
|
||||
auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
|
||||
for (IndexType k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_sub_16(acc[k], column[k]);
|
||||
}
|
||||
|
||||
// Difference calculation for the activated features
|
||||
for (const auto index : added[i])
|
||||
{
|
||||
const IndexType offset = HalfDimensions * index + j * TileHeight;
|
||||
auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
|
||||
for (IndexType k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_add_16(acc[k], column[k]);
|
||||
}
|
||||
|
||||
// Store accumulator
|
||||
auto accTileOut =
|
||||
reinterpret_cast<vec_t*>(&(states_to_update[i]->*accPtr)
|
||||
.accumulation[Perspective][j * TileHeight]);
|
||||
const IndexType offset = HalfDimensions * index + j * TileHeight;
|
||||
auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
|
||||
for (IndexType k = 0; k < NumRegs; ++k)
|
||||
vec_store(&accTileOut[k], acc[k]);
|
||||
acc[k] = vec_sub_16(acc[k], column[k]);
|
||||
}
|
||||
|
||||
// Difference calculation for the activated features
|
||||
for (const auto index : added[i])
|
||||
{
|
||||
const IndexType offset = HalfDimensions * index + j * TileHeight;
|
||||
auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
|
||||
for (IndexType k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_add_16(acc[k], column[k]);
|
||||
}
|
||||
|
||||
// Store accumulator
|
||||
auto accTileOut = reinterpret_cast<vec_t*>(
|
||||
&(states_to_update[i]->*accPtr).accumulation[Perspective][j * TileHeight]);
|
||||
for (IndexType k = 0; k < NumRegs; ++k)
|
||||
vec_store(&accTileOut[k], acc[k]);
|
||||
}
|
||||
}
|
||||
|
||||
for (IndexType j = 0; j < PSQTBuckets / PsqtTileHeight; ++j)
|
||||
{
|
||||
|
@ -601,10 +587,8 @@ class FeatureTransformer {
|
|||
#else
|
||||
for (IndexType i = 0; i < N; ++i)
|
||||
{
|
||||
if (!psqtOnly)
|
||||
std::memcpy((states_to_update[i]->*accPtr).accumulation[Perspective],
|
||||
(st->*accPtr).accumulation[Perspective],
|
||||
HalfDimensions * sizeof(BiasType));
|
||||
std::memcpy((states_to_update[i]->*accPtr).accumulation[Perspective],
|
||||
(st->*accPtr).accumulation[Perspective], HalfDimensions * sizeof(BiasType));
|
||||
|
||||
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
||||
(states_to_update[i]->*accPtr).psqtAccumulation[Perspective][k] =
|
||||
|
@ -615,12 +599,9 @@ class FeatureTransformer {
|
|||
// Difference calculation for the deactivated features
|
||||
for (const auto index : removed[i])
|
||||
{
|
||||
if (!psqtOnly)
|
||||
{
|
||||
const IndexType offset = HalfDimensions * index;
|
||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||
(st->*accPtr).accumulation[Perspective][j] -= weights[offset + j];
|
||||
}
|
||||
const IndexType offset = HalfDimensions * index;
|
||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||
(st->*accPtr).accumulation[Perspective][j] -= weights[offset + j];
|
||||
|
||||
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
||||
(st->*accPtr).psqtAccumulation[Perspective][k] -=
|
||||
|
@ -630,12 +611,9 @@ class FeatureTransformer {
|
|||
// Difference calculation for the activated features
|
||||
for (const auto index : added[i])
|
||||
{
|
||||
if (!psqtOnly)
|
||||
{
|
||||
const IndexType offset = HalfDimensions * index;
|
||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||
(st->*accPtr).accumulation[Perspective][j] += weights[offset + j];
|
||||
}
|
||||
const IndexType offset = HalfDimensions * index;
|
||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||
(st->*accPtr).accumulation[Perspective][j] += weights[offset + j];
|
||||
|
||||
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
||||
(st->*accPtr).psqtAccumulation[Perspective][k] +=
|
||||
|
@ -647,95 +625,84 @@ class FeatureTransformer {
|
|||
|
||||
template<Color Perspective>
|
||||
void update_accumulator_refresh_cache(const Position& pos,
|
||||
AccumulatorCaches::Cache<HalfDimensions>* cache,
|
||||
bool psqtOnly) const {
|
||||
AccumulatorCaches::Cache<HalfDimensions>* cache) const {
|
||||
assert(cache != nullptr);
|
||||
|
||||
Square ksq = pos.square<KING>(Perspective);
|
||||
auto& entry = (*cache)[ksq][Perspective];
|
||||
FeatureSet::IndexList removed, added;
|
||||
|
||||
if (entry.psqtOnly && !psqtOnly)
|
||||
for (Color c : {WHITE, BLACK})
|
||||
{
|
||||
entry.clear(biases);
|
||||
FeatureSet::append_active_indices<Perspective>(pos, added);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Color c : {WHITE, BLACK})
|
||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||
{
|
||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||
{
|
||||
const Piece piece = make_piece(c, pt);
|
||||
const Bitboard oldBB = entry.byColorBB[c] & entry.byTypeBB[pt];
|
||||
const Bitboard newBB = pos.pieces(c, pt);
|
||||
Bitboard toRemove = oldBB & ~newBB;
|
||||
Bitboard toAdd = newBB & ~oldBB;
|
||||
const Piece piece = make_piece(c, pt);
|
||||
const Bitboard oldBB = entry.byColorBB[c] & entry.byTypeBB[pt];
|
||||
const Bitboard newBB = pos.pieces(c, pt);
|
||||
Bitboard toRemove = oldBB & ~newBB;
|
||||
Bitboard toAdd = newBB & ~oldBB;
|
||||
|
||||
while (toRemove)
|
||||
{
|
||||
Square sq = pop_lsb(toRemove);
|
||||
removed.push_back(FeatureSet::make_index<Perspective>(sq, piece, ksq));
|
||||
}
|
||||
while (toAdd)
|
||||
{
|
||||
Square sq = pop_lsb(toAdd);
|
||||
added.push_back(FeatureSet::make_index<Perspective>(sq, piece, ksq));
|
||||
}
|
||||
while (toRemove)
|
||||
{
|
||||
Square sq = pop_lsb(toRemove);
|
||||
removed.push_back(FeatureSet::make_index<Perspective>(sq, piece, ksq));
|
||||
}
|
||||
while (toAdd)
|
||||
{
|
||||
Square sq = pop_lsb(toAdd);
|
||||
added.push_back(FeatureSet::make_index<Perspective>(sq, piece, ksq));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto& accumulator = pos.state()->*accPtr;
|
||||
accumulator.computed[Perspective] = !psqtOnly;
|
||||
accumulator.computedPSQT[Perspective] = true;
|
||||
auto& accumulator = pos.state()->*accPtr;
|
||||
accumulator.computed[Perspective] = true;
|
||||
|
||||
#ifdef VECTOR
|
||||
vec_t acc[NumRegs];
|
||||
psqt_vec_t psqt[NumPsqtRegs];
|
||||
|
||||
if (!psqtOnly)
|
||||
for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
|
||||
for (IndexType j = 0; j < HalfDimensions / TileHeight; ++j)
|
||||
{
|
||||
auto entryTile = reinterpret_cast<vec_t*>(&entry.accumulation[j * TileHeight]);
|
||||
for (IndexType k = 0; k < NumRegs; ++k)
|
||||
acc[k] = entryTile[k];
|
||||
|
||||
int i0 = 0;
|
||||
for (; i0 < int(std::min(removed.size(), added.size())); ++i0)
|
||||
{
|
||||
auto entryTile = reinterpret_cast<vec_t*>(&entry.accumulation[j * TileHeight]);
|
||||
for (IndexType k = 0; k < NumRegs; ++k)
|
||||
acc[k] = entryTile[k];
|
||||
IndexType indexR = removed[i0];
|
||||
const IndexType offsetR = HalfDimensions * indexR + j * TileHeight;
|
||||
auto columnR = reinterpret_cast<const vec_t*>(&weights[offsetR]);
|
||||
IndexType indexA = added[i0];
|
||||
const IndexType offsetA = HalfDimensions * indexA + j * TileHeight;
|
||||
auto columnA = reinterpret_cast<const vec_t*>(&weights[offsetA]);
|
||||
|
||||
int i0 = 0;
|
||||
for (; i0 < int(std::min(removed.size(), added.size())); ++i0)
|
||||
{
|
||||
IndexType indexR = removed[i0];
|
||||
const IndexType offsetR = HalfDimensions * indexR + j * TileHeight;
|
||||
auto columnR = reinterpret_cast<const vec_t*>(&weights[offsetR]);
|
||||
IndexType indexA = added[i0];
|
||||
const IndexType offsetA = HalfDimensions * indexA + j * TileHeight;
|
||||
auto columnA = reinterpret_cast<const vec_t*>(&weights[offsetA]);
|
||||
|
||||
for (unsigned k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_add_16(vec_sub_16(acc[k], columnR[k]), columnA[k]);
|
||||
}
|
||||
for (int i = i0; i < int(removed.size()); ++i)
|
||||
{
|
||||
IndexType index = removed[i];
|
||||
const IndexType offset = HalfDimensions * index + j * TileHeight;
|
||||
auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
|
||||
|
||||
for (unsigned k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_sub_16(acc[k], column[k]);
|
||||
}
|
||||
for (int i = i0; i < int(added.size()); ++i)
|
||||
{
|
||||
IndexType index = added[i];
|
||||
const IndexType offset = HalfDimensions * index + j * TileHeight;
|
||||
auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
|
||||
|
||||
for (unsigned k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_add_16(acc[k], column[k]);
|
||||
}
|
||||
|
||||
for (IndexType k = 0; k < NumRegs; k++)
|
||||
vec_store(&entryTile[k], acc[k]);
|
||||
for (unsigned k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_add_16(vec_sub_16(acc[k], columnR[k]), columnA[k]);
|
||||
}
|
||||
for (int i = i0; i < int(removed.size()); ++i)
|
||||
{
|
||||
IndexType index = removed[i];
|
||||
const IndexType offset = HalfDimensions * index + j * TileHeight;
|
||||
auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
|
||||
|
||||
for (unsigned k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_sub_16(acc[k], column[k]);
|
||||
}
|
||||
for (int i = i0; i < int(added.size()); ++i)
|
||||
{
|
||||
IndexType index = added[i];
|
||||
const IndexType offset = HalfDimensions * index + j * TileHeight;
|
||||
auto column = reinterpret_cast<const vec_t*>(&weights[offset]);
|
||||
|
||||
for (unsigned k = 0; k < NumRegs; ++k)
|
||||
acc[k] = vec_add_16(acc[k], column[k]);
|
||||
}
|
||||
|
||||
for (IndexType k = 0; k < NumRegs; k++)
|
||||
vec_store(&entryTile[k], acc[k]);
|
||||
}
|
||||
|
||||
for (IndexType j = 0; j < PSQTBuckets / PsqtTileHeight; ++j)
|
||||
{
|
||||
|
@ -771,24 +738,18 @@ class FeatureTransformer {
|
|||
|
||||
for (const auto index : removed)
|
||||
{
|
||||
if (!psqtOnly)
|
||||
{
|
||||
const IndexType offset = HalfDimensions * index;
|
||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||
entry.accumulation[j] -= weights[offset + j];
|
||||
}
|
||||
const IndexType offset = HalfDimensions * index;
|
||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||
entry.accumulation[j] -= weights[offset + j];
|
||||
|
||||
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
||||
entry.psqtAccumulation[k] -= psqtWeights[index * PSQTBuckets + k];
|
||||
}
|
||||
for (const auto index : added)
|
||||
{
|
||||
if (!psqtOnly)
|
||||
{
|
||||
const IndexType offset = HalfDimensions * index;
|
||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||
entry.accumulation[j] += weights[offset + j];
|
||||
}
|
||||
const IndexType offset = HalfDimensions * index;
|
||||
for (IndexType j = 0; j < HalfDimensions; ++j)
|
||||
entry.accumulation[j] += weights[offset + j];
|
||||
|
||||
for (std::size_t k = 0; k < PSQTBuckets; ++k)
|
||||
entry.psqtAccumulation[k] += psqtWeights[index * PSQTBuckets + k];
|
||||
|
@ -799,9 +760,8 @@ class FeatureTransformer {
|
|||
// The accumulator of the refresh entry has been updated.
|
||||
// Now copy its content to the actual accumulator we were refreshing
|
||||
|
||||
if (!psqtOnly)
|
||||
std::memcpy(accumulator.accumulation[Perspective], entry.accumulation,
|
||||
sizeof(BiasType) * HalfDimensions);
|
||||
std::memcpy(accumulator.accumulation[Perspective], entry.accumulation,
|
||||
sizeof(BiasType) * HalfDimensions);
|
||||
|
||||
std::memcpy(accumulator.psqtAccumulation[Perspective], entry.psqtAccumulation,
|
||||
sizeof(int32_t) * PSQTBuckets);
|
||||
|
@ -811,14 +771,11 @@ class FeatureTransformer {
|
|||
|
||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||
entry.byTypeBB[pt] = pos.pieces(pt);
|
||||
|
||||
entry.psqtOnly = psqtOnly;
|
||||
}
|
||||
|
||||
template<Color Perspective>
|
||||
void hint_common_access_for_perspective(const Position& pos,
|
||||
AccumulatorCaches::Cache<HalfDimensions>* cache,
|
||||
bool psqtOnly) const {
|
||||
AccumulatorCaches::Cache<HalfDimensions>* cache) const {
|
||||
|
||||
// Works like update_accumulator, but performs less work.
|
||||
// Updates ONLY the accumulator for pos.
|
||||
|
@ -826,33 +783,28 @@ class FeatureTransformer {
|
|||
// Look for a usable accumulator of an earlier position. We keep track
|
||||
// of the estimated gain in terms of features to be added/subtracted.
|
||||
// Fast early exit.
|
||||
if ((pos.state()->*accPtr).computed[Perspective]
|
||||
|| (psqtOnly && (pos.state()->*accPtr).computedPSQT[Perspective]))
|
||||
if ((pos.state()->*accPtr).computed[Perspective])
|
||||
return;
|
||||
|
||||
auto [oldest_st, _] = try_find_computed_accumulator<Perspective>(pos, psqtOnly);
|
||||
auto [oldest_st, _] = try_find_computed_accumulator<Perspective>(pos);
|
||||
|
||||
if ((oldest_st->*accPtr).computed[Perspective]
|
||||
|| (psqtOnly && (oldest_st->*accPtr).computedPSQT[Perspective]))
|
||||
if ((oldest_st->*accPtr).computed[Perspective])
|
||||
{
|
||||
// Only update current position accumulator to minimize work.
|
||||
StateInfo* states_to_update[1] = {pos.state()};
|
||||
update_accumulator_incremental<Perspective, 1>(pos, oldest_st, states_to_update,
|
||||
psqtOnly);
|
||||
update_accumulator_incremental<Perspective, 1>(pos, oldest_st, states_to_update);
|
||||
}
|
||||
else
|
||||
update_accumulator_refresh_cache<Perspective>(pos, cache, psqtOnly);
|
||||
update_accumulator_refresh_cache<Perspective>(pos, cache);
|
||||
}
|
||||
|
||||
template<Color Perspective>
|
||||
void update_accumulator(const Position& pos,
|
||||
AccumulatorCaches::Cache<HalfDimensions>* cache,
|
||||
bool psqtOnly) const {
|
||||
AccumulatorCaches::Cache<HalfDimensions>* cache) const {
|
||||
|
||||
auto [oldest_st, next] = try_find_computed_accumulator<Perspective>(pos, psqtOnly);
|
||||
auto [oldest_st, next] = try_find_computed_accumulator<Perspective>(pos);
|
||||
|
||||
if ((oldest_st->*accPtr).computed[Perspective]
|
||||
|| (psqtOnly && (oldest_st->*accPtr).computedPSQT[Perspective]))
|
||||
if ((oldest_st->*accPtr).computed[Perspective])
|
||||
{
|
||||
if (next == nullptr)
|
||||
return;
|
||||
|
@ -866,19 +818,17 @@ class FeatureTransformer {
|
|||
{
|
||||
StateInfo* states_to_update[1] = {next};
|
||||
|
||||
update_accumulator_incremental<Perspective, 1>(pos, oldest_st, states_to_update,
|
||||
psqtOnly);
|
||||
update_accumulator_incremental<Perspective, 1>(pos, oldest_st, states_to_update);
|
||||
}
|
||||
else
|
||||
{
|
||||
StateInfo* states_to_update[2] = {next, pos.state()};
|
||||
|
||||
update_accumulator_incremental<Perspective, 2>(pos, oldest_st, states_to_update,
|
||||
psqtOnly);
|
||||
update_accumulator_incremental<Perspective, 2>(pos, oldest_st, states_to_update);
|
||||
}
|
||||
}
|
||||
else
|
||||
update_accumulator_refresh_cache<Perspective>(pos, cache, psqtOnly);
|
||||
update_accumulator_refresh_cache<Perspective>(pos, cache);
|
||||
}
|
||||
|
||||
template<IndexType Size>
|
||||
|
|
|
@ -48,10 +48,9 @@ void hint_common_parent_position(const Position& pos,
|
|||
|
||||
int simpleEvalAbs = std::abs(simple_eval(pos, pos.side_to_move()));
|
||||
if (simpleEvalAbs > Eval::SmallNetThreshold)
|
||||
networks.small.hint_common_access(pos, &caches.small,
|
||||
simpleEvalAbs > Eval::PsqtOnlyThreshold);
|
||||
networks.small.hint_common_access(pos, &caches.small);
|
||||
else
|
||||
networks.big.hint_common_access(pos, &caches.big, false);
|
||||
networks.big.hint_common_access(pos, &caches.big);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -149,18 +148,14 @@ trace(Position& pos, const Eval::NNUE::Networks& networks, Eval::NNUE::Accumulat
|
|||
auto st = pos.state();
|
||||
|
||||
pos.remove_piece(sq);
|
||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||
st->accumulatorBig.computedPSQT[WHITE] = st->accumulatorBig.computedPSQT[BLACK] =
|
||||
false;
|
||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] = false;
|
||||
|
||||
Value eval = networks.big.evaluate(pos, &caches.big);
|
||||
eval = pos.side_to_move() == WHITE ? eval : -eval;
|
||||
v = base - eval;
|
||||
|
||||
pos.put_piece(pc, sq);
|
||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||
st->accumulatorBig.computedPSQT[WHITE] = st->accumulatorBig.computedPSQT[BLACK] =
|
||||
false;
|
||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] = false;
|
||||
}
|
||||
|
||||
writeSquare(f, r, pc, v);
|
||||
|
|
|
@ -680,11 +680,8 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) {
|
|||
++st->pliesFromNull;
|
||||
|
||||
// Used by NNUE
|
||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||
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;
|
||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||
st->accumulatorSmall.computed[WHITE] = st->accumulatorSmall.computed[BLACK] = false;
|
||||
|
||||
auto& dp = st->dirtyPiece;
|
||||
dp.dirty_num = 1;
|
||||
|
@ -968,13 +965,10 @@ void Position::do_null_move(StateInfo& newSt, TranspositionTable& tt) {
|
|||
newSt.previous = st;
|
||||
st = &newSt;
|
||||
|
||||
st->dirtyPiece.dirty_num = 0;
|
||||
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
|
||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||
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;
|
||||
st->dirtyPiece.dirty_num = 0;
|
||||
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
|
||||
st->accumulatorBig.computed[WHITE] = st->accumulatorBig.computed[BLACK] =
|
||||
st->accumulatorSmall.computed[WHITE] = st->accumulatorSmall.computed[BLACK] = false;
|
||||
|
||||
if (st->epSquare != SQ_NONE)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue