| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
|
|
| #ifndef NNUE_COMMON_H_INCLUDED |
| #define NNUE_COMMON_H_INCLUDED |
|
|
| #include <cstring> |
| #include <iostream> |
|
|
| #include "../misc.h" |
|
|
| #if defined(USE_AVX2) |
| #include <immintrin.h> |
|
|
| #elif defined(USE_SSE41) |
| #include <smmintrin.h> |
|
|
| #elif defined(USE_SSSE3) |
| #include <tmmintrin.h> |
|
|
| #elif defined(USE_SSE2) |
| #include <emmintrin.h> |
|
|
| #elif defined(USE_MMX) |
| #include <mmintrin.h> |
|
|
| #elif defined(USE_NEON) |
| #include <arm_neon.h> |
| #endif |
|
|
| namespace Stockfish::Eval::NNUE { |
|
|
| |
| constexpr std::uint32_t Version = 0x7AF32F20u; |
|
|
| |
| constexpr int OutputScale = 16; |
| constexpr int WeightScaleBits = 6; |
|
|
| |
| constexpr std::size_t CacheLineSize = 64; |
|
|
| |
| #if defined(USE_AVX2) |
| constexpr std::size_t SimdWidth = 32; |
|
|
| #elif defined(USE_SSE2) |
| constexpr std::size_t SimdWidth = 16; |
|
|
| #elif defined(USE_MMX) |
| constexpr std::size_t SimdWidth = 8; |
|
|
| #elif defined(USE_NEON) |
| constexpr std::size_t SimdWidth = 16; |
| #endif |
|
|
| constexpr std::size_t MaxSimdWidth = 32; |
|
|
| |
| using TransformedFeatureType = std::uint8_t; |
| using IndexType = std::uint32_t; |
|
|
| |
| template <typename IntType> |
| constexpr IntType ceil_to_multiple(IntType n, IntType base) { |
| return (n + base - 1) / base * base; |
| } |
|
|
| |
| |
| |
| template <typename IntType> |
| inline IntType read_little_endian(std::istream& stream) { |
| IntType result; |
|
|
| if (IsLittleEndian) |
| stream.read(reinterpret_cast<char*>(&result), sizeof(IntType)); |
| else |
| { |
| std::uint8_t u[sizeof(IntType)]; |
| typename std::make_unsigned<IntType>::type v = 0; |
|
|
| stream.read(reinterpret_cast<char*>(u), sizeof(IntType)); |
| for (std::size_t i = 0; i < sizeof(IntType); ++i) |
| v = (v << 8) | u[sizeof(IntType) - i - 1]; |
|
|
| std::memcpy(&result, &v, sizeof(IntType)); |
| } |
|
|
| return result; |
| } |
|
|
| |
| |
| |
| |
| template <typename IntType> |
| inline void write_little_endian(std::ostream& stream, IntType value) { |
|
|
| if (IsLittleEndian) |
| stream.write(reinterpret_cast<const char*>(&value), sizeof(IntType)); |
| else |
| { |
| std::uint8_t u[sizeof(IntType)]; |
| typename std::make_unsigned<IntType>::type v = value; |
|
|
| std::size_t i = 0; |
| |
| if constexpr (sizeof(IntType) > 1) |
| { |
| for (; i + 1 < sizeof(IntType); ++i) |
| { |
| u[i] = (std::uint8_t)v; |
| v >>= 8; |
| } |
| } |
| u[i] = (std::uint8_t)v; |
|
|
| stream.write(reinterpret_cast<char*>(u), sizeof(IntType)); |
| } |
| } |
|
|
| |
| |
| template <typename IntType> |
| inline void read_little_endian(std::istream& stream, IntType* out, std::size_t count) { |
| if (IsLittleEndian) |
| stream.read(reinterpret_cast<char*>(out), sizeof(IntType) * count); |
| else |
| for (std::size_t i = 0; i < count; ++i) |
| out[i] = read_little_endian<IntType>(stream); |
| } |
|
|
| |
| |
| template <typename IntType> |
| inline void write_little_endian(std::ostream& stream, const IntType* values, std::size_t count) { |
| if (IsLittleEndian) |
| stream.write(reinterpret_cast<const char*>(values), sizeof(IntType) * count); |
| else |
| for (std::size_t i = 0; i < count; ++i) |
| write_little_endian<IntType>(stream, values[i]); |
| } |
|
|
| } |
|
|
| #endif |
|
|