mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 20:57:10 +00:00
Add helpers for managing aligned memory
Previously, we had two type aliases, LargePagePtr and AlignedPtr, which required manually initializing the aligned memory for the pointer. The new helpers: - make_unique_aligned - make_unique_large_page are now available for allocating aligned memory (with large pages). They behave similarly to std::make_unique, ensuring objects allocated with these functions follow RAII. The old approach had issues with initializing non-trivial types or arrays of objects. The evaluation function of the network is now a unique pointer to an array instead of an array of unique pointers. Memory related functions have been moved into memory.h Passed High Hash Pressure Test Non-Regression STC: https://tests.stockfishchess.org/tests/view/665b2b36586058766677cfd2 LLR: 2.93 (-2.94,2.94) <-1.75,0.25> Total: 476992 W: 122426 L: 122677 D: 231889 Ptnml(0-2): 1145, 51027, 134419, 50744, 1161 Failed Normal Non-Regression STC: https://tests.stockfishchess.org/tests/view/665b2997586058766677cfc8 LLR: -2.94 (-2.94,2.94) <-1.75,0.25> Total: 877312 W: 225233 L: 226395 D: 425684 Ptnml(0-2): 2110, 94642, 246239, 93630, 2035 Probably a fluke since there shouldn't be a real slowndown and it has also passed the high hash pressure test. closes https://github.com/official-stockfish/Stockfish/pull/5332 No functional change
This commit is contained in:
+27
-50
@@ -20,7 +20,6 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@@ -30,6 +29,7 @@
|
||||
|
||||
#include "../evaluate.h"
|
||||
#include "../incbin/incbin.h"
|
||||
#include "../memory.h"
|
||||
#include "../misc.h"
|
||||
#include "../position.h"
|
||||
#include "../types.h"
|
||||
@@ -86,23 +86,6 @@ namespace Stockfish::Eval::NNUE {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
// Initialize the evaluation function parameters
|
||||
template<typename T>
|
||||
void initialize(AlignedPtr<T>& pointer) {
|
||||
|
||||
pointer.reset(reinterpret_cast<T*>(std_aligned_alloc(alignof(T), sizeof(T))));
|
||||
std::memset(pointer.get(), 0, sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void initialize(LargePagePtr<T>& pointer) {
|
||||
|
||||
static_assert(alignof(T) <= 4096,
|
||||
"aligned_large_pages_alloc() may fail for such a big alignment requirement of T");
|
||||
pointer.reset(reinterpret_cast<T*>(aligned_large_pages_alloc(sizeof(T))));
|
||||
std::memset(pointer.get(), 0, sizeof(T));
|
||||
}
|
||||
|
||||
// Read evaluation function parameters
|
||||
template<typename T>
|
||||
bool read_parameters(std::istream& stream, T& reference) {
|
||||
@@ -128,19 +111,17 @@ template<typename Arch, typename Transformer>
|
||||
Network<Arch, Transformer>::Network(const Network<Arch, Transformer>& other) :
|
||||
evalFile(other.evalFile),
|
||||
embeddedType(other.embeddedType) {
|
||||
|
||||
if (other.featureTransformer)
|
||||
{
|
||||
Detail::initialize(featureTransformer);
|
||||
*featureTransformer = *other.featureTransformer;
|
||||
}
|
||||
featureTransformer = make_unique_large_page<Transformer>(*other.featureTransformer);
|
||||
|
||||
network = make_unique_aligned<Arch[]>(LayerStacks);
|
||||
|
||||
if (!other.network)
|
||||
return;
|
||||
|
||||
for (std::size_t i = 0; i < LayerStacks; ++i)
|
||||
{
|
||||
if (other.network[i])
|
||||
{
|
||||
Detail::initialize(network[i]);
|
||||
*(network[i]) = *(other.network[i]);
|
||||
}
|
||||
}
|
||||
network[i] = other.network[i];
|
||||
}
|
||||
|
||||
template<typename Arch, typename Transformer>
|
||||
@@ -150,18 +131,15 @@ Network<Arch, Transformer>::operator=(const Network<Arch, Transformer>& other) {
|
||||
embeddedType = other.embeddedType;
|
||||
|
||||
if (other.featureTransformer)
|
||||
{
|
||||
Detail::initialize(featureTransformer);
|
||||
*featureTransformer = *other.featureTransformer;
|
||||
}
|
||||
featureTransformer = make_unique_large_page<Transformer>(*other.featureTransformer);
|
||||
|
||||
network = make_unique_aligned<Arch[]>(LayerStacks);
|
||||
|
||||
if (!other.network)
|
||||
return *this;
|
||||
|
||||
for (std::size_t i = 0; i < LayerStacks; ++i)
|
||||
{
|
||||
if (other.network[i])
|
||||
{
|
||||
Detail::initialize(network[i]);
|
||||
*(network[i]) = *(other.network[i]);
|
||||
}
|
||||
}
|
||||
network[i] = other.network[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -253,7 +231,7 @@ Value Network<Arch, Transformer>::evaluate(const Position&
|
||||
|
||||
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);
|
||||
const auto positional = network[bucket].propagate(transformedFeatures);
|
||||
|
||||
if (complexity)
|
||||
*complexity = std::abs(psqt - positional) / OutputScale;
|
||||
@@ -292,11 +270,11 @@ void Network<Arch, Transformer>::verify(std::string evalfilePath) const {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
size_t size = sizeof(*featureTransformer) + sizeof(*network) * LayerStacks;
|
||||
size_t size = sizeof(*featureTransformer) + sizeof(Arch) * LayerStacks;
|
||||
sync_cout << "info string NNUE evaluation using " << evalfilePath << " ("
|
||||
<< size / (1024 * 1024) << "MiB, (" << featureTransformer->InputDimensions << ", "
|
||||
<< network[0]->TransformedFeatureDimensions << ", " << network[0]->FC_0_OUTPUTS
|
||||
<< ", " << network[0]->FC_1_OUTPUTS << ", 1))" << sync_endl;
|
||||
<< network[0].TransformedFeatureDimensions << ", " << network[0].FC_0_OUTPUTS << ", "
|
||||
<< network[0].FC_1_OUTPUTS << ", 1))" << sync_endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -333,7 +311,7 @@ Network<Arch, Transformer>::trace_evaluate(const Position&
|
||||
{
|
||||
const auto materialist =
|
||||
featureTransformer->transform(pos, cache, transformedFeatures, bucket);
|
||||
const auto positional = network[bucket]->propagate(transformedFeatures);
|
||||
const auto positional = network[bucket].propagate(transformedFeatures);
|
||||
|
||||
t.psqt[bucket] = static_cast<Value>(materialist / OutputScale);
|
||||
t.positional[bucket] = static_cast<Value>(positional / OutputScale);
|
||||
@@ -386,9 +364,8 @@ void Network<Arch, Transformer>::load_internal() {
|
||||
|
||||
template<typename Arch, typename Transformer>
|
||||
void Network<Arch, Transformer>::initialize() {
|
||||
Detail::initialize(featureTransformer);
|
||||
for (std::size_t i = 0; i < LayerStacks; ++i)
|
||||
Detail::initialize(network[i]);
|
||||
featureTransformer = make_unique_large_page<Transformer>();
|
||||
network = make_unique_aligned<Arch[]>(LayerStacks);
|
||||
}
|
||||
|
||||
|
||||
@@ -455,7 +432,7 @@ bool Network<Arch, Transformer>::read_parameters(std::istream& stream,
|
||||
return false;
|
||||
for (std::size_t i = 0; i < LayerStacks; ++i)
|
||||
{
|
||||
if (!Detail::read_parameters(stream, *(network[i])))
|
||||
if (!Detail::read_parameters(stream, network[i]))
|
||||
return false;
|
||||
}
|
||||
return stream && stream.peek() == std::ios::traits_type::eof();
|
||||
@@ -471,7 +448,7 @@ bool Network<Arch, Transformer>::write_parameters(std::ostream& stream,
|
||||
return false;
|
||||
for (std::size_t i = 0; i < LayerStacks; ++i)
|
||||
{
|
||||
if (!Detail::write_parameters(stream, *(network[i])))
|
||||
if (!Detail::write_parameters(stream, network[i]))
|
||||
return false;
|
||||
}
|
||||
return bool(stream);
|
||||
|
||||
Reference in New Issue
Block a user