test: fix flat uniform DDF masking and clarify harness labels
Simulation.get_ddf() is flat (9*ny*nx); view it as (Q, cells) before applying the fluid mask, with a flat-DDF regression. Label A/E as runner-like force-read workloads (values discarded, no aggregation or validation; no macro/probe/CSV cost; not benchmark throughput) and split status lines into CONSTRUCTED and WARM_READY. Test/doc only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
724afb607c
commit
6c53d2e74a
@@ -4,14 +4,19 @@
|
||||
`run_refined_dfg.py` (same configuration, geometry and initial state functions). No numerical,
|
||||
physics-gate or production change; no force or accuracy result is produced.
|
||||
|
||||
| Variant | Loop | Force history |
|
||||
| Variant | Loop | Force reads |
|
||||
|---|---|---|
|
||||
| A | refined `step(1)` + `read_raw_exchange` per base step (as the runner) | valid |
|
||||
| A | refined `step(1)` + `read_raw_exchange` per base step | runner-like force-read workload (values discarded) |
|
||||
| B | refined `step(1)` only, no host reads (`observe_raw_exchange` stays on) | timing-only |
|
||||
| C | refined single `step(N)` | timing-only; ledger keeps the final base interval only |
|
||||
| E | uniform `sim.run(<=100)` + `read_force` (as the runner) | valid |
|
||||
| E | uniform `sim.run(<=100)` + `read_force` | runner-like force-read workload (values discarded) |
|
||||
| E' | uniform single `sim.run(2N)` | timing-only; at most a whole-window average, different summation order |
|
||||
|
||||
- No variant retains a valid force history; A/E omit the runner's interval aggregation and
|
||||
validation, and no variant includes macro/probe/CSV costs. Results are not full benchmark
|
||||
throughput.
|
||||
- Status lines: `CONSTRUCTED` (construction/JIT complete) and `WARM_READY` (first warm-up and
|
||||
health check passed) per case.
|
||||
- Equal simulated duration: N refined base steps vs 2N uniform D80 steps.
|
||||
- Every repeat starts from the same fresh state (refined `initialize`, uniform `snapshot/restore`)
|
||||
and the same warm-up; construction/JIT, warm-up, downloads and parity checks are untimed.
|
||||
|
||||
@@ -24,7 +24,9 @@ class TimingHarnessContract(unittest.TestCase):
|
||||
self.assertFalse(t.VARIANTS[name]["force_history_valid"])
|
||||
self.assertTrue(t.VARIANTS[name]["timing_only"])
|
||||
for name in ("A", "E"):
|
||||
self.assertTrue(t.VARIANTS[name]["force_history_valid"])
|
||||
self.assertFalse(t.VARIANTS[name]["force_history_valid"]) # reads discarded
|
||||
self.assertTrue(t.VARIANTS[name]["force_reads"])
|
||||
self.assertIn("runner-like", t.VARIANTS[name]["force_note"])
|
||||
self.assertEqual({v["case"] for v in t.VARIANTS.values()}, {"refined", "uniform"})
|
||||
self.assertIn("final base interval", t.VARIANTS["C"]["force_note"])
|
||||
self.assertIn("whole-window", t.VARIANTS["E'"]["force_note"])
|
||||
@@ -47,6 +49,18 @@ class TimingHarnessContract(unittest.TestCase):
|
||||
self.assertIn("infinite", t.same_state([inf], [inf.copy()])) # matching inf still fails
|
||||
self.assertIn("infinite", t.same_state([a], [inf]))
|
||||
|
||||
def test_flat_uniform_ddf(self):
|
||||
fluid = np.array([[True, False, True], [True, True, False]])
|
||||
flat = np.ones(9 * fluid.size, np.float32) # Simulation.get_ddf() layout
|
||||
self.assertTrue(t.uniform_populations_finite(flat, fluid))
|
||||
flat[1 * fluid.size + 1] = np.nan # q=1, solid cell 1: ignored
|
||||
self.assertTrue(t.uniform_populations_finite(flat, fluid))
|
||||
flat[4 * fluid.size + 0] = np.nan # q=4, fluid cell 0: detected
|
||||
self.assertFalse(t.uniform_populations_finite(flat, fluid))
|
||||
self.assertTrue(t.uniform_populations_finite(np.ones((9,) + fluid.shape), fluid))
|
||||
with self.assertRaises(RuntimeError):
|
||||
t.uniform_populations_finite(np.ones(9 * fluid.size + 1), fluid)
|
||||
|
||||
def test_physical_health_limits(self):
|
||||
ok = (np.array([1., 1.01]), np.array([.01, .02]), np.array([0., .01]))
|
||||
health = t.physical_health([ok])
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
"""Measurement-only wall timing for the matched MRT refined DFG case. No numerical edits.
|
||||
|
||||
Variants over EQUAL simulated duration (one refined base step = two uniform D80 steps):
|
||||
A refined: step(1) + read_raw_exchange per base step (as run_refined_dfg)
|
||||
A refined: step(1) + read_raw_exchange per base step -- runner-like force-read workload
|
||||
B refined: step(1) only, no host reads -- timing-only, no force history
|
||||
C refined: one step(N) call -- timing-only; ledger keeps final base interval only
|
||||
E uniform: sim.run(<=100) + read_force (as run_refined_dfg)
|
||||
E uniform: sim.run(<=100) + read_force -- runner-like force-read workload
|
||||
E' uniform: one sim.run(2N) call -- timing-only; at most a whole-window force
|
||||
average (different summation order), no history
|
||||
A/E read forces but discard them: no retained force history, no interval aggregation/validation,
|
||||
and no macro/probe/CSV cost, so they are not full benchmark throughput.
|
||||
observe_raw_exchange stays True for A/B/C: B/C omit host reads only.
|
||||
Status lines: CONSTRUCTED = backend/simulation built (JIT done); WARM_READY = first warm-up and
|
||||
health check passed for that case.
|
||||
Parity compares A/B/C with each other and E/E' with each other, never uniform with refined.
|
||||
A-B and B-C are measured comparative differences, not exact causal decompositions.
|
||||
Each repeat starts from the same fresh initial state with the same warm-up; construction,
|
||||
@@ -34,12 +38,14 @@ sys.path.insert(0, str(HERE))
|
||||
import run_refined_dfg as r # noqa: E402 (published runner: same setup functions)
|
||||
|
||||
VARIANTS = {
|
||||
"A": dict(case="refined", force_history_valid=True),
|
||||
"A": dict(case="refined", force_history_valid=False, force_reads=True,
|
||||
force_note="runner-like force-read workload; values discarded, no aggregation"),
|
||||
"B": dict(case="refined", force_history_valid=False, timing_only=True,
|
||||
force_note="no host reads"),
|
||||
"C": dict(case="refined", force_history_valid=False, timing_only=True,
|
||||
force_note="raw ledger retains only the final base interval"),
|
||||
"E": dict(case="uniform", force_history_valid=True),
|
||||
"E": dict(case="uniform", force_history_valid=False, force_reads=True,
|
||||
force_note="runner-like force-read workload; values discarded, no aggregation"),
|
||||
"E'": dict(case="uniform", force_history_valid=False, timing_only=True,
|
||||
force_note="at most a whole-window accumulated average; different summation order"),
|
||||
}
|
||||
@@ -80,6 +86,14 @@ def same_state(reference, values):
|
||||
return None
|
||||
|
||||
|
||||
def uniform_populations_finite(ddf, fluid):
|
||||
"""Simulation.get_ddf() may be flat (9*ny*nx); view it as (Q, cells) before masking."""
|
||||
ddf, fluid = np.asarray(ddf), np.asarray(fluid, bool).ravel()
|
||||
if fluid.size == 0 or ddf.size % fluid.size:
|
||||
raise RuntimeError(f"DDF size {ddf.size} incompatible with {fluid.size} cells")
|
||||
return bool(np.isfinite(ddf.reshape(ddf.size // fluid.size, fluid.size)[:, fluid]).all())
|
||||
|
||||
|
||||
def physical_health(fields):
|
||||
"""fields: (rho, ux, uy) arrays already restricted to physical leaves/fluid."""
|
||||
if not fields or any(not np.isfinite(v).all() or v.size == 0 for f in fields for v in f):
|
||||
@@ -165,13 +179,15 @@ def time_refined(a, h, sched):
|
||||
(pair.fine_kind == ACTIVE) & ((host.flags.reshape(pair.fine_shape) & SOLID) == 0)]
|
||||
fresh = (r.initial_state(pair.coarse_shape, (0.0, 0.0), 1.0, root=True),
|
||||
r.initial_state(pair.fine_shape, pair.fine_origin, 0.5))
|
||||
print(json.dumps(dict(status="READY", case="refined")), flush=True)
|
||||
print(json.dumps(dict(status="CONSTRUCTED", case="refined")), flush=True)
|
||||
for repeat in range(a.repeats):
|
||||
for variant in ("A", "B", "C"):
|
||||
check_deadline(a.deadline)
|
||||
backend.initialize(*fresh) # resets step count; same fresh state every time
|
||||
refined_loop(backend, variant, warm, a.deadline)
|
||||
warm_health = refined_health(backend, masks) # untimed
|
||||
if repeat == 0 and variant == "A":
|
||||
print(json.dumps(dict(status="WARM_READY", case="refined")), flush=True)
|
||||
sync_refined(backend)
|
||||
start = time.perf_counter()
|
||||
refined_loop(backend, variant, n, a.deadline)
|
||||
@@ -212,7 +228,7 @@ def time_uniform(a, h, sched):
|
||||
fluid = (sim.get_flags() & FLUID) != 0
|
||||
ny, nx = params["ny"], params["nx"]
|
||||
fluid = fluid.reshape(ny, nx)
|
||||
print(json.dumps(dict(status="READY", case="uniform")), flush=True)
|
||||
print(json.dumps(dict(status="CONSTRUCTED", case="uniform")), flush=True)
|
||||
for repeat in range(a.repeats):
|
||||
for variant in ("E", "E'"):
|
||||
check_deadline(a.deadline)
|
||||
@@ -221,6 +237,8 @@ def time_uniform(a, h, sched):
|
||||
raise RuntimeError("uniform restore parity changed between variants")
|
||||
uniform_loop(sim, variant, warm, a.deadline)
|
||||
warm_health = uniform_health(sim, fluid) # untimed
|
||||
if repeat == 0 and variant == "E":
|
||||
print(json.dumps(dict(status="WARM_READY", case="uniform")), flush=True)
|
||||
sync_uniform(sim)
|
||||
start = time.perf_counter()
|
||||
uniform_loop(sim, variant, n, a.deadline)
|
||||
@@ -228,7 +246,7 @@ def time_uniform(a, h, sched):
|
||||
seconds = time.perf_counter() - start
|
||||
end_health = uniform_health(sim, fluid) # untimed
|
||||
values = [sim.get_ddf()]
|
||||
if not np.isfinite(values[0].reshape(values[0].shape[0], -1)[:, fluid.ravel()]).all():
|
||||
if not uniform_populations_finite(values[0], fluid):
|
||||
raise RuntimeError(f"uniform {variant} repeat {repeat}: nonfinite fluid populations")
|
||||
mismatch = None
|
||||
if repeat == 0 and variant == "E":
|
||||
|
||||
Reference in New Issue
Block a user