clusterlin: only start/use search when enough iterations left

This commit is contained in:
Pieter Wuille
2024-07-25 00:13:11 -04:00
parent bd044356ed
commit 9ad2fe7e69
2 changed files with 47 additions and 12 deletions

View File

@@ -458,6 +458,7 @@ FUZZ_TARGET(clusterlin_ancestor_finder)
while (todo.Any()) {
// Call the ancestor finder's FindCandidateSet for what remains of the graph.
assert(!anc_finder.AllDone());
assert(todo.Count() == anc_finder.NumRemaining());
auto best_anc = anc_finder.FindCandidateSet();
// Sanity check the result.
assert(best_anc.transactions.Any());
@@ -489,6 +490,7 @@ FUZZ_TARGET(clusterlin_ancestor_finder)
anc_finder.MarkDone(del_set);
}
assert(anc_finder.AllDone());
assert(anc_finder.NumRemaining() == 0);
}
static constexpr auto MAX_SIMPLE_ITERATIONS = 300000;
@@ -523,6 +525,7 @@ FUZZ_TARGET(clusterlin_search_finder)
assert(!smp_finder.AllDone());
assert(!exh_finder.AllDone());
assert(!anc_finder.AllDone());
assert(anc_finder.NumRemaining() == todo.Count());
// For each iteration, read an iteration count limit from the fuzz input.
uint64_t max_iterations = 1;
@@ -605,6 +608,7 @@ FUZZ_TARGET(clusterlin_search_finder)
assert(smp_finder.AllDone());
assert(exh_finder.AllDone());
assert(anc_finder.AllDone());
assert(anc_finder.NumRemaining() == 0);
}
FUZZ_TARGET(clusterlin_linearization_chunking)
@@ -775,11 +779,16 @@ FUZZ_TARGET(clusterlin_linearize)
if (n <= 19 && iter_count > (uint64_t{1} << n)) {
assert(optimal);
}
// Additionally, if the assumption of sqrt(2^k)+1 iterations per step holds, the maximum number
// of iterations is also bounded by (2 + sqrt(2)) * (sqrt(2^n) - 1) + n, which is less than
// (2 + sqrt(2)) * sqrt(2^n) + n. Subtracting n and squaring gives
// (6 + 4 * sqrt(2)) * 2^n < 12 * 2^n.
if (n <= 35 && iter_count > n && (iter_count - n) * (iter_count - n) >= uint64_t{12} << n) {
// Additionally, if the assumption of sqrt(2^k)+1 iterations per step holds, plus ceil(k/4)
// start-up cost per step, plus ceil(n^2/64) start-up cost overall, we can compute the upper
// bound for a whole linearization (summing for k=1..n) using the Python expression
// [sum((k+3)//4 + int(math.sqrt(2**k)) + 1 for k in range(1, n + 1)) + (n**2 + 63) // 64 for n in range(0, 35)]:
static constexpr uint64_t MAX_OPTIMAL_ITERS[] = {
0, 4, 8, 12, 18, 26, 37, 51, 70, 97, 133, 182, 251, 346, 480, 666, 927, 1296, 1815, 2545,
3576, 5031, 7087, 9991, 14094, 19895, 28096, 39690, 56083, 79263, 112041, 158391, 223936,
316629, 447712
};
if (n < std::size(MAX_OPTIMAL_ITERS) && iter_count >= MAX_OPTIMAL_ITERS[n]) {
Assume(optimal);
}