Use incremental updates more often
authornoobpwnftw <guo.bojun@gmail.com>
Sun, 27 Sep 2020 18:29:21 +0000 (02:29 +0800)
committerJoost VandeVondele <Joost.VandeVondele@gmail.com>
Mon, 28 Sep 2020 14:54:35 +0000 (16:54 +0200)
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 https://github.com/official-stockfish/Stockfish/pull/3157

No functional change

src/nnue/features/feature_set.h
src/nnue/features/half_kp.cpp
src/nnue/features/half_kp.h
src/nnue/nnue_feature_transformer.h

index 558a6b228779e38607793b94623ecc0c4516caba..26198114a3054e5c34aaa2f74a3ef19b2af40b5f 100644 (file)
@@ -61,26 +61,69 @@ namespace Eval::NNUE::Features {
         const PositionType& pos, TriggerEvent trigger,
         IndexListType removed[2], IndexListType added[2], bool reset[2]) {
 
-      const auto& dp = pos.state()->dirtyPiece;
-      if (dp.dirty_num == 0) return;
-
-      for (Color perspective : { WHITE, BLACK }) {
-        reset[perspective] = false;
-        switch (trigger) {
-          case TriggerEvent::kFriendKingMoved:
-            reset[perspective] = dp.piece[0] == make_piece(perspective, KING);
-            break;
-          default:
-            assert(false);
-            break;
+      auto collect_for_one = [&](const DirtyPiece& dp) {
+        for (Color perspective : { WHITE, BLACK }) {
+          switch (trigger) {
+            case TriggerEvent::kFriendKingMoved:
+              reset[perspective] = dp.piece[0] == make_piece(perspective, KING);
+              break;
+            default:
+              assert(false);
+              break;
+          }
+          if (reset[perspective]) {
+            Derived::CollectActiveIndices(
+                pos, trigger, perspective, &added[perspective]);
+          } else {
+            Derived::CollectChangedIndices(
+                pos, dp, trigger, perspective,
+                &removed[perspective], &added[perspective]);
+          }
         }
-        if (reset[perspective]) {
-          Derived::CollectActiveIndices(
-              pos, trigger, perspective, &added[perspective]);
+      };
+
+      auto collect_for_two = [&](const DirtyPiece& dp1, const DirtyPiece& dp2) {
+        for (Color perspective : { WHITE, BLACK }) {
+          switch (trigger) {
+            case TriggerEvent::kFriendKingMoved:
+              reset[perspective] = dp1.piece[0] == make_piece(perspective, KING)
+                                || dp2.piece[0] == make_piece(perspective, KING);
+              break;
+            default:
+              assert(false);
+              break;
+          }
+          if (reset[perspective]) {
+            Derived::CollectActiveIndices(
+                pos, trigger, perspective, &added[perspective]);
+          } else {
+            Derived::CollectChangedIndices(
+                pos, dp1, trigger, perspective,
+                &removed[perspective], &added[perspective]);
+            Derived::CollectChangedIndices(
+                pos, dp2, trigger, perspective,
+                &removed[perspective], &added[perspective]);
+          }
+        }
+      };
+
+      if (pos.state()->previous->accumulator.computed_accumulation) {
+        const auto& prev_dp = pos.state()->dirtyPiece;
+        if (prev_dp.dirty_num == 0) return;
+        collect_for_one(prev_dp);
+      } else {
+        const auto& prev_dp = pos.state()->previous->dirtyPiece;
+        if (prev_dp.dirty_num == 0) {
+          const auto& prev2_dp = pos.state()->dirtyPiece;
+          if (prev2_dp.dirty_num == 0) return;
+          collect_for_one(prev2_dp);
         } else {
-          Derived::CollectChangedIndices(
-              pos, trigger, perspective,
-              &removed[perspective], &added[perspective]);
+          const auto& prev2_dp = pos.state()->dirtyPiece;
+          if (prev2_dp.dirty_num == 0) {
+            collect_for_one(prev_dp);
+          } else {
+            collect_for_two(prev_dp, prev2_dp);
+          }
         }
       }
     }
@@ -115,11 +158,11 @@ namespace Eval::NNUE::Features {
 
     // Get a list of indices for recently changed features
     static void CollectChangedIndices(
-        const Position& pos, const TriggerEvent trigger, const Color perspective,
+        const Position& pos, const DirtyPiece& dp, const TriggerEvent trigger, const Color perspective,
         IndexList* const removed, IndexList* const added) {
 
       if (FeatureType::kRefreshTrigger == trigger) {
-        FeatureType::AppendChangedIndices(pos, perspective, removed, added);
+        FeatureType::AppendChangedIndices(pos, dp, perspective, removed, added);
       }
     }
 
index 88e384a3578cf6156fc24c6a9c00e5a4a753aca5..116157cc19d1b6e555fb39a39dd18ee1822fd9a3 100644 (file)
@@ -52,11 +52,10 @@ namespace Eval::NNUE::Features {
   // Get a list of indices for recently changed features
   template <Side AssociatedKing>
   void HalfKP<AssociatedKing>::AppendChangedIndices(
-      const Position& pos, Color perspective,
+      const Position& pos, const DirtyPiece& dp, Color perspective,
       IndexList* removed, IndexList* added) {
 
     Square ksq = orient(perspective, pos.square<KING>(perspective));
-    const auto& dp = pos.state()->dirtyPiece;
     for (int i = 0; i < dp.dirty_num; ++i) {
       Piece pc = dp.piece[i];
       if (type_of(pc) == KING) continue;
index ee6a8df39aecc305e1d7157a6a92068da5dd4e24..52a83eecf3b77bfa94b885a56bb6615e7496412d 100644 (file)
@@ -50,7 +50,7 @@ namespace Eval::NNUE::Features {
                                     IndexList* active);
 
     // Get a list of indices for recently changed features
-    static void AppendChangedIndices(const Position& pos, Color perspective,
+    static void AppendChangedIndices(const Position& pos, const DirtyPiece& dp, Color perspective,
                                      IndexList* removed, IndexList* added);
 
    private:
index e71ee60d45a5274c2d340d5b69a5195c482cdfdf..2f86d20a639b712d6a0bcc51e4d70f5c1c373dd0 100644 (file)
@@ -127,9 +127,14 @@ namespace Eval::NNUE {
         return true;
 
       const auto prev = now->previous;
-      if (prev && prev->accumulator.computed_accumulation) {
-        UpdateAccumulator(pos);
-        return true;
+      if (prev) {
+        if (prev->accumulator.computed_accumulation) {
+          UpdateAccumulator(pos);
+          return true;
+        } else if (prev->previous && prev->previous->accumulator.computed_accumulation) {
+          UpdateAccumulator(pos);
+          return true;
+        }
       }
 
       return false;
@@ -289,11 +294,21 @@ namespace Eval::NNUE {
     // Calculate cumulative value using difference calculation
     void UpdateAccumulator(const Position& pos) const {
 
-      const auto prev_accumulator = pos.state()->previous->accumulator;
+      Accumulator* prev_accumulator;
+      assert(pos.state()->previous);
+      if (pos.state()->previous->accumulator.computed_accumulation) {
+        prev_accumulator = &pos.state()->previous->accumulator;
+      }
+      else {
+        assert(pos.state()->previous->previous);
+        assert(pos.state()->previous->previous->accumulator.computed_accumulation);
+        prev_accumulator = &pos.state()->previous->previous->accumulator;
+      }
+
       auto& accumulator = pos.state()->accumulator;
       IndexType i = 0;
       Features::IndexList removed_indices[2], added_indices[2];
-      bool reset[2];
+      bool reset[2] = { false, false };
       RawFeatures::AppendChangedIndices(pos, kRefreshTriggers[i],
                                         removed_indices, added_indices, reset);
 
@@ -311,7 +326,7 @@ namespace Eval::NNUE {
               acc[k] = biasesTile[k];
           } else {
             auto prevAccTile = reinterpret_cast<const vec_t*>(
-                &prev_accumulator.accumulation[perspective][i][j * kTileHeight]);
+                &prev_accumulator->accumulation[perspective][i][j * kTileHeight]);
             for (IndexType k = 0; k < kNumRegs; ++k)
               acc[k] = vec_load(&prevAccTile[k]);
 
@@ -350,7 +365,7 @@ namespace Eval::NNUE {
                       kHalfDimensions * sizeof(BiasType));
         } else {
           std::memcpy(accumulator.accumulation[perspective][i],
-                      prev_accumulator.accumulation[perspective][i],
+                      prev_accumulator->accumulation[perspective][i],
                       kHalfDimensions * sizeof(BiasType));
           // Difference calculation for the deactivated features
           for (const auto index : removed_indices[perspective]) {