RotationIndexer: keep 1024 indexing outcomes, keyed by a digest of the input
A run on data that index poorly asks over a hundred indexing questions - every rung of the spot-budget ladder, in every pass and walk probe - and a later pass repeats a probe's ladder, which the 32-entry memo had long evicted (about 20 s on one such sweep). The key holds every spot, so it is now kept as two independent 64-bit hashes and its length instead of whole. RUGNUX_VERIFY_FIRST_PASS_MEMO still recomputes and compares. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D1G8gJVAy6gp1K5Dz3NE5C
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
|
||||
namespace {
|
||||
// Sub-cell override thresholds used in candidate selection to undo a spurious axis doubling:
|
||||
@@ -160,16 +161,32 @@ namespace {
|
||||
static_cast<double>(x.GetIndexingThreads()), static_cast<double>(x.GetRefineThreads())});
|
||||
}
|
||||
|
||||
// The input key is kept as two independent 64-bit hashes of its bytes plus its length - a key
|
||||
// holds every spot, so keeping it whole would cost megabytes per entry.
|
||||
struct KeyDigest {
|
||||
size_t n;
|
||||
uint64_t fnv, std_hash;
|
||||
bool operator==(const KeyDigest &) const = default;
|
||||
};
|
||||
KeyDigest Digest(const std::vector<double> &key) {
|
||||
const std::string_view bytes(reinterpret_cast<const char *>(key.data()), key.size() * sizeof(double));
|
||||
uint64_t fnv = 14695981039346656037ULL; // FNV-1a
|
||||
for (const char c : bytes)
|
||||
fnv = (fnv ^ static_cast<uint8_t>(c)) * 1099511628211ULL;
|
||||
return {key.size(), fnv, std::hash<std::string_view>{}(bytes)};
|
||||
}
|
||||
|
||||
struct IndexingMemo {
|
||||
std::mutex m;
|
||||
std::vector<std::pair<std::vector<double>, RotationIndexer::IndexingOutcome>> entries;
|
||||
std::vector<std::pair<KeyDigest, RotationIndexer::IndexingOutcome>> entries;
|
||||
};
|
||||
IndexingMemo &Memo() {
|
||||
static IndexingMemo memo;
|
||||
return memo;
|
||||
}
|
||||
// A run asks a handful of distinct questions at most; the oldest go first.
|
||||
constexpr size_t MAX_INDEXING_MEMOS = 32;
|
||||
// A run on data that index poorly asks well over a hundred questions (every rung of the spot-budget
|
||||
// ladder, in every pass and probe), and a later pass repeats a probe's; the oldest go first.
|
||||
constexpr size_t MAX_INDEXING_MEMOS = 1024;
|
||||
|
||||
// Bitwise comparison of what a recomputation gave against what was kept.
|
||||
bool SameOutcome(const RotationIndexer::IndexingOutcome &a, const RotationIndexer::IndexingOutcome &b) {
|
||||
@@ -229,7 +246,7 @@ void RotationIndexer::RunIndexing() {
|
||||
if (!axis_)
|
||||
return;
|
||||
|
||||
const std::vector<double> key = InputKey();
|
||||
const KeyDigest key = Digest(InputKey());
|
||||
std::optional<IndexingOutcome> kept;
|
||||
{
|
||||
auto &memo = Memo();
|
||||
|
||||
Reference in New Issue
Block a user