Skip to content

Commit c065abd

Browse files
noobpwnftwvondele
authored andcommitted
Use incremental updates more often
Use incremental updates for accumulators for up to 2 plies. Do not copy accumulator. About 2% speedup. Passed STC: LLR: 2.95 (-2.94,2.94) {-0.25,1.25} Total: 21752 W: 2583 L: 2403 D: 16766 Ptnml(0-2): 128, 1761, 6923, 1931, 133 https://tests.stockfishchess.org/tests/view/5f7150cf3b22d6afa5069412 closes #3157 No functional change
1 parent 1dbd2a1 commit c065abd

File tree

4 files changed

+87
-30
lines changed

4 files changed

+87
-30
lines changed

src/nnue/features/feature_set.h

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -61,26 +61,69 @@ namespace Eval::NNUE::Features {
6161
const PositionType& pos, TriggerEvent trigger,
6262
IndexListType removed[2], IndexListType added[2], bool reset[2]) {
6363

64-
const auto& dp = pos.state()->dirtyPiece;
65-
if (dp.dirty_num == 0) return;
66-
67-
for (Color perspective : { WHITE, BLACK }) {
68-
reset[perspective] = false;
69-
switch (trigger) {
70-
case TriggerEvent::kFriendKingMoved:
71-
reset[perspective] = dp.piece[0] == make_piece(perspective, KING);
72-
break;
73-
default:
74-
assert(false);
75-
break;
64+
auto collect_for_one = [&](const DirtyPiece& dp) {
65+
for (Color perspective : { WHITE, BLACK }) {
66+
switch (trigger) {
67+
case TriggerEvent::kFriendKingMoved:
68+
reset[perspective] = dp.piece[0] == make_piece(perspective, KING);
69+
break;
70+
default:
71+
assert(false);
72+
break;
73+
}
74+
if (reset[perspective]) {
75+
Derived::CollectActiveIndices(
76+
pos, trigger, perspective, &added[perspective]);
77+
} else {
78+
Derived::CollectChangedIndices(
79+
pos, dp, trigger, perspective,
80+
&removed[perspective], &added[perspective]);
81+
}
7682
}
77-
if (reset[perspective]) {
78-
Derived::CollectActiveIndices(
79-
pos, trigger, perspective, &added[perspective]);
83+
};
84+
85+
auto collect_for_two = [&](const DirtyPiece& dp1, const DirtyPiece& dp2) {
86+
for (Color perspective : { WHITE, BLACK }) {
87+
switch (trigger) {
88+
case TriggerEvent::kFriendKingMoved:
89+
reset[perspective] = dp1.piece[0] == make_piece(perspective, KING)
90+
|| dp2.piece[0] == make_piece(perspective, KING);
91+
break;
92+
default:
93+
assert(false);
94+
break;
95+
}
96+
if (reset[perspective]) {
97+
Derived::CollectActiveIndices(
98+
pos, trigger, perspective, &added[perspective]);
99+
} else {
100+
Derived::CollectChangedIndices(
101+
pos, dp1, trigger, perspective,
102+
&removed[perspective], &added[perspective]);
103+
Derived::CollectChangedIndices(
104+
pos, dp2, trigger, perspective,
105+
&removed[perspective], &added[perspective]);
106+
}
107+
}
108+
};
109+
110+
if (pos.state()->previous->accumulator.computed_accumulation) {
111+
const auto& prev_dp = pos.state()->dirtyPiece;
112+
if (prev_dp.dirty_num == 0) return;
113+
collect_for_one(prev_dp);
114+
} else {
115+
const auto& prev_dp = pos.state()->previous->dirtyPiece;
116+
if (prev_dp.dirty_num == 0) {
117+
const auto& prev2_dp = pos.state()->dirtyPiece;
118+
if (prev2_dp.dirty_num == 0) return;
119+
collect_for_one(prev2_dp);
80120
} else {
81-
Derived::CollectChangedIndices(
82-
pos, trigger, perspective,
83-
&removed[perspective], &added[perspective]);
121+
const auto& prev2_dp = pos.state()->dirtyPiece;
122+
if (prev2_dp.dirty_num == 0) {
123+
collect_for_one(prev_dp);
124+
} else {
125+
collect_for_two(prev_dp, prev2_dp);
126+
}
84127
}
85128
}
86129
}
@@ -115,11 +158,11 @@ namespace Eval::NNUE::Features {
115158

116159
// Get a list of indices for recently changed features
117160
static void CollectChangedIndices(
118-
const Position& pos, const TriggerEvent trigger, const Color perspective,
161+
const Position& pos, const DirtyPiece& dp, const TriggerEvent trigger, const Color perspective,
119162
IndexList* const removed, IndexList* const added) {
120163

121164
if (FeatureType::kRefreshTrigger == trigger) {
122-
FeatureType::AppendChangedIndices(pos, perspective, removed, added);
165+
FeatureType::AppendChangedIndices(pos, dp, perspective, removed, added);
123166
}
124167
}
125168

src/nnue/features/half_kp.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,10 @@ namespace Eval::NNUE::Features {
5252
// Get a list of indices for recently changed features
5353
template <Side AssociatedKing>
5454
void HalfKP<AssociatedKing>::AppendChangedIndices(
55-
const Position& pos, Color perspective,
55+
const Position& pos, const DirtyPiece& dp, Color perspective,
5656
IndexList* removed, IndexList* added) {
5757

5858
Square ksq = orient(perspective, pos.square<KING>(perspective));
59-
const auto& dp = pos.state()->dirtyPiece;
6059
for (int i = 0; i < dp.dirty_num; ++i) {
6160
Piece pc = dp.piece[i];
6261
if (type_of(pc) == KING) continue;

src/nnue/features/half_kp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ namespace Eval::NNUE::Features {
5050
IndexList* active);
5151

5252
// Get a list of indices for recently changed features
53-
static void AppendChangedIndices(const Position& pos, Color perspective,
53+
static void AppendChangedIndices(const Position& pos, const DirtyPiece& dp, Color perspective,
5454
IndexList* removed, IndexList* added);
5555

5656
private:

src/nnue/nnue_feature_transformer.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,14 @@ namespace Eval::NNUE {
127127
return true;
128128

129129
const auto prev = now->previous;
130-
if (prev && prev->accumulator.computed_accumulation) {
131-
UpdateAccumulator(pos);
132-
return true;
130+
if (prev) {
131+
if (prev->accumulator.computed_accumulation) {
132+
UpdateAccumulator(pos);
133+
return true;
134+
} else if (prev->previous && prev->previous->accumulator.computed_accumulation) {
135+
UpdateAccumulator(pos);
136+
return true;
137+
}
133138
}
134139

135140
return false;
@@ -289,11 +294,21 @@ namespace Eval::NNUE {
289294
// Calculate cumulative value using difference calculation
290295
void UpdateAccumulator(const Position& pos) const {
291296

292-
const auto prev_accumulator = pos.state()->previous->accumulator;
297+
Accumulator* prev_accumulator;
298+
assert(pos.state()->previous);
299+
if (pos.state()->previous->accumulator.computed_accumulation) {
300+
prev_accumulator = &pos.state()->previous->accumulator;
301+
}
302+
else {
303+
assert(pos.state()->previous->previous);
304+
assert(pos.state()->previous->previous->accumulator.computed_accumulation);
305+
prev_accumulator = &pos.state()->previous->previous->accumulator;
306+
}
307+
293308
auto& accumulator = pos.state()->accumulator;
294309
IndexType i = 0;
295310
Features::IndexList removed_indices[2], added_indices[2];
296-
bool reset[2];
311+
bool reset[2] = { false, false };
297312
RawFeatures::AppendChangedIndices(pos, kRefreshTriggers[i],
298313
removed_indices, added_indices, reset);
299314

@@ -311,7 +326,7 @@ namespace Eval::NNUE {
311326
acc[k] = biasesTile[k];
312327
} else {
313328
auto prevAccTile = reinterpret_cast<const vec_t*>(
314-
&prev_accumulator.accumulation[perspective][i][j * kTileHeight]);
329+
&prev_accumulator->accumulation[perspective][i][j * kTileHeight]);
315330
for (IndexType k = 0; k < kNumRegs; ++k)
316331
acc[k] = vec_load(&prevAccTile[k]);
317332

@@ -350,7 +365,7 @@ namespace Eval::NNUE {
350365
kHalfDimensions * sizeof(BiasType));
351366
} else {
352367
std::memcpy(accumulator.accumulation[perspective][i],
353-
prev_accumulator.accumulation[perspective][i],
368+
prev_accumulator->accumulation[perspective][i],
354369
kHalfDimensions * sizeof(BiasType));
355370
// Difference calculation for the deactivated features
356371
for (const auto index : removed_indices[perspective]) {

0 commit comments

Comments
 (0)