Expert arena: when the RAM still falls short after the wait, the PLE table lock the residency policy took is given back before the arena is registered (#4846)

This commit is contained in:
Niko1221 committed 2026-11-01 01:29:51 +01:00
1 parent 31c3a16f4f
commit eb8917247a
3 files changed
+27

No files matched your search

+4
View File
@@ -1305,6 +1305,10 @@ public:
/// What backing was obtained and why, for the startup print. "The engine adapts to the machine it is on" is
/// only true if the engine says what it got.
const std::string& note() const { return note_; }
/// #4846: called by `open` once, when the RAM still falls short of the arena after the wait and before anything is registered.
/// The owner of a lock the engine took on its own (the PLE table's residency lock) gives it back here and returns the bytes
/// it released (0: nothing to give); `open` then reads the available RAM again. Unset: nothing is given back.
std::function<uint64_t()> give_back_ram;
/// #633: set by `open` when the RAM available is less than the arena needs (a recommendation; it still loads)
const std::string& ram_warning() const { return ram_warning_; }
uint64_t pinned_arena_bytes() const { return pinned_bytes_; } ///< what the driver registered (the pinned prefix, or the total by need)
+15
View File
@@ -5904,6 +5904,21 @@ bool ArenaExpertSource::open(const std::string& pack_dir, int64_t n_layers, int6
"expert arena\n", (double) avail / gib, waited);
hm.available = avail;
}
if (hm.available < need && give_back_ram) {
// #4846: the shortfall survived the wait. A lock the engine took by itself (the PLE table's residency lock) is
// given back before the registration starts: its pages stay cached, the OS may take them for the arena.
const uint64_t freed = give_back_ram();
if (freed > 0) {
detail::HostMemory h2;
if (detail::host_available_memory(h2)) {
std::fprintf(stderr, "strata generate: the expert arena needs %.2f GiB of RAM and %.2f GiB was available: "
"gave back %.2f GiB of locked RAM, %.2f GiB is available now
",
(double) need / gib, (double) hm.available / gib, (double) freed / gib, (double) h2.available / gib);
hm.available = h2.available;
}
}
}
if (hm.available < need) {
std::snprintf(buf, sizeof buf,
"the expert arena needs %.2f GiB of RAM but %.2f GiB is available (%.2f GiB short%s): the "
+8
View File
@@ -6776,6 +6776,14 @@ int main(int argc, char** argv) {
// The arena pins until the OS refuses; on Windows that leaves no page-locked memory for the small buffers the
// engine allocates after it (the verify window's staging: "mapped staging allocation failed", exit 1). Keep a
// reserve while the arena pins and hand it back after (pin_budget.hpp).
if (ple_lock_by_policy) // #4846: the residency policy priced the table against the arena before the rest of the start took its RAM
arena_src.give_back_ram = [&]() -> uint64_t {
if (!ple_table.locked()) return 0;
const uint64_t held = ple_table.table_bytes();
if (!ple_table.unlock()) return 0;
ple_lock_by_policy = false; // (given back: the conversation cache's give-back has nothing left to do)
return held;
};
strata::core::pin_reserve_take();
const bool arena_ok = arena_src.open(o.pack, g.n_layers, g.n_expert, /*threads=*/6, err, pin_limit,
o.shared_expert_arena);