From 6a50807e01773951e727d897cdd3549e8e4249ce Mon Sep 17 00:00:00 2001 From: anematode Date: Sun, 10 May 2026 11:46:31 +0200 Subject: [PATCH] On Linux, allow shared-memory network weights to be backed by huge pages This does require the user to have set `/sys/kernel/mm/transparent_hugepage/shmem_enabled` to something other than `never` (unfortunately the default, at least on Ubuntu). ``` Result of 50 runs ================== base (...kfish.master) = 1814244 +/- 4396 test (./stockfish ) = 1823756 +/- 3448 diff = +9512 +/- 5496 speedup = +0.0052 P(speedup > 0) = 0.9996 ``` ``` Performance counter stats for './stockfish bench': 237,561 dTLB-misses 5,783,003,231 cycles Performance counter stats for './bins/stockfish.master bench': 2,219,832 dTLB-misses 5,932,779,255 cycles ``` closes https://github.com/official-stockfish/Stockfish/pull/6805 No functional change --- src/shm_linux.h | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/shm_linux.h b/src/shm_linux.h index 29c9e90f5..fd5a0d27a 100644 --- a/src/shm_linux.h +++ b/src/shm_linux.h @@ -141,23 +141,6 @@ class CleanupHooks { inline std::once_flag CleanupHooks::register_once_; -inline int portable_fallocate(int fd, off_t offset, off_t length) { -#ifdef __APPLE__ - fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, offset, length, 0}; - int ret = fcntl(fd, F_PREALLOCATE, &store); - if (ret == -1) - { - store.fst_flags = F_ALLOCATEALL; - ret = fcntl(fd, F_PREALLOCATE, &store); - } - if (ret != -1) - ret = ftruncate(fd, offset + length); - return ret; -#else - return posix_fallocate(fd, offset, length); -#endif -} - } // namespace detail template @@ -599,9 +582,6 @@ class SharedMemory: public detail::SharedMemoryBase { if (ftruncate(fd_, static_cast(total_size_)) == -1) return false; - if (detail::portable_fallocate(fd_, 0, static_cast(total_size_)) != 0) - return false; - mapped_ptr_ = mmap(nullptr, total_size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0); if (mapped_ptr_ == MAP_FAILED) { @@ -609,6 +589,23 @@ class SharedMemory: public detail::SharedMemoryBase { return false; } +#ifdef MADV_POPULATE_WRITE + // Pre-populate, attempting first with THP, to guarantee that the memory + // is allocated and avoid crashing on the first write. + madvise(mapped_ptr_, total_size_, MADV_HUGEPAGE); + + const bool populated = madvise(mapped_ptr_, total_size_, MADV_POPULATE_WRITE) == 0; +#else + const bool populated = false; +#endif + // If the THP population failed, try with fallocate + if (!populated && posix_fallocate(fd_, 0, static_cast(total_size_)) != 0) + { + munmap(mapped_ptr_, total_size_); + mapped_ptr_ = nullptr; + return false; + } + data_ptr_ = static_cast(mapped_ptr_); header_ptr_ = reinterpret_cast(static_cast(mapped_ptr_) + sizeof(T)); @@ -642,6 +639,10 @@ class SharedMemory: public detail::SharedMemoryBase { return false; } +#ifdef MADV_HUGEPAGE + madvise(mapped_ptr_, total_size_, MADV_HUGEPAGE); +#endif + data_ptr_ = static_cast(mapped_ptr_); header_ptr_ = std::launder( reinterpret_cast(static_cast(mapped_ptr_) + sizeof(T)));