Consistent Integer Types

example of using, to avoid mixed usage of std::uint/std::int and uint/int...
```cpp
using u64 = std::uint64_t;
using u32 = std::uint32_t;
using u16 = std::uint16_t;
using u8  = std::uint8_t;

using i64 = std::int64_t;
using i32 = std::int32_t;
using i16 = std::int16_t;
using i8  = std::int8_t;

using usize = std::size_t;
using isize = std::ptrdiff_t;

#if defined(__GNUC__) && defined(IS_64BIT)
__extension__ using u128 = unsigned __int128;
__extension__ using i128 = signed __int128;
#endif
```

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

No functional change
This commit is contained in:
Disservin
2026-06-08 19:54:33 +02:00
committed by Joost VandeVondele
parent e4a635486a
commit dd3e1c4a50
50 changed files with 787 additions and 799 deletions
+7 -7
View File
@@ -39,7 +39,7 @@ alignas(64) Magic Magics[SQUARE_NB][2];
}
#ifdef USE_PEXT
using MagicMask = uint16_t;
using MagicMask = u16;
#else
using MagicMask = Bitboard;
#endif
@@ -77,10 +77,10 @@ static void init_magics(Magic magics[][2]) {
// Sliding attacks within a rank, indexed by the slider's file and the
// 8-bit rank occupancy, yielding the 8-bit attack set on that rank
constexpr auto RankAttacks = []() {
std::array<std::array<uint8_t, 256>, FILE_NB> table{};
std::array<std::array<u8, 256>, FILE_NB> table{};
for (int file = 0; file < 8; ++file)
for (int occ = 0; occ < 256; ++occ)
table[file][occ] = uint8_t(sliding_attack(ROOK, Square(file), occ));
table[file][occ] = u8(sliding_attack(ROOK, Square(file), occ));
return table;
}();
@@ -198,14 +198,14 @@ constexpr
#if defined(USE_COMPTIME_ATTACKS) && defined(USE_PEXT)
constexpr auto RookTable = []() {
std::array<uint16_t, 0x19000> result{};
Magic magics[64][2] = {};
std::array<u16, 0x19000> result{};
Magic magics[64][2] = {};
init_magics(ROOK, result.data(), magics, false);
return result;
}();
constexpr auto BishopTable = []() {
std::array<uint16_t, 0x1480> result{};
Magic magics[64][2] = {};
std::array<u16, 0x1480> result{};
Magic magics[64][2] = {};
init_magics(BISHOP, result.data(), magics, false);
return result;
}();
+3 -3
View File
@@ -81,7 +81,7 @@ struct DualMagic {
// Precomputed 2 * square_bb(sq), 2 * reverse(square_bb(sq))
Bitboard r, rr;
const uint8_t* RESTRICT rankAttacksLookup;
const u8* RESTRICT rankAttacksLookup;
// 8 * rank_of(sq)
int shift;
@@ -130,8 +130,8 @@ const DualMagic& dual_magic(Square s);
struct Magic {
Bitboard mask;
#ifdef USE_PEXT
uint16_t* attacks;
Bitboard pseudoAttacks;
u16* attacks;
Bitboard pseudoAttacks;
#else
Bitboard* attacks;
Bitboard magic;
+3 -3
View File
@@ -22,8 +22,8 @@
namespace Stockfish {
uint8_t PopCnt16[1 << 16];
uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
u8 PopCnt16[1 << 16];
u8 SquareDistance[SQUARE_NB][SQUARE_NB];
// Returns an ASCII representation of a bitboard suitable
// to be printed to standard output. Useful for debugging.
@@ -51,7 +51,7 @@ std::string Bitboards::pretty(Bitboard b) {
void Bitboards::init() {
for (unsigned i = 0; i < (1 << 16); ++i)
PopCnt16[i] = uint8_t(std::bitset<16>(i).count());
PopCnt16[i] = u8(std::bitset<16>(i).count());
for (Square s1 = SQ_A1; s1 <= SQ_H8; ++s1)
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
+10 -10
View File
@@ -23,11 +23,11 @@
#include <cassert>
#include <cmath>
#include <cstring>
#include <cstdint>
#include <cstdlib>
#include <string>
#include "types.h"
#include "misc.h"
namespace Stockfish {
@@ -65,8 +65,8 @@ constexpr Bitboard Rank6BB = Rank1BB << (8 * 5);
constexpr Bitboard Rank7BB = Rank1BB << (8 * 6);
constexpr Bitboard Rank8BB = Rank1BB << (8 * 7);
extern uint8_t PopCnt16[1 << 16];
extern uint8_t SquareDistance[SQUARE_NB][SQUARE_NB];
extern u8 PopCnt16[1 << 16];
extern u8 SquareDistance[SQUARE_NB][SQUARE_NB];
constexpr Bitboard square_bb(Square s) {
assert(is_ok(s));
@@ -169,7 +169,7 @@ inline int popcount(Bitboard b) {
#ifndef USE_POPCNT
std::uint16_t indices[4];
u16 indices[4];
std::memcpy(indices, &b, sizeof(b));
return PopCnt16[indices[0]] + PopCnt16[indices[1]] + PopCnt16[indices[2]]
+ PopCnt16[indices[3]];
@@ -190,9 +190,9 @@ inline constexpr int lsb_index64[64] = {
21, 44, 38, 32, 29, 23, 17, 11, 4, 62, 46, 55, 26, 59, 40, 36, 15, 53, 34, 51, 20, 43,
31, 22, 10, 45, 25, 39, 14, 33, 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63};
constexpr int constexpr_lsb(uint64_t bb) {
constexpr int constexpr_lsb(u64 bb) {
assert(bb != 0);
constexpr uint64_t debruijn64 = 0x03F79D71B4CB0A89ULL;
constexpr u64 debruijn64 = 0x03F79D71B4CB0A89ULL;
return lsb_index64[((bb ^ (bb - 1)) * debruijn64) >> 58];
}
@@ -216,12 +216,12 @@ inline Square lsb(Bitboard b) {
if (b & 0xffffffff)
{
_BitScanForward(&idx, int32_t(b));
_BitScanForward(&idx, i32(b));
return Square(idx);
}
else
{
_BitScanForward(&idx, int32_t(b >> 32));
_BitScanForward(&idx, i32(b >> 32));
return Square(idx + 32);
}
#endif
@@ -251,12 +251,12 @@ inline Square msb(Bitboard b) {
if (b >> 32)
{
_BitScanReverse(&idx, int32_t(b >> 32));
_BitScanReverse(&idx, i32(b >> 32));
return Square(idx + 32);
}
else
{
_BitScanReverse(&idx, int32_t(b));
_BitScanReverse(&idx, i32(b));
return Square(idx);
}
#endif
+9 -9
View File
@@ -142,7 +142,7 @@ Engine::Engine(std::optional<std::string> path) :
resize_threads();
}
std::uint64_t Engine::perft(const std::string& fen, Depth depth, bool isChess960) {
u64 Engine::perft(const std::string& fen, Depth depth, bool isChess960) {
verify_network();
return Benchmark::perft(fen, depth, isChess960);
@@ -246,7 +246,7 @@ void Engine::resize_threads() {
threads.ensure_network_replicated();
}
void Engine::set_tt_size(size_t mb) {
void Engine::set_tt_size(usize mb) {
wait_for_search_finished();
tt.resize(mb, threads);
}
@@ -259,7 +259,7 @@ void Engine::verify_network() const {
network->verify(options["EvalFile"], onVerifyNetwork);
auto statuses = network.get_status_and_errors();
for (size_t i = 0; i < statuses.size(); ++i)
for (usize i = 0; i < statuses.size(); ++i)
{
const auto [status, error] = statuses[i];
std::string message = "Network replica " + std::to_string(i + 1) + ": ";
@@ -336,11 +336,11 @@ std::string Engine::visualize() const {
int Engine::get_hashfull(int maxAge) const { return tt.hashfull(maxAge); }
std::vector<std::pair<size_t, size_t>> Engine::get_bound_thread_count_by_numa_node() const {
auto counts = threads.get_bound_thread_count_by_numa_node();
const NumaConfig& cfg = numaContext.get_numa_config();
std::vector<std::pair<size_t, size_t>> ratios;
NumaIndex n = 0;
std::vector<std::pair<usize, usize>> Engine::get_bound_thread_count_by_numa_node() const {
auto counts = threads.get_bound_thread_count_by_numa_node();
const NumaConfig& cfg = numaContext.get_numa_config();
std::vector<std::pair<usize, usize>> ratios;
NumaIndex n = 0;
for (; n < counts.size(); ++n)
ratios.emplace_back(counts[n], cfg.num_cpus_in_numa_node(n));
if (!counts.empty())
@@ -380,7 +380,7 @@ std::string Engine::thread_binding_information_as_string() const {
std::string Engine::thread_allocation_information_as_string() const {
std::stringstream ss;
size_t threadsSize = threads.size();
usize threadsSize = threads.size();
ss << "Using " << threadsSize << (threadsSize > 1 ? " threads" : " thread");
auto boundThreadsByNodeStr = thread_binding_information_as_string();
+11 -12
View File
@@ -19,8 +19,6 @@
#ifndef ENGINE_H_INCLUDED
#define ENGINE_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
@@ -30,6 +28,7 @@
#include <utility>
#include <vector>
#include "misc.h"
#include "history.h"
#include "nnue/network.h"
#include "numa.h"
@@ -58,7 +57,7 @@ class Engine {
~Engine() { wait_for_search_finished(); }
std::uint64_t perft(const std::string& fen, Depth depth, bool isChess960);
u64 perft(const std::string& fen, Depth depth, bool isChess960);
// non blocking call to start searching
void go(Search::LimitsType&);
@@ -75,7 +74,7 @@ class Engine {
void set_numa_config_from_option(const std::string& o);
void resize_threads();
void set_tt_size(size_t mb);
void set_tt_size(usize mb);
void set_ponderhit(bool);
void search_clear();
@@ -101,14 +100,14 @@ class Engine {
int get_hashfull(int maxAge = 0) const;
std::string fen() const;
void flip();
std::string visualize() const;
std::vector<std::pair<size_t, size_t>> get_bound_thread_count_by_numa_node() const;
std::string get_numa_config_as_string() const;
std::string numa_config_information_as_string() const;
std::string thread_allocation_information_as_string() const;
std::string thread_binding_information_as_string() const;
std::string fen() const;
void flip();
std::string visualize() const;
std::vector<std::pair<usize, usize>> get_bound_thread_count_by_numa_node() const;
std::string get_numa_config_as_string() const;
std::string numa_config_information_as_string() const;
std::string thread_allocation_information_as_string() const;
std::string thread_binding_information_as_string() const;
private:
const std::string binaryDirectory;
+22 -23
View File
@@ -36,7 +36,7 @@
namespace Stockfish {
constexpr int PAWN_HISTORY_BASE_SIZE = 8192; // has to be a power of 2
constexpr int UINT_16_HISTORY_SIZE = std::numeric_limits<uint16_t>::max() + 1;
constexpr int UINT_16_HISTORY_SIZE = std::numeric_limits<u16>::max() + 1;
constexpr int CORRHIST_BASE_SIZE = UINT_16_HISTORY_SIZE;
constexpr int CORRECTION_HISTORY_LIMIT = 1024;
constexpr int LOW_PLY_HISTORY_SIZE = 5;
@@ -89,10 +89,10 @@ enum StatsType {
Captures
};
template<typename T, int D, std::size_t... Sizes>
template<typename T, int D, usize... Sizes>
using Stats = MultiArray<StatsEntry<T, D>, Sizes...>;
template<typename T, int D, std::size_t... Sizes>
template<typename T, int D, usize... Sizes>
using AtomicStats = MultiArray<StatsEntry<T, D, true>, Sizes...>;
// DynStats is a dynamically sized array of Stats, used for thread-shared histories
@@ -100,31 +100,31 @@ using AtomicStats = MultiArray<StatsEntry<T, D, true>, Sizes...>;
// the per-thread allocation count of T.
template<typename T, int SizeMultiplier>
struct DynStats {
explicit DynStats(size_t s) {
explicit DynStats(usize s) {
size = s * SizeMultiplier;
data = make_unique_large_page<T[]>(size);
}
// Sets all values in the range to 0
void clear_range(int value, size_t threadIdx, size_t numaTotal) {
size_t start = uint64_t(threadIdx) * size / numaTotal;
void clear_range(int value, usize threadIdx, usize numaTotal) {
usize start = u64(threadIdx) * size / numaTotal;
assert(start < size);
size_t end = threadIdx + 1 == numaTotal ? size : uint64_t(threadIdx + 1) * size / numaTotal;
usize end = threadIdx + 1 == numaTotal ? size : u64(threadIdx + 1) * size / numaTotal;
while (start < end)
data[start++].fill(value);
}
size_t get_size() const { return size; }
T& operator[](size_t index) {
usize get_size() const { return size; }
T& operator[](usize index) {
assert(index < size);
return data.get()[index];
}
const T& operator[](size_t index) const {
const T& operator[](usize index) const {
assert(index < size);
return data.get()[index];
}
private:
size_t size;
usize size;
LargePagePtr<T[]> data;
};
@@ -132,17 +132,17 @@ struct DynStats {
// during the current search, and is used for reduction and move ordering decisions.
// It uses 2 tables (one for each color) indexed by the move's from and to squares,
// see https://www.chessprogramming.org/Butterfly_Boards
using ButterflyHistory = Stats<std::int16_t, 7183, COLOR_NB, UINT_16_HISTORY_SIZE>;
using ButterflyHistory = Stats<i16, 7183, COLOR_NB, UINT_16_HISTORY_SIZE>;
// LowPlyHistory is addressed by ply and move's from and to squares, used
// to improve move ordering near the root
using LowPlyHistory = Stats<std::int16_t, 7183, LOW_PLY_HISTORY_SIZE, UINT_16_HISTORY_SIZE>;
using LowPlyHistory = Stats<i16, 7183, LOW_PLY_HISTORY_SIZE, UINT_16_HISTORY_SIZE>;
// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
using CapturePieceToHistory = Stats<std::int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB>;
using CapturePieceToHistory = Stats<i16, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB>;
// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
using PieceToHistory = Stats<std::int16_t, 30000, PIECE_NB, SQUARE_NB>;
using PieceToHistory = Stats<i16, 30000, PIECE_NB, SQUARE_NB>;
// ContinuationHistory is the combined history of a given pair of moves, usually
// the current one given a previous one. The nested history table is based on
@@ -150,8 +150,7 @@ using PieceToHistory = Stats<std::int16_t, 30000, PIECE_NB, SQUARE_NB>;
using ContinuationHistory = MultiArray<PieceToHistory, PIECE_NB, SQUARE_NB>;
// PawnHistory is addressed by the pawn structure and a move's [piece][to]
using PawnHistory =
DynStats<AtomicStats<std::int16_t, 8192, PIECE_NB, SQUARE_NB>, PAWN_HISTORY_BASE_SIZE>;
using PawnHistory = DynStats<AtomicStats<i16, 8192, PIECE_NB, SQUARE_NB>, PAWN_HISTORY_BASE_SIZE>;
// Correction histories record differences between the static evaluation of
// positions and their search score. It is used to improve the static evaluation
@@ -184,7 +183,7 @@ struct CorrHistTypedef;
template<>
struct CorrHistTypedef<PieceTo> {
using type = Stats<std::int16_t, CORRECTION_HISTORY_LIMIT, PIECE_NB, SQUARE_NB>;
using type = Stats<i16, CORRECTION_HISTORY_LIMIT, PIECE_NB, SQUARE_NB>;
};
template<>
@@ -195,20 +194,20 @@ struct CorrHistTypedef<Continuation> {
}
using UnifiedCorrectionHistory =
DynStats<MultiArray<CorrectionBundle<std::int16_t, CORRECTION_HISTORY_LIMIT>, COLOR_NB>,
DynStats<MultiArray<CorrectionBundle<i16, CORRECTION_HISTORY_LIMIT>, COLOR_NB>,
CORRHIST_BASE_SIZE>;
template<CorrHistType T>
using CorrectionHistory = typename Detail::CorrHistTypedef<T>::type;
using TTMoveHistory = StatsEntry<std::int16_t, 8192>;
using TTMoveHistory = StatsEntry<i16, 8192>;
// Set of histories shared between groups of threads. To avoid excessive
// cross-node data transfer, histories are shared only between threads
// on a given NUMA node. The passed size must be a power of two to make
// the indexing more efficient.
struct SharedHistories {
SharedHistories(size_t threadCount) :
SharedHistories(usize threadCount) :
correctionHistory(threadCount),
pawnHistory(threadCount) {
assert((threadCount & (threadCount - 1)) == 0 && threadCount != 0);
@@ -216,7 +215,7 @@ struct SharedHistories {
pawnHistSizeMinus1 = pawnHistory.get_size() - 1;
}
size_t get_size() const { return sizeMinus1 + 1; }
usize get_size() const { return sizeMinus1 + 1; }
auto& pawn_entry(const Position& pos) {
return pawnHistory[pos.pawn_key() & pawnHistSizeMinus1];
@@ -253,7 +252,7 @@ struct SharedHistories {
private:
size_t sizeMinus1, pawnHistSizeMinus1;
usize sizeMinus1, pawnHistSizeMinus1;
};
} // namespace Stockfish
+28 -28
View File
@@ -294,17 +294,17 @@ constexpr int MaxDebugSlots = 32;
namespace {
template<size_t N>
template<usize N>
struct DebugInfo {
std::array<std::atomic<int64_t>, N> data = {0};
std::array<std::atomic<i64>, N> data = {0};
[[nodiscard]] constexpr std::atomic<int64_t>& operator[](size_t index) {
[[nodiscard]] constexpr std::atomic<i64>& operator[](usize index) {
assert(index < N);
return data[index];
}
constexpr DebugInfo& operator=(const DebugInfo& other) {
for (size_t i = 0; i < N; i++)
for (usize i = 0; i < N; i++)
data[i].store(other.data[i].load());
return *this;
}
@@ -312,8 +312,8 @@ struct DebugInfo {
struct DebugExtremes: public DebugInfo<3> {
DebugExtremes() {
data[1] = std::numeric_limits<int64_t>::min();
data[2] = std::numeric_limits<int64_t>::max();
data[1] = std::numeric_limits<i64>::min();
data[2] = std::numeric_limits<i64>::max();
}
};
@@ -332,32 +332,32 @@ void dbg_hit_on(bool cond, int slot) {
++hit.at(slot)[1];
}
void dbg_mean_of(int64_t value, int slot) {
void dbg_mean_of(i64 value, int slot) {
++mean.at(slot)[0];
mean.at(slot)[1] += value;
}
void dbg_stdev_of(int64_t value, int slot) {
void dbg_stdev_of(i64 value, int slot) {
++stdev.at(slot)[0];
stdev.at(slot)[1] += value;
stdev.at(slot)[2] += value * value;
}
void dbg_extremes_of(int64_t value, int slot) {
void dbg_extremes_of(i64 value, int slot) {
++extremes.at(slot)[0];
int64_t current_max = extremes.at(slot)[1].load();
i64 current_max = extremes.at(slot)[1].load();
while (current_max < value && !extremes.at(slot)[1].compare_exchange_weak(current_max, value))
{}
int64_t current_min = extremes.at(slot)[2].load();
i64 current_min = extremes.at(slot)[2].load();
while (current_min > value && !extremes.at(slot)[2].compare_exchange_weak(current_min, value))
{}
}
void dbg_correl_of(int64_t value1, int64_t value2, int slot) {
void dbg_correl_of(i64 value1, i64 value2, int slot) {
++correl.at(slot)[0];
correl.at(slot)[1] += value1;
@@ -369,9 +369,9 @@ void dbg_correl_of(int64_t value1, int64_t value2, int slot) {
void dbg_print() {
int64_t n;
auto E = [&n](int64_t x) { return double(x) / n; };
auto sqr = [](double x) { return x * x; };
i64 n;
auto E = [&n](i64 x) { return double(x) / n; };
auto sqr = [](double x) { return x * x; };
for (int i = 0; i < MaxDebugSlots; ++i)
if ((n = hit[i][0]))
@@ -435,17 +435,17 @@ void sync_cout_start() { std::cout << IO_LOCK; }
void sync_cout_end() { std::cout << IO_UNLOCK; }
// Hash function based on public domain MurmurHash64A, by Austin Appleby.
uint64_t hash_bytes(const char* data, size_t size) {
const uint64_t m = 0xc6a4a7935bd1e995ull;
const int r = 47;
u64 hash_bytes(const char* data, usize size) {
const u64 m = 0xc6a4a7935bd1e995ull;
const int r = 47;
uint64_t h = size * m;
u64 h = size * m;
const char* end = data + (size & ~(size_t) 7);
const char* end = data + (size & ~(usize) 7);
for (const char* p = data; p != end; p += 8)
{
uint64_t k;
u64 k;
std::memcpy(&k, p, sizeof(k));
k *= m;
@@ -458,9 +458,9 @@ uint64_t hash_bytes(const char* data, size_t size) {
if (size & 7)
{
uint64_t k = 0;
u64 k = 0;
for (int i = (size & 7) - 1; i >= 0; i--)
k = (k << 8) | (uint64_t) end[i];
k = (k << 8) | u64(end[i]);
h ^= k;
h *= m;
@@ -485,11 +485,11 @@ void start_logger(const std::string& fname) { Logger::start(fname); }
#define GETCWD getcwd
#endif
size_t str_to_size_t(const std::string& s) {
usize str_to_size_t(const std::string& s) {
unsigned long long value = std::stoull(s);
if (value > std::numeric_limits<size_t>::max())
if (value > std::numeric_limits<usize>::max())
std::exit(EXIT_FAILURE);
return static_cast<size_t>(value);
return static_cast<usize>(value);
}
std::optional<std::string> read_file_to_string(const std::string& path) {
@@ -527,8 +527,8 @@ std::string CommandLine::get_binary_directory(std::string argv0) {
auto workingDirectory = CommandLine::get_working_directory();
// Extract the binary directory path from argv0
auto binaryDirectory = argv0;
size_t pos = binaryDirectory.find_last_of("\\/");
auto binaryDirectory = argv0;
usize pos = binaryDirectory.find_last_of("\\/");
if (pos == std::string::npos)
binaryDirectory = "." + pathSeparator;
else
+67 -50
View File
@@ -23,6 +23,7 @@
#include <array>
#include <cassert>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <exception> // IWYU pragma: keep
@@ -46,6 +47,24 @@
namespace Stockfish {
using u64 = std::uint64_t;
using u32 = std::uint32_t;
using u16 = std::uint16_t;
using u8 = std::uint8_t;
using i64 = std::int64_t;
using i32 = std::int32_t;
using i16 = std::int16_t;
using i8 = std::int8_t;
using usize = std::size_t;
using isize = std::ptrdiff_t;
#if defined(__GNUC__) && defined(IS_64BIT)
__extension__ using u128 = unsigned __int128;
__extension__ using i128 = signed __int128;
#endif
std::string engine_version_info();
std::string engine_info(bool to_uci = false);
std::string compiler_info();
@@ -114,7 +133,7 @@ void prefetch(const void* addr) {
void start_logger(const std::string& fname);
size_t str_to_size_t(const std::string& s);
usize str_to_size_t(const std::string& s);
#if defined(__linux__)
@@ -134,15 +153,15 @@ struct PipeDeleter {
std::optional<std::string> read_file_to_string(const std::string& path);
void dbg_hit_on(bool cond, int slot = 0);
void dbg_mean_of(int64_t value, int slot = 0);
void dbg_stdev_of(int64_t value, int slot = 0);
void dbg_extremes_of(int64_t value, int slot = 0);
void dbg_correl_of(int64_t value1, int64_t value2, int slot = 0);
void dbg_mean_of(i64 value, int slot = 0);
void dbg_stdev_of(i64 value, int slot = 0);
void dbg_extremes_of(i64 value, int slot = 0);
void dbg_correl_of(i64 value1, i64 value2, int slot = 0);
void dbg_print();
void dbg_clear();
using TimePoint = std::chrono::milliseconds::rep; // A value in milliseconds
static_assert(sizeof(TimePoint) == sizeof(int64_t), "TimePoint should be 64 bits");
static_assert(sizeof(TimePoint) == sizeof(i64), "TimePoint should be 64 bits");
inline TimePoint now() {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch())
@@ -155,10 +174,10 @@ inline std::vector<std::string_view> split(std::string_view s, std::string_view
if (s.empty())
return res;
size_t begin = 0;
usize begin = 0;
for (;;)
{
const size_t end = s.find(delimiter, begin);
const usize end = s.find(delimiter, begin);
if (end == std::string::npos)
break;
@@ -187,17 +206,17 @@ void sync_cout_start();
void sync_cout_end();
// True if and only if the binary is compiled on a little-endian machine
static inline const std::uint16_t Le = 1;
static inline const bool IsLittleEndian = *reinterpret_cast<const char*>(&Le) == 1;
static inline const u16 Le = 1;
static inline const bool IsLittleEndian = *reinterpret_cast<const char*>(&Le) == 1;
template<typename T, std::size_t MaxSize>
template<typename T, usize MaxSize>
class ValueList {
public:
std::size_t size() const { return size_; }
int ssize() const { return int(size_); }
void push_back(const T& value) {
usize size() const { return size_; }
int ssize() const { return int(size_); }
void push_back(const T& value) {
assert(size_ < MaxSize);
values_[size_++] = value;
}
@@ -211,7 +230,7 @@ class ValueList {
const T* end() const { return values_ + size_; }
const T& operator[](int index) const { return values_[index]; }
T* make_space(size_t count) {
T* make_space(usize count) {
T* result = &values_[size_];
size_ += count;
assert(size_ <= MaxSize);
@@ -219,22 +238,22 @@ class ValueList {
}
private:
T values_[MaxSize];
std::size_t size_ = 0;
T values_[MaxSize];
usize size_ = 0;
};
template<typename T, std::size_t Size, std::size_t... Sizes>
template<typename T, usize Size, usize... Sizes>
class MultiArray;
namespace Detail {
template<typename T, std::size_t Size, std::size_t... Sizes>
template<typename T, usize Size, usize... Sizes>
struct MultiArrayHelper {
using ChildType = MultiArray<T, Sizes...>;
};
template<typename T, std::size_t Size>
template<typename T, usize Size>
struct MultiArrayHelper<T, Size> {
using ChildType = T;
};
@@ -247,7 +266,7 @@ constexpr bool is_strictly_assignable_v =
// MultiArray is a generic N-dimensional array.
// The template parameters (Size and Sizes) encode the dimensions of the array.
template<typename T, std::size_t Size, std::size_t... Sizes>
template<typename T, usize Size, usize... Sizes>
class MultiArray {
using ChildType = typename Detail::MultiArrayHelper<T, Size, Sizes...>::ChildType;
using ArrayType = std::array<ChildType, Size>;
@@ -338,16 +357,16 @@ class MultiArray {
class PRNG {
uint64_t s;
u64 s;
uint64_t rand64() {
u64 rand64() {
s ^= s >> 12, s ^= s << 25, s ^= s >> 27;
return s * 2685821657736338717LL;
}
public:
PRNG(uint64_t seed) :
PRNG(u64 seed) :
s(seed) {
assert(seed);
}
@@ -365,16 +384,15 @@ class PRNG {
}
};
inline uint64_t mul_hi64(uint64_t a, uint64_t b) {
inline u64 mul_hi64(u64 a, u64 b) {
#if defined(__GNUC__) && defined(IS_64BIT)
__extension__ using uint128 = unsigned __int128;
return (uint128(a) * uint128(b)) >> 64;
return (u128(a) * u128(b)) >> 64;
#else
uint64_t aL = uint32_t(a), aH = a >> 32;
uint64_t bL = uint32_t(b), bH = b >> 32;
uint64_t c1 = (aL * bL) >> 32;
uint64_t c2 = aH * bL + c1;
uint64_t c3 = aL * bH + uint32_t(c2);
u64 aL = u32(a), aH = a >> 32;
u64 bL = u32(b), bH = b >> 32;
u64 c1 = (aL * bL) >> 32;
u64 c2 = aH * bL + c1;
u64 c3 = aL * bH + u32(c2);
return aH * bH + (c2 >> 32) + (c3 >> 32);
#endif
}
@@ -385,20 +403,19 @@ inline constexpr T2 interpolate(T1 x, T1 x0, T1 x1, T2 y0, T2 y1) {
return T2(y0 + (y1 - y0) * (x - x0) / (x1 - x0));
}
uint64_t hash_bytes(const char*, size_t);
u64 hash_bytes(const char*, usize);
template<typename T>
inline std::size_t get_raw_data_hash(const T& value) {
inline usize get_raw_data_hash(const T& value) {
// We must have no padding bytes because we're reinterpreting as char
static_assert(std::has_unique_object_representations<T>());
return static_cast<std::size_t>(
hash_bytes(reinterpret_cast<const char*>(&value), sizeof(value)));
return static_cast<usize>(hash_bytes(reinterpret_cast<const char*>(&value), sizeof(value)));
}
template<typename T>
inline void hash_combine(std::size_t& seed, const T& v) {
std::size_t x;
inline void hash_combine(usize& seed, const T& v) {
usize x;
// For primitive types we avoid using the default hasher, which may be
// nondeterministic across program invocations
if constexpr (std::is_integral<T>())
@@ -408,9 +425,9 @@ inline void hash_combine(std::size_t& seed, const T& v) {
seed ^= x + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
inline std::uint64_t hash_string(const std::string& sv) { return hash_bytes(sv.data(), sv.size()); }
inline u64 hash_string(const std::string& sv) { return hash_bytes(sv.data(), sv.size()); }
template<std::size_t Capacity>
template<usize Capacity>
class FixedString {
public:
FixedString() :
@@ -419,7 +436,7 @@ class FixedString {
}
FixedString(const char* str) {
size_t len = std::strlen(str);
usize len = std::strlen(str);
if (len > Capacity)
std::terminate();
std::memcpy(data_, str, len);
@@ -435,18 +452,18 @@ class FixedString {
data_[length_] = '\0';
}
std::size_t size() const { return length_; }
std::size_t capacity() const { return Capacity; }
usize size() const { return length_; }
usize capacity() const { return Capacity; }
const char* c_str() const { return data_; }
const char* data() const { return data_; }
char& operator[](std::size_t i) { return data_[i]; }
char& operator[](usize i) { return data_[i]; }
const char& operator[](std::size_t i) const { return data_[i]; }
const char& operator[](usize i) const { return data_[i]; }
FixedString& operator+=(const char* str) {
size_t len = std::strlen(str);
usize len = std::strlen(str);
if (length_ + len > Capacity)
std::terminate();
std::memcpy(data_ + length_, str, len);
@@ -477,8 +494,8 @@ class FixedString {
}
private:
char data_[Capacity + 1]; // +1 for null terminator
std::size_t length_;
char data_[Capacity + 1]; // +1 for null terminator
usize length_;
};
struct CommandLine {
@@ -554,9 +571,9 @@ void move_to_front(std::vector<T>& vec, Predicate pred) {
} // namespace Stockfish
template<std::size_t N>
template<Stockfish::usize N>
struct std::hash<Stockfish::FixedString<N>> {
std::size_t operator()(const Stockfish::FixedString<N>& fstr) const noexcept {
Stockfish::usize operator()(const Stockfish::FixedString<N>& fstr) const noexcept {
return Stockfish::hash_bytes(fstr.data(), fstr.size());
}
};
+1 -1
View File
@@ -108,7 +108,7 @@ splat_precomputed_moves(Move* moveList, Square from, Bitboard occupied, Bitboard
static_assert(Pt != QUEEN && Pt != PAWN, "Unsupported piece type");
// The nth bit in the mask corresponds to the nth square in the piece's pseudo-attacks
uint32_t mask;
u32 mask;
if constexpr (Pt == BISHOP || Pt == ROOK)
{
const Attacks::Magic& magic = Attacks::magic(from, Pt);
+3 -3
View File
@@ -81,20 +81,20 @@ struct MoveSorter {
// Mask of all elements except the insertion point
assert(m.value != std::numeric_limits<int>::min());
const uint16_t expand = _kadd_mask16(_mm512_cmplt_epi32_mask(sortedValues, value), -1);
const u16 expand = _kadd_mask16(_mm512_cmplt_epi32_mask(sortedValues, value), -1);
sortedValues = _mm512_mask_expand_epi32(value, expand, sortedValues);
sortedMoves = _mm512_mask_expand_epi32(move, expand, sortedMoves);
}
void write_sorted(ExtMove* moves, std::ptrdiff_t count) const {
void write_sorted(ExtMove* moves, isize count) const {
static_assert(sizeof(ExtMove) == 8);
assert(count <= MAX_ELEMENTS);
// Because values and moves are stored separately, we need to reassemble the ExtMoves
auto write = [&](int offset, const __m512i indices) {
const __m512i extMoves = _mm512_permutex2var_epi32(sortedMoves, indices, sortedValues);
const std::ptrdiff_t storeCount = count - offset;
const isize storeCount = count - offset;
if (storeCount > 0)
_mm512_mask_storeu_epi64(moves + offset, (1 << storeCount) - 1, extMoves);
+11 -11
View File
@@ -48,7 +48,7 @@ template<PieceType PT>
constexpr auto make_piece_indices_type() {
static_assert(PT != PieceType::PAWN);
std::array<std::array<uint8_t, SQUARE_NB>, SQUARE_NB> out{};
std::array<std::array<u8, SQUARE_NB>, SQUARE_NB> out{};
for (Square from = SQ_A1; from <= SQ_H8; ++from)
{
@@ -67,7 +67,7 @@ template<Piece P>
constexpr auto make_piece_indices_piece() {
static_assert(type_of(P) == PieceType::PAWN);
std::array<std::array<uint8_t, SQUARE_NB>, SQUARE_NB> out{};
std::array<std::array<u8, SQUARE_NB>, SQUARE_NB> out{};
constexpr Color C = color_of(P);
@@ -91,7 +91,7 @@ constexpr auto index_lut2_array() {
constexpr auto QUEEN_ATTACKS = make_piece_indices_type<PieceType::QUEEN>();
constexpr auto KING_ATTACKS = make_piece_indices_type<PieceType::KING>();
std::array<std::array<std::array<uint8_t, SQUARE_NB>, SQUARE_NB>, PIECE_NB> indices{};
std::array<std::array<std::array<u8, SQUARE_NB>, SQUARE_NB>, PIECE_NB> indices{};
indices[W_PAWN] = make_piece_indices_piece<W_PAWN>();
indices[B_PAWN] = make_piece_indices_piece<B_PAWN>();
@@ -155,7 +155,7 @@ constexpr auto helper_offsets = init_threat_offsets().first;
constexpr auto offsets = init_threat_offsets().second;
constexpr auto init_index_luts() {
std::array<std::array<std::array<uint32_t, 2>, PIECE_NB>, PIECE_NB> indices{};
std::array<std::array<std::array<u32, 2>, PIECE_NB>, PIECE_NB> indices{};
for (Piece attacker : AllPieces)
{
@@ -192,13 +192,13 @@ constexpr auto index_lut2 = index_lut2_array();
// Index of a feature for a given king position and another piece on some square
inline sf_always_inline IndexType FullThreats::make_index(
Color perspective, Piece attacker, Square from, Square to, Piece attacked, Square ksq) {
const std::int8_t orientation = OrientTBL[ksq] ^ (56 * perspective);
unsigned from_oriented = uint8_t(from) ^ orientation;
unsigned to_oriented = uint8_t(to) ^ orientation;
const i8 orientation = OrientTBL[ksq] ^ (56 * perspective);
unsigned from_oriented = u8(from) ^ orientation;
unsigned to_oriented = u8(to) ^ orientation;
std::int8_t swap = 8 * perspective;
unsigned attacker_oriented = attacker ^ swap;
unsigned attacked_oriented = attacked ^ swap;
i8 swap = 8 * perspective;
unsigned attacker_oriented = attacker ^ swap;
unsigned attacked_oriented = attacked ^ swap;
return index_lut1[attacker_oriented][attacked_oriented][from_oriented < to_oriented]
+ offsets[attacker_oriented][from_oriented]
@@ -329,7 +329,7 @@ void FullThreats::append_changed_indices(Color perspective,
}
bool FullThreats::requires_refresh(const DiffType& diff, Color perspective) {
return perspective == diff.us && (int8_t(diff.ksq) & 0b100) != (int8_t(diff.prevKsq) & 0b100);
return perspective == diff.us && (i8(diff.ksq) & 0b100) != (i8(diff.prevKsq) & 0b100);
}
} // namespace Stockfish::Eval::NNUE::Features
+2 -3
View File
@@ -18,7 +18,6 @@
#ifndef NNUE_FEATURES_FULL_THREATS_INCLUDED
#define NNUE_FEATURES_FULL_THREATS_INCLUDED
#include <cstdint>
#include "../../misc.h"
#include "../../types.h"
@@ -39,14 +38,14 @@ class FullThreats {
static constexpr const char* Name = "Full_Threats(Friend)";
// Hash value embedded in the evaluation file
static constexpr std::uint32_t HashValue = 0x8f234cb8u;
static constexpr u32 HashValue = 0x8f234cb8u;
// Number of feature dimensions
static constexpr IndexType Dimensions = 60720;
// clang-format off
// Orient a square according to perspective (rotates by 180 for black)
static constexpr std::int8_t OrientTBL[SQUARE_NB] = {
static constexpr i8 OrientTBL[SQUARE_NB] = {
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
SQ_A1, SQ_A1, SQ_A1, SQ_A1, SQ_H1, SQ_H1, SQ_H1, SQ_H1,
+5 -5
View File
@@ -43,18 +43,18 @@ void HalfKAv2_hm::write_indices(const std::array<Piece, SQUARE_NB>& oldPieces,
const __m512i vecOldPieces = _mm512_loadu_si512(oldPieces.data());
const __m512i vecNewPieces = _mm512_loadu_si512(newPieces.data());
alignas(64) static constexpr uint16_t psiTable[COLOR_NB][16] = {
alignas(64) static constexpr u16 psiTable[COLOR_NB][16] = {
{PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE,
PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE},
{PS_NONE, PS_B_PAWN, PS_B_KNIGHT, PS_B_BISHOP, PS_B_ROOK, PS_B_QUEEN, PS_KING, PS_NONE,
PS_NONE, PS_W_PAWN, PS_W_KNIGHT, PS_W_BISHOP, PS_W_ROOK, PS_W_QUEEN, PS_KING, PS_NONE}};
const uint16_t flip = 56 * perspective;
const __m512i orient = _mm512_set1_epi16((uint16_t) OrientTBL[ksq] ^ flip);
const __m512i psi =
const u16 flip = 56 * perspective;
const __m512i orient = _mm512_set1_epi16((u16) OrientTBL[ksq] ^ flip);
const __m512i psi =
_mm512_castsi256_si512(_mm256_loadu_si256((const __m256i*) psiTable[perspective]));
const __m512i psi_plus_bucket =
_mm512_add_epi16(psi, _mm512_set1_epi16((uint16_t) KingBuckets[int(ksq) ^ flip]));
_mm512_add_epi16(psi, _mm512_set1_epi16((u16) KingBuckets[int(ksq) ^ flip]));
__m512i removed_squares = _mm512_maskz_compress_epi8(removedBB, AllSquares);
__m512i added_squares = _mm512_maskz_compress_epi8(addedBB, AllSquares);
+1 -3
View File
@@ -21,8 +21,6 @@
#ifndef NNUE_FEATURES_HALF_KA_V2_HM_H_INCLUDED
#define NNUE_FEATURES_HALF_KA_V2_HM_H_INCLUDED
#include <cstdint>
#include "../../misc.h"
#include "../../types.h"
#include "../nnue_common.h"
@@ -67,7 +65,7 @@ class HalfKAv2_hm {
static constexpr const char* Name = "HalfKAv2_hm(Friend)";
// Hash value embedded in the evaluation file
static constexpr std::uint32_t HashValue = 0x7f234cb8u;
static constexpr u32 HashValue = 0x7f234cb8u;
// Number of feature dimensions
static constexpr IndexType Dimensions =
+17 -22
View File
@@ -49,10 +49,8 @@ namespace Stockfish::Eval::NNUE::Layers {
#ifndef ENABLE_SEQ_OPT
template<IndexType InputDimensions, IndexType PaddedInputDimensions, IndexType OutputDimensions>
static void affine_transform_non_ssse3(std::int32_t* output,
const std::int8_t* weights,
const std::int32_t* biases,
const std::uint8_t* input) {
static void
affine_transform_non_ssse3(i32* output, const i8* weights, const i32* biases, const u8* input) {
#if defined(USE_SSE2) || defined(USE_NEON)
#if defined(USE_SSE2)
// At least a multiple of 16, with SSE2.
@@ -108,14 +106,14 @@ static void affine_transform_non_ssse3(std::int32_t* output,
#endif
}
#else
std::memcpy(output, biases, sizeof(std::int32_t) * OutputDimensions);
std::memcpy(output, biases, sizeof(i32) * OutputDimensions);
// Traverse weights in transpose order to take advantage of input sparsity
for (IndexType i = 0; i < InputDimensions; ++i)
if (input[i])
{
const std::int8_t* w = &weights[i];
const int in = input[i];
const i8* w = &weights[i];
const int in = input[i];
for (IndexType j = 0; j < OutputDimensions; ++j)
output[j] += w[j * PaddedInputDimensions] * in;
}
@@ -128,8 +126,8 @@ template<IndexType InDims, IndexType OutDims>
class AffineTransform {
public:
// Input/output type
using InputType = std::uint8_t;
using OutputType = std::int32_t;
using InputType = u8;
using OutputType = i32;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
@@ -143,8 +141,8 @@ class AffineTransform {
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0xCC03DAE4u;
static constexpr u32 get_hash_value(u32 prevHash) {
u32 hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions;
hashValue ^= prevHash >> 1;
hashValue ^= prevHash << 31;
@@ -183,8 +181,8 @@ class AffineTransform {
return !stream.fail();
}
std::size_t get_content_hash() const {
std::size_t h = 0;
usize get_content_hash() const {
usize h = 0;
hash_combine(h, get_raw_data_hash(biases));
hash_combine(h, get_raw_data_hash(weights));
hash_combine(h, get_hash_value(0));
@@ -254,11 +252,9 @@ class AffineTransform {
#if defined(USE_VNNI)
for (; i < NumChunks; i += 2)
{
const vec_t in0 =
vec_set_32(load_as<std::int32_t>(input + i * sizeof(std::int32_t)));
const vec_t in1 =
vec_set_32(load_as<std::int32_t>(input + (i + 1) * sizeof(std::int32_t)));
const auto col0 =
const vec_t in0 = vec_set_32(load_as<i32>(input + i * sizeof(i32)));
const vec_t in1 = vec_set_32(load_as<i32>(input + (i + 1) * sizeof(i32)));
const auto col0 =
reinterpret_cast<const vec_t*>(&weights[i * OutputDimensions * 4]);
const auto col1 =
reinterpret_cast<const vec_t*>(&weights[(i + 1) * OutputDimensions * 4]);
@@ -275,9 +271,8 @@ class AffineTransform {
#endif
for (; i < NumChunks; ++i)
{
const vec_t in0 =
vec_set_32(load_as<std::int32_t>(input + i * sizeof(std::int32_t)));
const auto col0 =
const vec_t in0 = vec_set_32(load_as<i32>(input + i * sizeof(i32)));
const auto col0 =
reinterpret_cast<const vec_t*>(&weights[i * OutputDimensions * 4]);
for (IndexType k = 0; k < NumRegs; ++k)
@@ -354,7 +349,7 @@ class AffineTransform {
private:
using BiasType = OutputType;
using WeightType = std::int8_t;
using WeightType = i8;
alignas(CacheLineSize) BiasType biases[OutputDimensions];
alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
+23 -26
View File
@@ -44,8 +44,8 @@ template<IndexType InDims, IndexType OutDims>
class AffineTransformSparseInput {
public:
// Input/output type
using InputType = std::uint8_t;
using OutputType = std::int32_t;
using InputType = u8;
using OutputType = i32;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
@@ -68,8 +68,8 @@ class AffineTransformSparseInput {
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0xCC03DAE4u;
static constexpr u32 get_hash_value(u32 prevHash) {
u32 hashValue = 0xCC03DAE4u;
hashValue += OutputDimensions;
hashValue ^= prevHash >> 1;
hashValue ^= prevHash << 31;
@@ -108,8 +108,8 @@ class AffineTransformSparseInput {
return !stream.fail();
}
std::size_t get_content_hash() const {
std::size_t h = 0;
usize get_content_hash() const {
usize h = 0;
hash_combine(h, get_raw_data_hash(biases));
hash_combine(h, get_raw_data_hash(weights));
hash_combine(h, get_hash_value(0));
@@ -179,7 +179,7 @@ class AffineTransformSparseInput {
acc[k] = biasvec[k];
// convince GCC to not do weird pointer arithmetic in the following loops
const std::int8_t* weights_cp = weights;
const i8* weights_cp = weights;
#if defined(USE_AVX512)
const auto* start = nnzInfo.nnz;
@@ -190,16 +190,13 @@ class AffineTransformSparseInput {
#if defined(USE_VNNI)
while (start < end - 2)
{
const std::ptrdiff_t i0 = *start++;
const std::ptrdiff_t i1 = *start++;
const std::ptrdiff_t i2 = *start++;
const invec_t in0 =
vec_set_32(load_as<std::int32_t>(input + i0 * sizeof(std::int32_t)));
const invec_t in1 =
vec_set_32(load_as<std::int32_t>(input + i1 * sizeof(std::int32_t)));
const invec_t in2 =
vec_set_32(load_as<std::int32_t>(input + i2 * sizeof(std::int32_t)));
const auto col0 =
const isize i0 = *start++;
const isize i1 = *start++;
const isize i2 = *start++;
const invec_t in0 = vec_set_32(load_as<i32>(input + i0 * sizeof(i32)));
const invec_t in1 = vec_set_32(load_as<i32>(input + i1 * sizeof(i32)));
const invec_t in2 = vec_set_32(load_as<i32>(input + i2 * sizeof(i32)));
const auto col0 =
reinterpret_cast<const invec_t*>(&weights_cp[i0 * OutputDimensions * ChunkSize]);
const auto col1 =
reinterpret_cast<const invec_t*>(&weights_cp[i1 * OutputDimensions * ChunkSize]);
@@ -219,8 +216,8 @@ class AffineTransformSparseInput {
while (start < end)
{
const std::ptrdiff_t i = *start++;
const invec_t in = vec_set_32(load_as<std::int32_t>(input + i * sizeof(std::int32_t)));
const isize i = *start++;
const invec_t in = vec_set_32(load_as<i32>(input + i * sizeof(i32)));
const auto col =
reinterpret_cast<const invec_t*>(&weights_cp[i * OutputDimensions * ChunkSize]);
for (IndexType k = 0; k < NumAccums; ++k)
@@ -231,10 +228,10 @@ class AffineTransformSparseInput {
for (IndexType k = 0; k < InputDimensions / 256; ++k)
{
uint64_t bits = load_as<uint64_t>(nnzInfo.bitset + k * 8);
ptrdiff_t base = k * 64;
u64 bits = load_as<u64>(nnzInfo.bitset + k * 8);
isize base = k * 64;
auto* base_addr = input + base * sizeof(std::int32_t);
auto* base_addr = input + base * sizeof(i32);
auto* weights_base = &weights_cp[base * OutputDimensions * ChunkSize];
#if defined(USE_NEON_DOTPROD) && defined(__GNUC__) && !defined(__clang__)
@@ -253,8 +250,8 @@ class AffineTransformSparseInput {
while (bits)
{
ptrdiff_t i = pop_lsb(bits);
const auto* input_addr = base_addr + i * sizeof(std::int32_t);
isize i = pop_lsb(bits);
const auto* input_addr = base_addr + i * sizeof(i32);
auto col =
reinterpret_cast<const invec_t*>(&weights_base[i * OutputDimensions * ChunkSize]);
@@ -263,7 +260,7 @@ class AffineTransformSparseInput {
#undef FIX_GCC15_MISOPTIMIZATION
#endif
const invec_t in = vec_set_32(load_as<std::int32_t>(input_addr));
const invec_t in = vec_set_32(load_as<i32>(input_addr));
for (IndexType l = 0; l < NumAccums; ++l)
vec_add_dpbusd_32(acc[l], in, col[l]);
}
@@ -287,7 +284,7 @@ class AffineTransformSparseInput {
private:
using BiasType = OutputType;
using WeightType = std::int8_t;
using WeightType = i8;
alignas(CacheLineSize) BiasType biases[OutputDimensions];
alignas(CacheLineSize) WeightType weights[OutputDimensions * PaddedInputDimensions];
+6 -6
View File
@@ -34,8 +34,8 @@ template<IndexType InDims, int WeightScaleBitsLocal = WeightScaleBits>
class ClippedReLU {
public:
// Input/output type
using InputType = std::int32_t;
using OutputType = std::uint8_t;
using InputType = i32;
using OutputType = u8;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
@@ -46,8 +46,8 @@ class ClippedReLU {
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0x538D24C7u;
static constexpr u32 get_hash_value(u32 prevHash) {
u32 hashValue = 0x538D24C7u;
hashValue += prevHash;
// TODO: consider including WeightScaleBitsLocal in the hash value.
// For now omitted on purpose because not written by trainer (yet)
@@ -60,8 +60,8 @@ class ClippedReLU {
// Write network parameters
bool write_parameters(std::ostream&) const { return true; }
std::size_t get_content_hash() const {
std::size_t h = 0;
usize get_content_hash() const {
usize h = 0;
hash_combine(h, get_hash_value(0));
return h;
}
+6 -6
View File
@@ -35,8 +35,8 @@ template<IndexType InDims, int WeightScaleBitsLocal = WeightScaleBits>
class SqrClippedReLU {
public:
// Input/output type
using InputType = std::int32_t;
using OutputType = std::uint8_t;
using InputType = i32;
using OutputType = u8;
// Number of input/output dimensions
static constexpr IndexType InputDimensions = InDims;
@@ -47,8 +47,8 @@ class SqrClippedReLU {
using OutputBuffer = OutputType[PaddedOutputDimensions];
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value(std::uint32_t prevHash) {
std::uint32_t hashValue = 0x538D24C7u;
static constexpr u32 get_hash_value(u32 prevHash) {
u32 hashValue = 0x538D24C7u;
hashValue += prevHash;
// TODO: consider including WeightScaleBitsLocal in the hash value.
// For now omitted on purpose because not written by trainer (yet)
@@ -61,8 +61,8 @@ class SqrClippedReLU {
// Write network parameters
bool write_parameters(std::ostream&) const { return true; }
std::size_t get_content_hash() const {
std::size_t h = 0;
usize get_content_hash() const {
usize h = 0;
hash_combine(h, get_hash_value(0));
return h;
}
+22 -24
View File
@@ -67,8 +67,8 @@ namespace Detail {
template<typename T>
bool read_parameters(std::istream& stream, T& reference) {
std::uint32_t header;
header = read_little_endian<std::uint32_t>(stream);
u32 header;
header = read_little_endian<u32>(stream);
if (!stream || header != T::get_hash_value())
return false;
return reference.read_parameters(stream);
@@ -78,7 +78,7 @@ bool read_parameters(std::istream& stream, T& reference) {
template<typename T>
bool write_parameters(std::ostream& stream, const T& reference) {
write_little_endian<std::uint32_t>(stream, T::get_hash_value());
write_little_endian<u32>(stream, T::get_hash_value());
return reference.write_parameters(stream);
}
@@ -142,7 +142,7 @@ NetworkOutput Network::evaluate(const Position& pos,
AccumulatorStack& accumulatorStack,
AccumulatorCaches& cache) const {
constexpr uint64_t alignment = CacheLineSize;
constexpr u64 alignment = CacheLineSize;
alignas(alignment) TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
@@ -188,7 +188,7 @@ void Network::verify(std::string evalfilePath,
if (f)
{
size_t size = sizeof(featureTransformer) + sizeof(NetworkArchitecture) * LayerStacks;
usize size = sizeof(featureTransformer) + sizeof(NetworkArchitecture) * LayerStacks;
f("NNUE evaluation using " + evalfilePath + " (" + std::to_string(size / (1024 * 1024))
+ "MiB, (" + std::to_string(featureTransformer.InputDimensions) + ", "
+ std::to_string(network[0].TransformedFeatureDimensions) + ", "
@@ -202,7 +202,7 @@ NnueEvalTrace Network::trace_evaluate(const Position& pos,
AccumulatorStack& accumulatorStack,
AccumulatorCaches& cache) const {
constexpr uint64_t alignment = CacheLineSize;
constexpr u64 alignment = CacheLineSize;
alignas(alignment) TransformedFeatureType transformedFeatures[FeatureTransformer::BufferSize];
@@ -241,7 +241,7 @@ void Network::load_internal() {
// C++ way to prepare a buffer for a memory stream
class MemoryBuffer: public std::basic_streambuf<char> {
public:
MemoryBuffer(char* p, size_t n) {
MemoryBuffer(char* p, usize n) {
setg(p, p, p + n);
setp(p, p + n);
}
@@ -253,7 +253,7 @@ void Network::load_internal() {
#endif
MemoryBuffer buffer(const_cast<char*>(reinterpret_cast<const char*>(gEmbeddedNNUEData)),
size_t(gEmbeddedNNUESize));
usize(gEmbeddedNNUESize));
std::istream stream(&buffer);
auto description = load(stream);
@@ -287,11 +287,11 @@ std::optional<std::string> Network::load(std::istream& stream) {
}
std::size_t Network::get_content_hash() const {
usize Network::get_content_hash() const {
if (!initialized)
return 0;
std::size_t h = 0;
usize h = 0;
hash_combine(h, featureTransformer);
for (auto&& layerstack : network)
hash_combine(h, layerstack);
@@ -300,12 +300,12 @@ std::size_t Network::get_content_hash() const {
}
// Read network header
bool Network::read_header(std::istream& stream, std::uint32_t* hashValue, std::string* desc) const {
std::uint32_t version, size;
bool Network::read_header(std::istream& stream, u32* hashValue, std::string* desc) const {
u32 version, size;
version = read_little_endian<std::uint32_t>(stream);
*hashValue = read_little_endian<std::uint32_t>(stream);
size = read_little_endian<std::uint32_t>(stream);
version = read_little_endian<u32>(stream);
*hashValue = read_little_endian<u32>(stream);
size = read_little_endian<u32>(stream);
if (!stream || version != Version)
return false;
desc->resize(size);
@@ -315,26 +315,24 @@ bool Network::read_header(std::istream& stream, std::uint32_t* hashValue, std::s
// Write network header
bool Network::write_header(std::ostream& stream,
std::uint32_t hashValue,
const std::string& desc) const {
write_little_endian<std::uint32_t>(stream, Version);
write_little_endian<std::uint32_t>(stream, hashValue);
write_little_endian<std::uint32_t>(stream, std::uint32_t(desc.size()));
bool Network::write_header(std::ostream& stream, u32 hashValue, const std::string& desc) const {
write_little_endian<u32>(stream, Version);
write_little_endian<u32>(stream, hashValue);
write_little_endian<u32>(stream, u32(desc.size()));
stream.write(&desc[0], desc.size());
return !stream.fail();
}
bool Network::read_parameters(std::istream& stream, std::string& netDescription) {
std::uint32_t hashValue;
u32 hashValue;
if (!read_header(stream, &hashValue, &netDescription))
return false;
if (hashValue != Network::hash)
return false;
if (!Detail::read_parameters(stream, featureTransformer))
return false;
for (std::size_t i = 0; i < LayerStacks; ++i)
for (usize i = 0; i < LayerStacks; ++i)
{
if (!Detail::read_parameters(stream, network[i]))
return false;
@@ -348,7 +346,7 @@ bool Network::write_parameters(std::ostream& stream, const std::string& netDescr
return false;
if (!Detail::write_parameters(stream, featureTransformer))
return false;
for (std::size_t i = 0; i < LayerStacks; ++i)
for (usize i = 0; i < LayerStacks; ++i)
{
if (!Detail::write_parameters(stream, network[i]))
return false;
+6 -7
View File
@@ -19,8 +19,6 @@
#ifndef NETWORK_H_INCLUDED
#define NETWORK_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iostream>
#include <memory>
@@ -30,6 +28,7 @@
#include <tuple>
#include "../types.h"
#include "../misc.h"
#include "nnue_architecture.h"
#include "nnue_feature_transformer.h"
#include "nnue_misc.h"
@@ -62,7 +61,7 @@ class Network {
void load(const std::string& rootDirectory, std::string evalfilePath);
bool save(const std::optional<std::string>& filename) const;
std::size_t get_content_hash() const;
usize get_content_hash() const;
NetworkOutput evaluate(const Position& pos,
AccumulatorStack& accumulatorStack,
@@ -83,8 +82,8 @@ class Network {
bool save(std::ostream&, const std::string&, const std::string&) const;
std::optional<std::string> load(std::istream&);
bool read_header(std::istream&, std::uint32_t*, std::string*) const;
bool write_header(std::ostream&, std::uint32_t, const std::string&) const;
bool read_header(std::istream&, u32*, std::string*) const;
bool write_header(std::ostream&, u32, const std::string&) const;
bool read_parameters(std::istream&, std::string&);
bool write_parameters(std::ostream&, const std::string&) const;
@@ -100,7 +99,7 @@ class Network {
bool initialized = false;
// Hash value of evaluation function structure
static constexpr std::uint32_t hash =
static constexpr u32 hash =
FeatureTransformer::get_hash_value() ^ NetworkArchitecture::get_hash_value();
friend struct AccumulatorCaches;
@@ -111,7 +110,7 @@ class Network {
template<>
struct std::hash<Stockfish::Eval::NNUE::Network> {
std::size_t operator()(const Stockfish::Eval::NNUE::Network& network) const noexcept {
Stockfish::usize operator()(const Stockfish::Eval::NNUE::Network& network) const noexcept {
return network.get_content_hash();
}
};
+51 -52
View File
@@ -19,7 +19,6 @@
#include "nnue_accumulator.h"
#include <cassert>
#include <cstdint>
#include <new>
#include <type_traits>
@@ -157,9 +156,9 @@ void AccumulatorStack::evaluate_side(Color perspective,
// Find the earliest usable accumulator, this can either be a computed accumulator or the accumulator
// state just before a change that requires full refresh.
template<typename FeatureSet>
std::size_t AccumulatorStack::find_last_usable_accumulator(Color perspective) const noexcept {
usize AccumulatorStack::find_last_usable_accumulator(Color perspective) const noexcept {
for (std::size_t curr_idx = size - 1; curr_idx > 0; curr_idx--)
for (usize curr_idx = size - 1; curr_idx > 0; curr_idx--)
{
if (accumulators<FeatureSet>()[curr_idx].computed[perspective])
return curr_idx;
@@ -175,14 +174,14 @@ template<typename FeatureSet>
void AccumulatorStack::forward_update_incremental(Color perspective,
const Position& pos,
const FeatureTransformer& featureTransformer,
const std::size_t begin) noexcept {
const usize begin) noexcept {
assert(begin < accumulators<FeatureSet>().size());
assert(accumulators<FeatureSet>()[begin].computed[perspective]);
const Square ksq = pos.square<KING>(perspective);
for (std::size_t next = begin + 1; next < size; next++)
for (usize next = begin + 1; next < size; next++)
{
update_accumulator_incremental<true>(perspective, featureTransformer, ksq,
mut_accumulators<FeatureSet>()[next],
@@ -197,7 +196,7 @@ void AccumulatorStack::backward_update_incremental(Color perspective,
const Position& pos,
const FeatureTransformer& featureTransformer,
const std::size_t end) noexcept {
const usize end) noexcept {
assert(end < accumulators<FeatureSet>().size());
assert(end < size);
@@ -205,7 +204,7 @@ void AccumulatorStack::backward_update_incremental(Color perspective,
const Square ksq = pos.square<KING>(perspective);
for (std::int64_t next = std::int64_t(size) - 2; next >= std::int64_t(end); next--)
for (i64 next = i64(size) - 2; next >= i64(end); next--)
update_accumulator_incremental<false>(perspective, featureTransformer, ksq,
mut_accumulators<FeatureSet>()[next],
accumulators<FeatureSet>()[next + 1]);
@@ -299,9 +298,9 @@ struct AccumulatorUpdateContext {
for (int i = 0; i < removed.ssize(); ++i)
{
size_t index = removed[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
usize index = removed[i];
const usize offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
#ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
@@ -317,9 +316,9 @@ struct AccumulatorUpdateContext {
for (int i = 0; i < added.ssize(); ++i)
{
size_t index = added[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
usize index = added[i];
const usize offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
#ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
@@ -351,23 +350,23 @@ struct AccumulatorUpdateContext {
for (int i = 0; i < removed.ssize(); ++i)
{
size_t index = removed[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
usize index = removed[i];
const usize offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
&featureTransformer.threatPsqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
for (usize k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]);
}
for (int i = 0; i < added.ssize(); ++i)
{
size_t index = added[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
usize index = added[i];
const usize offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt = reinterpret_cast<const psqt_vec_t*>(
&featureTransformer.threatPsqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
for (usize k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_add_psqt_32(psqt[k], columnPsqt[k]);
}
@@ -387,7 +386,7 @@ struct AccumulatorUpdateContext {
for (IndexType j = 0; j < Dimensions; ++j)
toAcc[j] -= featureTransformer.threatWeights[offset + j];
for (std::size_t k = 0; k < PSQTBuckets; ++k)
for (usize k = 0; k < PSQTBuckets; ++k)
toPsqtAcc[k] -= featureTransformer.threatPsqtWeights[index * PSQTBuckets + k];
}
@@ -398,7 +397,7 @@ struct AccumulatorUpdateContext {
for (IndexType j = 0; j < Dimensions; ++j)
toAcc[j] += featureTransformer.threatWeights[offset + j];
for (std::size_t k = 0; k < PSQTBuckets; ++k)
for (usize k = 0; k < PSQTBuckets; ++k)
toPsqtAcc[k] += featureTransformer.threatPsqtWeights[index * PSQTBuckets + k];
}
@@ -511,8 +510,8 @@ Bitboard get_changed_pieces(const std::array<Piece, SQUARE_NB>& oldPieces,
{
const __m256i old_v = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(&oldPieces[i]));
const __m256i new_v = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(&newPieces[i]));
const __m256i cmpEqual = _mm256_cmpeq_epi8(old_v, new_v);
const std::uint32_t equalMask = _mm256_movemask_epi8(cmpEqual);
const __m256i cmpEqual = _mm256_cmpeq_epi8(old_v, new_v);
const u32 equalMask = _mm256_movemask_epi8(cmpEqual);
sameBB |= static_cast<Bitboard>(equalMask) << i;
}
return ~sameBB;
@@ -551,8 +550,8 @@ Bitboard get_changed_pieces(const std::array<Piece, SQUARE_NB>& oldPieces,
return changed;
#elif defined(USE_NEON)
uint8x16x4_t old_v = vld4q_u8(reinterpret_cast<const uint8_t*>(oldPieces.data()));
uint8x16x4_t new_v = vld4q_u8(reinterpret_cast<const uint8_t*>(newPieces.data()));
uint8x16x4_t old_v = vld4q_u8(reinterpret_cast<const u8*>(oldPieces.data()));
uint8x16x4_t new_v = vld4q_u8(reinterpret_cast<const u8*>(newPieces.data()));
auto cmp = [=](const int i) { return vceqq_u8(old_v.val[i], new_v.val[i]); };
uint8x16_t cmp0_1 = vsriq_n_u8(cmp(1), cmp(0), 1);
@@ -627,18 +626,18 @@ void update_accumulator_refresh_cache(Color perspecti
for (int i = 0; i < removed.ssize(); ++i)
{
size_t index = removed[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_t*>(&weights[offset]);
usize index = removed[i];
const usize offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_t*>(&weights[offset]);
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = vec_sub_16(acc[k], column[k]);
}
for (int i = 0; i < added.ssize(); ++i)
{
size_t index = added[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_t*>(&weights[offset]);
usize index = added[i];
const usize offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_t*>(&weights[offset]);
for (IndexType k = 0; k < Tiling::NumRegs; ++k)
acc[k] = vec_add_16(acc[k], column[k]);
@@ -664,22 +663,22 @@ void update_accumulator_refresh_cache(Color perspecti
for (int i = 0; i < removed.ssize(); ++i)
{
size_t index = removed[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
usize index = removed[i];
const usize offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
reinterpret_cast<const psqt_vec_t*>(&featureTransformer.psqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
for (usize k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_sub_psqt_32(psqt[k], columnPsqt[k]);
}
for (int i = 0; i < added.ssize(); ++i)
{
size_t index = added[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
usize index = added[i];
const usize offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
reinterpret_cast<const psqt_vec_t*>(&featureTransformer.psqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
for (usize k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_add_psqt_32(psqt[k], columnPsqt[k]);
}
@@ -697,7 +696,7 @@ void update_accumulator_refresh_cache(Color perspecti
for (IndexType j = 0; j < Dimensions; ++j)
entry.accumulation[j] -= featureTransformer.weights[offset + j];
for (std::size_t k = 0; k < PSQTBuckets; ++k)
for (usize k = 0; k < PSQTBuckets; ++k)
entry.psqtAccumulation[k] -= featureTransformer.psqtWeights[index * PSQTBuckets + k];
}
for (const auto index : added)
@@ -706,7 +705,7 @@ void update_accumulator_refresh_cache(Color perspecti
for (IndexType j = 0; j < Dimensions; ++j)
entry.accumulation[j] += featureTransformer.weights[offset + j];
for (std::size_t k = 0; k < PSQTBuckets; ++k)
for (usize k = 0; k < PSQTBuckets; ++k)
entry.psqtAccumulation[k] += featureTransformer.psqtWeights[index * PSQTBuckets + k];
}
@@ -747,9 +746,9 @@ void update_threats_accumulator_full(Color perspec
for (; i < active.ssize(); ++i)
{
size_t index = active[i];
const size_t offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
usize index = active[i];
const usize offset = Dimensions * index;
auto* column = reinterpret_cast<const vec_i8_t*>(&threatWeights[offset]);
#ifdef USE_NEON
for (IndexType k = 0; k < Tiling::NumRegs; k += 2)
@@ -779,12 +778,12 @@ void update_threats_accumulator_full(Color perspec
for (int i = 0; i < active.ssize(); ++i)
{
size_t index = active[i];
const size_t offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
usize index = active[i];
const usize offset = PSQTBuckets * index + j * Tiling::PsqtTileHeight;
auto* columnPsqt =
reinterpret_cast<const psqt_vec_t*>(&featureTransformer.threatPsqtWeights[offset]);
for (std::size_t k = 0; k < Tiling::NumPsqtRegs; ++k)
for (usize k = 0; k < Tiling::NumPsqtRegs; ++k)
psqt[k] = vec_add_psqt_32(psqt[k], columnPsqt[k]);
}
@@ -797,7 +796,7 @@ void update_threats_accumulator_full(Color perspec
for (IndexType j = 0; j < Dimensions; ++j)
accumulator.accumulation[perspective][j] = 0;
for (std::size_t k = 0; k < PSQTBuckets; ++k)
for (usize k = 0; k < PSQTBuckets; ++k)
accumulator.psqtAccumulation[perspective][k] = 0;
for (const auto index : active)
@@ -808,7 +807,7 @@ void update_threats_accumulator_full(Color perspec
accumulator.accumulation[perspective][j] +=
featureTransformer.threatWeights[offset + j];
for (std::size_t k = 0; k < PSQTBuckets; ++k)
for (usize k = 0; k < PSQTBuckets; ++k)
accumulator.psqtAccumulation[perspective][k] +=
featureTransformer.threatPsqtWeights[index * PSQTBuckets + k];
}
+9 -9
View File
@@ -23,11 +23,11 @@
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <utility>
#include "../types.h"
#include "../misc.h"
#include "nnue_architecture.h"
#include "nnue_common.h"
@@ -43,9 +43,9 @@ class FeatureTransformer;
// Class that holds the result of affine transformation of input features
struct alignas(CacheLineSize) Accumulator {
std::array<std::array<std::int16_t, L1>, COLOR_NB> accumulation;
std::array<std::array<std::int32_t, PSQTBuckets>, COLOR_NB> psqtAccumulation;
std::array<bool, COLOR_NB> computed = {};
std::array<std::array<i16, L1>, COLOR_NB> accumulation;
std::array<std::array<i32, PSQTBuckets>, COLOR_NB> psqtAccumulation;
std::array<bool, COLOR_NB> computed = {};
};
@@ -106,7 +106,7 @@ struct AccumulatorState: public Accumulator {
class AccumulatorStack {
public:
static constexpr std::size_t MaxSize = MAX_PLY + 1;
static constexpr usize MaxSize = MAX_PLY + 1;
template<typename T>
[[nodiscard]] const AccumulatorState<T>& latest() const noexcept;
@@ -138,23 +138,23 @@ class AccumulatorStack {
[[maybe_unused]] AccumulatorCaches& cache) noexcept;
template<typename FeatureSet>
[[nodiscard]] std::size_t find_last_usable_accumulator(Color perspective) const noexcept;
[[nodiscard]] usize find_last_usable_accumulator(Color perspective) const noexcept;
template<typename FeatureSet>
void forward_update_incremental(Color perspective,
const Position& pos,
const FeatureTransformer& featureTransformer,
const std::size_t begin) noexcept;
const usize begin) noexcept;
template<typename FeatureSet>
void backward_update_incremental(Color perspective,
const Position& pos,
const FeatureTransformer& featureTransformer,
const std::size_t end) noexcept;
const usize end) noexcept;
std::array<AccumulatorState<PSQFeatureSet>, MaxSize> psq_accumulators;
std::array<AccumulatorState<ThreatFeatureSet>, MaxSize> threat_accumulators;
std::size_t size = 1;
usize size = 1;
};
} // namespace Stockfish::Eval::NNUE
+14 -14
View File
@@ -67,9 +67,9 @@ struct NetworkArchitecture {
Layers::AffineTransform<FC_1_OUTPUTS, 1> fc_2;
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() {
static constexpr u32 get_hash_value() {
// input slice hash
std::uint32_t hashValue = 0xEC42E90Du;
u32 hashValue = 0xEC42E90Du;
hashValue ^= TransformedFeatureDimensions * 2;
hashValue = decltype(fc_0)::get_hash_value(hashValue);
@@ -97,8 +97,8 @@ struct NetworkArchitecture {
&& fc_2.write_parameters(stream);
}
std::int32_t propagate(const TransformedFeatureType* transformedFeatures,
const NNZInfo<L1>& nnzInfo) const {
i32 propagate(const TransformedFeatureType* transformedFeatures,
const NNZInfo<L1>& nnzInfo) const {
struct alignas(CacheLineSize) Buffer {
alignas(CacheLineSize) typename decltype(fc_0)::OutputBuffer fc_0_out;
alignas(CacheLineSize) typename decltype(ac_sqr_0)::OutputType
@@ -126,21 +126,20 @@ struct NetworkArchitecture {
// for int8 activations and weights this is (L1 + L3) * 16129 making
// fwdOut safe from overflow until (L1 + L3) > 133,144
// first layer and last layer use WeightScaleBits + 1
std::int32_t fwdOut = buffer.fc_2_out[0] + buffer.fc_0_out[FC_0_OUTPUTS];
i32 fwdOut = buffer.fc_2_out[0] + buffer.fc_0_out[FC_0_OUTPUTS];
// fwdOut is such that 1.0 is equal to HiddenOneVal*(1<<WeightScaleBits)*2 in
// quantized form, but we want 1.0 to be equal to 600*OutputScale
// to make overflow impossible we cast to int64_t
constexpr std::int64_t multiplier = 600 * OutputScale;
constexpr std::int64_t denominator = static_cast<std::int64_t>(HiddenOneVal)
* static_cast<std::int64_t>(1U << WeightScaleBits) * 2;
// to make overflow impossible we cast to i64
constexpr i64 multiplier = 600 * OutputScale;
constexpr i64 denominator =
static_cast<i64>(HiddenOneVal) * static_cast<i64>(1U << WeightScaleBits) * 2;
std::int32_t outputValue =
static_cast<std::int32_t>((static_cast<std::int64_t>(fwdOut) * multiplier) / denominator);
i32 outputValue = static_cast<i32>((static_cast<i64>(fwdOut) * multiplier) / denominator);
return outputValue;
}
std::size_t get_content_hash() const {
std::size_t h = 0;
usize get_content_hash() const {
usize h = 0;
hash_combine(h, fc_0.get_content_hash());
hash_combine(h, ac_sqr_0.get_content_hash());
hash_combine(h, ac_0.get_content_hash());
@@ -156,7 +155,8 @@ struct NetworkArchitecture {
template<>
struct std::hash<Stockfish::Eval::NNUE::NetworkArchitecture> {
std::size_t operator()(const Stockfish::Eval::NNUE::NetworkArchitecture& arch) const noexcept {
Stockfish::usize
operator()(const Stockfish::Eval::NNUE::NetworkArchitecture& arch) const noexcept {
return arch.get_content_hash();
}
};
+46 -46
View File
@@ -55,14 +55,14 @@
namespace Stockfish::Eval::NNUE {
using BiasType = std::int16_t;
using ThreatWeightType = std::int8_t;
using WeightType = std::int16_t;
using PSQTWeightType = std::int32_t;
using IndexType = std::uint32_t;
using BiasType = i16;
using ThreatWeightType = i8;
using WeightType = i16;
using PSQTWeightType = i32;
using IndexType = u32;
// Version of the evaluation file
constexpr std::uint32_t Version = 0x6A448AFAu;
constexpr u32 Version = 0x6A448AFAu;
// Constant used in evaluation value calculation
constexpr int OutputScale = 16;
@@ -73,32 +73,32 @@ constexpr int HiddenOneVal = 128;
constexpr int HiddenMaxVal = 127;
// Size of cache line (in bytes)
constexpr std::size_t CacheLineSize = 64;
constexpr usize CacheLineSize = 64;
constexpr const char Leb128MagicString[] = "COMPRESSED_LEB128";
constexpr const std::size_t Leb128MagicStringSize = sizeof(Leb128MagicString) - 1;
constexpr const char Leb128MagicString[] = "COMPRESSED_LEB128";
constexpr const usize Leb128MagicStringSize = sizeof(Leb128MagicString) - 1;
// SIMD width (in bytes)
#if defined(USE_AVX2)
constexpr std::size_t SimdWidth = 32;
constexpr usize SimdWidth = 32;
#elif defined(USE_LASX)
constexpr std::size_t SimdWidth = 32;
constexpr usize SimdWidth = 32;
#elif defined(USE_SSE2)
constexpr std::size_t SimdWidth = 16;
constexpr usize SimdWidth = 16;
#elif defined(USE_NEON)
constexpr std::size_t SimdWidth = 16;
constexpr usize SimdWidth = 16;
#elif defined(USE_LSX)
constexpr std::size_t SimdWidth = 16;
constexpr usize SimdWidth = 16;
#endif
constexpr std::size_t MaxSimdWidth = 32;
constexpr usize MaxSimdWidth = 32;
// Type of input feature after conversion
using TransformedFeatureType = std::uint8_t;
using TransformedFeatureType = u8;
// Round n up to be a multiple of base
template<typename IntType>
@@ -118,11 +118,11 @@ inline IntType read_little_endian(std::istream& stream) {
stream.read(reinterpret_cast<char*>(&result), sizeof(IntType));
else
{
std::uint8_t u[sizeof(IntType)];
u8 u[sizeof(IntType)];
std::make_unsigned_t<IntType> v = 0;
stream.read(reinterpret_cast<char*>(u), sizeof(IntType));
for (std::size_t i = 0; i < sizeof(IntType); ++i)
for (usize i = 0; i < sizeof(IntType); ++i)
v = (v << 8) | u[sizeof(IntType) - i - 1];
std::memcpy(&result, &v, sizeof(IntType));
@@ -143,20 +143,20 @@ inline void write_little_endian(std::ostream& stream, IntType value) {
stream.write(reinterpret_cast<const char*>(&value), sizeof(IntType));
else
{
std::uint8_t u[sizeof(IntType)];
u8 u[sizeof(IntType)];
std::make_unsigned_t<IntType> v = value;
std::size_t i = 0;
usize i = 0;
// if constexpr to silence the warning about shift by 8
if constexpr (sizeof(IntType) > 1)
{
for (; i + 1 < sizeof(IntType); ++i)
{
u[i] = std::uint8_t(v);
u[i] = u8(v);
v >>= 8;
}
}
u[i] = std::uint8_t(v);
u[i] = u8(v);
stream.write(reinterpret_cast<char*>(u), sizeof(IntType));
}
@@ -166,11 +166,11 @@ inline void write_little_endian(std::ostream& stream, IntType value) {
// Read integers in bulk from a little-endian stream.
// This reads N integers from stream s and puts them in array out.
template<typename IntType>
inline void read_little_endian(std::istream& stream, IntType* out, std::size_t count) {
inline void read_little_endian(std::istream& stream, IntType* out, usize count) {
if (IsLittleEndian)
stream.read(reinterpret_cast<char*>(out), sizeof(IntType) * count);
else
for (std::size_t i = 0; i < count; ++i)
for (usize i = 0; i < count; ++i)
out[i] = read_little_endian<IntType>(stream);
}
@@ -178,39 +178,39 @@ inline void read_little_endian(std::istream& stream, IntType* out, std::size_t c
// Write integers in bulk to a little-endian stream.
// This takes N integers from array values and writes them on stream s.
template<typename IntType>
inline void write_little_endian(std::ostream& stream, const IntType* values, std::size_t count) {
inline void write_little_endian(std::ostream& stream, const IntType* values, usize count) {
if (IsLittleEndian)
stream.write(reinterpret_cast<const char*>(values), sizeof(IntType) * count);
else
for (std::size_t i = 0; i < count; ++i)
for (usize i = 0; i < count; ++i)
write_little_endian<IntType>(stream, values[i]);
}
// Read N signed integers from the stream s, putting them in the array out.
// The stream is assumed to be compressed using the signed LEB128 format.
// See https://en.wikipedia.org/wiki/LEB128 for a description of the compression scheme.
template<typename BufType, typename IntType, std::size_t Count>
template<typename BufType, typename IntType, usize Count>
inline void read_leb_128_detail(std::istream& stream,
std::array<IntType, Count>& out,
std::uint32_t& bytes_left,
u32& bytes_left,
BufType& buf,
std::uint32_t& buf_pos) {
u32& buf_pos) {
static_assert(std::is_signed_v<IntType>, "Not implemented for unsigned types");
static_assert(sizeof(IntType) <= 4, "Not implemented for types larger than 32 bit");
IntType result = 0;
size_t shift = 0, i = 0;
usize shift = 0, i = 0;
while (i < Count)
{
if (buf_pos == buf.size())
{
stream.read(reinterpret_cast<char*>(buf.data()),
std::min(std::size_t(bytes_left), buf.size()));
std::min(usize(bytes_left), buf.size()));
buf_pos = 0;
}
std::uint8_t byte = buf[buf_pos++];
u8 byte = buf[buf_pos++];
--bytes_left;
result |= (byte & 0x7f) << (shift % 32);
shift += 7;
@@ -231,9 +231,9 @@ inline void read_leb_128(std::istream& stream, Arrays&... outs) {
stream.read(leb128MagicString, Leb128MagicStringSize);
assert(strncmp(Leb128MagicString, leb128MagicString, Leb128MagicStringSize) == 0);
auto bytes_left = read_little_endian<std::uint32_t>(stream);
std::array<std::uint8_t, 8192> buf;
std::uint32_t buf_pos = std::uint32_t(buf.size());
auto bytes_left = read_little_endian<u32>(stream);
std::array<u8, 8192> buf;
u32 buf_pos = u32(buf.size());
(read_leb_128_detail(stream, outs, bytes_left, buf, buf_pos), ...);
@@ -245,7 +245,7 @@ inline void read_leb_128(std::istream& stream, Arrays&... outs) {
// This takes N integers from array values, compresses them with
// the LEB128 algorithm and writes the result on the stream s.
// See https://en.wikipedia.org/wiki/LEB128 for a description of the compression scheme.
template<typename IntType, std::size_t Count>
template<typename IntType, usize Count>
inline void write_leb_128(std::ostream& stream, const std::array<IntType, Count>& values) {
// Write our LEB128 magic string
@@ -253,11 +253,11 @@ inline void write_leb_128(std::ostream& stream, const std::array<IntType, Count>
static_assert(std::is_signed_v<IntType>, "Not implemented for unsigned types");
std::uint32_t byte_count = 0;
for (std::size_t i = 0; i < Count; ++i)
u32 byte_count = 0;
for (usize i = 0; i < Count; ++i)
{
IntType value = values[i];
std::uint8_t byte;
IntType value = values[i];
u8 byte;
do
{
byte = value & 0x7f;
@@ -268,9 +268,9 @@ inline void write_leb_128(std::ostream& stream, const std::array<IntType, Count>
write_little_endian(stream, byte_count);
const std::uint32_t BUF_SIZE = 4096;
std::uint8_t buf[BUF_SIZE];
std::uint32_t buf_pos = 0;
const u32 BUF_SIZE = 4096;
u8 buf[BUF_SIZE];
u32 buf_pos = 0;
auto flush = [&]() {
if (buf_pos > 0)
@@ -280,18 +280,18 @@ inline void write_leb_128(std::ostream& stream, const std::array<IntType, Count>
}
};
auto write = [&](std::uint8_t b) {
auto write = [&](u8 b) {
buf[buf_pos++] = b;
if (buf_pos == BUF_SIZE)
flush();
};
for (std::size_t i = 0; i < Count; ++i)
for (usize i = 0; i < Count; ++i)
{
IntType value = values[i];
while (true)
{
std::uint8_t byte = value & 0x7f;
u8 byte = value & 0x7f;
value >>= 7;
if ((byte & 0x40) == 0 ? value == 0 : value == -1)
{
+25 -25
View File
@@ -37,35 +37,34 @@
namespace Stockfish::Eval::NNUE {
// Returns the inverse of a permutation
template<std::size_t Len>
constexpr std::array<std::size_t, Len>
invert_permutation(const std::array<std::size_t, Len>& order) {
std::array<std::size_t, Len> inverse{};
for (std::size_t i = 0; i < order.size(); i++)
template<usize Len>
constexpr std::array<usize, Len> invert_permutation(const std::array<usize, Len>& order) {
std::array<usize, Len> inverse{};
for (usize i = 0; i < order.size(); i++)
inverse[order[i]] = i;
return inverse;
}
// Divide a byte region of size TotalSize to chunks of size
// BlockSize, and permute the blocks by a given order
template<std::size_t BlockSize, typename T, std::size_t N, std::size_t OrderSize>
void permute(std::array<T, N>& data, const std::array<std::size_t, OrderSize>& order) {
constexpr std::size_t TotalSize = N * sizeof(T);
template<usize BlockSize, typename T, usize N, usize OrderSize>
void permute(std::array<T, N>& data, const std::array<usize, OrderSize>& order) {
constexpr usize TotalSize = N * sizeof(T);
static_assert(TotalSize % (BlockSize * OrderSize) == 0,
"ChunkSize * OrderSize must perfectly divide TotalSize");
constexpr std::size_t ProcessChunkSize = BlockSize * OrderSize;
constexpr usize ProcessChunkSize = BlockSize * OrderSize;
std::array<std::byte, ProcessChunkSize> buffer{};
std::byte* const bytes = reinterpret_cast<std::byte*>(data.data());
for (std::size_t i = 0; i < TotalSize; i += ProcessChunkSize)
for (usize i = 0; i < TotalSize; i += ProcessChunkSize)
{
std::byte* const values = &bytes[i];
for (std::size_t j = 0; j < OrderSize; j++)
for (usize j = 0; j < OrderSize; j++)
{
auto* const buffer_chunk = &buffer[j * BlockSize];
auto* const value_chunk = &values[order[j] * BlockSize];
@@ -92,12 +91,12 @@ class FeatureTransformer {
static constexpr IndexType OutputDimensions = HalfDimensions;
// Size of forward propagation buffer
static constexpr std::size_t BufferSize = OutputDimensions * sizeof(OutputType);
static constexpr usize BufferSize = OutputDimensions * sizeof(OutputType);
// Store the order by which 128-bit blocks of a 1024-bit data must
// be permuted so that calling packus on adjacent vectors of 16-bit
// integers loaded from the data results in the pre-permutation order
static constexpr auto PackusEpi16Order = []() -> std::array<std::size_t, 8> {
static constexpr auto PackusEpi16Order = []() -> std::array<usize, 8> {
#if defined(USE_AVX512)
// _mm512_packus_epi16 after permutation:
// | 0 | 2 | 4 | 6 | // Vector 0
@@ -117,8 +116,8 @@ class FeatureTransformer {
static constexpr auto InversePackusEpi16Order = invert_permutation(PackusEpi16Order);
static constexpr std::uint32_t combine_hash(std::initializer_list<std::uint32_t> hashes) {
std::uint32_t hash = 0;
static constexpr u32 combine_hash(std::initializer_list<u32> hashes) {
u32 hash = 0;
for (const auto component_hash : hashes)
{
hash = (hash << 1) | (hash >> 31);
@@ -128,7 +127,7 @@ class FeatureTransformer {
}
// Hash value embedded in the evaluation file
static constexpr std::uint32_t get_hash_value() {
static constexpr u32 get_hash_value() {
return combine_hash({ThreatFeatureSet::HashValue, PSQFeatureSet::HashValue})
^ (OutputDimensions * 2);
}
@@ -181,8 +180,8 @@ class FeatureTransformer {
return !stream.fail();
}
std::size_t get_content_hash() const {
std::size_t h = 0;
usize get_content_hash() const {
usize h = 0;
hash_combine(h, get_raw_data_hash(biases));
hash_combine(h, get_raw_data_hash(weights));
@@ -197,12 +196,12 @@ class FeatureTransformer {
}
// Convert input features
std::int32_t transform(const Position& pos,
AccumulatorStack& accumulatorStack,
AccumulatorCaches& cache,
OutputType* output,
int bucket,
NNZInfo<OutputDimensions>& nnzInfo) const {
i32 transform(const Position& pos,
AccumulatorStack& accumulatorStack,
AccumulatorCaches& cache,
OutputType* output,
int bucket,
NNZInfo<OutputDimensions>& nnzInfo) const {
using namespace SIMD;
accumulatorStack.evaluate(pos, *this, cache);
@@ -381,7 +380,8 @@ class FeatureTransformer {
template<>
struct std::hash<Stockfish::Eval::NNUE::FeatureTransformer> {
std::size_t operator()(const Stockfish::Eval::NNUE::FeatureTransformer& ft) const noexcept {
Stockfish::usize
operator()(const Stockfish::Eval::NNUE::FeatureTransformer& ft) const noexcept {
return ft.get_content_hash();
}
};
+2 -1
View File
@@ -28,6 +28,7 @@
#include <sstream>
#include "../position.h"
#include "../misc.h"
#include "../types.h"
#include "../uci.h"
#include "network.h"
@@ -71,7 +72,7 @@ trace(Position& pos, const Eval::NNUE::Network& network, Eval::NNUE::Accumulator
<< "| | (PSQT) | (Layers) | |\n"
<< "+------------+------------+------------+------------+\n";
for (std::size_t bucket = 0; bucket < LayerStacks; ++bucket)
for (usize bucket = 0; bucket < LayerStacks; ++bucket)
{
ss << "| " << bucket << " " //
<< " | ";
+5 -6
View File
@@ -19,7 +19,6 @@
#ifndef NNUE_MISC_H_INCLUDED
#define NNUE_MISC_H_INCLUDED
#include <cstddef>
#include <memory>
#include <string>
@@ -47,9 +46,9 @@ struct EvalFile {
struct NnueEvalTrace {
static_assert(LayerStacks == PSQTBuckets);
Value psqt[LayerStacks];
Value positional[LayerStacks];
std::size_t correctBucket;
Value psqt[LayerStacks];
Value positional[LayerStacks];
usize correctBucket;
};
class Network;
@@ -62,8 +61,8 @@ std::string trace(Position& pos, const Network& network, AccumulatorCaches& cach
template<>
struct std::hash<Stockfish::Eval::NNUE::EvalFile> {
std::size_t operator()(const Stockfish::Eval::NNUE::EvalFile& evalFile) const noexcept {
std::size_t h = 0;
Stockfish::usize operator()(const Stockfish::Eval::NNUE::EvalFile& evalFile) const noexcept {
Stockfish::usize h = 0;
Stockfish::hash_combine(h, evalFile.defaultName);
Stockfish::hash_combine(h, evalFile.current);
Stockfish::hash_combine(h, evalFile.netDescription);
+8 -8
View File
@@ -32,27 +32,27 @@ struct NNZInfo {
#if defined(USE_AVX512)
unsigned count = 0;
// indices of non-zero chunks
uint16_t nnz[Dimensions / 4];
u16 nnz[Dimensions / 4];
#ifdef USE_AVX512ICL
alignas(64) static constexpr auto Indices = []() {
std::array<std::array<uint16_t, 32>, 2> indices{};
std::array<std::array<u16, 32>, 2> indices{};
for (int i = 0; i < 2; ++i)
{
indices[i] = {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23,
8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31};
for (uint16_t& m : indices[i])
for (u16& m : indices[i])
m += i * Dimensions / 8;
}
return indices;
}();
#else
alignas(64) static constexpr auto Indices = []() {
std::array<std::array<uint32_t, 16>, 2> indices{};
std::array<std::array<u32, 16>, 2> indices{};
for (int i = 0; i < 2; ++i)
{
indices[i] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
for (uint32_t& m : indices[i])
for (u32& m : indices[i])
m += i * Dimensions / 8;
}
return indices;
@@ -105,10 +105,10 @@ struct NNZInfo {
NNZCursor make_cursor(bool perspective) { return {*this, perspective, count}; }
#else
// Each 8-bit chunk
uint8_t bitset[(Dimensions + 31) / 32];
u8 bitset[(Dimensions + 31) / 32];
struct NNZCursor {
uint8_t* out;
u8* out;
NNZCursor(NNZInfo& info, bool perspective) {
out = info.bitset + perspective * Dimensions / 64;
@@ -119,7 +119,7 @@ struct NNZInfo {
using namespace SIMD;
#ifdef USE_NEON
alignas(16) static constexpr uint16_t Mask8[8] = {1, 16, 2, 32, 4, 64, 8, 128};
alignas(16) static constexpr u16 Mask8[8] = {1, 16, 2, 32, 4, 64, 8, 128};
uint32x4_t n1 = vreinterpretq_u32_s16(neurons1);
uint32x4_t n2 = vreinterpretq_u32_s16(neurons2);
+14 -14
View File
@@ -135,7 +135,7 @@ using vec_uint_t = __m256i;
#elif USE_SSE2
using vec_t = __m128i;
using vec_i8_t = std::uint64_t; // for the correct size -- will be loaded into an xmm reg
using vec_i8_t = u64; // for the correct size -- will be loaded into an xmm reg
using vec128_t = __m128i;
using psqt_vec_t = __m128i;
using vec_uint_t = __m128i;
@@ -162,17 +162,17 @@ using vec_uint_t = __m128i;
#endif
#ifdef __i386__
inline __m128i _mm_cvtsi64_si128(int64_t val) {
inline __m128i _mm_cvtsi64_si128(i64 val) {
return _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&val));
}
#endif
#ifdef USE_SSE41
#define vec_convert_8_16(a) _mm_cvtepi8_epi16(_mm_cvtsi64_si128(static_cast<int64_t>(a)))
#define vec_convert_8_16(a) _mm_cvtepi8_epi16(_mm_cvtsi64_si128(static_cast<i64>(a)))
#else
// Credit: Yoshie2000
inline __m128i vec_convert_8_16(uint64_t x) {
__m128i v8 = _mm_cvtsi64_si128(static_cast<int64_t>(x));
inline __m128i vec_convert_8_16(u64 x) {
__m128i v8 = _mm_cvtsi64_si128(static_cast<i64>(x));
__m128i sign = _mm_cmpgt_epi8(_mm_setzero_si128(), v8);
return _mm_unpacklo_epi8(v8, sign);
}
@@ -216,13 +216,13 @@ using vec_uint_t __attribute__((may_alias)) = uint32x4_t;
#define vec_sub_psqt_32(a, b) vsubq_s32(a, b)
#define vec_zero_psqt() psqt_vec_t{0}
static constexpr std::uint32_t Mask[4] = {1, 2, 4, 8};
static constexpr u32 Mask[4] = {1, 2, 4, 8};
#define vec_nnz(a) \
vaddvq_u32(vandq_u32(vtstq_u32((uint32x4_t) a, (uint32x4_t) a), vld1q_u32(Mask)))
#define vec128_zero vdupq_n_u16(0)
#define vec128_set_16(a) vdupq_n_u16(a)
#define vec128_load(a) vld1q_u16(reinterpret_cast<const std::uint16_t*>(a))
#define vec128_storeu(a, b) vst1q_u16(reinterpret_cast<std::uint16_t*>(a), b)
#define vec128_load(a) vld1q_u16(reinterpret_cast<const u16*>(a))
#define vec128_storeu(a, b) vst1q_u16(reinterpret_cast<u16*>(a), b)
#define vec128_add(a, b) vaddq_u16(a, b)
#define NumRegistersSIMD 16
@@ -302,8 +302,8 @@ inline __m256i lasx_cvtepi8_epi16(__m128i a) {
__asm__("vext2xv.h.b %u0, %u1" : "=f"(out) : "f"(a));
return out;
#else
int64_t lo = (int64_t) __lsx_vpickve2gr_d(a, 0);
int64_t hi = (int64_t) __lsx_vpickve2gr_d(a, 1);
i64 lo = (i64) __lsx_vpickve2gr_d(a, 0);
i64 hi = (i64) __lsx_vpickve2gr_d(a, 1);
__m256i v = __lasx_xvldi(0);
v = __lasx_xvinsgr2vr_d(v, lo, 0);
v = __lasx_xvinsgr2vr_d(v, hi, 2);
@@ -319,7 +319,7 @@ inline int lasx_vec_nnz(__m256i a) {
#elif USE_LSX
using vec_t = __m128i;
using vec_i8_t = std::uint64_t;
using vec_i8_t = u64;
using vec128_t = __m128i;
using psqt_vec_t = __m128i;
using vec_uint_t = __m128i;
@@ -365,7 +365,7 @@ inline int lsx_vec_nnz(__m128i a) {
}
#define vec_nnz(a) lsx_vec_nnz(a)
inline __m128i vec_convert_8_16(std::uint64_t x) {
inline __m128i vec_convert_8_16(u64 x) {
__m128i v = __lsx_vldrepl_d(reinterpret_cast<const void*>(&x), 0);
return __lsx_vsllwil_h_b(v, 0);
}
@@ -589,8 +589,8 @@ class SIMDTiling {
template<typename SIMDRegisterType, typename LaneType, int NumLanes, int MaxRegisters>
static constexpr int BestRegisterCount() {
constexpr std::size_t RegisterSize = sizeof(SIMDRegisterType);
constexpr std::size_t LaneSize = sizeof(LaneType);
constexpr usize RegisterSize = sizeof(SIMDRegisterType);
constexpr usize LaneSize = sizeof(LaneType);
static_assert(RegisterSize >= LaneSize);
static_assert(MaxRegisters <= NumRegistersSIMD);
+44 -43
View File
@@ -37,6 +37,7 @@
#include <vector>
#include <cstring>
#include "misc.h"
#include "shm.h"
// We support linux very well, but we explicitly do NOT support Android,
@@ -53,10 +54,6 @@
#define _WIN32_WINNT 0x0601 // Force to include needed API prototypes
#endif
// On Windows each processor group can have up to 64 processors.
// https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups
static constexpr size_t WIN_PROCESSOR_GROUP_SIZE = 64;
#if !defined(NOMINMAX)
#define NOMINMAX
#endif
@@ -77,8 +74,8 @@ using GetThreadSelectedCpuSetMasks_t = BOOL (*)(HANDLE, PGROUP_AFFINITY, USHORT,
namespace Stockfish {
using CpuIndex = size_t;
using NumaIndex = size_t;
using CpuIndex = usize;
using NumaIndex = usize;
inline CpuIndex get_hardware_concurrency() {
CpuIndex concurrency = std::thread::hardware_concurrency();
@@ -97,6 +94,10 @@ inline const CpuIndex SYSTEM_THREADS_NB = std::max<CpuIndex>(1, get_hardware_con
#if defined(_WIN64)
// On Windows each processor group can have up to 64 processors.
// https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups
static constexpr usize WIN_PROCESSOR_GROUP_SIZE = 64;
struct WindowsAffinity {
std::optional<std::set<CpuIndex>> oldApi;
std::optional<std::set<CpuIndex>> newApi;
@@ -134,7 +135,7 @@ inline std::pair<BOOL, std::vector<USHORT>> get_process_group_affinity() {
// GetProcessGroupAffinity requires the GroupArray argument to be
// aligned to 4 bytes instead of just 2.
static constexpr size_t GroupArrayMinimumAlignment = 4;
static constexpr usize GroupArrayMinimumAlignment = 4;
static_assert(GroupArrayMinimumAlignment >= alignof(USHORT));
// The function should succeed the second time, but it may fail if the group
@@ -217,9 +218,9 @@ inline WindowsAffinity get_process_affinity() {
for (USHORT i = 0; i < RequiredMaskCount; ++i)
{
const size_t procGroupIndex = groupAffinities[i].Group;
const usize procGroupIndex = groupAffinities[i].Group;
for (size_t j = 0; j < WIN_PROCESSOR_GROUP_SIZE; ++j)
for (usize j = 0; j < WIN_PROCESSOR_GROUP_SIZE; ++j)
{
if (groupAffinities[i].Mask & (KAFFINITY(1) << j))
cpus.insert(procGroupIndex * WIN_PROCESSOR_GROUP_SIZE + j);
@@ -271,10 +272,10 @@ inline WindowsAffinity get_process_affinity() {
{
std::set<CpuIndex> cpus;
const size_t procGroupIndex = groupAffinity[0];
const usize procGroupIndex = groupAffinity[0];
const uint64_t mask = static_cast<uint64_t>(proc);
for (size_t j = 0; j < WIN_PROCESSOR_GROUP_SIZE; ++j)
const u64 mask = static_cast<u64>(proc);
for (usize j = 0; j < WIN_PROCESSOR_GROUP_SIZE; ++j)
{
if (mask & (KAFFINITY(1) << j))
cpus.insert(procGroupIndex * WIN_PROCESSOR_GROUP_SIZE + j);
@@ -312,8 +313,8 @@ inline WindowsAffinity get_process_affinity() {
// choice could influence the resulting affinity.
// We assume the processor IDs within the group are
// filled sequentially from 0.
uint64_t procCombined = std::numeric_limits<uint64_t>::max();
uint64_t sysCombined = std::numeric_limits<uint64_t>::max();
u64 procCombined = std::numeric_limits<u64>::max();
u64 sysCombined = std::numeric_limits<u64>::max();
for (int i = 0; i < std::min(numActiveProcessors, 2); ++i)
{
@@ -341,14 +342,14 @@ inline WindowsAffinity get_process_affinity() {
return;
}
procCombined &= static_cast<uint64_t>(proc2);
sysCombined &= static_cast<uint64_t>(sys2);
procCombined &= static_cast<u64>(proc2);
sysCombined &= static_cast<u64>(sys2);
}
if (procCombined != sysCombined)
isAffinityFull = false;
for (size_t j = 0; j < WIN_PROCESSOR_GROUP_SIZE; ++j)
for (usize j = 0; j < WIN_PROCESSOR_GROUP_SIZE; ++j)
{
if (procCombined & (KAFFINITY(1) << j))
cpus.insert(procGroupIndex * WIN_PROCESSOR_GROUP_SIZE + j);
@@ -439,7 +440,7 @@ inline std::set<CpuIndex> get_process_affinity() {
if (mask == nullptr)
std::exit(EXIT_FAILURE);
const size_t masksize = CPU_ALLOC_SIZE(MaxNumCpus);
const usize masksize = CPU_ALLOC_SIZE(MaxNumCpus);
CPU_ZERO_S(masksize, mask);
@@ -502,7 +503,7 @@ struct SystemNumaPolicy {};
struct L3DomainsPolicy {};
// Group system-reported L3 domains until they reach bundleSize
struct BundledL3Policy {
size_t bundleSize;
usize bundleSize;
};
using NumaAutoPolicy = std::variant<SystemNumaPolicy, L3DomainsPolicy, BundledL3Policy>;
@@ -581,7 +582,7 @@ class NumaConfig {
bool l3Success = false;
if (!std::holds_alternative<SystemNumaPolicy>(policy))
{
size_t l3BundleSize = 0;
usize l3BundleSize = 0;
if (const auto* v = std::get_if<BundledL3Policy>(&policy))
{
l3BundleSize = v->bundleSize;
@@ -627,10 +628,10 @@ class NumaConfig {
if (cpus.empty())
continue;
size_t lastProcGroupIndex = *(cpus.begin()) / WIN_PROCESSOR_GROUP_SIZE;
usize lastProcGroupIndex = *(cpus.begin()) / WIN_PROCESSOR_GROUP_SIZE;
for (CpuIndex c : cpus)
{
const size_t procGroupIndex = c / WIN_PROCESSOR_GROUP_SIZE;
const usize procGroupIndex = c / WIN_PROCESSOR_GROUP_SIZE;
if (procGroupIndex != lastProcGroupIndex)
{
splitNodeIndex += 1;
@@ -769,7 +770,7 @@ class NumaConfig {
if (numThreads <= 1)
return false;
size_t largestNodeSize = 0;
usize largestNodeSize = 0;
for (auto&& cpus : nodes)
if (cpus.size() > largestNodeSize)
largestNodeSize = cpus.size();
@@ -780,7 +781,7 @@ class NumaConfig {
<= SmallNodeThreshold;
};
size_t numNotSmallNodes = 0;
usize numNotSmallNodes = 0;
for (auto&& cpus : nodes)
if (!is_node_small(cpus))
numNotSmallNodes += 1;
@@ -800,7 +801,7 @@ class NumaConfig {
}
else
{
std::vector<size_t> occupation(nodes.size(), 0);
std::vector<usize> occupation(nodes.size(), 0);
for (CpuIndex c = 0; c < numThreads; ++c)
{
NumaIndex bestNode{0};
@@ -838,7 +839,7 @@ class NumaConfig {
if (mask == nullptr)
std::exit(EXIT_FAILURE);
const size_t masksize = CPU_ALLOC_SIZE(highestCpuIndex + 1);
const usize masksize = CPU_ALLOC_SIZE(highestCpuIndex + 1);
CPU_ZERO_S(masksize, mask);
@@ -880,8 +881,8 @@ class NumaConfig {
for (CpuIndex c : nodes[n])
{
const size_t procGroupIndex = c / WIN_PROCESSOR_GROUP_SIZE;
const size_t idxWithinProcGroup = c % WIN_PROCESSOR_GROUP_SIZE;
const usize procGroupIndex = c / WIN_PROCESSOR_GROUP_SIZE;
const usize idxWithinProcGroup = c % WIN_PROCESSOR_GROUP_SIZE;
groupAffinities[procGroupIndex].Mask |= KAFFINITY(1) << idxWithinProcGroup;
}
@@ -919,12 +920,12 @@ class NumaConfig {
GROUP_AFFINITY affinity;
std::memset(&affinity, 0, sizeof(GROUP_AFFINITY));
// We use an ordered set to be sure to get the smallest cpu number here.
const size_t forcedProcGroupIndex = *(nodes[n].begin()) / WIN_PROCESSOR_GROUP_SIZE;
affinity.Group = static_cast<WORD>(forcedProcGroupIndex);
const usize forcedProcGroupIndex = *(nodes[n].begin()) / WIN_PROCESSOR_GROUP_SIZE;
affinity.Group = static_cast<WORD>(forcedProcGroupIndex);
for (CpuIndex c : nodes[n])
{
const size_t procGroupIndex = c / WIN_PROCESSOR_GROUP_SIZE;
const size_t idxWithinProcGroup = c % WIN_PROCESSOR_GROUP_SIZE;
const usize procGroupIndex = c / WIN_PROCESSOR_GROUP_SIZE;
const usize idxWithinProcGroup = c % WIN_PROCESSOR_GROUP_SIZE;
// We skip processors that are not in the same processor group.
// If everything was set up correctly this will never be an issue,
// but we have to account for bad NUMA node specification.
@@ -1026,8 +1027,8 @@ class NumaConfig {
return true;
}
static std::vector<size_t> indices_from_shortened_string(const std::string& s) {
std::vector<size_t> indices;
static std::vector<usize> indices_from_shortened_string(const std::string& s) {
std::vector<usize> indices;
if (s.empty())
return indices;
@@ -1047,7 +1048,7 @@ class NumaConfig {
{
const CpuIndex cfirst = CpuIndex{str_to_size_t(std::string(parts[0]))};
const CpuIndex clast = CpuIndex{str_to_size_t(std::string(parts[1]))};
for (size_t c = cfirst; c <= clast; ++c)
for (usize c = cfirst; c <= clast; ++c)
{
indices.emplace_back(c);
}
@@ -1088,7 +1089,7 @@ class NumaConfig {
else
{
remove_whitespace(*nodeIdsStr);
for (size_t n : indices_from_shortened_string(*nodeIdsStr))
for (usize n : indices_from_shortened_string(*nodeIdsStr))
{
// /sys/devices/system/node/node.../cpulist
std::string path =
@@ -1105,7 +1106,7 @@ class NumaConfig {
else
{
remove_whitespace(*cpuIdsStr);
for (size_t c : indices_from_shortened_string(*cpuIdsStr))
for (usize c : indices_from_shortened_string(*cpuIdsStr))
{
if (is_cpu_allowed(c))
cfg.add_cpu_to_node(n, c);
@@ -1156,7 +1157,7 @@ class NumaConfig {
template<typename Pred>
static std::optional<NumaConfig> try_get_l3_aware_config(
bool respectProcessAffinity, size_t bundleSize, [[maybe_unused]] Pred&& is_cpu_allowed) {
bool respectProcessAffinity, usize bundleSize, [[maybe_unused]] Pred&& is_cpu_allowed) {
// Get the normal system configuration so we know to which NUMA node
// each L3 domain belongs.
NumaConfig systemConfig =
@@ -1180,7 +1181,7 @@ class NumaConfig {
continue;
L3Domain domain;
for (size_t c : indices_from_shortened_string(*siblingsStr))
for (usize c : indices_from_shortened_string(*siblingsStr))
{
if (is_cpu_allowed(c))
{
@@ -1233,7 +1234,7 @@ class NumaConfig {
}
static NumaConfig from_l3_info(std::vector<L3Domain>&& domains, size_t bundleSize) {
static NumaConfig from_l3_info(std::vector<L3Domain>&& domains, usize bundleSize) {
assert(!domains.empty());
std::map<NumaIndex, std::vector<L3Domain>> list;
@@ -1250,7 +1251,7 @@ class NumaConfig {
do
{
changed = false;
for (size_t j = 0; j + 1 < ds.size(); ++j)
for (usize j = 0; j + 1 < ds.size(); ++j)
{
if (ds[j].cpus.size() + ds[j + 1].cpus.size() <= bundleSize)
{
@@ -1574,14 +1575,14 @@ class LazyNumaReplicatedSystemWide: public NumaReplicatedBase {
mutable std::vector<SystemWideSharedConstant<T>> instances;
mutable std::mutex mutex;
std::size_t get_discriminator(NumaIndex idx) const {
usize get_discriminator(NumaIndex idx) const {
const NumaConfig& cfg = get_numa_config();
const NumaConfig& cfg_sys = NumaConfig::from_system(SystemNumaPolicy{}, false);
// as a discriminator, locate the hardware/system numadomain this cpuindex belongs to
CpuIndex cpu = *cfg.nodes[idx].begin(); // get a CpuIndex from NumaIndex
NumaIndex sys_idx = cfg_sys.is_cpu_assigned(cpu) ? cfg_sys.nodeByCpu.at(cpu) : 0;
std::string s = cfg_sys.to_string() + "$" + std::to_string(sys_idx);
return static_cast<std::size_t>(hash_string(s));
return static_cast<usize>(hash_string(s));
}
void ensure_present(NumaIndex idx) const {
+3 -3
View File
@@ -31,11 +31,11 @@ namespace Stockfish::Benchmark {
// Utility to verify move generation. All the leaf nodes up
// to the given depth are generated and counted, and the sum is returned.
template<bool Root>
uint64_t perft(Position& pos, Depth depth) {
u64 perft(Position& pos, Depth depth) {
StateInfo st;
uint64_t cnt, nodes = 0;
u64 cnt, nodes = 0;
const bool leaf = (depth == 2);
for (const auto& m : MoveList<LEGAL>(pos))
@@ -55,7 +55,7 @@ uint64_t perft(Position& pos, Depth depth) {
return nodes;
}
inline uint64_t perft(const std::string& fen, Depth depth, bool isChess960) {
inline u64 perft(const std::string& fen, Depth depth, bool isChess960) {
StateInfo st;
Position p;
p.set(fen, isChess960, &st);
+1 -1
View File
@@ -252,7 +252,7 @@ Position::set(const string& fenStr, bool isChess960, StateInfo* si) {
if (file >= FILE_NB)
return PositionSetError("Invalid FEN. Invalid file reached.");
const size_t idx = PieceToChar.find(token);
const usize idx = PieceToChar.find(token);
if (idx == string::npos)
return PositionSetError(std::string("Invalid FEN. Invalid piece: ")
+ std::string(1, token));
+22 -25
View File
@@ -24,7 +24,6 @@
#include <cassert>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <initializer_list>
#include <iostream>
@@ -67,7 +66,7 @@ using namespace Search;
namespace {
constexpr uint64_t NODES_LIMIT_OUTPUT = 10'000'000;
constexpr u64 NODES_LIMIT_OUTPUT = 10'000'000;
constexpr int SEARCHEDLIST_CAPACITY = 32;
using SearchedList = ValueList<Move, SEARCHEDLIST_CAPACITY>;
@@ -130,7 +129,7 @@ void update_correction_history(const Position& pos,
}
// Add a small random component to draw evaluations to avoid 3-fold blindness
Value value_draw(size_t nodes) { return VALUE_DRAW - 1 + Value(nodes & 0x2); }
Value value_draw(usize nodes) { return VALUE_DRAW - 1 + Value(nodes & 0x2); }
Value value_to_tt(Value v, int ply);
Value value_from_tt(Value v, int ply, int r50c);
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
@@ -160,9 +159,9 @@ bool is_shuffling(Move move, Stack* const ss, const Position& pos) {
Search::Worker::Worker(SharedState& sharedState,
std::unique_ptr<ISearchManager> sm,
size_t threadId,
size_t numaThreadId,
size_t numaTotalThreads,
usize threadId,
usize numaThreadId,
usize numaTotalThreads,
NumaReplicatedAccessToken token) :
// Unpack the SharedState struct into member variables
sharedHistory(sharedState.sharedHistories.at(token.get_numa_index())),
@@ -306,13 +305,13 @@ bool Search::Worker::iterative_deepening() {
mainThread->iterValue.fill(mainThread->bestPreviousScore);
}
size_t multiPV = size_t(options["MultiPV"]);
usize multiPV = usize(options["MultiPV"]);
Skill skill(options["Skill Level"], options["UCI_LimitStrength"] ? int(options["UCI_Elo"]) : 0);
// When playing with strength handicap enable MultiPV search that we will
// use behind-the-scenes to retrieve a set of possible moves.
if (skill.enabled())
multiPV = std::max(multiPV, size_t(4));
multiPV = std::max(multiPV, usize(4));
multiPV = std::min(multiPV, rootMoves.size());
@@ -343,8 +342,8 @@ bool Search::Worker::iterative_deepening() {
for (RootMove& rm : rootMoves)
rm.previousScore = rm.score;
size_t pvFirst = 0;
pvLast = 0;
usize pvFirst = 0;
pvLast = 0;
if (!threads.increaseDepth)
searchAgainCounter++;
@@ -530,8 +529,7 @@ bool Search::Worker::iterative_deepening() {
// Do we have time for the next iteration? Can we stop searching now?
if (limits.use_time_management() && !threads.stop && !mainThread->stopOnPonderhit)
{
uint64_t nodesEffort =
rootMoves[0].effort * 100000 / std::max(uint64_t(1), uint64_t(nodes));
u64 nodesEffort = rootMoves[0].effort * 100000 / std::max(u64(1), u64(nodes));
double fallingEval = (11.87 + 2.21 * (mainThread->bestPreviousAverageScore - bestValue)
+ 1.0 * (mainThread->iterValue[iterIdx] - bestValue))
@@ -548,8 +546,7 @@ bool Search::Worker::iterative_deepening() {
double bestMoveInstability = 1.096 + 2.29 * totBestMoveChanges / threads.size();
double highBestMoveEffort = std::clamp(
interpolate(int64_t(nodesEffort), int64_t(79219), int64_t(101822), 0.924, 0.71), 0.71,
0.924);
interpolate(i64(nodesEffort), i64(79219), i64(101822), 0.924, 0.71), 0.71, 0.924);
double totalTime = mainThread->tm.optimum() * fallingEval * reduction
* bestMoveInstability * highBestMoveEffort;
@@ -652,7 +649,7 @@ void Search::Worker::clear() {
for (auto& h : to)
h.fill(-552);
for (size_t i = 1; i < reductions.size(); ++i)
for (usize i = 1; i < reductions.size(); ++i)
reductions[i] = int(2834 / 128.0 * std::log(i));
refreshTable.clear(network[numaAccessToken]);
@@ -712,7 +709,7 @@ Value Search::Worker::search(
maxValue = VALUE_INFINITE;
ss->followPV = rootNode
|| ((ss - 1)->followPV && static_cast<size_t>(ss->ply - 1) < lastIterationPV.size()
|| ((ss - 1)->followPV && static_cast<usize>(ss->ply - 1) < lastIterationPV.size()
&& (ss - 1)->currentMove == lastIterationPV[ss->ply - 1]);
// Check for the available remaining time
@@ -1241,7 +1238,7 @@ moves_loop: // When in check, search starts here
extension = -2;
}
uint64_t nodeCount = rootNode ? uint64_t(nodes) : 0;
u64 nodeCount = rootNode ? u64(nodes) : 0;
// Step 16. Make the move
do_move(pos, move, st, givesCheck, ss);
@@ -1885,7 +1882,7 @@ void update_all_stats(const Position& pos,
if (!PvNode)
// Important: don't remove the cast to a 64-bit number else the multiplication
// can overflow on 32-bit platforms which would change the bench signature
bonus += bonus * uint64_t(quietsSearched.size() + capturesSearched.size()) / 256;
bonus += bonus * u64(quietsSearched.size() + capturesSearched.size()) / 256;
if (!pos.capture_stage(bestMove))
{
@@ -1969,7 +1966,7 @@ void update_quiet_histories(
// When playing with strength handicap, choose the best move among a set of
// RootMoves using a statistical rule dependent on 'level'. Idea by Heinz van Saanen.
Move Skill::pick_best(const RootMoves& rootMoves, size_t multiPV) {
Move Skill::pick_best(const RootMoves& rootMoves, usize multiPV) {
static PRNG rng(now()); // PRNG sequence should be non-deterministic
// RootMoves are already sorted by score in descending order
@@ -1981,7 +1978,7 @@ Move Skill::pick_best(const RootMoves& rootMoves, size_t multiPV) {
// Choose best move. For each move score we add two terms, both dependent on
// weakness. One is deterministic and bigger for weaker levels, and one is
// random. Then we choose the move with the resulting highest score.
for (size_t i = 0; i < multiPV; ++i)
for (usize i = 0; i < multiPV; ++i)
{
// This is our magic formula
int push = int(weakness * int(topScore - rootMoves[i].score)
@@ -2058,7 +2055,7 @@ void syzygy_extend_pv(const OptionsMap& options,
int ply = 1;
// Step 1, walk the PV to the last position in TB with correct decisive score
while (size_t(ply) < rootMove.pv.size())
while (usize(ply) < rootMove.pv.size())
{
Move& pvMove = rootMove.pv[ply];
@@ -2154,7 +2151,7 @@ void syzygy_extend_pv(const OptionsMap& options,
v = VALUE_DRAW;
// Undo the PV moves
for (size_t i = rootMove.pv.size(); i > 0; --i)
for (usize i = rootMove.pv.size(); i > 0; --i)
pos.undo_move(rootMove.pv[i - 1]);
// Inform if we couldn't get a full extension in time
@@ -2172,10 +2169,10 @@ void SearchManager::pv(Search::Worker& worker,
const auto nodes = threads.nodes_searched();
auto& rootMoves = worker.rootMoves;
auto& pos = worker.rootPos;
size_t multiPV = std::min(size_t(worker.options["MultiPV"]), rootMoves.size());
uint64_t tbHits = threads.tb_hits() + (worker.tbConfig.rootInTB ? rootMoves.size() : 0);
usize multiPV = std::min(usize(worker.options["MultiPV"]), rootMoves.size());
u64 tbHits = threads.tb_hits() + (worker.tbConfig.rootInTB ? rootMoves.size() : 0);
for (size_t i = 0; i < multiPV; ++i)
for (usize i = 0; i < multiPV; ++i)
{
bool usePreviousScore = rootMoves[i].score == -VALUE_INFINITE;
+35 -36
View File
@@ -23,7 +23,6 @@
#include <array>
#include <atomic>
#include <cassert>
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
@@ -59,19 +58,19 @@ class OptionsMap;
namespace Search {
struct PVMoves {
Move moves[MAX_PLY + 1];
std::size_t length = 0;
Move moves[MAX_PLY + 1];
usize length = 0;
Move* begin() { return moves; }
const Move* begin() const { return moves; }
Move* end() { return moves + length; }
const Move* end() const { return moves + length; }
Move& operator[](std::size_t index) { return moves[index]; }
const Move& operator[](std::size_t index) const { return moves[index]; }
Move& operator[](usize index) { return moves[index]; }
const Move& operator[](usize index) const { return moves[index]; }
bool empty() const { return length == 0; }
std::size_t size() const { return length; }
bool empty() const { return length == 0; }
usize size() const { return length; }
void clear() { length = 0; }
@@ -80,7 +79,7 @@ struct PVMoves {
moves[length++] = move;
}
void resize(std::size_t newSize) {
void resize(usize newSize) {
assert(newSize <= length);
length = newSize;
}
@@ -136,18 +135,18 @@ struct RootMove {
return m.score != score ? m.score < score : m.previousScore < previousScore;
}
uint64_t effort = 0;
Value score = -VALUE_INFINITE;
Value previousScore = -VALUE_INFINITE;
Value averageScore = -VALUE_INFINITE;
Value meanSquaredScore = -VALUE_INFINITE * VALUE_INFINITE;
Value uciScore = -VALUE_INFINITE;
bool scoreLowerbound = false;
bool scoreUpperbound = false;
int selDepth = 0;
int tbRank = 0;
Value tbScore;
PVMoves pv;
u64 effort = 0;
Value score = -VALUE_INFINITE;
Value previousScore = -VALUE_INFINITE;
Value averageScore = -VALUE_INFINITE;
Value meanSquaredScore = -VALUE_INFINITE * VALUE_INFINITE;
Value uciScore = -VALUE_INFINITE;
bool scoreLowerbound = false;
bool scoreUpperbound = false;
int selDepth = 0;
int tbRank = 0;
Value tbScore;
PVMoves pv;
};
using RootMoves = std::vector<RootMove>;
@@ -169,7 +168,7 @@ struct LimitsType {
std::vector<std::string> searchmoves;
TimePoint time[COLOR_NB], inc[COLOR_NB], npmsec, movetime, startTime;
int movestogo, depth, mate, perft, infinite;
uint64_t nodes;
u64 nodes;
bool ponderMode;
};
@@ -212,13 +211,13 @@ struct InfoShort {
struct InfoFull: InfoShort {
int selDepth;
size_t multiPV;
usize multiPV;
std::string_view wdl;
std::string_view bound;
size_t timeMs;
size_t nodes;
size_t nps;
size_t tbHits;
usize timeMs;
usize nodes;
usize nps;
usize tbHits;
std::string_view pv;
int hashfull;
};
@@ -226,7 +225,7 @@ struct InfoFull: InfoShort {
struct InfoIteration {
int depth;
std::string_view currmove;
size_t currmovenumber;
usize currmovenumber;
};
// Skill structure is used to implement strength limit. If we have a UCI_Elo,
@@ -251,7 +250,7 @@ struct Skill {
}
bool enabled() const { return level < 20.0; }
bool time_to_pick(Depth depth) const { return depth == 1 + int(level); }
Move pick_best(const RootMoves&, size_t multiPV);
Move pick_best(const RootMoves&, usize multiPV);
double level;
Move best = Move::none();
@@ -295,7 +294,7 @@ class SearchManager: public ISearchManager {
Value bestPreviousAverageScore;
bool stopOnPonderhit;
size_t id;
usize id;
const UpdateContext& updates;
};
@@ -312,9 +311,9 @@ class Worker {
public:
Worker(SharedState&,
std::unique_ptr<ISearchManager>,
size_t,
size_t,
size_t,
usize,
usize,
usize,
NumaReplicatedAccessToken);
// Called at instantiation to initialize reductions tables.
@@ -373,9 +372,9 @@ class Worker {
LimitsType limits;
size_t pvIdx, pvLast;
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges;
int selDepth, nmpMinPly;
usize pvIdx, pvLast;
std::atomic<u64> nodes, tbHits, bestMoveChanges;
int selDepth, nmpMinPly;
Value optimism[COLOR_NB];
@@ -387,7 +386,7 @@ class Worker {
PVMoves lastIterationPV;
size_t threadIdx, numaThreadIdx, numaTotal;
usize threadIdx, numaThreadIdx, numaTotal;
NumaReplicatedAccessToken numaAccessToken;
// Reductions lookup table initialized at startup
+15 -15
View File
@@ -100,14 +100,14 @@ namespace Stockfish {
// amount of bytes of the path; in particular it can a hash of an empty string.
inline std::string getExecutablePathHash() {
char executable_path[4096] = {0};
std::size_t path_length = 0;
char executable_path[4096] = {0};
usize path_length = 0;
#if defined(_WIN32)
path_length = GetModuleFileNameA(NULL, executable_path, sizeof(executable_path));
#elif defined(__APPLE__)
uint32_t size = sizeof(executable_path);
u32 size = sizeof(executable_path);
if (_NSGetExecutablePath(executable_path, &size) == 0)
{
path_length = std::strlen(executable_path);
@@ -122,8 +122,8 @@ inline std::string getExecutablePathHash() {
}
#elif defined(__FreeBSD__)
size_t size = sizeof(executable_path);
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
usize size = sizeof(executable_path);
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
if (sysctl(mib, 4, executable_path, &size, NULL, 0) == 0)
{
path_length = std::strlen(executable_path);
@@ -171,10 +171,10 @@ inline std::string GetLastErrorAsString(DWORD error) {
//Ask Win32 to give us the string version of that message ID.
//The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be).
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &messageBuffer, 0, NULL);
usize size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &messageBuffer, 0, NULL);
//Copy the error message into a std::string.
std::string message(messageBuffer, size);
@@ -278,12 +278,12 @@ class SharedMemoryBackend {
private:
void initialize(const std::string& shm_name, const T& value) {
const size_t total_size = sizeof(T) + sizeof(IS_INITIALIZED_VALUE);
const usize total_size = sizeof(T) + sizeof(IS_INITIALIZED_VALUE);
// Try allocating with large pages first.
hMapFile = windows_try_with_large_page_priviliges(
[&](size_t largePageSize) {
const size_t total_size_aligned =
[&](usize largePageSize) {
const usize total_size_aligned =
(total_size + largePageSize - 1) / largePageSize * largePageSize;
#if defined(_WIN64)
@@ -530,9 +530,9 @@ struct SystemWideSharedConstant {
// Content is addressed by its hash. An additional discriminator can be added to account for differences
// that are not present in the content, for example NUMA node allocation.
SystemWideSharedConstant(const T& value, std::size_t discriminator = 0) {
std::size_t content_hash = std::hash<T>{}(value);
std::size_t executable_hash = hash_string(getExecutablePathHash());
SystemWideSharedConstant(const T& value, usize discriminator = 0) {
usize content_hash = std::hash<T>{}(value);
usize executable_hash = hash_string(getExecutablePathHash());
char buf[1024];
std::snprintf(buf, sizeof(buf), "Local\\sf_%zu$%zu$%zu", content_hash, executable_hash,
+10 -10
View File
@@ -54,11 +54,11 @@ namespace Stockfish::shm {
namespace detail {
struct ShmHeader {
static constexpr uint32_t SHM_MAGIC = 0xAD5F1A12;
pthread_mutex_t mutex;
std::atomic<uint32_t> ref_count{0};
std::atomic<bool> initialized{false};
uint32_t magic = SHM_MAGIC;
static constexpr u32 SHM_MAGIC = 0xAD5F1A12;
pthread_mutex_t mutex;
std::atomic<u32> ref_count{0};
std::atomic<bool> initialized{false};
u32 magic = SHM_MAGIC;
};
class SharedMemoryBase {
@@ -154,11 +154,11 @@ class SharedMemory: public detail::SharedMemoryBase {
void* mapped_ptr_ = nullptr;
T* data_ptr_ = nullptr;
detail::ShmHeader* header_ptr_ = nullptr;
size_t total_size_ = 0;
usize total_size_ = 0;
std::string sentinel_base_;
std::string sentinel_path_;
static constexpr size_t calculate_total_size() noexcept {
static constexpr usize calculate_total_size() noexcept {
return sizeof(T) + sizeof(detail::ShmHeader);
}
@@ -370,7 +370,7 @@ class SharedMemory: public detail::SharedMemoryBase {
[[nodiscard]] const T& operator*() const noexcept { return *data_ptr_; }
[[nodiscard]] uint32_t ref_count() const noexcept {
[[nodiscard]] u32 ref_count() const noexcept {
return header_ptr_ ? header_ptr_->ref_count.load(std::memory_order_acquire) : 0;
}
@@ -435,7 +435,7 @@ class SharedMemory: public detail::SharedMemoryBase {
if (!header_ptr_)
return;
uint32_t expected = header_ptr_->ref_count.load(std::memory_order_relaxed);
u32 expected = header_ptr_->ref_count.load(std::memory_order_relaxed);
while (expected != 0
&& !header_ptr_->ref_count.compare_exchange_weak(
expected, expected - 1, std::memory_order_acq_rel, std::memory_order_relaxed))
@@ -631,7 +631,7 @@ class SharedMemory: public detail::SharedMemoryBase {
struct stat st;
fstat(fd_, &st);
if (static_cast<size_t>(st.st_size) < total_size_)
if (static_cast<usize>(st.st_size) < total_size_)
{
invalid_header = true;
return false;
+77 -78
View File
@@ -115,12 +115,12 @@ template<typename T, int Half = sizeof(T) / 2, int End = sizeof(T) - 1>
inline void swap_endian(T& x) {
static_assert(std::is_unsigned_v<T>, "Argument of swap_endian not unsigned");
uint8_t tmp, *c = (uint8_t*) &x;
u8 tmp, *c = (u8*) &x;
for (int i = 0; i < Half; ++i)
tmp = c[i], c[i] = c[End - i], c[End - i] = tmp;
}
template<>
inline void swap_endian<uint8_t>(uint8_t&) {}
inline void swap_endian<u8>(u8&) {}
template<typename T, int LE>
T number(void* addr) {
@@ -161,7 +161,7 @@ struct SparseEntry {
static_assert(sizeof(SparseEntry) == 6, "SparseEntry must be 6 bytes");
using Sym = uint16_t; // Huffman symbol
using Sym = u16; // Huffman symbol
struct LR {
enum Side {
@@ -169,9 +169,9 @@ struct LR {
Right
};
uint8_t lr[3]; // The first 12 bits is the left-hand symbol, the second 12
// bits is the right-hand symbol. If the symbol has length 1,
// then the left-hand symbol is the stored value.
u8 lr[3]; // The first 12 bits is the left-hand symbol, the second 12
// bits is the right-hand symbol. If the symbol has length 1,
// then the left-hand symbol is the stored value.
template<Side S>
Sym get() {
return S == Left ? ((lr[1] & 0xF) << 8) | lr[0]
@@ -224,7 +224,7 @@ class TBFile: public std::ifstream {
}
// Memory map the file and check it.
uint8_t* map(void** baseAddress, uint64_t* mapping, TBType type) {
u8* map(void** baseAddress, u64* mapping, TBType type) {
if (is_open())
close(); // Need to re-open to get native file descriptor
@@ -281,7 +281,7 @@ class TBFile: public std::ifstream {
exit(EXIT_FAILURE);
}
*mapping = uint64_t(mmap);
*mapping = u64(mmap);
*baseAddress = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0);
if (!*baseAddress)
@@ -291,9 +291,9 @@ class TBFile: public std::ifstream {
exit(EXIT_FAILURE);
}
#endif
uint8_t* data = (uint8_t*) *baseAddress;
u8* data = (u8*) *baseAddress;
constexpr uint8_t Magics[][4] = {{0xD7, 0x66, 0x0C, 0xA5}, {0x71, 0xE8, 0x23, 0x5D}};
constexpr u8 Magics[][4] = {{0xD7, 0x66, 0x0C, 0xA5}, {0x71, 0xE8, 0x23, 0x5D}};
if (memcmp(data, Magics[type == WDL], 4))
{
@@ -305,7 +305,7 @@ class TBFile: public std::ifstream {
return data + 4; // Skip Magics's header
}
static void unmap(void* baseAddress, uint64_t mapping) {
static void unmap(void* baseAddress, u64 mapping) {
#ifndef _WIN32
munmap(baseAddress, mapping);
@@ -322,27 +322,26 @@ std::string TBFile::Paths;
// There are 8, 4, or 2 PairsData records for each TBTable, according to the type
// of table and if positions have pawns or not. It is populated at first access.
struct PairsData {
uint8_t flags; // Table flags, see enum TBFlag
uint8_t maxSymLen; // Maximum length in bits of the Huffman symbols
uint8_t minSymLen; // Minimum length in bits of the Huffman symbols
uint32_t blocksNum; // Number of blocks in the TB file
size_t sizeofBlock; // Block size in bytes
size_t span; // About every span values there is a SparseIndex[] entry
Sym* lowestSym; // lowestSym[l] is the symbol of length l with the lowest value
LR* btree; // btree[sym] stores the left and right symbols that expand sym
uint16_t* blockLength; // Number of stored positions (minus one) for each block: 1..65536
uint32_t blockLengthSize; // Size of blockLength[] table: padded so it's bigger than blocksNum
SparseEntry* sparseIndex; // Partial indices into blockLength[]
size_t sparseIndexSize; // Size of SparseIndex[] table
uint8_t* data; // Start of Huffman compressed data
std::vector<uint64_t>
u8 flags; // Table flags, see enum TBFlag
u8 maxSymLen; // Maximum length in bits of the Huffman symbols
u8 minSymLen; // Minimum length in bits of the Huffman symbols
u32 blocksNum; // Number of blocks in the TB file
usize sizeofBlock; // Block size in bytes
usize span; // About every span values there is a SparseIndex[] entry
Sym* lowestSym; // lowestSym[l] is the symbol of length l with the lowest value
LR* btree; // btree[sym] stores the left and right symbols that expand sym
u16* blockLength; // Number of stored positions (minus one) for each block: 1..65536
u32 blockLengthSize; // Size of blockLength[] table: padded so it's bigger than blocksNum
SparseEntry* sparseIndex; // Partial indices into blockLength[]
usize sparseIndexSize; // Size of SparseIndex[] table
u8* data; // Start of Huffman compressed data
std::vector<u64>
base64; // base64[l - min_sym_len] is the 64bit-padded lowest symbol of length l
std::vector<uint8_t>
symlen; // Number of values (-1) represented by a given Huffman symbol: 1..256
Piece pieces[TBPIECES]; // Position pieces: the order of pieces defines the groups
uint64_t groupIdx[TBPIECES + 1]; // Start index used for the encoding of the group's pieces
int groupLen[TBPIECES + 1]; // Number of pieces in a given group: KRKN -> (3, 1)
uint16_t map_idx[4]; // WDLWin, WDLLoss, WDLCursedWin, WDLBlessedLoss (used in DTZ)
std::vector<u8> symlen; // Number of values (-1) represented by a given Huffman symbol: 1..256
Piece pieces[TBPIECES]; // Position pieces: the order of pieces defines the groups
u64 groupIdx[TBPIECES + 1]; // Start index used for the encoding of the group's pieces
int groupLen[TBPIECES + 1]; // Number of pieces in a given group: KRKN -> (3, 1)
u16 map_idx[4]; // WDLWin, WDLLoss, WDLCursedWin, WDLBlessedLoss (used in DTZ)
};
// struct TBTable contains indexing information to access the corresponding TBFile.
@@ -357,14 +356,14 @@ struct TBTable {
std::atomic_bool ready;
void* baseAddress;
uint8_t* map;
uint64_t mapping;
u8* map;
u64 mapping;
Key key;
Key key2;
int pieceCount;
bool hasPawns;
bool hasUniquePieces;
uint8_t pawnCount[2]; // [Lead color / other color]
u8 pawnCount[2]; // [Lead color / other color]
PairsData items[Sides][4]; // [wtm / btm][FILE_A..FILE_D or 0]
PairsData* get(int stm, int f) { return &items[stm % Sides][hasPawns ? f : 0]; }
@@ -464,15 +463,15 @@ class TBTables {
std::deque<TBTable<WDL>> wdlTable;
std::deque<TBTable<DTZ>> dtzTable;
size_t foundDTZFiles = 0;
size_t foundWDLFiles = 0;
usize foundDTZFiles = 0;
usize foundWDLFiles = 0;
void insert(Key key, TBTable<WDL>* wdl, TBTable<DTZ>* dtz) {
uint32_t homeBucket = uint32_t(key) & (Size - 1);
Entry entry{key, wdl, dtz};
u32 homeBucket = u32(key) & (Size - 1);
Entry entry{key, wdl, dtz};
// Ensure last element is empty to avoid overflow when looking up
for (uint32_t bucket = homeBucket; bucket < Size + Overflow - 1; ++bucket)
for (u32 bucket = homeBucket; bucket < Size + Overflow - 1; ++bucket)
{
Key otherKey = hashTable[bucket].key;
if (otherKey == key || !hashTable[bucket].get<WDL>())
@@ -483,7 +482,7 @@ class TBTables {
// Robin Hood hashing: If we've probed for longer than this element,
// insert here and search for a new spot for the other element instead.
uint32_t otherHomeBucket = uint32_t(otherKey) & (Size - 1);
u32 otherHomeBucket = u32(otherKey) & (Size - 1);
if (otherHomeBucket > homeBucket)
{
std::swap(entry, hashTable[bucket]);
@@ -498,7 +497,7 @@ class TBTables {
public:
template<TBType Type>
TBTable<Type>* get(Key key) {
for (const Entry* entry = &hashTable[uint32_t(key) & (Size - 1)];; ++entry)
for (const Entry* entry = &hashTable[u32(key) & (Size - 1)];; ++entry)
{
if (entry->key == key || !entry->get<Type>())
return entry->get<Type>();
@@ -573,7 +572,7 @@ void TBTables::add(const std::vector<PieceType>& pieces) {
// Huffman codes are the same for all blocks in the table. A non-symmetric pawnless TB file
// will have one table for wtm and one for btm, a TB file with pawns will have tables per
// file a,b,c,d also, in this case, one set for wtm and one for btm.
int decompress_pairs(PairsData* d, uint64_t idx) {
int decompress_pairs(PairsData* d, u64 idx) {
// Special case where all table positions store the same value
if (d->flags & TBFlag::SingleValue)
@@ -594,11 +593,11 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
// I(k) = k * d->span + d->span / 2 (1)
// First step is to get the 'k' of the I(k) nearest to our idx, using definition (1)
uint32_t k = uint32_t(idx / d->span);
u32 k = u32(idx / d->span);
// Then we read the corresponding SparseIndex[] entry
uint32_t block = number<uint32_t, LittleEndian>(&d->sparseIndex[k].block);
int offset = number<uint16_t, LittleEndian>(&d->sparseIndex[k].offset);
u32 block = number<u32, LittleEndian>(&d->sparseIndex[k].block);
int offset = number<u16, LittleEndian>(&d->sparseIndex[k].offset);
// Now compute the difference idx - I(k). From the definition of k, we know that
//
@@ -619,12 +618,12 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
offset -= d->blockLength[block++] + 1;
// Finally, we find the start address of our block of canonical Huffman symbols
uint32_t* ptr = (uint32_t*) (d->data + (uint64_t(block) * d->sizeofBlock));
u32* ptr = (u32*) (d->data + (u64(block) * d->sizeofBlock));
// Read the first 64 bits in our block, this is a (truncated) sequence of
// unknown number of symbols of unknown length but we know the first one
// is at the beginning of this 64-bit sequence.
uint64_t buf64 = number<uint64_t, BigEndian>(ptr);
u64 buf64 = number<u64, BigEndian>(ptr);
ptr += 2;
int buf64Size = 64;
Sym sym;
@@ -661,7 +660,7 @@ int decompress_pairs(PairsData* d, uint64_t idx) {
if (buf64Size <= 32)
{ // Refill the buffer
buf64Size += 32;
buf64 |= uint64_t(number<uint32_t, BigEndian>(ptr++)) << (64 - buf64Size);
buf64 |= u64(number<u32, BigEndian>(ptr++)) << (64 - buf64Size);
}
}
@@ -709,12 +708,12 @@ int map_score(TBTable<DTZ>* entry, File f, int value, WDLScore wdl) {
auto flags = entry->get(0, f)->flags;
uint8_t* map = entry->map;
uint16_t* idx = entry->get(0, f)->map_idx;
u8* map = entry->map;
u16* idx = entry->get(0, f)->map_idx;
if (flags & TBFlag::Mapped)
{
if (flags & TBFlag::Wide)
value = ((uint16_t*) map)[idx[WDLMap[wdl + 2]] + value];
value = ((u16*) map)[idx[WDLMap[wdl + 2]] + value];
else
value = map[idx[WDLMap[wdl + 2]] + value];
}
@@ -747,7 +746,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
Square squares[TBPIECES];
Piece pieces[TBPIECES];
uint64_t idx;
u64 idx;
int next = 0, size = 0, leadPawnsCnt = 0;
PairsData* d;
Bitboard b, leadPawns = 0;
@@ -944,7 +943,7 @@ encode_remaining:
while (d->groupLen[++next])
{
std::stable_sort(groupSq, groupSq + d->groupLen[next]);
uint64_t n = 0;
u64 n = 0;
// Map down a square if "comes later" than a square in the previous
// groups (similar to what was done earlier for leading group pieces).
@@ -1003,10 +1002,10 @@ void set_groups(T& e, PairsData* d, int order[], File f) {
// pawns/pieces -> remaining pawns -> remaining pieces. In particular the
// first group is at order[0] position and the remaining pawns, when present,
// are at order[1] position.
bool pp = e.hasPawns && e.pawnCount[1]; // Pawns on both sides
int next = pp ? 2 : 1;
int freeSquares = 64 - d->groupLen[0] - (pp ? d->groupLen[1] : 0);
uint64_t idx = 1;
bool pp = e.hasPawns && e.pawnCount[1]; // Pawns on both sides
int next = pp ? 2 : 1;
int freeSquares = 64 - d->groupLen[0] - (pp ? d->groupLen[1] : 0);
u64 idx = 1;
for (int k = 0; next < n || k == order[0] || k == order[1]; ++k)
if (k == order[0]) // Leading pawns or pieces
@@ -1032,7 +1031,7 @@ void set_groups(T& e, PairsData* d, int order[], File f) {
// In Recursive Pairing each symbol represents a pair of children symbols. So
// read d->btree[] symbols data and expand each one in his left and right child
// symbol until reaching the leaves that represent the symbol value.
uint8_t set_symlen(PairsData* d, Sym s, std::vector<bool>& visited) {
u8 set_symlen(PairsData* d, Sym s, std::vector<bool>& visited) {
visited[s] = true; // We can set it now because tree is acyclic
Sym sr = d->btree[s].get<LR::Right>();
@@ -1051,7 +1050,7 @@ uint8_t set_symlen(PairsData* d, Sym s, std::vector<bool>& visited) {
return d->symlen[sl] + d->symlen[sr] + 1;
}
uint8_t* set_sizes(PairsData* d, uint8_t* data) {
u8* set_sizes(PairsData* d, u8* data) {
d->flags = *data++;
@@ -1065,14 +1064,14 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) {
// groupLen[] is a zero-terminated list of group lengths, the last groupIdx[]
// element stores the biggest index that is the tb size.
uint64_t tbSize = d->groupIdx[std::find(d->groupLen, d->groupLen + 7, 0) - d->groupLen];
u64 tbSize = d->groupIdx[std::find(d->groupLen, d->groupLen + 7, 0) - d->groupLen];
d->sizeofBlock = 1ULL << *data++;
d->span = 1ULL << *data++;
d->sparseIndexSize = size_t((tbSize + d->span - 1) / d->span); // Round up
auto padding = number<uint8_t, LittleEndian>(data++);
d->blocksNum = number<uint32_t, LittleEndian>(data);
data += sizeof(uint32_t);
d->sparseIndexSize = usize((tbSize + d->span - 1) / d->span); // Round up
auto padding = number<u8, LittleEndian>(data++);
d->blocksNum = number<u32, LittleEndian>(data);
data += sizeof(u32);
d->blockLengthSize = d->blocksNum + padding; // Padded to ensure SparseIndex[]
// does not point out of range.
d->maxSymLen = *data++;
@@ -1109,8 +1108,8 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) {
d->base64[i] <<= 64 - i - d->minSymLen; // Right-padding to 64 bits
data += base64_size * sizeof(Sym);
d->symlen.resize(number<uint16_t, LittleEndian>(data));
data += sizeof(uint16_t);
d->symlen.resize(number<u16, LittleEndian>(data));
data += sizeof(u16);
d->btree = (LR*) data;
// The compression scheme used is "Recursive Pairing", that replaces the most
@@ -1127,9 +1126,9 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) {
return data + d->symlen.size() * sizeof(LR) + (d->symlen.size() & 1);
}
uint8_t* set_dtz_map(TBTable<WDL>&, uint8_t* data, File) { return data; }
u8* set_dtz_map(TBTable<WDL>&, u8* data, File) { return data; }
uint8_t* set_dtz_map(TBTable<DTZ>& e, uint8_t* data, File maxFile) {
u8* set_dtz_map(TBTable<DTZ>& e, u8* data, File maxFile) {
e.map = data;
@@ -1143,15 +1142,15 @@ uint8_t* set_dtz_map(TBTable<DTZ>& e, uint8_t* data, File maxFile) {
data += uintptr_t(data) & 1; // Word alignment, we may have a mixed table
for (int i = 0; i < 4; ++i)
{ // Sequence like 3,x,x,x,1,x,0,2,x,x
e.get(0, f)->map_idx[i] = uint16_t((uint16_t*) data - (uint16_t*) e.map + 1);
data += 2 * number<uint16_t, LittleEndian>(data) + 2;
e.get(0, f)->map_idx[i] = u16((u16*) data - (u16*) e.map + 1);
data += 2 * number<u16, LittleEndian>(data) + 2;
}
}
else
{
for (int i = 0; i < 4; ++i)
{
e.get(0, f)->map_idx[i] = uint16_t(data - e.map + 1);
e.get(0, f)->map_idx[i] = u16(data - e.map + 1);
data += *data + 1;
}
}
@@ -1164,7 +1163,7 @@ uint8_t* set_dtz_map(TBTable<DTZ>& e, uint8_t* data, File maxFile) {
// Populate entry's PairsData records with data from the just memory-mapped file.
// Called at first access.
template<typename T>
void set(T& e, uint8_t* data) {
void set(T& e, u8* data) {
PairsData* d;
@@ -1221,14 +1220,14 @@ void set(T& e, uint8_t* data) {
for (File f = FILE_A; f <= maxFile; ++f)
for (int i = 0; i < sides; i++)
{
(d = e.get(i, f))->blockLength = (uint16_t*) data;
data += d->blockLengthSize * sizeof(uint16_t);
(d = e.get(i, f))->blockLength = (u16*) data;
data += d->blockLengthSize * sizeof(u16);
}
for (File f = FILE_A; f <= maxFile; ++f)
for (int i = 0; i < sides; i++)
{
data = (uint8_t*) ((uintptr_t(data) + 0x3F) & ~0x3F); // 64 byte alignment
data = (u8*) ((uintptr_t(data) + 0x3F) & ~0x3F); // 64 byte alignment
(d = e.get(i, f))->data = data;
data += d->blocksNum * d->sizeofBlock;
}
@@ -1266,7 +1265,7 @@ void* mapped(TBTable<Type>& e, const Position& pos) {
fname =
(e.key == pos.material_key() ? w + 'v' + b : b + 'v' + w) + (Type == WDL ? ".rtbw" : ".rtbz");
uint8_t* data = TBFile(fname).map(&e.baseAddress, &e.mapping, Type);
u8* data = TBFile(fname).map(&e.baseAddress, &e.mapping, Type);
if (data)
set(e, data);
@@ -1308,8 +1307,8 @@ WDLScore search(Position& pos, ProbeState* result) {
WDLScore value, bestValue = WDLLoss;
StateInfo st;
auto moveList = MoveList<LEGAL>(pos);
size_t totalCount = moveList.size(), moveCount = 0;
auto moveList = MoveList<LEGAL>(pos);
usize totalCount = moveList.size(), moveCount = 0;
for (const Move move : moveList)
{
+21 -21
View File
@@ -47,9 +47,9 @@ namespace Stockfish {
// in idle_loop(). Note that 'searching' and 'exit' should be already set.
Thread::Thread(Search::SharedState& sharedState,
std::unique_ptr<Search::ISearchManager> sm,
size_t n,
size_t numaN,
size_t totalNumaCount,
usize n,
usize numaN,
usize totalNumaCount,
OptionalThreadToNumaNodeBinder binder) :
idx(n),
idxInNuma(numaN),
@@ -141,10 +141,10 @@ void Thread::idle_loop() {
Search::SearchManager* ThreadPool::main_manager() { return main_thread()->worker->main_manager(); }
uint64_t ThreadPool::nodes_searched() const { return accumulate(&Search::Worker::nodes); }
uint64_t ThreadPool::tb_hits() const { return accumulate(&Search::Worker::tbHits); }
u64 ThreadPool::nodes_searched() const { return accumulate(&Search::Worker::nodes); }
u64 ThreadPool::tb_hits() const { return accumulate(&Search::Worker::tbHits); }
static size_t next_power_of_two(uint64_t count) { return count > 1 ? (2ULL << msb(count - 1)) : 1; }
static usize next_power_of_two(u64 count) { return count > 1 ? (2ULL << msb(count - 1)) : 1; }
// Creates/destroys threads to match the requested number.
// Created and launched threads will immediately go to sleep in idle_loop.
@@ -162,7 +162,7 @@ void ThreadPool::set(const NumaConfig& numaConfig,
boundThreadToNumaNode.clear();
}
const size_t requested = sharedState.options["Threads"];
const usize requested = sharedState.options["Threads"];
if (requested > 0) // create new thread(s)
{
@@ -184,7 +184,7 @@ void ThreadPool::set(const NumaConfig& numaConfig,
return true;
}();
std::map<NumaIndex, size_t> counts;
std::map<NumaIndex, usize> counts;
boundThreadToNumaNode = doBindThreads
? numaConfig.distribute_threads_among_numa_nodes(requested)
: std::vector<NumaIndex>{};
@@ -193,7 +193,7 @@ void ThreadPool::set(const NumaConfig& numaConfig,
counts[0] = requested; // Pretend all threads are part of numa node 0
else
{
for (size_t i = 0; i < boundThreadToNumaNode.size(); ++i)
for (usize i = 0; i < boundThreadToNumaNode.size(); ++i)
counts[boundThreadToNumaNode[i]]++;
}
@@ -201,7 +201,7 @@ void ThreadPool::set(const NumaConfig& numaConfig,
for (auto pair : counts)
{
NumaIndex numaIndex = pair.first;
uint64_t count = pair.second;
u64 count = pair.second;
auto f = [&]() {
sharedState.sharedHistories.try_emplace(numaIndex, next_power_of_two(count));
};
@@ -216,7 +216,7 @@ void ThreadPool::set(const NumaConfig& numaConfig,
while (threads.size() < requested)
{
const size_t threadId = threads.size();
const usize threadId = threads.size();
const NumaIndex numaId = doBindThreads ? boundThreadToNumaNode[threadId] : 0;
auto create_thread = [&]() {
auto manager = threadId == 0
@@ -271,17 +271,17 @@ void ThreadPool::clear() {
main_manager()->tm.clear();
}
void ThreadPool::run_on_thread(size_t threadId, std::function<void()> f) {
void ThreadPool::run_on_thread(usize threadId, std::function<void()> f) {
assert(threads.size() > threadId);
threads[threadId]->run_custom_job(std::move(f));
}
void ThreadPool::wait_on_thread(size_t threadId) {
void ThreadPool::wait_on_thread(usize threadId) {
assert(threads.size() > threadId);
threads[threadId]->wait_for_search_finished();
}
size_t ThreadPool::num_threads() const { return threads.size(); }
usize ThreadPool::num_threads() const { return threads.size(); }
// Wakes up main thread waiting in idle_loop() and returns immediately.
@@ -352,7 +352,7 @@ Thread* ThreadPool::get_best_thread() const {
Thread* bestThread = threads.front().get();
Value minScore = VALUE_NONE;
std::unordered_map<Move, int64_t, Move::MoveHash> votes(
std::unordered_map<Move, i64, Move::MoveHash> votes(
2 * std::min(size(), bestThread->worker->rootMoves.size()));
// Find the minimum score of all threads
@@ -428,12 +428,12 @@ void ThreadPool::wait_for_search_finished() const {
th->wait_for_search_finished();
}
std::vector<size_t> ThreadPool::get_bound_thread_to_numa_node() const {
std::vector<usize> ThreadPool::get_bound_thread_to_numa_node() const {
return boundThreadToNumaNode;
}
std::vector<size_t> ThreadPool::get_bound_thread_count_by_numa_node() const {
std::vector<size_t> counts;
std::vector<usize> ThreadPool::get_bound_thread_count_by_numa_node() const {
std::vector<usize> counts;
if (!boundThreadToNumaNode.empty())
{
@@ -451,11 +451,11 @@ std::vector<size_t> ThreadPool::get_bound_thread_count_by_numa_node() const {
return counts;
}
size_t ThreadPool::numa_nodes() const {
std::unordered_set<size_t> seen;
usize ThreadPool::numa_nodes() const {
std::unordered_set<usize> seen;
for (NumaIndex n : boundThreadToNumaNode)
seen.insert(n);
return std::max(seen.size(), size_t(1));
return std::max(seen.size(), usize(1));
}
void ThreadPool::ensure_network_replicated() {
+22 -23
View File
@@ -21,13 +21,12 @@
#include <atomic>
#include <condition_variable>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <vector>
#include "misc.h"
#include "memory.h"
#include "numa.h"
#include "position.h"
@@ -75,9 +74,9 @@ class Thread {
public:
Thread(Search::SharedState&,
std::unique_ptr<Search::ISearchManager>,
size_t,
size_t,
size_t,
usize,
usize,
usize,
OptionalThreadToNumaNodeBinder);
virtual ~Thread();
@@ -93,8 +92,8 @@ class Thread {
// require further work to make them properly generic while maintaining
// appropriate specificity regarding search, from the point of view of an
// outside user, so renaming of this function is left for whenever that happens.
void wait_for_search_finished();
size_t id() const { return idx; }
void wait_for_search_finished();
usize id() const { return idx; }
LargePagePtr<Search::Worker> worker;
std::function<void()> jobFunc;
@@ -102,7 +101,7 @@ class Thread {
private:
std::mutex mutex;
std::condition_variable cv;
size_t idx, idxInNuma, totalNuma, nthreads;
usize idx, idxInNuma, totalNuma, nthreads;
bool exit = false, searching = true; // Set before starting std::thread
NativeThread stdThread;
NumaReplicatedAccessToken numaAccessToken;
@@ -132,26 +131,26 @@ class ThreadPool {
ThreadPool& operator=(const ThreadPool&) = delete;
ThreadPool& operator=(ThreadPool&&) = delete;
void start_thinking(const OptionsMap&, Position&, StateListPtr&, Search::LimitsType);
void run_on_thread(size_t threadId, std::function<void()> f);
void wait_on_thread(size_t threadId);
size_t num_threads() const;
void clear();
void set(const NumaConfig& numaConfig,
Search::SharedState,
const Search::SearchManager::UpdateContext&);
void start_thinking(const OptionsMap&, Position&, StateListPtr&, Search::LimitsType);
void run_on_thread(usize threadId, std::function<void()> f);
void wait_on_thread(usize threadId);
usize num_threads() const;
void clear();
void set(const NumaConfig& numaConfig,
Search::SharedState,
const Search::SearchManager::UpdateContext&);
Search::SearchManager* main_manager();
Thread* main_thread() const { return threads.front().get(); }
uint64_t nodes_searched() const;
uint64_t tb_hits() const;
u64 nodes_searched() const;
u64 tb_hits() const;
Thread* get_best_thread() const;
void start_searching();
void wait_for_search_finished() const;
std::vector<size_t> get_bound_thread_to_numa_node() const;
std::vector<size_t> get_bound_thread_count_by_numa_node() const;
size_t numa_nodes() const;
std::vector<usize> get_bound_thread_to_numa_node() const;
std::vector<usize> get_bound_thread_count_by_numa_node() const;
usize numa_nodes() const;
void ensure_network_replicated();
@@ -169,9 +168,9 @@ class ThreadPool {
std::vector<std::unique_ptr<Thread>> threads;
std::vector<NumaIndex> boundThreadToNumaNode;
uint64_t accumulate(std::atomic<uint64_t> Search::Worker::* member) const {
u64 accumulate(std::atomic<u64> Search::Worker::* member) const {
uint64_t sum = 0;
u64 sum = 0;
for (auto&& th : threads)
sum += (th->worker.get()->*member).load(std::memory_order_relaxed);
return sum;
+3 -4
View File
@@ -21,7 +21,6 @@
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdint>
#include "search.h"
#include "ucioption.h"
@@ -35,9 +34,9 @@ void TimeManagement::clear() {
availableNodes = -1; // When in 'nodes as time' mode
}
void TimeManagement::advance_nodes_time(std::int64_t nodes) {
void TimeManagement::advance_nodes_time(i64 nodes) {
assert(useNodesTime);
availableNodes = std::max(int64_t(0), availableNodes - nodes);
availableNodes = std::max(i64(0), availableNodes - nodes);
}
// Called at the beginning of the search and calculates
@@ -83,7 +82,7 @@ void TimeManagement::init(Search::LimitsType& limits,
// These numbers are used where multiplications, divisions,
// or comparisons with constants are involved.
const int64_t scaleFactor = useNodesTime ? npmsec : 1;
const i64 scaleFactor = useNodesTime ? npmsec : 1;
const TimePoint scaledTime = limits.time[us] / scaleFactor;
// Maximum move horizon
+4 -5
View File
@@ -19,14 +19,13 @@
#ifndef TIMEMAN_H_INCLUDED
#define TIMEMAN_H_INCLUDED
#include <cstdint>
#include "misc.h"
namespace Stockfish {
class OptionsMap;
enum Color : uint8_t;
enum Color : u8;
namespace Search {
struct LimitsType;
@@ -51,15 +50,15 @@ class TimeManagement {
TimePoint elapsed_time() const { return now() - startTime; };
void clear();
void advance_nodes_time(std::int64_t nodes);
void advance_nodes_time(i64 nodes);
private:
TimePoint startTime;
TimePoint optimumTime;
TimePoint maximumTime;
std::int64_t availableNodes = -1; // When in 'nodes as time' mode
bool useNodesTime = false; // True if we are in 'nodes as time' mode
i64 availableNodes = -1; // When in 'nodes as time' mode
bool useNodesTime = false; // True if we are in 'nodes as time' mode
};
} // namespace Stockfish
+39 -40
View File
@@ -20,7 +20,6 @@
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
@@ -53,12 +52,12 @@ namespace Stockfish {
// externally, so we offset the internal depth by DEPTH_NONE.
//
// Pv, bound and generation are packed in a single byte.
static constexpr uint8_t GENERATION_BITS = 5;
static constexpr uint8_t GENERATION_MASK = (1 << GENERATION_BITS) - 1;
static constexpr uint8_t BOUND_SHIFT = GENERATION_BITS;
static constexpr uint8_t BOUND_MASK = 0b11 << BOUND_SHIFT;
static constexpr uint8_t PV_SHIFT = BOUND_SHIFT + 2;
static constexpr uint8_t PV_MASK = 1 << PV_SHIFT;
static constexpr u8 GENERATION_BITS = 5;
static constexpr u8 GENERATION_MASK = (1 << GENERATION_BITS) - 1;
static constexpr u8 BOUND_SHIFT = GENERATION_BITS;
static constexpr u8 BOUND_MASK = 0b11 << BOUND_SHIFT;
static constexpr u8 PV_SHIFT = BOUND_SHIFT + 2;
static constexpr u8 PV_MASK = 1 << PV_SHIFT;
struct TTEntry {
@@ -73,43 +72,43 @@ struct TTEntry {
}
bool is_occupied() const { return bool(depth8); };
void save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t curr_generation);
uint8_t relative_age(const uint8_t curr_generation) const;
void save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, u8 curr_generation);
u8 relative_age(const u8 curr_generation) const;
private:
friend class TranspositionTable;
friend struct TTWriter;
uint16_t key16;
uint8_t depth8;
uint8_t genBound8;
Move move16;
int16_t value16;
int16_t eval16;
u16 key16;
u8 depth8;
u8 genBound8;
Move move16;
i16 value16;
i16 eval16;
};
// Populates the TTEntry with a new node's data, possibly
// overwriting an old position. The update is non-atomic and can be racy.
void TTEntry::save(
Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t curr_generation) {
Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, u8 curr_generation) {
// Preserve the old ttmove if we don't have a new one
if (m || uint16_t(k) != key16)
if (m || u16(k) != key16)
move16 = m;
// Overwrite less valuable entries (cheapest checks first)
if (b == BOUND_EXACT || uint16_t(k) != key16 || d - DEPTH_NONE + 2 * pv > depth8 - 4
if (b == BOUND_EXACT || u16(k) != key16 || d - DEPTH_NONE + 2 * pv > depth8 - 4
|| relative_age(curr_generation))
{
assert(d > DEPTH_NONE);
assert(d - DEPTH_NONE < 256);
assert(curr_generation <= GENERATION_MASK); // TT::new_search() plays nice
key16 = uint16_t(k);
depth8 = uint8_t(d - DEPTH_NONE);
genBound8 = uint8_t(curr_generation | b << BOUND_SHIFT | uint8_t(pv) << PV_SHIFT);
value16 = int16_t(v);
eval16 = int16_t(ev);
key16 = u16(k);
depth8 = u8(d - DEPTH_NONE);
genBound8 = u8(curr_generation | b << BOUND_SHIFT | u8(pv) << PV_SHIFT);
value16 = i16(v);
eval16 = i16(ev);
}
// Secondary aging. Important for elementary mate finding.
// (*Scaler) Secondary aging on entries relevant to singular extensions
@@ -125,7 +124,7 @@ void TTEntry::save(
}
uint8_t TTEntry::relative_age(const uint8_t curr_generation) const {
u8 TTEntry::relative_age(const u8 curr_generation) const {
// Returns this entry's age. We count generations like clocks count hours,
// i.e. we require 0 - 1 == 31. Unsigned subtraction guarantees the required
// borrowing regardless of the upper pv/bound bits.
@@ -138,7 +137,7 @@ TTWriter::TTWriter(TTEntry* tte) :
entry(tte) {}
void TTWriter::write(
Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t curr_generation) {
Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, u8 curr_generation) {
entry->save(k, v, pv, b, d, m, ev, curr_generation);
}
@@ -165,11 +164,11 @@ static_assert(sizeof(Cluster) == 32, "Suboptimal Cluster size");
// Sets the size of the transposition table,
// measured in megabytes. Transposition table consists
// of clusters and each cluster consists of ClusterSize number of TTEntry.
void TranspositionTable::resize(size_t mbSize, ThreadPool& threads) {
void TranspositionTable::resize(usize mbSize, ThreadPool& threads) {
aligned_large_pages_free(table);
clusterCount = mbSize * 1024 * 1024 / sizeof(Cluster);
size_t ttBytes = clusterCount * sizeof(Cluster);
clusterCount = mbSize * 1024 * 1024 / sizeof(Cluster);
usize ttBytes = clusterCount * sizeof(Cluster);
// Request 1GB pages if we'd get at least eight per NUMA node, to avoid
// memory oversubscription
@@ -190,36 +189,36 @@ void TranspositionTable::resize(size_t mbSize, ThreadPool& threads) {
// Initializes the entire transposition table to zero,
// in a multi-threaded way.
void TranspositionTable::clear(ThreadPool& threads) {
generation8 = 0;
const size_t threadCount = threads.num_threads();
generation8 = 0;
const usize threadCount = threads.num_threads();
std::vector<size_t> threadToNuma = threads.get_bound_thread_to_numa_node();
std::vector<usize> threadToNuma = threads.get_bound_thread_to_numa_node();
std::vector<size_t> order(threadCount);
std::vector<usize> order(threadCount);
std::iota(order.begin(), order.end(), 0);
// To promote good NUMA distribution (esp. with huge pages), we permute threads so that
// all threads in a NUMA node clear a contiguous region of the TT.
if (threadToNuma.size() == threadCount)
{
std::stable_sort(order.begin(), order.end(), [&threadToNuma](size_t t1, size_t t2) {
std::stable_sort(order.begin(), order.end(), [&threadToNuma](usize t1, usize t2) {
return threadToNuma.at(t1) < threadToNuma.at(t2);
});
}
for (size_t i = 0; i < threadCount; ++i)
for (usize i = 0; i < threadCount; ++i)
{
threads.run_on_thread(order[i], [this, i, threadCount]() {
// Each thread will zero its part of the hash table
const size_t stride = clusterCount / threadCount;
const size_t start = stride * i;
const size_t len = i + 1 != threadCount ? stride : clusterCount - start;
const usize stride = clusterCount / threadCount;
const usize start = stride * i;
const usize len = i + 1 != threadCount ? stride : clusterCount - start;
std::memset(&table[start], 0, len * sizeof(Cluster));
});
}
for (size_t i = 0; i < threadCount; ++i)
for (usize i = 0; i < threadCount; ++i)
threads.wait_on_thread(i);
}
@@ -245,7 +244,7 @@ void TranspositionTable::new_search() {
}
uint8_t TranspositionTable::generation() const { return generation8; }
u8 TranspositionTable::generation() const { return generation8; }
// Looks up the current position in the transposition table.
@@ -255,7 +254,7 @@ uint8_t TranspositionTable::generation() const { return generation8; }
std::tuple<bool, TTData, TTWriter> TranspositionTable::probe(const Key key) const {
TTEntry* const tte = first_entry(key);
const uint16_t key16 = uint16_t(key); // Use the low 16 bits as key inside the cluster
const u16 key16 = u16(key); // Use the low 16 bits as key inside the cluster
for (int i = 0; i < ClusterSize; ++i)
if (tte[i].key16 == key16)
+7 -8
View File
@@ -19,10 +19,9 @@
#ifndef TT_H_INCLUDED
#define TT_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include <tuple>
#include "misc.h"
#include "memory.h"
#include "types.h"
@@ -67,7 +66,7 @@ struct TTData {
// for chess reasons, we may decide the new data is less important than the old.
struct TTWriter {
public:
void write(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, uint8_t generation8);
void write(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev, u8 generation8);
void penalize(int penalty); // decrement stored depth by the penalty
private:
@@ -82,12 +81,12 @@ class TranspositionTable {
public:
~TranspositionTable() { aligned_large_pages_free(table); }
void resize(size_t mbSize, ThreadPool& threads); // Set TT size in MiB
void clear(ThreadPool& threads); // Re-initialize memory, multithreaded
void resize(usize mbSize, ThreadPool& threads); // Set TT size in MiB
void clear(ThreadPool& threads); // Re-initialize memory, multithreaded
void
new_search(); // This must be called at the beginning of each root search to track entry aging
uint8_t generation() const; // The current age, used when writing new data to the TT
u8 generation() const; // The current age, used when writing new data to the TT
// Approximate what fraction of entries (permille) have been written to during this root search
int hashfull(int maxAge = 0) const;
@@ -102,10 +101,10 @@ class TranspositionTable {
private:
friend struct TTEntry;
size_t clusterCount;
usize clusterCount;
Cluster* table = nullptr;
uint8_t generation8 = 0;
u8 generation8 = 0;
};
} // namespace Stockfish
+21 -23
View File
@@ -110,19 +110,19 @@ constexpr bool Is64Bit = true;
constexpr bool Is64Bit = false;
#endif
using Key = uint64_t;
using Bitboard = uint64_t;
using Key = u64;
using Bitboard = u64;
constexpr int MAX_MOVES = 256;
constexpr int MAX_PLY = 246;
enum Color : uint8_t {
enum Color : u8 {
WHITE,
BLACK,
COLOR_NB = 2
};
enum CastlingRights : uint8_t {
enum CastlingRights : u8 {
NO_CASTLING,
WHITE_OO,
WHITE_OOO = WHITE_OO << 1,
@@ -138,7 +138,7 @@ enum CastlingRights : uint8_t {
CASTLING_RIGHT_NB = 16
};
enum Bound : uint8_t {
enum Bound : u8 {
BOUND_NONE,
BOUND_UPPER,
BOUND_LOWER,
@@ -201,13 +201,13 @@ constexpr Value QueenValue = 2538;
// clang-format off
enum PieceType : std::uint8_t {
enum PieceType : u8 {
NO_PIECE_TYPE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING,
ALL_PIECES = 0,
PIECE_TYPE_NB = 8
};
enum Piece : std::uint8_t {
enum Piece : u8 {
NO_PIECE,
W_PAWN = PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
B_PAWN = PAWN + 8, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING,
@@ -238,7 +238,7 @@ constexpr Depth DEPTH_UNSEARCHED = -2;
constexpr Depth DEPTH_NONE = -3;
// clang-format off
enum Square : uint8_t {
enum Square : u8 {
SQ_A1, SQ_B1, SQ_C1, SQ_D1, SQ_E1, SQ_F1, SQ_G1, SQ_H1,
SQ_A2, SQ_B2, SQ_C2, SQ_D2, SQ_E2, SQ_F2, SQ_G2, SQ_H2,
SQ_A3, SQ_B3, SQ_C3, SQ_D3, SQ_E3, SQ_F3, SQ_G3, SQ_H3,
@@ -254,7 +254,7 @@ enum Square : uint8_t {
};
// clang-format on
enum Direction : int8_t {
enum Direction : i8 {
NORTH = 8,
EAST = 1,
SOUTH = -NORTH,
@@ -266,7 +266,7 @@ enum Direction : int8_t {
NORTH_WEST = NORTH + WEST
};
enum File : uint8_t {
enum File : u8 {
FILE_A,
FILE_B,
FILE_C,
@@ -278,7 +278,7 @@ enum File : uint8_t {
FILE_NB
};
enum Rank : uint8_t {
enum Rank : u8 {
RANK_1,
RANK_2,
RANK_3,
@@ -310,10 +310,10 @@ struct DirtyThreat {
static constexpr int PcOffset = 20;
DirtyThreat() { /* don't initialize data */ }
DirtyThreat(uint32_t raw) :
DirtyThreat(u32 raw) :
data(raw) {}
DirtyThreat(Piece pc, Piece threatened_pc, Square pc_sq, Square threatened_sq, bool add) {
data = (uint32_t(add) << 31) | (pc << PcOffset) | (threatened_pc << ThreatenedPcOffset)
data = (u32(add) << 31) | (pc << PcOffset) | (threatened_pc << ThreatenedPcOffset)
| (threatened_sq << ThreatenedSqOffset) | (pc_sq << PcSqOffset);
}
@@ -322,10 +322,10 @@ struct DirtyThreat {
Square threatened_sq() const { return static_cast<Square>(data >> ThreatenedSqOffset & 0xff); }
Square pc_sq() const { return static_cast<Square>(data >> PcSqOffset & 0xff); }
bool add() const { return data >> 31; }
uint32_t raw() const { return data; }
u32 raw() const { return data; }
private:
uint32_t data;
u32 data;
};
// A piece can be involved in at most 8 outgoing attacks and 16 incoming attacks.
@@ -410,12 +410,10 @@ constexpr Direction pawn_push(Color c) { return c == WHITE ? NORTH : SOUTH; }
// Based on a congruential pseudo-random number generator
constexpr Key make_key(uint64_t seed) {
return seed * 6364136223846793005ULL + 1442695040888963407ULL;
}
constexpr Key make_key(u64 seed) { return seed * 6364136223846793005ULL + 1442695040888963407ULL; }
enum MoveType : uint16_t {
enum MoveType : u16 {
NORMAL,
PROMOTION = 1 << 14,
EN_PASSANT = 2 << 14,
@@ -437,7 +435,7 @@ enum MoveType : uint16_t {
class Move {
public:
Move() = default;
constexpr explicit Move(std::uint16_t d) :
constexpr explicit Move(u16 d) :
data(d) {}
constexpr Move(Square from, Square to) :
@@ -476,17 +474,17 @@ class Move {
constexpr explicit operator bool() const { return data != 0; }
constexpr std::uint16_t raw() const { return data; }
constexpr u16 raw() const { return data; }
struct MoveHash {
std::size_t operator()(const Move& m) const { return make_key(m.data); }
usize operator()(const Move& m) const { return make_key(m.data); }
};
static constexpr int FromSqShift = 6;
static constexpr int ToSqShift = 0;
protected:
std::uint16_t data;
u16 data;
};
template<typename T, typename... Ts>
+5 -6
View File
@@ -21,7 +21,6 @@
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <iterator>
#include <optional>
@@ -226,8 +225,8 @@ void UCIEngine::go(std::istringstream& is) {
void UCIEngine::bench(std::istream& args) {
std::string token;
uint64_t num, nodes = 0, cnt = 1;
uint64_t nodesSearched = 0;
u64 num, nodes = 0, cnt = 1;
u64 nodesSearched = 0;
const auto& options = engine.get_options();
engine.set_on_update_full([&](const auto& i) {
@@ -298,8 +297,8 @@ void UCIEngine::benchmark(std::istream& args) {
static constexpr int NUM_WARMUP_POSITIONS = 3;
std::string token;
uint64_t nodes = 0, cnt = 1;
uint64_t nodesSearched = 0;
u64 nodes = 0, cnt = 1;
u64 nodesSearched = 0;
engine.set_on_update_full([&](const Engine::InfoFull& i) { nodesSearched = i.nodes; });
@@ -456,7 +455,7 @@ void UCIEngine::setoption(std::istringstream& is) {
engine.get_options().setoption(is);
}
std::uint64_t UCIEngine::perft(const Search::LimitsType& limits) {
u64 UCIEngine::perft(const Search::LimitsType& limits) {
auto nodes = engine.perft(engine.fen(), limits.perft, engine.get_options()["UCI_Chess960"]);
sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl;
return nodes;
+7 -8
View File
@@ -19,7 +19,6 @@
#ifndef UCI_H_INCLUDED
#define UCI_H_INCLUDED
#include <cstdint>
#include <iostream>
#include <string>
#include <string_view>
@@ -33,7 +32,7 @@ namespace Stockfish {
class Position;
class Move;
class Score;
enum Square : uint8_t;
enum Square : u8;
using Value = int;
constexpr auto StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
@@ -62,12 +61,12 @@ class UCIEngine {
static void print_info_string(std::string_view str);
void go(std::istringstream& is);
void bench(std::istream& args);
void benchmark(std::istream& args);
void position(std::istringstream& is);
void setoption(std::istringstream& is);
std::uint64_t perft(const Search::LimitsType&);
void go(std::istringstream& is);
void bench(std::istream& args);
void benchmark(std::istream& args);
void position(std::istringstream& is);
void setoption(std::istringstream& is);
u64 perft(const Search::LimitsType&);
static void on_update_no_moves(const Engine::InfoShort& info);
static void on_update_full(const Engine::InfoFull& info, bool showWDL);
+3 -3
View File
@@ -68,7 +68,7 @@ const Option& OptionsMap::operator[](const std::string& name) const {
void OptionsMap::add(const std::string& name, const Option& option) {
if (!options_map.count(name))
{
static size_t insert_order = 0;
static usize insert_order = 0;
options_map[name] = option;
@@ -83,7 +83,7 @@ void OptionsMap::add(const std::string& name, const Option& option) {
}
std::size_t OptionsMap::count(const std::string& name) const { return options_map.count(name); }
usize OptionsMap::count(const std::string& name) const { return options_map.count(name); }
Option::Option(const OptionsMap* map) :
parent(map) {}
@@ -185,7 +185,7 @@ Option& Option::operator=(const std::string& v) {
}
std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
for (size_t idx = 0; idx < om.options_map.size(); ++idx)
for (usize idx = 0; idx < om.options_map.size(); ++idx)
for (const auto& it : om.options_map)
if (it.second.idx == idx)
{
+4 -3
View File
@@ -19,13 +19,14 @@
#ifndef UCIOPTION_H_INCLUDED
#define UCIOPTION_H_INCLUDED
#include <cstddef>
#include <functional>
#include <iosfwd>
#include <map>
#include <optional>
#include <string>
#include "misc.h"
namespace Stockfish {
// Define a custom comparator, because the UCI options should be case-insensitive
struct CaseInsensitiveLess {
@@ -64,7 +65,7 @@ class Option {
std::string defaultValue, currentValue, type;
int min, max;
size_t idx;
usize idx;
OnChange on_change;
const OptionsMap* parent = nullptr;
};
@@ -87,7 +88,7 @@ class OptionsMap {
void add(const std::string&, const Option& option);
std::size_t count(const std::string&) const;
usize count(const std::string&) const;
private:
friend class Engine;
+7 -7
View File
@@ -34,12 +34,12 @@
#include <unistd.h>
// Must be kept in sync with patch_x86_slice.sh
extern const volatile uint64_t gUniversalNNUEOffset = 0xCAFE0FF5E70FF5E7ULL;
extern const volatile uint64_t gUniversalNNUESize = 0xCAFE512ECAFE512EULL;
extern const volatile Stockfish::u64 gUniversalNNUEOffset = 0xCAFE0FF5E70FF5E7ULL;
extern const volatile Stockfish::u64 gUniversalNNUESize = 0xCAFE512ECAFE512EULL;
static const unsigned char* map_embedded_nnue() {
char path[PATH_MAX];
uint32_t len = sizeof(path);
char path[PATH_MAX];
Stockfish::u32 len = sizeof(path);
if (_NSGetExecutablePath(path, &len) != 0)
return nullptr;
@@ -51,9 +51,9 @@ static const unsigned char* map_embedded_nnue() {
return nullptr;
// Align down to page size for mmap
const uint64_t pageSize = uint64_t(sysconf(_SC_PAGESIZE));
const uint64_t base = gUniversalNNUEOffset & ~(pageSize - 1);
const uint64_t pad = gUniversalNNUEOffset - base;
const Stockfish::u64 pageSize = Stockfish::u64(sysconf(_SC_PAGESIZE));
const Stockfish::u64 base = gUniversalNNUEOffset & ~(pageSize - 1);
const Stockfish::u64 pad = gUniversalNNUEOffset - base;
void* p =
mmap(nullptr, size_t(gUniversalNNUESize + pad), PROT_READ, MAP_PRIVATE, fd, off_t(base));