mirror of
https://github.com/official-stockfish/Stockfish.git
synced 2026-07-22 12:47:08 +00:00
Prefetch threat weight rows during append_changed_indices
Passed STC (first run): https://tests.stockfishchess.org/tests/view/698030ee6362aee5c8a552c7 LLR: 2.96 (-2.94,2.94) <0.00,2.00> Total: 120800 W: 31336 L: 30912 D: 58552 Ptnml(0-2): 330, 13084, 33172, 13460, 354 Passed LTC: https://tests.stockfishchess.org/tests/view/6983946d473df9d1d24a916d LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 86850 W: 22352 L: 21951 D: 42547 Ptnml(0-2): 45, 8506, 25934, 8883, 57 Passed STC SMP (after changes made after opening the PR): https://tests.stockfishchess.org/tests/view/6987b4c1b0f3ca5200aaf9da LLR: 2.95 (-2.94,2.94) <0.00,2.00> Total: 84480 W: 21994 L: 21627 D: 40859 Ptnml(0-2): 98, 9378, 22932, 9723, 109 Passed STC (second run, as a sanity check made after changes made after opening the PR -- these changed, however, didn't change assembly code produced by the compiler): https://tests.stockfishchess.org/tests/view/6987ad21b0f3ca5200aaf9c9 LLR: 2.93 (-2.94,2.94) <0.00,2.00> Total: 132192 W: 34526 L: 34083 D: 63583 Ptnml(0-2): 421, 14511, 35759, 15014, 391 GCC maps __builtin_prefetch locality=1 to PREFETCHT2 instruction, targeting L2 cache. To make things clear, added template-based approach as suggested by Disservin. PREFETCHT2 should be the appropriate choice for the 78 MB threat weight table: avoids L1d pollution, parks data in L2 where it is promoted to L1d on actual load. With 200-500 cycle lead time from make_index, data has time to arrive in L2. suggestions by Disservin and anematode included closes https://github.com/official-stockfish/Stockfish/pull/6602 No functional change
This commit is contained in:
committed by
Joost VandeVondele
parent
99221e5ee6
commit
238ef05bb0
+63
-2
@@ -37,6 +37,10 @@
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#if !defined(NO_PREFETCH) && (defined(_MSC_VER) || defined(__INTEL_COMPILER))
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
#define stringify2(x) #x
|
||||
#define stringify(x) stringify2(x)
|
||||
|
||||
@@ -46,10 +50,67 @@ std::string engine_version_info();
|
||||
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
|
||||
// Prefetch hint enums for explicit call-site control.
|
||||
enum class PrefetchRw {
|
||||
READ,
|
||||
WRITE
|
||||
};
|
||||
|
||||
// NOTE: PrefetchLoc controls locality / cache level, not whether a prefetch
|
||||
// is issued. In particular, PrefetchLoc::NONE maps to a non-temporal /
|
||||
// lowest-locality prefetch (Intel: _MM_HINT_NTA, GCC/Clang: locality = 0)
|
||||
// and therefore still performs a prefetch. To completely disable
|
||||
// prefetching, define NO_PREFETCH so that prefetch() becomes a no-op.
|
||||
enum class PrefetchLoc {
|
||||
NONE, // Non-temporal / no cache locality (still issues a prefetch)
|
||||
LOW, // Low locality (e.g. T2 / L2)
|
||||
MODERATE, // Moderate locality (e.g. T1 / L1)
|
||||
HIGH // High locality (e.g. T0 / closest cache)
|
||||
};
|
||||
|
||||
// Preloads the given address into 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(const void* addr);
|
||||
#ifdef NO_PREFETCH
|
||||
template<PrefetchRw RW = PrefetchRw::READ, PrefetchLoc LOC = PrefetchLoc::HIGH>
|
||||
void prefetch(const void*) {}
|
||||
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||
|
||||
constexpr int get_intel_hint(PrefetchRw rw, PrefetchLoc loc) {
|
||||
if (rw == PrefetchRw::WRITE)
|
||||
{
|
||||
#ifdef _MM_HINT_ET0
|
||||
return _MM_HINT_ET0;
|
||||
#else
|
||||
// Fallback when write-prefetch hint is not available: use T0
|
||||
return _MM_HINT_T0;
|
||||
#endif
|
||||
}
|
||||
switch (loc)
|
||||
{
|
||||
case PrefetchLoc::NONE :
|
||||
return _MM_HINT_NTA;
|
||||
case PrefetchLoc::LOW :
|
||||
return _MM_HINT_T2;
|
||||
case PrefetchLoc::MODERATE :
|
||||
return _MM_HINT_T1;
|
||||
case PrefetchLoc::HIGH :
|
||||
return _MM_HINT_T0;
|
||||
default :
|
||||
return _MM_HINT_T0;
|
||||
}
|
||||
}
|
||||
|
||||
template<PrefetchRw RW = PrefetchRw::READ, PrefetchLoc LOC = PrefetchLoc::HIGH>
|
||||
void prefetch(const void* addr) {
|
||||
_mm_prefetch(static_cast<const char*>(addr), get_intel_hint(RW, LOC));
|
||||
}
|
||||
#else
|
||||
template<PrefetchRw RW = PrefetchRw::READ, PrefetchLoc LOC = PrefetchLoc::HIGH>
|
||||
void prefetch(const void* addr) {
|
||||
__builtin_prefetch(addr, static_cast<int>(RW), static_cast<int>(LOC));
|
||||
}
|
||||
#endif
|
||||
|
||||
void start_logger(const std::string& fname);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user