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
This commit is contained in:
anematode
2026-05-10 11:46:31 +02:00
committed by Joost VandeVondele
parent c2500b1165
commit 6a50807e01
+21 -20
View File
@@ -141,23 +141,6 @@ class CleanupHooks {
inline std::once_flag CleanupHooks::register_once_; 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 } // namespace detail
template<typename T> template<typename T>
@@ -599,9 +582,6 @@ class SharedMemory: public detail::SharedMemoryBase {
if (ftruncate(fd_, static_cast<off_t>(total_size_)) == -1) if (ftruncate(fd_, static_cast<off_t>(total_size_)) == -1)
return false; return false;
if (detail::portable_fallocate(fd_, 0, static_cast<off_t>(total_size_)) != 0)
return false;
mapped_ptr_ = mmap(nullptr, total_size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0); mapped_ptr_ = mmap(nullptr, total_size_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0);
if (mapped_ptr_ == MAP_FAILED) if (mapped_ptr_ == MAP_FAILED)
{ {
@@ -609,6 +589,23 @@ class SharedMemory: public detail::SharedMemoryBase {
return false; 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<off_t>(total_size_)) != 0)
{
munmap(mapped_ptr_, total_size_);
mapped_ptr_ = nullptr;
return false;
}
data_ptr_ = static_cast<T*>(mapped_ptr_); data_ptr_ = static_cast<T*>(mapped_ptr_);
header_ptr_ = header_ptr_ =
reinterpret_cast<detail::ShmHeader*>(static_cast<char*>(mapped_ptr_) + sizeof(T)); reinterpret_cast<detail::ShmHeader*>(static_cast<char*>(mapped_ptr_) + sizeof(T));
@@ -642,6 +639,10 @@ class SharedMemory: public detail::SharedMemoryBase {
return false; return false;
} }
#ifdef MADV_HUGEPAGE
madvise(mapped_ptr_, total_size_, MADV_HUGEPAGE);
#endif
data_ptr_ = static_cast<T*>(mapped_ptr_); data_ptr_ = static_cast<T*>(mapped_ptr_);
header_ptr_ = std::launder( header_ptr_ = std::launder(
reinterpret_cast<detail::ShmHeader*>(static_cast<char*>(mapped_ptr_) + sizeof(T))); reinterpret_cast<detail::ShmHeader*>(static_cast<char*>(mapped_ptr_) + sizeof(T)));