diff options
Diffstat (limited to 'research/experiments/001-checkpoint-granularity')
6 files changed, 1186 insertions, 0 deletions
diff --git a/research/experiments/001-checkpoint-granularity/README.md b/research/experiments/001-checkpoint-granularity/README.md new file mode 100644 index 0000000..4c04950 --- /dev/null +++ b/research/experiments/001-checkpoint-granularity/README.md @@ -0,0 +1,110 @@ +# Experiment 001: checkpoint granularity + +This is a native measurement apparatus for one known space/time tradeoff. It is +not a new algorithm, a general dependency-graph runtime, or the product's language +choice. The apparatus uses C17 and Python's standard library so it can be run +with the tools present on the initial Linux host and with a C compiler on macOS. + +## Question and pre-measurement expectations + +How much does storing intermediate results at different intervals save, once the +editable program and scheduling state are included? How much extra work does it +cause when a rule changes? + +Expected, not measured at the time of writing this section: + +- Uniformly spaced checkpoints shrink the result cache at the cost of starting + recomputation before the changed instruction. +- Root input changes offer no prefix to reuse. Fine checkpoints may only add + cache writes and comparisons in this workload. +- Edits near the end favor fine checkpoints. This deliberately favorable case + must not stand in for all edits. +- The editable model stays resident, so shrinking the cache 16-fold will not + shrink total core storage 16-fold. + +## Semantics and comparison + +The model consists of independent, statically connected chains. Each instruction +is an 8-byte record with a scalar operator and parameter. Values are uint64_t; +overflow wraps. Supported operators are add, XOR, multiply, and rotate/XOR. +Only the final result of each chain is observed. + +One update applies a batch of changes, then computes all affected observed +outputs. Changes alter roots, operators, and parameters, not graph topology. +There is no renderer, effectful I/O, concurrent execution, or state migration. + +- Block 1 stores every intermediate result (fine incremental baseline). +- Blocks 4, 16, and 64 store results at block ends. +- A block equal to chain length recomputes the whole affected chain, retaining + only its final output (full recomputation baseline). + +All variants share program representation, input handling and per-chain dirty +ranges. Unaffected chains are skipped by every variant. Fine and full variants +use dedicated loops. Fine/block variants stop at an unchanged cached boundary +only after passing the last changed instruction in the batch. + +The chain structure makes dependency information implicit. No general graph +edge storage or graph partitioning is needed. This is an optimistic case for +compact checkpoints; it cannot establish results for arbitrary graphs. + +For G chains of length L and checkpoint spacing B, the requested persistent +storage in this implementation is: + +```text +sizeof(Engine) + 8*G*L + 16*G + 8*G*ceil(L/B) + model inputs+ cached values, + dirty including outputs +``` + +This includes all live core arrays and the engine descriptor, but not allocator +bookkeeping, stack, executable code, trace storage or OS pages. Trace size is +recorded separately. It is not RSS, physical footprint, or total application RAM. +There are no allocations in the timed update path. + +## Workloads + +The fixed initial matrix uses 16 chains, lengths 256 and 1024, and 256 updates per +trace. Workload seed: 20260922. + +- `roots`: every chain's input changes on every update. +- `uniform`: one uniformly selected instruction changes per update. +- `tail`: one instruction in the last eight positions changes per update. +- `dense`: eight instruction edits per chain per update, with replacement. + +Changes are XOR deltas so repeated traces continue changing the model. Two +warm-up passes precede timing. Even measured replay counts leave identical final +models across strategies; the runner checks their output checksums. Differential +tests additionally compare every output after every update against independent +from-scratch evaluation across multiple seeds, odd sizes and edge cases. + +## Reproduce + +From this directory, with Python 3 and a C compiler with ASan/UBSan support: + +```sh +python3 run.py --check-only +python3 run.py --output results/local-run +``` + +The runner refuses to overwrite an existing result directory. `CC` can select a +compiler, such as `CC=clang`. It builds into a temporary directory. On Linux it +pins itself and child processes to one available CPU and records that choice. + +Default measurements use seven trials with randomized strategy order within +each trial. Pilot timings choose an even replay count per case, targeting 20 ms +per measurement. All raw samples, memory counts, instruction counts, compiler +flags, source hashes and host metadata are retained. Timing excludes program +creation, trace creation, warm-up, and output verification. It includes change +application, scheduling and recomputation. + +`median_ns_per_tick` is the median of batch-average processing times. It is not a +P50/P99 input-to-display latency measurement. A shared host without controlled +power or temperature permits preliminary comparisons, not hardware guarantees. + +The reported storage reduction is largely predicted by the formula. The useful +observations are the whole-core reduction, processing cost and losing workloads. +This experiment cannot establish automatic policy quality, novel research, +editor usability, M3 performance, or universal memory savings. + +The first run and its interpretation are available in the +[Korean research report](../../../docs/research/002-checkpoint-results.md). diff --git a/research/experiments/001-checkpoint-granularity/benchmark.c b/research/experiments/001-checkpoint-granularity/benchmark.c new file mode 100644 index 0000000..1c3f98b --- /dev/null +++ b/research/experiments/001-checkpoint-granularity/benchmark.c @@ -0,0 +1,276 @@ +#define _POSIX_C_SOURCE 200809L +#include <errno.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +/* Experimental apparatus, not the Pure runtime. All arithmetic is modulo 2^64. */ +typedef struct { uint32_t salt, control; } Op; +typedef struct { + uint32_t chain, index; + uint64_t mask; +} Change; +typedef struct { + uint32_t chains, length, block, slots; + Op *ops; + uint64_t *inputs, *cache; + uint32_t *first, *last; +} Engine; +typedef struct { + uint32_t ticks, per_tick; + Change *changes; +} Trace; + +static void die(const char *s) { fprintf(stderr, "%s\n", s); exit(1); } +static void require(int condition, const char *s) { if (!condition) die(s); } +static void *allocate(size_t count, size_t size) { + if (size && count > SIZE_MAX / size) die("allocation size overflow"); + void *p = calloc(count, size); + if (!p) die("allocation failed"); + return p; +} +static uint64_t random64(uint64_t *s) { + uint64_t z = (*s += UINT64_C(0x9e3779b97f4a7c15)); + z = (z ^ (z >> 30)) * UINT64_C(0xbf58476d1ce4e5b9); + z = (z ^ (z >> 27)) * UINT64_C(0x94d049bb133111eb); + return z ^ (z >> 31); +} +static uint64_t rotate(uint64_t x, uint32_t n) { + return (x << n) | (x >> (64 - n)); +} +static uint64_t evaluate(Op op, uint64_t x) { + switch (op.control & 3u) { + case 0: return x + op.salt; + case 1: return x ^ ((uint64_t)op.salt << 17); + case 2: return x * ((uint64_t)op.salt | 1u); + default: return rotate(x, 1u + ((op.control >> 2) % 63u)) ^ op.salt; + } +} +static uint64_t now_ns(void) { + struct timespec t; + if (clock_gettime(CLOCK_MONOTONIC, &t)) die("clock_gettime failed"); + return (uint64_t)t.tv_sec * UINT64_C(1000000000) + (uint64_t)t.tv_nsec; +} +static uint64_t output(const Engine *e, uint32_t c) { + return e->cache[(size_t)c * e->slots + e->slots - 1]; +} +static uint64_t reference_output(const Engine *e, uint32_t c) { + uint64_t x = e->inputs[c]; + for (uint32_t n = 0; n < e->length; ++n) + x = evaluate(e->ops[(size_t)c * e->length + n], x); + return x; +} +static Engine create_engine(uint32_t chains, uint32_t length, + uint32_t block, uint64_t seed) { + Engine e = { .chains = chains, .length = length, .block = block, + .slots = (length + block - 1) / block }; + e.ops = allocate((size_t)chains * length, sizeof(*e.ops)); + e.inputs = allocate(chains, sizeof(*e.inputs)); + e.cache = allocate((size_t)chains * e.slots, sizeof(*e.cache)); + e.first = allocate(chains, sizeof(*e.first)); + e.last = allocate(chains, sizeof(*e.last)); + for (uint32_t c = 0; c < chains; ++c) { + e.inputs[c] = random64(&seed); + uint64_t x = e.inputs[c]; + for (uint32_t n = 0; n < length; ++n) { + Op *op = &e.ops[(size_t)c * length + n]; + op->salt = (uint32_t)random64(&seed); + op->control = (uint32_t)random64(&seed); + x = evaluate(*op, x); + if ((n + 1) % block == 0 || n + 1 == length) + e.cache[(size_t)c * e.slots + n / block] = x; + } + e.first[c] = length; + } + return e; +} +static void destroy_engine(Engine *e) { + free(e->ops); free(e->inputs); free(e->cache); + free(e->first); free(e->last); +} +static void apply(Engine *e, Change change) { + uint32_t c = change.chain, n = change.index; + require(c < e->chains && n <= e->length, "invalid change"); + if (!change.mask) return; + if (n == e->length) { + e->inputs[c] ^= change.mask; + n = 0; + } else { + Op *op = &e->ops[(size_t)c * e->length + n]; + op->salt ^= (uint32_t)change.mask; + op->control ^= (uint32_t)(change.mask >> 32); + } + if (n < e->first[c]) e->first[c] = n; + if (n > e->last[c]) e->last[c] = n; +} +static uint64_t update(Engine *e) { + uint64_t work = 0; + for (uint32_t c = 0; c < e->chains; ++c) { + uint32_t first = e->first[c], last = e->last[c]; + if (first == e->length) continue; + const Op *ops = e->ops + (size_t)c * e->length; + uint64_t *cache = e->cache + (size_t)c * e->slots; + /* Full and fine have dedicated loops: no block-loop penalty for B=1. */ + if (e->block == e->length) { + uint64_t x = e->inputs[c]; + for (uint32_t n = 0; n < e->length; ++n) x = evaluate(ops[n], x); + cache[0] = x; + work += e->length; + } else if (e->block == 1) { + uint64_t x = first ? cache[first - 1] : e->inputs[c]; + uint32_t n = first; + while (n < e->length) { + uint64_t old = cache[n]; + cache[n] = x = evaluate(ops[n], x); + ++n; + /* Do not skip a later edit in the same batch. */ + if (n > last && x == old) break; + } + work += n - first; + } else { + uint32_t start = first / e->block; + uint64_t x = start ? cache[start - 1] : e->inputs[c]; + for (uint32_t b = start; b < e->slots; ++b) { + uint32_t begin = b * e->block, end = begin + e->block; + if (end > e->length) end = e->length; + for (uint32_t n = begin; n < end; ++n) x = evaluate(ops[n], x); + uint64_t old = cache[b]; + cache[b] = x; + work += end - begin; + if (end > last && x == old) break; + } + } + e->first[c] = e->length; + e->last[c] = 0; + } + return work; +} +static uint64_t checksum(const Engine *e) { + uint64_t h = UINT64_C(0xcbf29ce484222325); + for (uint32_t c = 0; c < e->chains; ++c) + h = (h ^ output(e, c)) * UINT64_C(0x100000001b3); + return h; +} +static Trace create_trace(const char *kind, uint32_t chains, uint32_t length, + uint32_t ticks, uint64_t seed) { + uint32_t per_tick = 1; + int roots = !strcmp(kind, "roots"); + int dense = !strcmp(kind, "dense"); + int uniform = !strcmp(kind, "uniform"); + int tail = !strcmp(kind, "tail"); + require(roots || dense || uniform || tail, "unknown workload"); + if (roots) per_tick = chains; + if (dense) per_tick = chains * 8; + Trace t = { .ticks = ticks, .per_tick = per_tick }; + t.changes = allocate((size_t)ticks * per_tick, sizeof(*t.changes)); + for (uint32_t i = 0; i < ticks; ++i) { + for (uint32_t k = 0; k < per_tick; ++k) { + Change *p = &t.changes[(size_t)i * per_tick + k]; + p->chain = roots ? k : dense ? k / 8 : (uint32_t)(random64(&seed) % chains); + p->index = roots ? length : (uint32_t)(random64(&seed) % length); + if (tail) { + uint32_t width = length < 8 ? length : 8; + p->index = length - width + p->index % width; + } + /* XOR changes keep every replay active; fixed assignments would not. */ + p->mask = random64(&seed) | 1u; + } + } + return t; +} +static uint64_t replay(Engine *e, const Trace *t) { + uint64_t work = 0; + for (uint32_t i = 0; i < t->ticks; ++i) { + for (uint32_t k = 0; k < t->per_tick; ++k) + apply(e, t->changes[(size_t)i * t->per_tick + k]); + work += update(e); + } + return work; +} +static size_t owned_bytes(const Engine *e) { + return sizeof(*e) + (size_t)e->chains * e->length * sizeof(*e->ops) + + (size_t)e->chains * (sizeof(*e->inputs) + sizeof(*e->first) + sizeof(*e->last)) + + (size_t)e->chains * e->slots * sizeof(*e->cache); +} +static void check_outputs(const Engine *e) { + for (uint32_t c = 0; c < e->chains; ++c) + require(output(e, c) == reference_output(e, c), "output disagrees with full reference"); +} +static void self_test(void) { + const uint32_t lengths[] = {1, 2, 7, 17, 65, 257}; + const uint32_t blocks[] = {1, 2, 4, 16, 64, 256}; + uint64_t checked_ticks = 0; + for (uint64_t seed = 1; seed <= 8; ++seed) { + for (size_t l = 0; l < sizeof(lengths) / sizeof(*lengths); ++l) { + uint32_t length = lengths[l]; + for (size_t b = 0; b <= sizeof(blocks) / sizeof(*blocks); ++b) { + uint32_t block = b == sizeof(blocks) / sizeof(*blocks) ? length : blocks[b]; + if (block > length) continue; + Engine e = create_engine(3, length, block, seed); + check_outputs(&e); + uint64_t rng = seed; + for (uint32_t tick = 0; tick < 500; ++tick) { + uint32_t count = (uint32_t)(random64(&rng) % 9); + for (uint32_t k = 0; k < count; ++k) { + Change change = { + .chain = (uint32_t)(random64(&rng) % e.chains), + .index = (uint32_t)(random64(&rng) % (length + 1)), + .mask = random64(&rng) + }; + if (tick % 11 == 0) change.mask = 0; + apply(&e, change); + if (tick % 13 == 0) apply(&e, change); /* cancelling edits */ + } + (void)update(&e); + check_outputs(&e); + require(update(&e) == 0, "clean update performed work"); + ++checked_ticks; + } + destroy_engine(&e); + } + } + } + /* An unchanged early checkpoint must not suppress a later dirty operation. */ + for (uint32_t block = 1; block <= 4; block *= 2) { + Engine e = create_engine(1, 8, block, 77); + Change cancel = {0, 0, 123}, later = {0, 7, 987}; + apply(&e, cancel); apply(&e, cancel); apply(&e, later); + (void)update(&e); check_outputs(&e); destroy_engine(&e); + } + printf("{\"checked_ticks\":%" PRIu64 ",\"status\":\"passed\"}\n", checked_ticks); +} +static uint32_t number(const char *s, uint32_t max) { + char *end; + errno = 0; + unsigned long n = strtoul(s, &end, 10); + if (errno || end == s || *end || !n || n > max) die("invalid positive integer"); + return (uint32_t)n; +} +int main(int argc, char **argv) { + if (argc == 2 && !strcmp(argv[1], "--check")) { self_test(); return 0; } + if (argc != 8) die("usage: benchmark CHAINS LENGTH BLOCK WORKLOAD TICKS REPLAYS SEED | --check"); + uint32_t chains = number(argv[1], 1024), length = number(argv[2], 65536); + uint32_t block = number(argv[3], length), ticks = number(argv[5], 4096); + uint32_t replays = number(argv[6], 4096), seed = number(argv[7], UINT32_MAX); + require((uint64_t)chains * length <= UINT64_C(1048576), "model too large for this lab"); + Engine e = create_engine(chains, length, block, seed); + Trace t = create_trace(argv[4], chains, length, ticks, seed + UINT64_C(1234567)); + (void)replay(&e, &t); (void)replay(&e, &t); /* two warm-up replays */ + uint64_t work = 0, start = now_ns(); + for (uint32_t r = 0; r < replays; ++r) work += replay(&e, &t); + uint64_t elapsed = now_ns() - start; + check_outputs(&e); /* correctness check is outside the measured interval */ + printf("{\"elapsed_ns\":%" PRIu64 ",\"ticks\":%" PRIu64 + ",\"node_evaluations\":%" PRIu64 ",\"core_owned_bytes\":%zu" + ",\"model_bytes\":%zu,\"cache_bytes\":%zu,\"engine_bytes\":%zu" + ",\"trace_bytes\":%zu,\"checksum\":\"%016" PRIx64 "\"}\n", + elapsed, (uint64_t)ticks * replays, work, owned_bytes(&e), + (size_t)chains * length * sizeof(Op), + (size_t)chains * e.slots * sizeof(uint64_t), sizeof(Engine), + sizeof(t) + (size_t)t.ticks * t.per_tick * sizeof(Change), checksum(&e)); + free(t.changes); destroy_engine(&e); + return 0; +} diff --git a/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/environment.json b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/environment.json new file mode 100644 index 0000000..1e967ad --- /dev/null +++ b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/environment.json @@ -0,0 +1,330 @@ +{ + "started_utc": "2026-09-22T09:32:06.820074+00:00", + "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41", + "machine": "aarch64", + "compiler": "cc (Debian 14.2.0-19) 14.2.0\nCopyright (C) 2024 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions. There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.", + "flags": [ + "-std=c17", + "-O3", + "-Wall", + "-Wextra", + "-Wpedantic", + "-Werror" + ], + "python": "3.14.7", + "source_sha256": "9e1b1108f58a8725458531207bd1edf06d9af43ae3255c3b97d4388c2b58c707", + "runner_sha256": "4c3e8ae899eb5068813df9529a8c7953d63730ee3ca507a0a7dbe58963b1db01", + "trials": 7, + "target_ms": 20.0, + "seed": 20260922, + "timing": "batch elapsed time / update ticks; not input latency", + "memory": "sizeof engine + requested live array bytes; excludes allocator, harness, code, OS", + "power_control": "not controlled; shared host; preliminary measurements", + "original_affinity": [ + 0, + 1, + 2, + 3 + ], + "measurement_affinity": [ + 0 + ], + "cpu_description": [ + "CPU architecture: 8", + "CPU implementer\t: 0x41", + "CPU part\t: 0xd0b", + "Model\t\t: Raspberry Pi 5 Model B Rev 1.1" + ], + "release_check": { + "checked_ticks": 108000, + "status": "passed" + }, + "sanitizer_check": { + "checked_ticks": 108000, + "status": "passed" + }, + "calibration_replays": [ + { + "chains": 16, + "length": 256, + "workload": "roots", + "block": 1, + "replays": 6 + }, + { + "chains": 16, + "length": 256, + "workload": "roots", + "block": 4, + "replays": 4 + }, + { + "chains": 16, + "length": 256, + "workload": "roots", + "block": 16, + "replays": 6 + }, + { + "chains": 16, + "length": 256, + "workload": "roots", + "block": 64, + "replays": 6 + }, + { + "chains": 16, + "length": 256, + "workload": "roots", + "block": 256, + "replays": 6 + }, + { + "chains": 16, + "length": 256, + "workload": "uniform", + "block": 1, + "replays": 130 + }, + { + "chains": 16, + "length": 256, + "workload": "uniform", + "block": 4, + "replays": 110 + }, + { + "chains": 16, + "length": 256, + "workload": "uniform", + "block": 16, + "replays": 130 + }, + { + "chains": 16, + "length": 256, + "workload": "uniform", + "block": 64, + "replays": 124 + }, + { + "chains": 16, + "length": 256, + "workload": "uniform", + "block": 256, + "replays": 74 + }, + { + "chains": 16, + "length": 256, + "workload": "tail", + "block": 1, + "replays": 968 + }, + { + "chains": 16, + "length": 256, + "workload": "tail", + "block": 4, + "replays": 870 + }, + { + "chains": 16, + "length": 256, + "workload": "tail", + "block": 16, + "replays": 730 + }, + { + "chains": 16, + "length": 256, + "workload": "tail", + "block": 64, + "replays": 384 + }, + { + "chains": 16, + "length": 256, + "workload": "tail", + "block": 256, + "replays": 86 + }, + { + "chains": 16, + "length": 256, + "workload": "dense", + "block": 1, + "replays": 4 + }, + { + "chains": 16, + "length": 256, + "workload": "dense", + "block": 4, + "replays": 4 + }, + { + "chains": 16, + "length": 256, + "workload": "dense", + "block": 16, + "replays": 4 + }, + { + "chains": 16, + "length": 256, + "workload": "dense", + "block": 64, + "replays": 4 + }, + { + "chains": 16, + "length": 256, + "workload": "dense", + "block": 256, + "replays": 4 + }, + { + "chains": 16, + "length": 1024, + "workload": "roots", + "block": 1, + "replays": 2 + }, + { + "chains": 16, + "length": 1024, + "workload": "roots", + "block": 4, + "replays": 2 + }, + { + "chains": 16, + "length": 1024, + "workload": "roots", + "block": 16, + "replays": 2 + }, + { + "chains": 16, + "length": 1024, + "workload": "roots", + "block": 64, + "replays": 2 + }, + { + "chains": 16, + "length": 1024, + "workload": "roots", + "block": 1024, + "replays": 2 + }, + { + "chains": 16, + "length": 1024, + "workload": "uniform", + "block": 1, + "replays": 24 + }, + { + "chains": 16, + "length": 1024, + "workload": "uniform", + "block": 4, + "replays": 22 + }, + { + "chains": 16, + "length": 1024, + "workload": "uniform", + "block": 16, + "replays": 24 + }, + { + "chains": 16, + "length": 1024, + "workload": "uniform", + "block": 64, + "replays": 24 + }, + { + "chains": 16, + "length": 1024, + "workload": "uniform", + "block": 1024, + "replays": 14 + }, + { + "chains": 16, + "length": 1024, + "workload": "tail", + "block": 1, + "replays": 912 + }, + { + "chains": 16, + "length": 1024, + "workload": "tail", + "block": 4, + "replays": 834 + }, + { + "chains": 16, + "length": 1024, + "workload": "tail", + "block": 16, + "replays": 708 + }, + { + "chains": 16, + "length": 1024, + "workload": "tail", + "block": 64, + "replays": 384 + }, + { + "chains": 16, + "length": 1024, + "workload": "tail", + "block": 1024, + "replays": 14 + }, + { + "chains": 16, + "length": 1024, + "workload": "dense", + "block": 1, + "replays": 2 + }, + { + "chains": 16, + "length": 1024, + "workload": "dense", + "block": 4, + "replays": 2 + }, + { + "chains": 16, + "length": 1024, + "workload": "dense", + "block": 16, + "replays": 2 + }, + { + "chains": 16, + "length": 1024, + "workload": "dense", + "block": 64, + "replays": 2 + }, + { + "chains": 16, + "length": 1024, + "workload": "dense", + "block": 1024, + "replays": 2 + } + ], + "completed_utc": "2026-09-22T09:32:24.887753+00:00", + "binary_bytes": 71208 +} diff --git a/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/raw.csv b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/raw.csv new file mode 100644 index 0000000..1ed88ef --- /dev/null +++ b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/raw.csv @@ -0,0 +1,281 @@ +trial,chains,length,workload,block,replays,elapsed_ns,ticks,node_evaluations,core_owned_bytes,model_bytes,cache_bytes,engine_bytes,trace_bytes,checksum,ns_per_tick,evaluations_per_tick
+0,16,256,uniform,256,74,19423930,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1025.3341427364865,256.0
+0,16,256,dense,256,4,27889701,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27236.0361328125,4096.0
+0,16,256,dense,64,4,27252683,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26613.9482421875,3984.5
+0,16,256,tail,16,730,16031339,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,85.78413420376712,16.0
+0,16,1024,roots,1,2,58533196,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,114322.6484375,16384.0
+0,16,1024,uniform,1,24,20859539,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3395.1072591145835,533.7734375
+0,16,256,roots,256,6,23781630,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,15482.83203125,4096.0
+0,16,1024,dense,4,2,63661600,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,124339.0625,14567.8125
+0,16,1024,uniform,1024,14,22677705,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6327.484654017857,1024.0
+0,16,256,tail,1,968,15760618,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,63.60011783316116,4.5546875
+0,16,1024,tail,4,834,14631637,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,68.53097365857315,5.984375
+0,16,1024,tail,1,912,15252766,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,65.33017235471492,4.5546875
+0,16,256,dense,4,4,28737719,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28064.1787109375,3665.4375
+0,16,1024,roots,64,2,54914217,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,107254.330078125,16384.0
+0,16,256,roots,1,6,30769606,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,20032.295572916668,4096.0
+0,16,1024,roots,16,2,57387697,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,112085.345703125,16384.0
+0,16,1024,roots,1024,2,55510329,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,108418.611328125,16384.0
+0,16,1024,uniform,64,24,20219114,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3290.8714192708335,565.25
+0,16,1024,roots,4,2,69964336,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,136649.09375,16384.0
+0,16,1024,uniform,16,24,20636818,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3358.8570963541665,540.9375
+0,16,256,roots,4,4,21918928,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21405.203125,4096.0
+0,16,1024,uniform,4,22,21167687,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3758.4671519886365,535.203125
+0,16,256,uniform,4,110,17970005,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,638.1393821022727,132.203125
+0,16,1024,tail,16,708,15733117,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,86.80436197916667,16.0
+0,16,256,roots,16,6,25329389,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16490.487630208332,4096.0
+0,16,1024,dense,64,2,55407347,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108217.474609375,15004.25
+0,16,1024,tail,64,384,18079579,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,183.91498819986978,64.0
+0,16,1024,dense,16,2,57109105,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,111541.220703125,14661.375
+0,16,256,uniform,1,130,19115671,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,574.3891526442308,130.7734375
+0,16,256,uniform,16,130,18864226,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,566.8337139423077,137.9375
+0,16,256,dense,1,4,26646406,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26021.880859375,3642.171875
+0,16,1024,dense,1024,2,60125695,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,117432.998046875,16384.0
+0,16,256,tail,4,870,15279896,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,68.60585488505747,5.984375
+0,16,256,tail,64,384,18427282,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,187.4520060221354,64.0
+0,16,256,tail,256,86,19077985,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,866.5509175145348,256.0
+0,16,256,uniform,64,124,19114097,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,602.1325919858871,162.25
+0,16,256,dense,16,4,27271257,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26632.0869140625,3752.0
+0,16,1024,dense,1,2,56247180,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,109857.7734375,14544.31640625
+0,16,1024,tail,1024,14,22547316,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6291.103794642857,1024.0
+0,16,256,roots,64,6,24836741,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,16169.753255208334,4096.0
+1,16,256,tail,16,730,15723896,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,84.13899828767123,16.0
+1,16,1024,roots,64,2,53830403,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,105137.505859375,16384.0
+1,16,256,uniform,64,124,19164986,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,603.7356980846774,162.25
+1,16,1024,roots,16,2,57857808,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,113003.53125,16384.0
+1,16,256,tail,256,86,18910930,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,858.9630268895348,256.0
+1,16,256,uniform,1,130,19119244,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,574.496514423077,130.7734375
+1,16,256,uniform,256,74,19320449,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1019.8716744087837,256.0
+1,16,256,dense,64,4,27044701,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26410.8408203125,3984.5
+1,16,1024,tail,4,834,14780378,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,69.22763976318944,5.984375
+1,16,1024,tail,1,912,15955191,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,68.33877724095395,4.5546875
+1,16,256,dense,256,4,27838608,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27186.140625,4096.0
+1,16,256,uniform,4,110,18108468,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,643.0563920454546,132.203125
+1,16,1024,uniform,64,24,20199430,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3287.6676432291665,565.25
+1,16,256,tail,4,870,15577488,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,69.94202586206896,5.984375
+1,16,1024,dense,4,2,63503118,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,124029.52734375,14567.8125
+1,16,1024,roots,1,2,60590399,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,118340.623046875,16384.0
+1,16,1024,dense,16,2,58815196,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,114873.4296875,14661.375
+1,16,1024,uniform,1,24,20999687,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3417.9178059895835,533.7734375
+1,16,1024,dense,64,2,55368532,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108141.6640625,15004.25
+1,16,256,roots,64,6,25027166,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,16293.727864583334,4096.0
+1,16,256,dense,4,4,28726459,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28053.1826171875,3665.4375
+1,16,1024,dense,1024,2,59377529,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,115971.736328125,16384.0
+1,16,1024,uniform,1024,14,22664872,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6323.904017857143,1024.0
+1,16,1024,tail,16,708,16137451,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,89.03519487111582,16.0
+1,16,1024,dense,1,2,59209844,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,115644.2265625,14544.31640625
+1,16,1024,tail,1024,14,28440553,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,7935.422154017857,1024.0
+1,16,1024,uniform,16,24,22939408,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3733.6276041666665,540.9375
+1,16,1024,roots,4,2,68243319,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,133287.732421875,16384.0
+1,16,1024,uniform,4,22,22284502,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3956.7652698863635,535.203125
+1,16,1024,tail,64,384,19017726,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,193.45831298828125,64.0
+1,16,1024,roots,1024,2,54456218,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,106359.80078125,16384.0
+1,16,256,roots,1,6,29430274,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,19160.334635416668,4096.0
+1,16,256,tail,1,968,16229803,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,65.4934586454029,4.5546875
+1,16,256,uniform,16,130,18842745,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,566.1882512019231,137.9375
+1,16,256,roots,256,6,25712943,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,16740.197265625,4096.0
+1,16,256,roots,16,6,24999092,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16275.450520833334,4096.0
+1,16,256,tail,64,384,18145560,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,184.586181640625,64.0
+1,16,256,roots,4,4,21467262,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,20964.123046875,4096.0
+1,16,256,dense,1,4,26614572,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,25990.79296875,3642.171875
+1,16,256,dense,16,4,27211406,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26573.638671875,3752.0
+2,16,1024,dense,64,2,55177792,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,107769.125,15004.25
+2,16,1024,roots,1024,2,56337550,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,110034.27734375,16384.0
+2,16,256,uniform,256,74,19340633,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1020.9371304898649,256.0
+2,16,1024,roots,4,2,70127632,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,136968.03125,16384.0
+2,16,256,uniform,16,130,18852485,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,566.4809194711538,137.9375
+2,16,256,uniform,64,124,19214726,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,605.3026083669355,162.25
+2,16,256,dense,4,4,29007978,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28328.103515625,3665.4375
+2,16,1024,roots,64,2,55147181,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,107709.337890625,16384.0
+2,16,1024,uniform,16,24,20757910,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3378.5660807291665,540.9375
+2,16,256,roots,16,6,24347186,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,15851.032552083334,4096.0
+2,16,1024,uniform,1024,14,23230334,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6481.678013392857,1024.0
+2,16,1024,dense,1024,2,59534306,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,116277.94140625,16384.0
+2,16,1024,uniform,1,24,20842391,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3392.3162434895835,533.7734375
+2,16,256,uniform,1,130,19198967,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,576.8920372596153,130.7734375
+2,16,256,uniform,4,110,17994653,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,639.0146661931818,132.203125
+2,16,256,dense,64,4,27086276,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26451.44140625,3984.5
+2,16,256,roots,4,4,21994113,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21478.6259765625,4096.0
+2,16,1024,roots,16,2,57820049,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,112929.783203125,16384.0
+2,16,256,dense,256,4,27941793,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27286.9072265625,4096.0
+2,16,1024,tail,16,708,16133895,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,89.01557534427967,16.0
+2,16,1024,tail,64,384,18182820,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,184.9652099609375,64.0
+2,16,256,tail,256,86,18779634,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,852.9993640988372,256.0
+2,16,256,roots,256,6,22007890,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,14328.053385416666,4096.0
+2,16,1024,tail,1024,14,22562372,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6295.3046875,1024.0
+2,16,1024,tail,1,912,15219507,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,65.18771844161184,4.5546875
+2,16,256,tail,1,968,16217302,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,65.4430123321281,4.5546875
+2,16,256,tail,16,730,15889117,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,85.02310038527398,16.0
+2,16,256,roots,64,6,24043260,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,15653.1640625,4096.0
+2,16,256,tail,64,384,18128542,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,184.4130655924479,64.0
+2,16,256,roots,1,6,28856219,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,18786.600911458332,4096.0
+2,16,256,dense,1,4,26688073,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26062.5712890625,3642.171875
+2,16,1024,roots,1,2,59012937,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,115259.642578125,16384.0
+2,16,1024,tail,4,834,15146304,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,70.94154676258992,5.984375
+2,16,1024,uniform,4,22,21112966,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3748.751065340909,535.203125
+2,16,1024,uniform,64,24,20180244,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3284.544921875,565.25
+2,16,256,dense,16,4,27251979,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26613.2607421875,3752.0
+2,16,1024,dense,1,2,56115124,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,109599.8515625,14544.31640625
+2,16,256,tail,4,870,15574118,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,69.92689475574713,5.984375
+2,16,1024,dense,4,2,63355452,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,123741.1171875,14567.8125
+2,16,1024,dense,16,2,59015622,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,115264.88671875,14661.375
+3,16,1024,dense,1024,2,59351733,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,115921.353515625,16384.0
+3,16,256,tail,64,384,18358098,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,186.74822998046875,64.0
+3,16,256,tail,256,86,18854430,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,856.3967114825581,256.0
+3,16,1024,tail,4,834,14976119,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,70.14444225869305,5.984375
+3,16,1024,uniform,1024,14,22676798,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6327.231584821428,1024.0
+3,16,1024,tail,1024,14,22703465,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6334.672154017857,1024.0
+3,16,256,dense,64,4,27086110,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26451.279296875,3984.5
+3,16,256,roots,256,6,25762944,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,16772.75,4096.0
+3,16,256,uniform,1,130,19111541,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,574.2650540865385,130.7734375
+3,16,1024,roots,4,2,70026373,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,136770.259765625,16384.0
+3,16,1024,tail,1,912,16096766,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,68.94516687225877,4.5546875
+3,16,256,dense,16,4,27379350,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26737.646484375,3752.0
+3,16,256,roots,16,6,24957185,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16248.167317708334,4096.0
+3,16,256,tail,16,730,15562896,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,83.27748287671233,16.0
+3,16,256,roots,1,6,28879071,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,18801.478515625,4096.0
+3,16,256,dense,256,4,27899146,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27245.259765625,4096.0
+3,16,1024,uniform,16,24,20733021,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3374.51513671875,540.9375
+3,16,1024,roots,16,2,58642974,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,114537.05859375,16384.0
+3,16,256,roots,4,4,21769853,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21259.6220703125,4096.0
+3,16,1024,dense,4,2,63265711,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,123565.841796875,14567.8125
+3,16,256,uniform,4,110,17831783,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,633.2309303977273,132.203125
+3,16,1024,roots,1,2,59387770,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,115991.73828125,16384.0
+3,16,256,dense,1,4,26625294,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26001.263671875,3642.171875
+3,16,256,uniform,64,124,19081356,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,601.1011844758065,162.25
+3,16,1024,roots,64,2,54379514,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,106209.98828125,16384.0
+3,16,256,roots,64,6,23421927,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,15248.650390625,4096.0
+3,16,1024,tail,64,384,18163616,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,184.76985677083334,64.0
+3,16,256,uniform,256,74,19326707,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1020.2020164695946,256.0
+3,16,256,tail,1,968,16443302,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,66.35500871642562,4.5546875
+3,16,256,uniform,16,130,18945597,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,569.2787560096153,137.9375
+3,16,256,tail,4,870,15606951,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,70.07431303879311,5.984375
+3,16,1024,uniform,4,22,21160558,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3757.201349431818,535.203125
+3,16,1024,tail,16,708,16127914,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,88.98257635946328,16.0
+3,16,1024,dense,1,2,56464457,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,110282.142578125,14544.31640625
+3,16,1024,dense,16,2,58168790,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,113610.91796875,14661.375
+3,16,1024,uniform,1,24,21266872,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3461.4049479166665,533.7734375
+3,16,1024,uniform,64,24,20355706,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3313.1031901041665,565.25
+3,16,1024,roots,1024,2,55149236,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,107713.3515625,16384.0
+3,16,256,dense,4,4,28735811,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28062.3154296875,3665.4375
+3,16,1024,dense,64,2,55532161,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108461.251953125,15004.25
+4,16,1024,roots,16,2,58275974,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,113820.26171875,16384.0
+4,16,1024,uniform,1,24,20898336,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3401.421875,533.7734375
+4,16,1024,tail,4,834,14866877,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,69.63277971372902,5.984375
+4,16,1024,tail,16,708,16058932,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,88.60198181497175,16.0
+4,16,1024,roots,64,2,54187366,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,105834.69921875,16384.0
+4,16,256,uniform,4,110,18060098,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,641.3387073863636,132.203125
+4,16,1024,uniform,4,22,21147503,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3754.8833451704545,535.203125
+4,16,256,roots,64,6,24374259,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,15868.658203125,4096.0
+4,16,1024,dense,4,2,63382933,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,123794.791015625,14567.8125
+4,16,256,dense,64,4,27028257,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26394.7822265625,3984.5
+4,16,1024,tail,64,384,18112820,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,184.25313313802084,64.0
+4,16,1024,uniform,1024,14,22717760,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6338.660714285715,1024.0
+4,16,1024,dense,1,2,56368123,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,110093.990234375,14544.31640625
+4,16,256,dense,16,4,27298090,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26658.291015625,3752.0
+4,16,256,tail,256,86,18729560,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,850.7249273255813,256.0
+4,16,256,tail,4,870,15490173,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,69.54998653017242,5.984375
+4,16,1024,dense,1024,2,59373955,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,115964.755859375,16384.0
+4,16,256,uniform,64,124,19073782,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,600.8625882056451,162.25
+4,16,256,roots,16,6,25373629,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16519.289713541668,4096.0
+4,16,1024,uniform,64,24,20210356,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3289.4459635416665,565.25
+4,16,256,uniform,256,74,19265226,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1016.9566089527027,256.0
+4,16,1024,uniform,16,24,20671781,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3364.5476888020835,540.9375
+4,16,1024,roots,1024,2,54991477,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,107405.228515625,16384.0
+4,16,256,dense,1,4,26646128,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26021.609375,3642.171875
+4,16,256,roots,1,6,27778090,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,18084.694010416668,4096.0
+4,16,256,tail,16,730,15578766,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,83.36240368150685,16.0
+4,16,1024,tail,1024,14,22511631,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6281.147042410715,1024.0
+4,16,256,dense,256,4,27817794,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27165.814453125,4096.0
+4,16,256,roots,256,6,23618612,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,15376.700520833334,4096.0
+4,16,1024,tail,1,912,15076693,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,64.57602196408992,4.5546875
+4,16,256,dense,4,4,28763201,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28089.0634765625,3665.4375
+4,16,256,uniform,16,130,18825430,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,565.66796875,137.9375
+4,16,256,uniform,1,130,19054708,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,572.5573317307692,130.7734375
+4,16,256,tail,1,968,16474654,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,66.48152602014463,4.5546875
+4,16,256,roots,4,4,21753002,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21243.166015625,4096.0
+4,16,1024,roots,4,2,65107229,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,127162.556640625,16384.0
+4,16,1024,roots,1,2,59380214,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,115976.98046875,16384.0
+4,16,1024,dense,64,2,55434866,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108271.22265625,15004.25
+4,16,1024,dense,16,2,58074048,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,113425.875,14661.375
+4,16,256,tail,64,384,18460486,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,187.7897745768229,64.0
+5,16,256,uniform,64,124,19329263,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,608.9107547883065,162.25
+5,16,1024,roots,16,2,57375679,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,112061.873046875,16384.0
+5,16,1024,tail,1024,14,22579761,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6300.156529017857,1024.0
+5,16,1024,tail,4,834,14960082,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,70.0693289118705,5.984375
+5,16,256,tail,1,968,16278580,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,65.69029248450413,4.5546875
+5,16,1024,dense,16,2,57445975,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,112199.169921875,14661.375
+5,16,1024,tail,64,384,18213134,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,185.2735799153646,64.0
+5,16,256,roots,1,6,27856293,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,18135.607421875,4096.0
+5,16,256,dense,64,4,27057813,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26423.6455078125,3984.5
+5,16,256,dense,1,4,26671387,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26046.2763671875,3642.171875
+5,16,256,uniform,16,130,18836911,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,566.0129507211539,137.9375
+5,16,1024,uniform,1,24,20823781,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3389.2872721354165,533.7734375
+5,16,256,tail,4,870,15190562,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,68.2047503591954,5.984375
+5,16,1024,tail,1,912,15649600,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,67.02987938596492,4.5546875
+5,16,256,roots,256,6,24620815,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,16029.176432291666,4096.0
+5,16,1024,dense,4,2,63311137,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,123654.564453125,14567.8125
+5,16,1024,uniform,4,22,21326706,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3786.702059659091,535.203125
+5,16,256,tail,256,86,19151578,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,869.8936228197674,256.0
+5,16,256,roots,4,4,22301428,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21778.73828125,4096.0
+5,16,256,dense,4,4,29056293,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28375.2861328125,3665.4375
+5,16,256,uniform,256,74,19565633,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1032.8142419763512,256.0
+5,16,256,uniform,4,110,18057894,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,641.2604403409091,132.203125
+5,16,1024,dense,1024,2,60140195,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,117461.318359375,16384.0
+5,16,1024,tail,16,708,16254099,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,89.67877714512711,16.0
+5,16,1024,dense,1,2,56663290,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,110670.48828125,14544.31640625
+5,16,256,dense,256,4,27836682,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27184.259765625,4096.0
+5,16,256,uniform,1,130,19151874,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,575.476983173077,130.7734375
+5,16,256,dense,16,4,27268739,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26629.6279296875,3752.0
+5,16,1024,roots,1024,2,55194940,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,107802.6171875,16384.0
+5,16,256,roots,64,6,24760574,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,16120.165364583334,4096.0
+5,16,1024,uniform,16,24,20702411,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3369.5330403645835,540.9375
+5,16,256,tail,16,730,15642655,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,83.70427547089041,16.0
+5,16,1024,roots,1,2,58483900,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,114226.3671875,16384.0
+5,16,1024,roots,64,2,54285033,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,106025.455078125,16384.0
+5,16,256,tail,64,384,18131930,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,184.4475301106771,64.0
+5,16,1024,uniform,1024,14,22782001,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6356.585100446428,1024.0
+5,16,1024,roots,4,2,70559817,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,137812.142578125,16384.0
+5,16,1024,uniform,64,24,20210762,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3289.5120442708335,565.25
+5,16,256,roots,16,6,25681295,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,16719.593098958332,4096.0
+5,16,1024,dense,64,2,55456236,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108312.9609375,15004.25
+6,16,1024,roots,1024,2,54870791,512,8388608,131512,131072,128,56,65552,cc440e349b9b5a57,107169.513671875,16384.0
+6,16,1024,uniform,16,24,20742114,6144,3323520,139576,131072,8192,56,4112,cc440e349b9b5a57,3375.9951171875,540.9375
+6,16,256,tail,16,730,15687340,186880,2990080,35128,32768,2048,56,4112,07e316e8e83163f0,83.94338613013699,16.0
+6,16,1024,dense,1024,2,59332807,512,8388608,131512,131072,128,56,524304,cc440e349b9b5a57,115884.388671875,16384.0
+6,16,1024,uniform,64,24,20222374,6144,3472896,133432,131072,2048,56,4112,cc440e349b9b5a57,3291.4020182291665,565.25
+6,16,1024,roots,1,2,58901437,512,8388608,262456,131072,131072,56,65552,cc440e349b9b5a57,115041.869140625,16384.0
+6,16,1024,tail,64,384,18025357,98304,6291456,133432,131072,2048,56,4112,cc440e349b9b5a57,183.36341349283853,64.0
+6,16,256,roots,256,6,25008240,1536,6291456,33208,32768,128,56,65552,07e316e8e83163f0,16281.40625,4096.0
+6,16,1024,dense,4,2,63551748,512,7458720,164152,131072,32768,56,524304,cc440e349b9b5a57,124124.5078125,14567.8125
+6,16,1024,roots,64,2,56267698,512,8388608,133432,131072,2048,56,65552,cc440e349b9b5a57,109897.84765625,16384.0
+6,16,256,tail,256,86,18806949,22016,5636096,33208,32768,128,56,4112,07e316e8e83163f0,854.2400526889535,256.0
+6,16,1024,roots,4,2,68814522,512,8388608,164152,131072,32768,56,65552,cc440e349b9b5a57,134403.36328125,16384.0
+6,16,256,dense,256,4,27934608,1024,4194304,33208,32768,128,56,524304,07e316e8e83163f0,27279.890625,4096.0
+6,16,256,tail,4,870,15578303,222720,1332840,41272,32768,8192,56,4112,07e316e8e83163f0,69.94568516522989,5.984375
+6,16,256,dense,4,4,28803219,1024,3753408,41272,32768,8192,56,524304,07e316e8e83163f0,28128.1435546875,3665.4375
+6,16,1024,uniform,4,22,21089521,5632,3014264,164152,131072,32768,56,4112,cc440e349b9b5a57,3744.5882457386365,535.203125
+6,16,1024,tail,4,834,14739063,213504,1277688,164152,131072,32768,56,4112,cc440e349b9b5a57,69.03413050809353,5.984375
+6,16,1024,uniform,1,24,20910965,6144,3279504,262456,131072,131072,56,4112,cc440e349b9b5a57,3403.4773763020835,533.7734375
+6,16,256,roots,4,4,22458464,1024,4194304,41272,32768,8192,56,65552,07e316e8e83163f0,21932.09375,4096.0
+6,16,1024,dense,1,2,56255976,512,7446690,262456,131072,131072,56,524304,cc440e349b9b5a57,109874.953125,14544.31640625
+6,16,256,tail,64,384,18071820,98304,6291456,33592,32768,512,56,4112,07e316e8e83163f0,183.8360595703125,64.0
+6,16,256,tail,1,968,15814117,247808,1128688,65848,32768,32768,56,4112,07e316e8e83163f0,63.81600674715909,4.5546875
+6,16,1024,roots,16,2,57245493,512,8388608,139576,131072,8192,56,65552,cc440e349b9b5a57,111807.603515625,16384.0
+6,16,1024,dense,16,2,57808882,512,7506624,139576,131072,8192,56,524304,cc440e349b9b5a57,112907.97265625,14661.375
+6,16,256,roots,64,6,25547351,1536,6291456,33592,32768,512,56,65552,07e316e8e83163f0,16632.389973958332,4096.0
+6,16,1024,tail,16,708,15922932,181248,2899968,139576,131072,8192,56,4112,cc440e349b9b5a57,87.85162870762711,16.0
+6,16,256,dense,64,4,27213979,1024,4080128,33592,32768,512,56,524304,07e316e8e83163f0,26576.1513671875,3984.5
+6,16,256,uniform,256,74,19487226,18944,4849664,33208,32768,128,56,4112,07e316e8e83163f0,1028.6753589527027,256.0
+6,16,1024,tail,1,912,16061655,233472,1063392,262456,131072,131072,56,4112,cc440e349b9b5a57,68.79478053042763,4.5546875
+6,16,1024,dense,64,2,55728624,512,7682176,133432,131072,2048,56,524304,cc440e349b9b5a57,108844.96875,15004.25
+6,16,256,uniform,4,110,17905042,28160,3722840,41272,32768,8192,56,4112,07e316e8e83163f0,635.8324573863637,132.203125
+6,16,256,dense,16,4,27274238,1024,3842048,35128,32768,2048,56,524304,07e316e8e83163f0,26634.998046875,3752.0
+6,16,256,uniform,1,130,18982300,33280,4352140,65848,32768,32768,56,4112,07e316e8e83163f0,570.3816105769231,130.7734375
+6,16,256,uniform,64,124,19114171,31744,5150464,33592,32768,512,56,4112,07e316e8e83163f0,602.1349231350806,162.25
+6,16,256,roots,1,6,29285699,1536,6291456,65848,32768,32768,56,65552,07e316e8e83163f0,19066.210286458332,4096.0
+6,16,256,dense,1,4,26745535,1024,3729584,65848,32768,32768,56,524304,07e316e8e83163f0,26118.6865234375,3642.171875
+6,16,256,uniform,16,130,18815023,33280,4590560,35128,32768,2048,56,4112,07e316e8e83163f0,565.3552584134616,137.9375
+6,16,256,roots,16,6,24256649,1536,6291456,35128,32768,2048,56,65552,07e316e8e83163f0,15792.089192708334,4096.0
+6,16,1024,uniform,1024,14,22782186,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6356.63671875,1024.0
+6,16,1024,tail,1024,14,22543335,3584,3670016,131512,131072,128,56,4112,cc440e349b9b5a57,6289.993024553572,1024.0
diff --git a/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/summary.csv b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/summary.csv new file mode 100644 index 0000000..861c9d1 --- /dev/null +++ b/research/experiments/001-checkpoint-granularity/results/2026-09-22-linux-aarch64/summary.csv @@ -0,0 +1,41 @@ +chains,length,workload,block,median_ns_per_tick,min_ns_per_tick,max_ns_per_tick,core_owned_bytes,cache_bytes,evaluations_per_tick
+16,256,roots,1,18801.478515625,18084.694010416668,20032.295572916668,65848,32768,4096.0
+16,256,roots,4,21405.203125,20964.123046875,21932.09375,41272,8192,4096.0
+16,256,roots,16,16275.450520833334,15792.089192708334,16719.593098958332,35128,2048,4096.0
+16,256,roots,64,16120.165364583334,15248.650390625,16632.389973958332,33592,512,4096.0
+16,256,roots,256,16029.176432291666,14328.053385416666,16772.75,33208,128,4096.0
+16,256,uniform,1,574.3891526442308,570.3816105769231,576.8920372596153,65848,32768,130.7734375
+16,256,uniform,4,639.0146661931818,633.2309303977273,643.0563920454546,41272,8192,132.203125
+16,256,uniform,16,566.1882512019231,565.3552584134616,569.2787560096153,35128,2048,137.9375
+16,256,uniform,64,602.1349231350806,600.8625882056451,608.9107547883065,33592,512,162.25
+16,256,uniform,256,1020.9371304898649,1016.9566089527027,1032.8142419763512,33208,128,256.0
+16,256,tail,1,65.4934586454029,63.60011783316116,66.48152602014463,65848,32768,4.5546875
+16,256,tail,4,69.92689475574713,68.2047503591954,70.07431303879311,41272,8192,5.984375
+16,256,tail,16,83.94338613013699,83.27748287671233,85.78413420376712,35128,2048,16.0
+16,256,tail,64,184.586181640625,183.8360595703125,187.7897745768229,33592,512,64.0
+16,256,tail,256,856.3967114825581,850.7249273255813,869.8936228197674,33208,128,256.0
+16,256,dense,1,26021.880859375,25990.79296875,26118.6865234375,65848,32768,3642.171875
+16,256,dense,4,28089.0634765625,28053.1826171875,28375.2861328125,41272,8192,3665.4375
+16,256,dense,16,26632.0869140625,26573.638671875,26737.646484375,35128,2048,3752.0
+16,256,dense,64,26451.279296875,26394.7822265625,26613.9482421875,33592,512,3984.5
+16,256,dense,256,27236.0361328125,27165.814453125,27286.9072265625,33208,128,4096.0
+16,1024,roots,1,115259.642578125,114226.3671875,118340.623046875,262456,131072,16384.0
+16,1024,roots,4,136649.09375,127162.556640625,137812.142578125,164152,32768,16384.0
+16,1024,roots,16,112929.783203125,111807.603515625,114537.05859375,139576,8192,16384.0
+16,1024,roots,64,106209.98828125,105137.505859375,109897.84765625,133432,2048,16384.0
+16,1024,roots,1024,107713.3515625,106359.80078125,110034.27734375,131512,128,16384.0
+16,1024,uniform,1,3401.421875,3389.2872721354165,3461.4049479166665,262456,131072,533.7734375
+16,1024,uniform,4,3757.201349431818,3744.5882457386365,3956.7652698863635,164152,32768,535.203125
+16,1024,uniform,16,3374.51513671875,3358.8570963541665,3733.6276041666665,139576,8192,540.9375
+16,1024,uniform,64,3289.5120442708335,3284.544921875,3313.1031901041665,133432,2048,565.25
+16,1024,uniform,1024,6338.660714285715,6323.904017857143,6481.678013392857,131512,128,1024.0
+16,1024,tail,1,67.02987938596492,64.57602196408992,68.94516687225877,262456,131072,4.5546875
+16,1024,tail,4,69.63277971372902,68.53097365857315,70.94154676258992,164152,32768,5.984375
+16,1024,tail,16,88.98257635946328,86.80436197916667,89.67877714512711,139576,8192,16.0
+16,1024,tail,64,184.76985677083334,183.36341349283853,193.45831298828125,133432,2048,64.0
+16,1024,tail,1024,6295.3046875,6281.147042410715,7935.422154017857,131512,128,1024.0
+16,1024,dense,1,110093.990234375,109599.8515625,115644.2265625,262456,131072,14544.31640625
+16,1024,dense,4,123794.791015625,123565.841796875,124339.0625,164152,32768,14567.8125
+16,1024,dense,16,113425.875,111541.220703125,115264.88671875,139576,8192,14661.375
+16,1024,dense,64,108271.22265625,107769.125,108844.96875,133432,2048,15004.25
+16,1024,dense,1024,115971.736328125,115884.388671875,117461.318359375,131512,128,16384.0
diff --git a/research/experiments/001-checkpoint-granularity/run.py b/research/experiments/001-checkpoint-granularity/run.py new file mode 100644 index 0000000..b2d66f2 --- /dev/null +++ b/research/experiments/001-checkpoint-granularity/run.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +"""Build, check, measure, and preserve raw data using only the Python stdlib.""" +import argparse +import csv +import hashlib +import json +import math +import os +from pathlib import Path +import platform +import random +import shlex +import statistics +import subprocess +import tempfile +from datetime import datetime, timezone + + +ROOT = Path(__file__).resolve().parent +SOURCE = ROOT / "benchmark.c" +FLAGS = ["-std=c17", "-O3", "-Wall", "-Wextra", "-Wpedantic", "-Werror"] + + +def command(args): + return subprocess.check_output(args, text=True).strip() + + +def write_csv(path, rows): + with path.open("w", newline="") as f: + writer = csv.DictWriter(f, fieldnames=list(rows[0])) + writer.writeheader() + writer.writerows(rows) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--output", type=Path) + parser.add_argument("--trials", type=int, default=7) + parser.add_argument("--target-ms", type=float, default=20.0) + parser.add_argument("--check-only", action="store_true") + args = parser.parse_args() + if args.trials < 3 or not 1 <= args.target_ms <= 1000: + parser.error("use at least 3 trials and a target from 1 to 1000 ms") + if not args.check_only and args.output is None: + parser.error("--output is required for measurements") + cc = shlex.split(os.environ.get("CC", "cc")) + environment = { + "started_utc": datetime.now(timezone.utc).isoformat(), + "platform": platform.platform(), "machine": platform.machine(), + "compiler": command(cc + ["--version"]), "flags": FLAGS, + "python": platform.python_version(), + "source_sha256": hashlib.sha256(SOURCE.read_bytes()).hexdigest(), + "runner_sha256": hashlib.sha256(Path(__file__).read_bytes()).hexdigest(), + "trials": args.trials, "target_ms": args.target_ms, + "seed": 20260922, "timing": "batch elapsed time / update ticks; not input latency", + "memory": "sizeof engine + requested live array bytes; excludes allocator, harness, code, OS", + "power_control": "not controlled; shared host; preliminary measurements", + } + # One CPU reduces migration noise. This is recorded, not assumed to remove noise. + if hasattr(os, "sched_getaffinity"): + affinity = sorted(os.sched_getaffinity(0)) + environment["original_affinity"] = affinity + os.sched_setaffinity(0, {affinity[0]}) + environment["measurement_affinity"] = sorted(os.sched_getaffinity(0)) + cpuinfo = Path("/proc/cpuinfo") + if cpuinfo.exists(): + allowed = ("model name", "CPU implementer", "CPU architecture", "CPU part", "Model") + environment["cpu_description"] = sorted({ + line for line in cpuinfo.read_text().splitlines() + if line.split(":", 1)[0].strip() in allowed + }) + with tempfile.TemporaryDirectory(prefix="pure-checkpoints-") as tmp: + binary = Path(tmp) / "benchmark" + subprocess.run(cc + FLAGS + [str(SOURCE), "-o", str(binary)], check=True) + environment["release_check"] = json.loads(command([str(binary), "--check"])) + checked = Path(tmp) / "benchmark-checked" + check_flags = ["-std=c17", "-O1", "-g", "-Wall", "-Wextra", "-Wpedantic", "-Werror", + "-fsanitize=address,undefined", "-fno-omit-frame-pointer"] + subprocess.run(cc + check_flags + [str(SOURCE), "-o", str(checked)], check=True) + environment["sanitizer_check"] = json.loads(command([str(checked), "--check"])) + print("Differential checks passed in release and ASan/UBSan builds.", flush=True) + if args.check_only: + print(json.dumps(environment, indent=2)) + return + # Fail before measurements if a previous run would be overwritten. + args.output.mkdir(parents=True, exist_ok=False) + + cases = [] + for chains, length in [(16, 256), (16, 1024)]: + for workload in ["roots", "uniform", "tail", "dense"]: + for block in [1, 4, 16, 64, length]: + cases.append((chains, length, workload, block)) + + def sample(case, replays): + chains, length, workload, block = case + return json.loads(command([str(binary), str(chains), str(length), str(block), + workload, "256", str(replays), str(environment["seed"])])) + + calibration = {} + for case in cases: + pilot = sample(case, 2) + wanted = math.ceil(2 * args.target_ms * 1e6 / max(1, pilot["elapsed_ns"])) + # Even replay counts leave the same final model in every strategy. + calibration[case] = min(2048, max(2, wanted + wanted % 2)) + environment["calibration_replays"] = [ + {"chains": c[0], "length": c[1], "workload": c[2], "block": c[3], "replays": r} + for c, r in calibration.items() + ] + rows = [] + checksums = {} + rng = random.Random(81173) + for trial in range(args.trials): + order = cases.copy() + rng.shuffle(order) + for case in order: + result = sample(case, calibration[case]) + chains, length, workload, block = case + key = (chains, length, workload) + if checksums.setdefault(key, result["checksum"]) != result["checksum"]: + raise RuntimeError(f"cross-strategy output mismatch: {case}") + row = {"trial": trial, "chains": chains, "length": length, + "workload": workload, "block": block, "replays": calibration[case], + **result} + row["ns_per_tick"] = result["elapsed_ns"] / result["ticks"] + row["evaluations_per_tick"] = result["node_evaluations"] / result["ticks"] + rows.append(row) + write_csv(args.output / "raw.csv", rows) + print(f"Completed trial {trial + 1}/{args.trials}.", flush=True) + summary = [] + for case in cases: + chains, length, workload, block = case + group = [r for r in rows if (r["chains"], r["length"], r["workload"], r["block"]) == case] + times = [r["ns_per_tick"] for r in group] + summary.append({"chains": chains, "length": length, "workload": workload, "block": block, + "median_ns_per_tick": statistics.median(times), + "min_ns_per_tick": min(times), "max_ns_per_tick": max(times), + "core_owned_bytes": group[0]["core_owned_bytes"], + "cache_bytes": group[0]["cache_bytes"], + "evaluations_per_tick": group[0]["evaluations_per_tick"]}) + write_csv(args.output / "summary.csv", summary) + environment["completed_utc"] = datetime.now(timezone.utc).isoformat() + environment["binary_bytes"] = binary.stat().st_size + (args.output / "environment.json").write_text(json.dumps(environment, indent=2) + "\n") + print(f"Saved raw data, summary, and environment to {args.output}") + + +if __name__ == "__main__": + main() |
