X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fmisc.h;h=682ef81641c041869fb255e6732a53b6b651da9c;hp=4b238df549decf27c75768ce7fa8177ddcfaab1e;hb=HEAD;hpb=784e7d91455246361871f2f950dfb05e428c2c58 diff --git a/src/misc.h b/src/misc.h index 4b238df5..91fdb72f 100644 --- a/src/misc.h +++ b/src/misc.h @@ -1,8 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (C) 2004-2008 Tord Romstad (Glaurung author) - Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad - Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad + Copyright (C) 2004-2023 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,92 +21,168 @@ #include #include -#include +#include +#include +#include #include -#include -#include "types.h" +#define stringify2(x) #x +#define stringify(x) stringify2(x) -const std::string engine_info(bool to_uci = false); +namespace Stockfish { + +std::string engine_info(bool to_uci = false); +std::string compiler_info(); + +// Preloads the given address in L1/L2 cache. This is a non-blocking +// function that doesn't stall the CPU waiting for data to be loaded from memory, +// which can be quite slow. void prefetch(void* addr); -void prefetch2(void* addr); -void start_logger(const std::string& fname); -void dbg_hit_on(bool b); -void dbg_hit_on(bool c, bool b); -void dbg_mean_of(int v); +void start_logger(const std::string& fname); +void* std_aligned_alloc(size_t alignment, size_t size); +void std_aligned_free(void* ptr); +// memory aligned by page size, min alignment: 4096 bytes +void* aligned_large_pages_alloc(size_t size); +// nop if mem == nullptr +void aligned_large_pages_free(void* mem); + +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_correl_of(int64_t value1, int64_t value2, int slot = 0); void dbg_print(); -typedef std::chrono::milliseconds::rep TimePoint; // A value in milliseconds - +using TimePoint = std::chrono::milliseconds::rep; // A value in milliseconds static_assert(sizeof(TimePoint) == sizeof(int64_t), "TimePoint should be 64 bits"); - inline TimePoint now() { - return std::chrono::duration_cast - (std::chrono::steady_clock::now().time_since_epoch()).count(); + return std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); } -template -struct HashTable { - Entry* operator[](Key key) { return &table[(uint32_t)key & (Size - 1)]; } -private: - std::vector table = std::vector(Size); // Allocate on the heap +enum SyncCout { + IO_LOCK, + IO_UNLOCK }; - - -enum SyncCout { IO_LOCK, IO_UNLOCK }; std::ostream& operator<<(std::ostream&, SyncCout); #define sync_cout std::cout << IO_LOCK #define sync_endl std::endl << IO_UNLOCK -/// xorshift64star Pseudo-Random Number Generator -/// This class is based on original code written and dedicated -/// to the public domain by Sebastiano Vigna (2014). -/// It has the following characteristics: -/// -/// - Outputs 64-bit numbers -/// - Passes Dieharder and SmallCrush test batteries -/// - Does not require warm-up, no zeroland to escape -/// - Internal state is a single 64-bit integer -/// - Period is 2^64 - 1 -/// - Speed: 1.60 ns/call (Core i7 @3.40GHz) -/// -/// For further analysis see -/// +// Get the first aligned element of an array. +// ptr must point to an array of size at least `sizeof(T) * N + alignment` bytes, +// where N is the number of elements in the array. +template +T* align_ptr_up(T* ptr) { + static_assert(alignof(T) < Alignment); -class PRNG { + const uintptr_t ptrint = reinterpret_cast(reinterpret_cast(ptr)); + return reinterpret_cast( + reinterpret_cast((ptrint + (Alignment - 1)) / Alignment * Alignment)); +} - uint64_t s; - uint64_t rand64() { +// True if and only if the binary is compiled on a little-endian machine +static inline const union { + uint32_t i; + char c[4]; +} Le = {0x01020304}; +static inline const bool IsLittleEndian = (Le.c[0] == 4); - s ^= s >> 12, s ^= s << 25, s ^= s >> 27; - return s * 2685821657736338717LL; - } -public: - PRNG(uint64_t seed) : s(seed) { assert(seed); } +template +class ValueList { - template T rand() { return T(rand64()); } + public: + std::size_t size() const { return size_; } + void push_back(const T& value) { values_[size_++] = value; } + const T* begin() const { return values_; } + const T* end() const { return values_ + size_; } + const T& operator[](int index) const { return values_[index]; } - /// Special generator used to fast init magic numbers. - /// Output values only have 1/8th of their bits set on average. - template T sparse_rand() - { return T(rand64() & rand64() & rand64()); } + private: + T values_[MaxSize]; + std::size_t size_ = 0; }; -/// Under Windows it is not possible for a process to run on more than one -/// logical processor group. This usually means to be limited to use max 64 -/// cores. To overcome this, some special platform specific API should be -/// called to set group affinity for each thread. Original code from Texel by -/// Peter Österlund. +// xorshift64star Pseudo-Random Number Generator +// This class is based on original code written and dedicated +// to the public domain by Sebastiano Vigna (2014). +// It has the following characteristics: +// +// - Outputs 64-bit numbers +// - Passes Dieharder and SmallCrush test batteries +// - Does not require warm-up, no zeroland to escape +// - Internal state is a single 64-bit integer +// - Period is 2^64 - 1 +// - Speed: 1.60 ns/call (Core i7 @3.40GHz) +// +// For further analysis see +// + +class PRNG { + + uint64_t s; + + uint64_t rand64() { + s ^= s >> 12, s ^= s << 25, s ^= s >> 27; + return s * 2685821657736338717LL; + } + + public: + PRNG(uint64_t seed) : + s(seed) { + assert(seed); + } + + template + T rand() { + return T(rand64()); + } + + // Special generator used to fast init magic numbers. + // Output values only have 1/8th of their bits set on average. + template + T sparse_rand() { + return T(rand64() & rand64() & rand64()); + } +}; + +inline uint64_t mul_hi64(uint64_t a, uint64_t b) { +#if defined(__GNUC__) && defined(IS_64BIT) + __extension__ using uint128 = unsigned __int128; + return (uint128(a) * uint128(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); + return aH * bH + (c2 >> 32) + (c3 >> 32); +#endif +} + +// Under Windows it is not possible for a process to run on more than one +// logical processor group. This usually means being limited to using max 64 +// cores. To overcome this, some special platform-specific API should be +// called to set group affinity for each thread. Original code from Texel by +// Peter Österlund. namespace WinProcGroup { - void bindThisThread(size_t idx); +void bindThisThread(size_t idx); } -#endif // #ifndef MISC_H_INCLUDED +namespace CommandLine { +void init(int argc, char* argv[]); + +extern std::string binaryDirectory; // path of the executable directory +extern std::string workingDirectory; // path of the working directory +} + +} // namespace Stockfish + +#endif // #ifndef MISC_H_INCLUDED