diff options
| author | eunhhu <[email protected]> | 2026-10-08 17:04:12 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-08 17:04:12 +0100 |
| commit | ba35fb24dd8105f2b6492c103c4cb2471b15b715 (patch) | |
| tree | f375947761568b97fb5e481066a5734a89120159 /tests/check.py | |
| parent | be51c8a15d4f220ea8322f3c562f1f0c51b1e8e7 (diff) | |
| download | pure-ba35fb24dd8105f2b6492c103c4cb2471b15b715.tar.gz pure-ba35fb24dd8105f2b6492c103c4cb2471b15b715.zip | |
Batch executor, stage 4 of design 025: a column read at affine rows in memory's order in four or eight bytes is a view of the column itself (cells_at), no copy, read only while the pass runs; what outlives the pass (a local, a set's rows and value, an append's cells, a sum's rows and e, a filter's key, a read's rows) copies it (own); knapsack 4.0% fewer instructions, 6.6% fewer cycles; VIEW_SOURCE in check.py (a local holding a field the batch sets, a set from the same column in the order that overwrites what it reads, a set widening the column under a view), which differs and trips ASan's memcpy overlap when the copies are left out; seeds 1 2 3 5 23 (default and PURE_SELECT=all), the fixed sources (also sanitized) and the unit tests pass
Diffstat (limited to 'tests/check.py')
| -rw-r--r-- | tests/check.py | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/tests/check.py b/tests/check.py index 2314c36..1d98f05 100644 --- a/tests/check.py +++ b/tests/check.py @@ -1227,6 +1227,53 @@ on go { """ +# Columns read in place (VIEW_SOURCE, docs/design/025's stage 4): a local +# holding a row's field while the batch sets that field (its last value +# written back after the sets), a set whose value is the same column three +# rows over in the order that overwrites what it reads, and a set that widens +# the column to eight bytes while a local holds a view of it. +VIEW_SOURCE = """record Cell { + at = 0 + v = 0 +} +state last = 0 +state back = 0 +state wide = 0 +state sum = 0 +input go = message { + n: u32 + q: u32 +} +on go { + let t: list of Cell by at + for i in 0 .. go.n { + t.add(Cell { at: i, v: i * 3 }) + } + let a = 0 + for i in 0 .. go.n - 3 { + a = t[i].v + t[i].v = t[i + 3].v + 1 + } + last = a + for k in 0 .. go.n - 3 { + let i = go.n - 1 - k + t[i].v = t[i - 3].v + } + back = t[go.n - 1].v + t[go.n - 2].v * 1000 + let w = 0 + for i in 0 .. go.n - 3 { + w = t[i].v + t[i].v = t[i + 3].v + go.q + 0.5 + } + wide = w + let s = 0 + for c in t { + s = s + c.v + } + sum = s +} +""" + # Reductions that start with no lanes (REDUCE_SOURCE, docs/design/025): the # same e in every lane (a count, a uniform max and min, a fraction, a sum # past 2^53 one a lane), a count in a nested loop of the same rounds in @@ -1711,6 +1758,19 @@ def module_assumptions(aup, pure, work): assert outputs[name] == outputs['batches'], ('reduce', name, next((a, b) for a, b in zip(outputs[name].splitlines(), outputs['batches'].splitlines()) if a != b)) faults = [json.loads(line)['fault'] for line in outputs['batches'].splitlines() if line.startswith('{"states"')] assert 'none' in faults and 'work' in faults, faults + source, program = work / 'view.aup', work / 'view.pmod' # columns read in place, against the rounds one by one + source.write_text(VIEW_SOURCE) + compile_module(aup, source, program) + given = ''.join(f'message go {struct.pack("<II", n, q).hex()}\nwork\n' for n, q in + ((3000, 7), (3000, 70000), (2049, 1), (40, 3), (5, 2), (1500, 100000))) + given += 'budget 30011\n' + given + 'budget 0\n' + outputs = {name: subprocess.run([str(pure / 'build/pure-run'), str(program)], input=given, capture_output=True, text=True, + timeout=120, env=dict(os.environ, **env)).stdout + for name, env in (('batches', {'PURE_JIT': '0'}), ('rounds', {'PURE_JIT': '0', 'PURE_BATCH': '0'}), ('all', {'PURE_JIT': 'all'}))} + for name in ('rounds', 'all'): + assert outputs[name] == outputs['batches'], ('view', name, next((a, b) for a, b in zip(outputs[name].splitlines(), outputs['batches'].splitlines()) if a != b)) + faults = [json.loads(line)['fault'] for line in outputs['batches'].splitlines() if line.startswith('{"states"')] + assert 'none' in faults and 'work' in faults, faults return len(runs) |
