Tweak nnue_accumulator indexing

```
LLR: 2.93 (-2.94,2.94) <0.00,2.00>
Total: 92736 W: 24149 L: 23764 D: 44823
Ptnml(0-2): 280, 10056, 25334, 10395, 303
```

The use of `IndexType` in the loops is suboptimal because it requires
truncation to 32 bits, and thereby defeats some optimizations. Using
`size_t` for the loop body works nicely, and a signed index into the
index lists allows the compiler to assume the case `added.size() ==
UINT_MAX`, which would be an infinite loop, to not happen.

Passed STC
https://tests.stockfishchess.org/tests/live_elo/692fd98ab23dfeae38d01d98

closes https://github.com/official-stockfish/Stockfish/pull/6466

No functional change
This commit is contained in:
Timothy Herchen
2025-12-21 15:43:32 +01:00
committed by Disservin
parent e1c919fd7e
commit e0e6fdf094
2 changed files with 62 additions and 52 deletions
+1
View File
@@ -134,6 +134,7 @@ class ValueList {
public: public:
std::size_t size() const { return size_; } std::size_t size() const { return size_; }
int ssize() const { return int(size_); }
void push_back(const T& value) { void push_back(const T& value) {
assert(size_ < MaxSize); assert(size_ < MaxSize);
values_[size_++] = value; values_[size_++] = value;
+56 -47
View File
@@ -360,6 +360,8 @@ struct AccumulatorUpdateContext {
vec_t acc[Tiling::NumRegs]; vec_t acc[Tiling::NumRegs];
psqt_vec_t psqt[Tiling::NumPsqtRegs]; psqt_vec_t psqt[Tiling::NumPsqtRegs];
const auto* threatWeights = &featureTransformer.threatWeights[0];
for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j) for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j)
{ {
auto* fromTile = reinterpret_cast<const vec_t*>(&fromAcc[j * Tiling::TileHeight]); 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) for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = fromTile[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]; size_t index = removed[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight; const size_t offset = Dimensions * index;
auto* column = auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
reinterpret_cast<const vec_i8_t*>(&featureTransformer.threatWeights[offset]);
#ifdef USE_NEON #ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2) for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
@@ -387,12 +388,11 @@ struct AccumulatorUpdateContext {
#endif #endif
} }
for (IndexType i = 0; i < added.size(); ++i) for (int i = 0; i < added.ssize(); ++i)
{ {
IndexType index = added[i]; size_t index = added[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight; const size_t offset = Dimensions * index;
auto* column = auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
reinterpret_cast<const vec_i8_t*>(&featureTransformer.threatWeights[offset]);
#ifdef USE_NEON #ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2) for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
@@ -408,6 +408,8 @@ struct AccumulatorUpdateContext {
for (IndexType k = 0; k < Tiling::NumRegs; k++) for (IndexType k = 0; k < Tiling::NumRegs; k++)
vec_store(&toTile[k], acc[k]); vec_store(&toTile[k], acc[k]);
threatWeights += Tiling::TileHeight;
} }
for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j) for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j)
@@ -420,10 +422,10 @@ struct AccumulatorUpdateContext {
for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k) for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = fromTilePsqt[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]; size_t index = removed[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>( auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
&featureTransformer.threatPsqtWeights[offset]); &featureTransformer.threatPsqtWeights[offset]);
@@ -431,10 +433,10 @@ struct AccumulatorUpdateContext {
psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[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]; size_t index = added[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>( auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
&featureTransformer.threatPsqtWeights[offset]); &featureTransformer.threatPsqtWeights[offset]);
@@ -691,6 +693,8 @@ void update_accumulator_refresh_cache(Color pers
vec_t acc[Tiling::NumRegs]; vec_t acc[Tiling::NumRegs];
psqt_vec_t psqt[Tiling::NumPsqtRegs]; psqt_vec_t psqt[Tiling::NumPsqtRegs];
const auto* weights = &featureTransformer.weights[0];
for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j) for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j)
{ {
auto* accTile = auto* accTile =
@@ -700,33 +704,33 @@ void update_accumulator_refresh_cache(Color pers
for (IndexType k = 0; k < Tiling::NumRegs; ++k) for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = entryTile[k]; acc[k] = entryTile[k];
IndexType i = 0; int i = 0;
for (; i < std::min(removed.size(), added.size()); ++i) for (; i < std::min(removed.ssize(), added.ssize()); ++i)
{ {
IndexType indexR = removed[i]; size_t indexR = removed[i];
const IndexType offsetR = Dimensions * indexR + j * Tiling::TileHeight; const size_t offsetR = Dimensions * indexR;
auto* columnR = reinterpret_cast<const vec_t*>(&featureTransformer.weights[offsetR]); auto* columnR = reinterpret_cast<const vec_t*>(&weights[offsetR]);
IndexType indexA = added[i]; size_t indexA = added[i];
const IndexType offsetA = Dimensions * indexA + j * Tiling::TileHeight; const size_t offsetA = Dimensions * indexA;
auto* columnA = reinterpret_cast<const vec_t*>(&featureTransformer.weights[offsetA]); auto* columnA = reinterpret_cast<const vec_t*>(&weights[offsetA]);
for (IndexType k = 0; k < Tiling::NumRegs; ++k) for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = fused<Vec16Wrapper, Add, Sub>(acc[k], columnA[k], columnR[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]; size_t index = removed[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight; const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_t*>(&featureTransformer.weights[offset]); auto* column = reinterpret_cast<const vec_t*>(&weights[offset]);
for (IndexType k = 0; k < Tiling::NumRegs; ++k) for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = vec_sub_16(acc[k], column[k]); acc[k] = vec_sub_16(acc[k], column[k]);
} }
for (; i < added.size(); ++i) for (; i < added.ssize(); ++i)
{ {
IndexType index = added[i]; size_t index = added[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight; const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_t*>(&featureTransformer.weights[offset]); auto* column = reinterpret_cast<const vec_t*>(&weights[offset]);
for (IndexType k = 0; k < Tiling::NumRegs; ++k) for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = vec_add_16(acc[k], column[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]); vec_store(&entryTile[k], acc[k]);
for (IndexType k = 0; k < Tiling::NumRegs; k++) for (IndexType k = 0; k < Tiling::NumRegs; k++)
vec_store(&accTile[k], acc[k]); vec_store(&accTile[k], acc[k]);
weights += Tiling::TileHeight;
} }
for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j) for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j)
@@ -748,20 +754,20 @@ void update_accumulator_refresh_cache(Color pers
for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k) for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = entryTilePsqt[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]; size_t index = removed[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = auto* columnPsqt =
reinterpret_cast<const psqt_vec_t*>(&featureTransformer.psqtWeights[offset]); reinterpret_cast<const psqt_vec_t*>(&featureTransformer.psqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k) for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[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]; size_t index = added[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = auto* columnPsqt =
reinterpret_cast<const psqt_vec_t*>(&featureTransformer.psqtWeights[offset]); reinterpret_cast<const psqt_vec_t*>(&featureTransformer.psqtWeights[offset]);
@@ -820,6 +826,8 @@ void update_threats_accumulator_full(Color persp
vec_t acc[Tiling::NumRegs]; vec_t acc[Tiling::NumRegs];
psqt_vec_t psqt[Tiling::NumPsqtRegs]; psqt_vec_t psqt[Tiling::NumPsqtRegs];
const auto* threatWeights = &featureTransformer.threatWeights[0];
for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j) for (IndexType j = 0; j < Dimensions / Tiling::TileHeight; ++j)
{ {
auto* accTile = auto* accTile =
@@ -828,14 +836,13 @@ void update_threats_accumulator_full(Color persp
for (IndexType k = 0; k < Tiling::NumRegs; ++k) for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = vec_zero(); acc[k] = vec_zero();
IndexType i = 0; int i = 0;
for (; i < active.size(); ++i) for (; i < active.ssize(); ++i)
{ {
IndexType index = active[i]; size_t index = active[i];
const IndexType offset = Dimensions * index + j * Tiling::TileHeight; const size_t offset = Dimensions * index;
auto* column = auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
reinterpret_cast<const vec_i8_t*>(&featureTransformer.threatWeights[offset]);
#ifdef USE_NEON #ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2) 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++) for (IndexType k = 0; k < Tiling::NumRegs; k++)
vec_store(&accTile[k], acc[k]); vec_store(&accTile[k], acc[k]);
threatWeights += Tiling::TileHeight;
} }
for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j) for (IndexType j = 0; j < PSQTBuckets / Tiling::PsqtTileHeight; ++j)
@@ -861,10 +870,10 @@ void update_threats_accumulator_full(Color persp
for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k) for (IndexType k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_zero_psqt(); 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]; size_t index = active[i];
const IndexType offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight; const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = auto* columnPsqt =
reinterpret_cast<const psqt_vec_t*>(&featureTransformer.threatPsqtWeights[offset]); reinterpret_cast<const psqt_vec_t*>(&featureTransformer.threatPsqtWeights[offset]);