]> git.sesse.net Git - stockfish/commitdiff
Clean up and simplify some nnue code.
authormstembera <MissingEmail@email>
Thu, 24 Feb 2022 02:19:36 +0000 (18:19 -0800)
committerJoost VandeVondele <Joost.VandeVondele@gmail.com>
Fri, 25 Feb 2022 07:37:57 +0000 (08:37 +0100)
Remove some unnecessary code and it's execution during inference. Also the change on line 49 in nnue_architecture.h results in a more efficient SIMD code path through ClippedReLU::propagate().

passed STC:
https://tests.stockfishchess.org/tests/view/6217d3bfda649bba32ef25d5
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 12056 W: 3281 L: 3092 D: 5683
Ptnml(0-2): 55, 1213, 3312, 1384, 64

passed STC SMP:
https://tests.stockfishchess.org/tests/view/6217f344da649bba32ef295e
LLR: 2.94 (-2.94,2.94) <-2.25,0.25>
Total: 27376 W: 7295 L: 7137 D: 12944
Ptnml(0-2): 52, 2859, 7715, 3003, 59

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

No functional change

bench: 6820724

src/nnue/evaluate_nnue.cpp
src/nnue/layers/affine_transform.h
src/nnue/layers/clipped_relu.h
src/nnue/nnue_architecture.h
src/nnue/nnue_common.h
src/nnue/nnue_feature_transformer.h

index 0fd58462b78b9dc2bafe273e9bb5ac2498626511..9254e36f9ba9d7252bdf20e120980f24c5856e8e 100644 (file)
@@ -109,7 +109,7 @@ namespace Stockfish::Eval::NNUE {
   {
     write_little_endian<std::uint32_t>(stream, Version);
     write_little_endian<std::uint32_t>(stream, hashValue);
-    write_little_endian<std::uint32_t>(stream, desc.size());
+    write_little_endian<std::uint32_t>(stream, (std::uint32_t)desc.size());
     stream.write(&desc[0], desc.size());
     return !stream.fail();
   }
@@ -157,7 +157,7 @@ namespace Stockfish::Eval::NNUE {
 
     ASSERT_ALIGNED(transformedFeatures, alignment);
 
-    const std::size_t bucket = (pos.count<ALL_PIECES>() - 1) / 4;
+    const int bucket = (pos.count<ALL_PIECES>() - 1) / 4;
     const auto psqt = featureTransformer->transform(pos, transformedFeatures, bucket);
     const auto positional = network[bucket]->propagate(transformedFeatures);
 
@@ -197,7 +197,7 @@ namespace Stockfish::Eval::NNUE {
 
     NnueEvalTrace t{};
     t.correctBucket = (pos.count<ALL_PIECES>() - 1) / 4;
-    for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket) {
+    for (IndexType bucket = 0; bucket < LayerStacks; ++bucket) {
       const auto materialist = featureTransformer->transform(pos, transformedFeatures, bucket);
       const auto positional = network[bucket]->propagate(transformedFeatures);
 
index 22451915ba1eb2f547c823c52c95c703d5ebdba1..9a992608cc1a06a9808c4c96228a696bde3cc280 100644 (file)
@@ -235,10 +235,10 @@ namespace Stockfish::Eval::NNUE::Layers {
 
     // Read network parameters
     bool read_parameters(std::istream& stream) {
-      for (std::size_t i = 0; i < OutputDimensions; ++i)
+      for (IndexType i = 0; i < OutputDimensions; ++i)
         biases[i] = read_little_endian<BiasType>(stream);
 
-      for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
+      for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
         weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
 
       return !stream.fail();
@@ -246,10 +246,10 @@ namespace Stockfish::Eval::NNUE::Layers {
 
     // Write network parameters
     bool write_parameters(std::ostream& stream) const {
-      for (std::size_t i = 0; i < OutputDimensions; ++i)
+      for (IndexType i = 0; i < OutputDimensions; ++i)
           write_little_endian<BiasType>(stream, biases[i]);
 
-      for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
+      for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
         write_little_endian<WeightType>(stream, weights[get_weight_index(i)]);
 
       return !stream.fail();
@@ -422,9 +422,9 @@ namespace Stockfish::Eval::NNUE::Layers {
 
     // Read network parameters
     bool read_parameters(std::istream& stream) {
-      for (std::size_t i = 0; i < OutputDimensions; ++i)
+      for (IndexType i = 0; i < OutputDimensions; ++i)
         biases[i] = read_little_endian<BiasType>(stream);
-      for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
+      for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
         weights[get_weight_index(i)] = read_little_endian<WeightType>(stream);
 
       return !stream.fail();
@@ -432,10 +432,10 @@ namespace Stockfish::Eval::NNUE::Layers {
 
     // Write network parameters
     bool write_parameters(std::ostream& stream) const {
-      for (std::size_t i = 0; i < OutputDimensions; ++i)
+      for (IndexType i = 0; i < OutputDimensions; ++i)
         write_little_endian<BiasType>(stream, biases[i]);
 
-      for (std::size_t i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
+      for (IndexType i = 0; i < OutputDimensions * PaddedInputDimensions; ++i)
         write_little_endian<WeightType>(stream, weights[get_weight_index(i)]);
 
       return !stream.fail();
index ffd2e3b76a94523eec1beb01d6b67bec122a89d2..f94d30828d73ad7ce71b56be3c475071b92de257 100644 (file)
@@ -171,14 +171,6 @@ namespace Stockfish::Eval::NNUE::Layers {
             std::max(0, std::min(127, input[i] >> WeightScaleBits)));
       }
 
-      // Affine transform layers expect that there is at least
-      // ceil_to_multiple(OutputDimensions, 32) initialized values.
-      // We cannot do this in the affine transform because it requires
-      // preallocating space here.
-      for (IndexType i = OutputDimensions; i < PaddedOutputDimensions; ++i) {
-        output[i] = 0;
-      }
-
       return output;
     }
   };
index 725b40fb43d2e87d9ab484603528f9965a06f59d..b4f65364c2e1c4bb727721ab3922550b75685e41 100644 (file)
@@ -46,7 +46,7 @@ struct Network
   static constexpr int FC_1_OUTPUTS = 32;
 
   Layers::AffineTransform<TransformedFeatureDimensions, FC_0_OUTPUTS + 1> fc_0;
-  Layers::ClippedReLU<FC_0_OUTPUTS> ac_0;
+  Layers::ClippedReLU<FC_0_OUTPUTS + 1> ac_0;
   Layers::AffineTransform<FC_0_OUTPUTS, FC_1_OUTPUTS> fc_1;
   Layers::ClippedReLU<FC_1_OUTPUTS> ac_1;
   Layers::AffineTransform<FC_1_OUTPUTS, 1> fc_2;
@@ -97,14 +97,19 @@ struct Network
       alignas(CacheLineSize) decltype(fc_1)::OutputBuffer fc_1_out;
       alignas(CacheLineSize) decltype(ac_1)::OutputBuffer ac_1_out;
       alignas(CacheLineSize) decltype(fc_2)::OutputBuffer fc_2_out;
+
+      Buffer()
+      {
+          std::memset(this, 0, sizeof(*this));
+      }
     };
 
 #if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
-    char bufferRaw[sizeof(Buffer) + alignment];
-    char* bufferRawAligned = align_ptr_up<alignment>(&bufferRaw[0]);
-    Buffer& buffer = *(new (bufferRawAligned) Buffer);
+    static thread_local char bufferRaw[sizeof(Buffer) + alignment];
+    static thread_local char* bufferRawAligned = align_ptr_up<alignment>(&bufferRaw[0]);
+    static thread_local Buffer& buffer = *(new (bufferRawAligned) Buffer);
 #else
-    alignas(alignment) Buffer buffer;
+    alignas(alignment) static thread_local Buffer buffer;
 #endif
 
     fc_0.propagate(transformedFeatures, buffer.fc_0_out);
@@ -118,10 +123,6 @@ struct Network
     std::int32_t fwdOut = int(buffer.fc_0_out[FC_0_OUTPUTS]) * (600*OutputScale) / (127*(1<<WeightScaleBits));
     std::int32_t outputValue = buffer.fc_2_out[0] + fwdOut;
 
-#if defined(ALIGNAS_ON_STACK_VARIABLES_BROKEN)
-    buffer.~Buffer();
-#endif
-
     return outputValue;
   }
 };
index 1bce00ae4650aa72a03ec9d577ceb7f8a4e2b41c..1795618946f6c4eca027728509e7c8a23598c0d9 100644 (file)
@@ -127,11 +127,11 @@ namespace Stockfish::Eval::NNUE {
           {
             for (; i + 1 < sizeof(IntType); ++i)
             {
-                u[i] = v;
+                u[i] = (std::uint8_t)v;
                 v >>= 8;
             }
           }
-          u[i] = v;
+          u[i] = (std::uint8_t)v;
 
           stream.write(reinterpret_cast<char*>(u), sizeof(IntType));
       }
index fb867421f6c249b7513190ef5f2a48296726ac03..855980182fccafd731879a91b6458f93e3c6570d 100644 (file)
@@ -123,8 +123,10 @@ namespace Stockfish::Eval::NNUE {
       // We use __m* types as template arguments, which causes GCC to emit warnings
       // about losing some attribute information. This is irrelevant to us as we
       // only take their size, so the following pragma are harmless.
+      #if defined(__GNUC__)
       #pragma GCC diagnostic push
       #pragma GCC diagnostic ignored "-Wignored-attributes"
+      #endif
 
       template <typename SIMDRegisterType,
                 typename LaneType,
@@ -156,9 +158,9 @@ namespace Stockfish::Eval::NNUE {
 
       static constexpr int NumRegs     = BestRegisterCount<vec_t, WeightType, TransformedFeatureDimensions, NumRegistersSIMD>();
       static constexpr int NumPsqtRegs = BestRegisterCount<psqt_vec_t, PSQTWeightType, PSQTBuckets, NumRegistersSIMD>();
-
+      #if defined(__GNUC__)
       #pragma GCC diagnostic pop
-
+      #endif
   #endif