profile: per-LOD whole-view breakdown for the four-strate owner world (L73, no world change)
FI/TN/VS (legacy compiled-analytic) skip ZERO tiles at every LOD and evaluate ~44k density points per LOD0/1 tile; SW skips 359/512 at LOD0. The whole-tile skip requires a native tile with a uniform verdict, and the legacy paths return Mixed/unknown (R39 notes attached). Opt-in stage timers, sampled field timer, per-LOD classification and composer counters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
d970d75be8
commit
bd1b2a8f1d
10 files changed
+702
-5
No files matched your search
@@ -0,0 +1,209 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reduce the L73 per-tile capture logs into reviewable CSV tables."""
|
||||
from __future__ import annotations
|
||||
|
||||
import csv
|
||||
import json
|
||||
import statistics
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[4]
|
||||
OUT = ROOT / "Saved/Linux/l73/breakdown"
|
||||
SUMMARY = OUT / "summary.json"
|
||||
EXPECTED_TILES = {0: 2850, 1: 2249, 2: 2233, 3: 2329}
|
||||
LODS = range(9)
|
||||
|
||||
|
||||
def median(values: list[float]) -> float:
|
||||
return statistics.median(values) if values else 0.0
|
||||
|
||||
|
||||
def metric(rows: list[dict], section: str, lod: int, key: str) -> float:
|
||||
return median([float(row["details"].get(section, {}).get(str(lod), {}).get(key, 0) or 0)
|
||||
for row in rows])
|
||||
|
||||
|
||||
def sum_metric(details: dict, section: str, key: str) -> float:
|
||||
return sum(float(row.get(key, 0) or 0)
|
||||
for row in details.get(section, {}).values())
|
||||
|
||||
|
||||
def write_csv(path: Path, rows: list[dict], fields: list[str]) -> None:
|
||||
with path.open("w", newline="", encoding="utf-8") as stream:
|
||||
writer = csv.DictWriter(stream, fieldnames=fields)
|
||||
writer.writeheader()
|
||||
writer.writerows(rows)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
runs = json.loads(SUMMARY.read_text(encoding="utf-8"))
|
||||
if len(runs) != 24 or any(row["exit_code"] != 0 for row in runs):
|
||||
raise SystemExit("L73 matrix is incomplete or contains a failed run")
|
||||
signatures = {(row["plan_hash"], row["layout_identity"]) for row in runs}
|
||||
if len(signatures) != 1:
|
||||
raise SystemExit(f"plan/layout changed across runs: {sorted(signatures)}")
|
||||
for strate, expected in EXPECTED_TILES.items():
|
||||
if {row["whole_tiles"] for row in runs if row["strate"] == strate} != {expected}:
|
||||
raise SystemExit(f"strate {strate} tile count differs from {expected}")
|
||||
|
||||
lod_rows = []
|
||||
strategy_rows = []
|
||||
for strate in range(4):
|
||||
all_rows = [row for row in runs if row["strate"] == strate]
|
||||
clean = [row for row in all_rows if row["mode"] == "clean"]
|
||||
profile = [row for row in all_rows if row["mode"] == "profile"]
|
||||
paired_wall_delta = [
|
||||
row["whole_view_ready_s"] - next(other["whole_view_ready_s"]
|
||||
for other in all_rows if other["pair"] == row["pair"]
|
||||
and other["mode"] == "clean") for row in profile]
|
||||
paired_worker_delta = [
|
||||
row["worker_seconds"] - next(other["worker_seconds"]
|
||||
for other in all_rows if other["pair"] == row["pair"]
|
||||
and other["mode"] == "clean") for row in profile]
|
||||
|
||||
stage_keys = (
|
||||
("classify_ms", "stages_by_lod", "classify_ms"),
|
||||
("field_eval_ms_est", "classification_by_lod", "field_eval_ms_est"),
|
||||
("mc_total_ms", "worker_by_lod", "mc_exclusive_ms"),
|
||||
("mc_grid_ms", "cost_by_lod", "mc_grid_ms"),
|
||||
("mc_cell_class_ms", "cost_by_lod", "mc_cell_class_ms"),
|
||||
("mc_gradient_ms", "cost_by_lod", "mc_gradient_ms"),
|
||||
("mc_interpolation_ms", "cost_by_lod", "mc_interpolation_ms"),
|
||||
("mc_dedup_stream_ms", "cost_by_lod", "mc_dedup_stream_ms"),
|
||||
("mc_other_ms", "cost_by_lod", "mc_other_ms"),
|
||||
("skirt_ms", "worker_by_lod", "skirt_ms"),
|
||||
("ground_refine_ms", "worker_by_lod", "ground_refine_exclusive_ms"),
|
||||
("cap_refine_ms", "worker_by_lod", "cap_refine_exclusive_ms"),
|
||||
("connector_shell_ms", "cost_by_lod", "connector_shell_ms"),
|
||||
("mesh_assembly_ms", "worker_by_lod", "mesh_assembly_ms"),
|
||||
("payload_build_ms", "classification_by_lod", "payload_build_ms"),
|
||||
)
|
||||
profile_stage_sums = []
|
||||
for row in profile:
|
||||
details = row["details"]
|
||||
profile_stage_sums.append({name: sum_metric(details, section, key)
|
||||
for name, section, key in stage_keys})
|
||||
stage_totals = {name: median([item[name] for item in profile_stage_sums])
|
||||
for name, _, _ in stage_keys}
|
||||
strategy_row = {
|
||||
"strate": strate,
|
||||
"tiles": EXPECTED_TILES[strate],
|
||||
"clean_wall_median_s": round(median([row["whole_view_ready_s"] for row in clean]), 3),
|
||||
"clean_worker_median_s": round(median([row["worker_seconds"] for row in clean]), 3),
|
||||
"profile_wall_median_s": round(median([row["whole_view_ready_s"] for row in profile]), 3),
|
||||
"profile_worker_median_s": round(median([row["worker_seconds"] for row in profile]), 3),
|
||||
"paired_profile_wall_delta_median_s": round(median(paired_wall_delta), 3),
|
||||
"paired_profile_worker_delta_median_s": round(median(paired_worker_delta), 3),
|
||||
"profile_all_air_tiles_median": 0,
|
||||
"profile_all_solid_tiles_median": 0,
|
||||
"profile_whole_tile_skips_median": 0,
|
||||
"profile_density_point_calls_median": 0,
|
||||
"profile_tile_lod_visits_median": 0,
|
||||
"profile_density_points_per_tile": 0.0,
|
||||
**{name: round(value, 3) for name, value in stage_totals.items()},
|
||||
}
|
||||
|
||||
for lod in LODS:
|
||||
cls = [row["details"]["classification_by_lod"].get(str(lod), {})
|
||||
for row in profile]
|
||||
cost = [row["details"]["cost_by_lod"].get(str(lod), {}) for row in profile]
|
||||
worker = [row["details"]["worker_by_lod"].get(str(lod), {}) for row in profile]
|
||||
stages = [row["details"]["stages_by_lod"].get(str(lod), {}) for row in profile]
|
||||
island = [row["details"]["floating_island_attribution_by_lod"].get(str(lod), {})
|
||||
for row in profile]
|
||||
passage = [row["details"]["passage_composer_by_lod"].get(str(lod), {})
|
||||
for row in profile]
|
||||
first = cls[0] if cls else {}
|
||||
if not first:
|
||||
continue
|
||||
|
||||
row = {
|
||||
"strate": strate,
|
||||
"lod": lod,
|
||||
"tiles": int(median([float(item.get("tiles", 0)) for item in cls])),
|
||||
"all_air_tiles": int(median([float(item.get("all_air", 0)) for item in cls])),
|
||||
"all_solid_tiles": int(median([float(item.get("all_solid", 0)) for item in cls])),
|
||||
"mixed_tiles": int(median([float(item.get("mixed", 0)) for item in cls])),
|
||||
"unclassified_tiles": int(median([float(item.get("unclassified", 0)) for item in cls])),
|
||||
"whole_tile_skips": int(median([float(item.get("tile_skips", 0)) for item in cls])),
|
||||
"density_grid_tiles": int(median([float(item.get("density_grid_tiles", 0)) for item in cls])),
|
||||
"density_grid_sample_points": int(median([float(item.get("density_samples", 0))
|
||||
for item in cost])),
|
||||
"density_point_calls": int(median([float(item.get("density_point_calls", 0)) for item in cls])),
|
||||
"density_points_per_tile": round(median([float(item.get("density_points_per_tile", 0))
|
||||
for item in cls]), 1),
|
||||
"field_eval_sample_points": int(median([float(item.get("field_eval_sample_points", 0))
|
||||
for item in cls])),
|
||||
"proof_air_cells": int(median([float(item.get("proof_air_cells", 0)) for item in cls])),
|
||||
"proof_solid_cells": int(median([float(item.get("proof_solid_cells", 0)) for item in cls])),
|
||||
"classify_worker_ms": round(median([float(item.get("classify_ms", 0))
|
||||
for item in stages]), 3),
|
||||
"field_eval_worker_ms_est": round(median([float(item.get("field_eval_ms_est", 0))
|
||||
for item in cls]), 3),
|
||||
"mc_total_worker_ms": round(median([float(item.get("mc_exclusive_ms", 0))
|
||||
for item in worker]), 3),
|
||||
"mc_grid_worker_ms": round(median([float(item.get("mc_grid_ms", 0))
|
||||
for item in cost]), 3),
|
||||
"mc_cell_class_worker_ms": round(median([float(item.get("mc_cell_class_ms", 0))
|
||||
for item in cost]), 3),
|
||||
"mc_normals_worker_ms": round(median([float(item.get("mc_gradient_ms", 0))
|
||||
for item in cost]), 3),
|
||||
"mc_interpolation_worker_ms": round(median([float(item.get("mc_interpolation_ms", 0))
|
||||
for item in cost]), 3),
|
||||
"mc_dedup_worker_ms": round(median([float(item.get("mc_dedup_stream_ms", 0))
|
||||
for item in cost]), 3),
|
||||
"mc_other_worker_ms": round(median([float(item.get("mc_other_ms", 0))
|
||||
for item in cost]), 3),
|
||||
"skirt_worker_ms": round(median([float(item.get("skirt_ms", 0))
|
||||
for item in worker]), 3),
|
||||
"ground_refine_worker_ms": round(median([float(item.get("ground_refine_exclusive_ms", 0))
|
||||
for item in worker]), 3),
|
||||
"cap_refine_worker_ms": round(median([float(item.get("cap_refine_exclusive_ms", 0))
|
||||
for item in worker]), 3),
|
||||
"connector_shell_worker_ms": round(median([float(item.get("connector_shell_ms", 0))
|
||||
for item in cost]), 3),
|
||||
"mesh_assembly_worker_ms": round(median([float(item.get("mesh_assembly_ms", 0))
|
||||
for item in worker]), 3),
|
||||
"payload_build_worker_ms": round(median([float(item.get("payload_build_ms", 0))
|
||||
for item in cls]), 3),
|
||||
"passage_queries": int(median([float(item.get("queries", 0)) for item in passage])),
|
||||
"passage_relief_field_calls": int(median([float(item.get("relief_field_calls", 0))
|
||||
for item in passage])),
|
||||
"passage_carve_segment_visits": int(median([float(item.get("carve_segment_visits", 0))
|
||||
for item in passage])),
|
||||
"passage_support_segment_visits": int(median([float(item.get("support_segment_visits", 0))
|
||||
for item in passage])),
|
||||
"passage_mouth_route_checks": int(median([float(item.get("mouth_route_segment_checks", 0))
|
||||
for item in passage])),
|
||||
"passage_smoothstep_evaluations": int(median([float(item.get("smoothstep_evaluations", 0))
|
||||
for item in passage])),
|
||||
"fi_component_field_ns_est": int(median([float(item.get("comp_field_ns_est", 0))
|
||||
for item in island])),
|
||||
"fi_component_island_ns_est": int(median([float(item.get("comp_island_ns_est", 0))
|
||||
for item in island])),
|
||||
"fi_component_roots_ns_est": int(median([float(item.get("comp_roots_ns_est", 0))
|
||||
for item in island])),
|
||||
}
|
||||
lod_rows.append(row)
|
||||
for name in ("all_air_tiles", "all_solid_tiles", "whole_tile_skips",
|
||||
"density_point_calls"):
|
||||
strategy_row["profile_" + name + "_median"] += row[name]
|
||||
strategy_row["profile_tile_lod_visits_median"] += row["tiles"]
|
||||
|
||||
strategy_row["profile_density_points_per_tile"] = round(
|
||||
strategy_row["profile_density_point_calls_median"] /
|
||||
strategy_row["profile_tile_lod_visits_median"], 1)
|
||||
strategy_rows.append(strategy_row)
|
||||
|
||||
write_csv(OUT / "lod-breakdown.csv", lod_rows, list(lod_rows[0]))
|
||||
write_csv(OUT / "strate-summary.csv", strategy_rows, list(strategy_rows[0]))
|
||||
print(f"[L73Analysis] lod_rows={len(lod_rows)} strategy_rows={len(strategy_rows)} "
|
||||
f"plan_hash={next(iter(signatures))[0]} layout={next(iter(signatures))[1]}")
|
||||
for row in strategy_rows:
|
||||
print("[L73Summary] " + json.dumps(row, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,38 @@
|
||||
## Revised ranked proposals
|
||||
|
||||
**What changed:** I withdraw the earlier claim that an FI interval is ready to add. The active owner FI path has no island plan, so I cannot identify a field term with a numeric bound that blocks the air proof. The native FI interval cannot stand in for that missing bound.
|
||||
|
||||
1. **[CODE] [INFERENCE] FI: bound the active compiled analytic field, including composition.** This has the highest potential gain given the reported 6.343 s FI whole view, but it is not implementation ready: the current classifier has no interval for this path. A new interval could preserve output bit for bit only if it bounds the actual field and all later composition conservatively. **No complete bound or term value is verified.** Falsifier: at the arrival and nearby FI tiles, the interval proves no `AllAir` tiles, or the field-call reduction is smaller than the classification cost.
|
||||
|
||||
2. **[CODE] [INFERENCE] TN: replace the midpoint verdict with a conservative box interval.** Current TN classification has composer and primitive overlap guards, then may return the midpoint’s sign; that sign is not an interval proof for the whole box. A bit-identical skip is possible only after bounding the active SDF, blends and detail, and vetoing composer changes. The detail clamp to **±3.9** is code verified; the complete TN interval is not. Falsifier: safe `AllAir` proofs are rare, or field-call savings do not exceed classification cost.
|
||||
|
||||
3. **[CODE] [INFERENCE] Keep composer overlap as a fail-closed veto; tighten only proven-empty regions.** Passage and cavern composition can change signs, including support that adds solid. A classifier must return `Mixed` if any such feature may affect the box, unless it also bounds that effect. Fixed ceiling and bedrock bands are checked, but transition displacement needs its expanded interval included. This can be bit-identical if every uncertain case fails closed. Falsifier: the new composer checks still veto nearly every would-be FI/TN air tile, or matched timings show no gain. L72’s route-mouth checks fell 80–87%, but its single timing comparison was mixed and did not establish a stable wall-time gain ([L72 report](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux72/REPORT.md:33)).
|
||||
|
||||
4. **[REPORT] Do not re-enable native FI as a performance fix.** L70’s native FI experiment changed hashes and failed the audit, including 1,843 blocked route samples and 945 open-air violations. It changes the world ([L70 report](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux70/REPORT.md:98)).
|
||||
|
||||
## FI arrival tile, walked by hand
|
||||
|
||||
The L70 arrival script gives FI camera position `(25.8369, 3.1992, -737)` metres ([arrival inputs](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux70/RunHeadlessArrivalBenchmarksL70.py:13)). Using the 0.25 m core voxel and 32-voxel tile size, the central LOD0 tile is key `(3, 0, -93)`, with voxel origin `(96, 0, -2976)` ([tile size and key units](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h:27); [origin and cell setup](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/VoxelForgeCore.cpp:2058)).
|
||||
|
||||
`ClassifyBoxDetailed` pads this tile by one voxel, producing Z bounds `[-2977, -2943]`. With the 32-voxel layout chunk width, it scans chunks `-94` through `-92`. L70 reports FI at `-93..-64` and TN at `-109..-94` ([slot bounds](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux70/REPORT.md:5)). So the padded box crosses FI and TN.
|
||||
|
||||
Hand-walk:
|
||||
|
||||
- The `-94` chunk is legacy TN; `-93` and `-92` are FI.
|
||||
- FI is assigned kind `FloatingIslands`, but its plan and evaluator are only installed if the matching plan exists ([binding code](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:395)). L70 reports that this owner has no native FI plan and uses `compiled-analytic/FloatingIslands` ([dispatch report](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux70/REPORT.md:37)).
|
||||
- The missing FI plan sets `bBadPlan`; overlap with TN also sets the cross-stratum flag. After any earlier passage or band veto, the cross-recipe guard returns `Mixed, unknown` ([overlap scan](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:5980); [guard](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:6118)).
|
||||
- A tile wholly inside FI still fails closed: the FI interval branch returns `Mixed, unknown` when `IslandPlan` or `IslandField` is absent ([FI interval branch](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:6214)).
|
||||
|
||||
**I cannot verify that this particular tile is mostly air:** the L72 report gives arrival-wide times and tile counts, not per-tile occupancy. I also cannot name a field term’s bound or value as the blocker. The blocker here is structural: **`IslandPlan == null` and `IslandField == null`**, with an additional FI/TN stratum crossing for this padded tile. There is no active numeric field bound to report.
|
||||
|
||||
Either way, the tile is not skipped. The whole-tile early-out requires a native tile and a known uniform verdict ([tile skip gate](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/VoxelForgeCore.cpp:2365)). TN’s final fallback can classify from the box midpoint after its guards ([fallback](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:6257)), but TN is non-native, so that verdict does not enable the tile skip. The legacy FI and TN tiles therefore proceed to grid evaluation.
|
||||
|
||||
## Bound audit
|
||||
|
||||
- **[CODE] Native FI field interval:** `FloatingIslandFieldV1::interval` includes contour warp, island/root geometry, roughness, connector blends and rounding slack ([range formulas](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FloatingIslandsInternal.h:1088), [field interval](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/FloatingIslandsInternal.h:2492)). By code inspection, those terms are represented in the **raw field interval**. It is not a bound for the current compiled analytic FI path, nor by itself for all of `NativeFloatingIslandDensityAt`: that function also applies mouth filtering, route preservation, fragment handling and boundary sealing ([post-processing](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:6818)). Composer effects must also be covered or vetoed.
|
||||
|
||||
- **[CODE] TN noise and warps:** the shared roughness code applies domain warp before evaluating fractal noise and interpolates anchored values with `Lerp` ([roughness evaluator](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/VoxelForgeFieldShared.h:415)). If bounding that field locally, the proved `sup|FBM| = 1.5` must be used, not 1.0; the warp amplitude is at most `1.25 × 1.5 × |strength|` per component, and interpolation must use the envelope of its endpoints ([bound note](/home/jahni/VoxelM/Plugins/VoxelForge/Docs/archive/OPSTACK-PROGRESS.md:3565)). The final detail blend is clamped to ±3.9 ([detail clamp](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:7917)). These are verified component bounds, **not a verified supremum for the whole TN `Eval`**.
|
||||
|
||||
- **[CODE] Composer bands and support:** the classifier returns `Mixed` for passage overlap, and its passage proof bounds include passage segments, mouth-support routes and support columns ([passage bounds](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:4510)). Those are spatial vetoes, not a numeric density interval. The composer also applies boundary bands and passage composition after the base field ([composition order](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:1981)). The classifier’s direct band loop checks authored ceiling and bedrock bands, while expanded transition bounds are built separately ([expanded intervals](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:520)); I did not verify that the classifier uses those expanded intervals for every active transition. A new all-air proof must account for that gap and retain the passage-support veto.
|
||||
|
||||
Read-only review only; no builds, tests or benchmarks were run.
|
||||
@@ -0,0 +1,85 @@
|
||||
# Linux 73 — whole-view breakdown
|
||||
|
||||
No generator fix this round. The timed data identifies density/grid work as the broad FI/TN cost, but does not isolate one composer term or show how many tiles a safe interval proof would remove.
|
||||
|
||||
## Whole view and worker breakdown
|
||||
|
||||
Three interleaved clean/profile pairs per strate. Clean medians are the readiness measurements; **wall time gates readiness**. Worker-seconds sum tile-worker durations and show aggregate work. Stage values below are profiled worker-seconds. `field` is a sampled estimate (one in 256 calls); it overlaps grid/MC. `MC` includes grid fill, and normals are a subset of MC, so these columns must not be added. `Other` is ground+cap refinement, connector shell, and mesh assembly. Payload is separately timed.
|
||||
|
||||
Profile whole-view medians (wall / worker s) were SW 2.427/16.250, FI 6.531/49.151, TN 5.593/41.435, VS 2.698/18.206. The clean/profile pairs retained one plan and layout identity throughout.
|
||||
|
||||
| Strate | Tiles | Clean wall / worker s | Classify s | Field est. s | Grid fill s | MC s | Normals s | Skirts s | Other s | Payload s |
|
||||
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
|
||||
| SW | 2,850 | 2.324 / 15.044 | 0.425 | 10.135 | 7.871 | 8.395 | 0.113 | 1.013 | 3.541 | 0.011 |
|
||||
| FI | 2,249 | 6.120 / 45.967 | 0.004 | 39.912 | 36.137 | 40.576 | 0.306 | 1.079 | 2.861 | 0.012 |
|
||||
| TN | 2,233 | 5.259 / 38.815 | 0.003 | 33.248 | 29.372 | 32.634 | 0.246 | 1.091 | 2.777 | 0.012 |
|
||||
| VS | 2,329 | 2.548 / 16.929 | 0.004 | 11.656 | 9.349 | 10.095 | 0.200 | 0.640 | 3.305 | 0.012 |
|
||||
|
||||
### Per LOD classification and density calls
|
||||
|
||||
`A/S/M/U` = all-air / all-solid / mixed / unclassified tiles. `Skip` is whole-tile skips. `Grid` is tiles with at least one density sample (it does not claim every possible lattice point was filled). Calls/tile is the measured density point-call count divided by tiles at that LOD.
|
||||
|
||||
| Strate | LOD | Tiles | A/S/M/U | Skip | Grid | Calls/tile |
|
||||
|---|---:|---:|---:|---:|---:|---:|
|
||||
| SW | 0 | 512 | 256/103/153/0 | 359 | 71 | 3,952 |
|
||||
| SW | 1 | 448 | 122/173/153/0 | 295 | 77 | 3,025 |
|
||||
| SW | 2 | 448 | 154/114/116/64 | 268 | 126 | 1,733 |
|
||||
| SW | 3 | 384 | 64/42/230/48 | 106 | 271 | 4,507 |
|
||||
| SW | 4 | 320 | 12/0/84/224 | 12 | 308 | 6,260 |
|
||||
| SW | 5 | 192 | 0/0/0/192 | 0 | 192 | 7,527 |
|
||||
| SW | 6 | 144 | 0/0/0/144 | 0 | 144 | 11,820 |
|
||||
| SW | 7 | 96 | 0/0/0/96 | 0 | 96 | 8,621 |
|
||||
| SW | 8 | 306 | 0/0/0/306 | 0 | 306 | 8,660 |
|
||||
| FI | 0 | 512 | 0/0/256/256 | 0 | 512 | 44,121 |
|
||||
| FI | 1 | 448 | 0/0/224/224 | 0 | 448 | 43,322 |
|
||||
| FI | 2 | 256 | 0/0/160/96 | 0 | 218 | 6,286 |
|
||||
| FI | 3 | 272 | 0/0/176/96 | 0 | 272 | 7,073 |
|
||||
| FI | 4 | 272 | 0/0/0/272 | 0 | 272 | 7,342 |
|
||||
| FI | 5 | 192 | 0/0/0/192 | 0 | 192 | 7,802 |
|
||||
| FI | 6 | 96 | 0/0/0/96 | 0 | 96 | 13,996 |
|
||||
| FI | 7 | 48 | 0/0/0/48 | 0 | 48 | 9,773 |
|
||||
| FI | 8 | 153 | 0/0/0/153 | 0 | 153 | 9,852 |
|
||||
| TN | 0 | 512 | 0/0/128/384 | 0 | 512 | 44,076 |
|
||||
| TN | 1 | 448 | 0/0/112/336 | 0 | 448 | 43,315 |
|
||||
| TN | 2 | 384 | 0/0/112/272 | 0 | 344 | 6,550 |
|
||||
| TN | 3 | 256 | 0/0/48/208 | 0 | 256 | 7,185 |
|
||||
| TN | 4 | 192 | 0/0/0/192 | 0 | 192 | 7,466 |
|
||||
| TN | 5 | 144 | 0/0/0/144 | 0 | 144 | 7,836 |
|
||||
| TN | 6 | 96 | 0/0/0/96 | 0 | 96 | 13,996 |
|
||||
| TN | 7 | 48 | 0/0/0/48 | 0 | 48 | 9,773 |
|
||||
| TN | 8 | 153 | 0/0/0/153 | 0 | 153 | 9,853 |
|
||||
| VS | 0 | 512 | 0/0/0/512 | 0 | 512 | 43,824 |
|
||||
| VS | 1 | 448 | 0/0/0/448 | 0 | 448 | 43,230 |
|
||||
| VS | 2 | 384 | 0/0/0/384 | 0 | 384 | 7,050 |
|
||||
| VS | 3 | 256 | 0/0/0/256 | 0 | 256 | 7,163 |
|
||||
| VS | 4 | 192 | 0/0/0/192 | 0 | 192 | 7,290 |
|
||||
| VS | 5 | 144 | 0/0/0/144 | 0 | 144 | 7,536 |
|
||||
| VS | 6 | 144 | 0/0/0/144 | 0 | 144 | 11,617 |
|
||||
| VS | 7 | 96 | 0/0/0/96 | 0 | 96 | 8,316 |
|
||||
| VS | 8 | 153 | 0/0/0/153 | 0 | 153 | 9,855 |
|
||||
|
||||
Per-LOD stage timers, proof-cell counts, grid sample totals, field-timer sample counts, and composer counters are in [`lod-breakdown.csv`](../../../../Saved/Linux/l73/breakdown/lod-breakdown.csv); medians and paired overhead are in [`strate-summary.csv`](../../../../Saved/Linux/l73/breakdown/strate-summary.csv). The tile counter distinguishes whole-tile skips from tiles with any density samples; it does not prove every lattice point was filled. The field timer samples aggregate evaluation, not individual composer terms. FI native-component attribution stayed zero on this compiled-analytic path. Composer counters are counts only: at LOD0 FI recorded 54.5M relief calls, 63.4M carve visits, 20.4M support visits, and 24.6M mouth-route checks; TN recorded 46.9M, 54.2M, 15.5M, and 20.4M respectively. They show work volume, not time share.
|
||||
|
||||
## Skip verdict
|
||||
|
||||
FI has **zero all-air/all-solid skips at every LOD**. At LOD0/1 it classifies half the tiles mixed and half unclassified, yet evaluates about 44k/43k density points per tile. TN also has zero skips; its LOD0/1 tiles are mixed or unclassified and have the same roughly 44k/43k calls per tile.
|
||||
|
||||
The active FI owner export has no matching native `IslandPlan`/field adapter. The FI interior therefore falls back to Mixed/unknown; the mesher skips only AllAir or AllSolid tiles. Its inactive native-FI interval cannot prove the compiled-analytic field. Any future finite-support bound must cover the true FBM supremum (1.5) and downward root tails, then include shared solid writers.
|
||||
|
||||
TN is still on the legacy compiled-analytic path. Its nearby-primitive checks are vetoes; the fallback evaluates the box center, not a whole-box interval, and does not feed a tile skip. The shared composer can force Mixed for local partial passage/band intersections, but is not forcing every tile: FI/TN bands are 0.5 m thick against 240 m/128 m interiors, and tiles are unclassified across LODs, not only at strate boundaries. A box wholly inside a band can be AllSolid.
|
||||
|
||||
## Next options (no fix selected)
|
||||
|
||||
1. **FI finite-support interval for the active compiled-analytic field.** Highest potential: many proven-empty tiles could remove a large share of FI's roughly 40 worker-seconds of field evaluation. Gain is unquantified until proof-hit rate and classifier cost are measured. Bound roughness, roots, connectors, and shared solid writers.
|
||||
2. **TN interval for the active compiled-analytic cave field.** Second potential: prove host-rock tiles outside cave influence and skip them. Could save substantial TN work if most blocks miss cave bounds; proof coverage is unknown.
|
||||
3. **Composer-aware uniform verdicts.** Carry air proofs through carve-only passage intersections and resolve boundary/support writers by polarity. Expected smaller and local to overlap tiles; count the rejected-Mixed reasons before implementing.
|
||||
|
||||
No before/after generator comparison, passage audit, fast-tier run, or world version bump applies because no generator change was made. No output tile hashes were collected: `--stream-hash` disables tile skips, which would invalidate this measurement. No Unreal build was needed. All 24 final clean/profile generator jobs exited 0. Two preliminary reduction attempts failed only while parsing zero-sample profiler counters; the reducer was corrected.
|
||||
|
||||
## Identity
|
||||
|
||||
- HEAD: `d970d75be80fd31f16e2dc41006456bc52ad180d` (`assembler/world`)
|
||||
- Build source stamp: `ab7f0e95f415c0dc4eb81ae3b9a355fe98e5ceb89faf4aefc54b65d936d09fdf`
|
||||
- Plan hash: `bcc0d0d33ea39435`; resolved layout: `resolved-layout-v3-fnv64:0589300eb07dfe06`
|
||||
- World assembly schema/evaluator: 2 / 213; owner export schema: 1. No world content or generator version changed.
|
||||
- Profiling self-cost (median paired profile-minus-clean): SW +0.089 s wall / +0.732 worker-s; FI +0.503 / +3.840; TN +0.073 / +0.437; VS +0.151 / +1.210. These differences varied across the three pairs.
|
||||
@@ -0,0 +1,180 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run interleaved clean/profiled whole views for the four owner arrivals."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[4]
|
||||
OUT = ROOT / "Saved/Linux/l73/breakdown"
|
||||
DATA = ROOT / "Standalone/data/owner_world.json"
|
||||
CLEAN_BIN = ROOT / "Saved/Linux/l72/bin-final-clang/VoxelForgeCoreHeadless-l72-final-clang"
|
||||
PROFILE_BIN = ROOT / "Saved/Linux/l73/bin/VoxelForgeCoreHeadless-l73-clang"
|
||||
CAMERAS = {
|
||||
0: (8.0, 16.0, -372.2626953125),
|
||||
1: (25.8369140625, 3.19921875, -737.0),
|
||||
2: (19.166015625, -14.2001953125, -753.3740234375),
|
||||
3: (-20.0625, -5.068359375, -900.353515625),
|
||||
}
|
||||
PAIR_ORDER = (("clean", "profile"), ("profile", "clean"), ("clean", "profile"))
|
||||
KV = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)")
|
||||
|
||||
|
||||
def parse_profile_log(path: Path) -> dict:
|
||||
pipeline = {}
|
||||
worker_by_lod: dict[str, dict] = {}
|
||||
classes_by_lod: dict[str, dict] = {}
|
||||
costs_by_lod: dict[str, dict] = {}
|
||||
stages_by_lod: dict[str, dict] = {}
|
||||
island_by_lod: dict[str, dict] = {}
|
||||
passage_by_lod: dict[str, dict] = {}
|
||||
plan_hash = None
|
||||
layout_identity = None
|
||||
whole_tiles = None
|
||||
|
||||
with path.open(encoding="utf-8", errors="replace") as stream:
|
||||
for line in stream:
|
||||
if line.startswith("[WorldAssemblerPlanSource]"):
|
||||
plan_hash = re.search(r"manifest_hash=(\S+)", line).group(1)
|
||||
elif line.startswith("[ResolvedLayoutSnapshot]"):
|
||||
layout_identity = re.search(r"stable_identity=(\S+)", line).group(1)
|
||||
elif line.startswith("[WorldAssemblerLODWorker]"):
|
||||
row = dict(KV.findall(line))
|
||||
worker_by_lod[row["lod"]] = row
|
||||
elif line.startswith("[WorldAssemblerLODClassification]"):
|
||||
row = dict(KV.findall(line))
|
||||
classes_by_lod[row["lod"]] = row
|
||||
elif line.startswith("[WorldAssemblerLODCostDetail]"):
|
||||
row = dict(KV.findall(line))
|
||||
costs_by_lod[row["lod"]] = row
|
||||
elif line.startswith("[CpuTileStages]"):
|
||||
row = dict(KV.findall(line))
|
||||
key = row.get("key", "")
|
||||
match = re.search(r"lod(\d+)", key)
|
||||
if match:
|
||||
target = stages_by_lod.setdefault(match.group(1), {})
|
||||
for name in ("payload_ms", "classify_ms"):
|
||||
target[name] = target.get(name, 0.0) + float(row.get(name, "0"))
|
||||
elif line.startswith("[FiFieldAttribution]"):
|
||||
row = dict(KV.findall(line))
|
||||
match = re.search(r"lod(\d+)", row.get("key", ""))
|
||||
if match:
|
||||
target = island_by_lod.setdefault(match.group(1), {})
|
||||
for name, value in row.items():
|
||||
if name.endswith("_ns_est"):
|
||||
target[name] = target.get(name, 0) + int(value.split("/", 1)[0])
|
||||
elif line.startswith("[PassageComposerTile]"):
|
||||
row = dict(KV.findall(line))
|
||||
key = row.get("key", "")
|
||||
match = re.search(r"lod(\d+)", key)
|
||||
if match:
|
||||
target = passage_by_lod.setdefault(match.group(1), {})
|
||||
for name, value in row.items():
|
||||
if name in ("native_field_calls", "queries", "passage_iterations",
|
||||
"carve_segment_visits", "smooth_carve_joins",
|
||||
"support_segment_visits", "smooth_support_joins",
|
||||
"mouth_route_segment_checks", "relief_field_calls",
|
||||
"smoothstep_evaluations"):
|
||||
target[name] = target.get(name, 0) + int(value.split("/", 1)[0])
|
||||
elif line.startswith("[StreamPipeline]"):
|
||||
pipeline = dict(KV.findall(line))
|
||||
whole_tiles = re.search(r"whole_tiles=(\d+)/(\d+)", line)
|
||||
|
||||
worker_seconds = sum(float(row.get("worker_sum_s", 0))
|
||||
for row in worker_by_lod.values())
|
||||
return {
|
||||
"pipeline": pipeline,
|
||||
"whole_tiles": int(whole_tiles.group(1)) if whole_tiles else None,
|
||||
"plan_hash": plan_hash,
|
||||
"layout_identity": layout_identity,
|
||||
"worker_seconds": worker_seconds,
|
||||
"worker_by_lod": worker_by_lod,
|
||||
"classification_by_lod": classes_by_lod,
|
||||
"cost_by_lod": costs_by_lod,
|
||||
"stages_by_lod": stages_by_lod,
|
||||
"floating_island_attribution_by_lod": island_by_lod,
|
||||
"passage_composer_by_lod": passage_by_lod,
|
||||
}
|
||||
|
||||
|
||||
def run(strate: int, pair: int, mode: str) -> dict:
|
||||
binary = CLEAN_BIN if mode == "clean" else PROFILE_BIN
|
||||
label = f"strate{strate}-pair{pair}-{mode}"
|
||||
folder = OUT / f"strate{strate}"
|
||||
folder.mkdir(parents=True, exist_ok=True)
|
||||
log = folder / f"{label}.log"
|
||||
camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0"
|
||||
command = [
|
||||
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
||||
"timeout", "1740s", str(binary), str(DATA),
|
||||
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
|
||||
"--force-generate", "--workers=8", "--clip-radius=3", "--max-clip-level=8",
|
||||
"--max-level=8", f"--camera={camera}",
|
||||
]
|
||||
if mode == "profile":
|
||||
command += ["--profile-lod-work", "--instrument-tile-drain",
|
||||
"--profile-passage-composer"]
|
||||
|
||||
started = time.monotonic()
|
||||
with log.open("w", encoding="utf-8") as output:
|
||||
result = subprocess.run(command, cwd=ROOT, stdout=output,
|
||||
stderr=subprocess.STDOUT, check=False, timeout=1740)
|
||||
process_wall = time.monotonic() - started
|
||||
parsed = parse_profile_log(log)
|
||||
pipeline = parsed["pipeline"]
|
||||
row = {
|
||||
"strate": strate,
|
||||
"pair": pair,
|
||||
"mode": mode,
|
||||
"exit_code": result.returncode,
|
||||
"process_wall_s": process_wall,
|
||||
"whole_view_ready_s": float(pipeline["whole_view_ready"][:-1])
|
||||
if "whole_view_ready" in pipeline else None,
|
||||
"worker_seconds": parsed["worker_seconds"],
|
||||
"whole_tiles": parsed["whole_tiles"],
|
||||
"plan_hash": parsed["plan_hash"],
|
||||
"layout_identity": parsed["layout_identity"],
|
||||
"log": str(log.relative_to(ROOT)),
|
||||
"details": parsed if mode == "profile" else None,
|
||||
}
|
||||
result_path = folder / f"{label}.json"
|
||||
result_path.write_text(json.dumps(row, indent=2) + "\n", encoding="utf-8")
|
||||
print("[L73Run] " + json.dumps({key: value for key, value in row.items()
|
||||
if key != "details"}, sort_keys=True), flush=True)
|
||||
return row
|
||||
|
||||
|
||||
def main() -> int:
|
||||
missing = [str(path) for path in (DATA, CLEAN_BIN, PROFILE_BIN) if not path.is_file()]
|
||||
if missing:
|
||||
raise SystemExit("missing input: " + ", ".join(missing))
|
||||
rows = []
|
||||
for strate in range(4):
|
||||
for pair, order in enumerate(PAIR_ORDER, start=1):
|
||||
for mode in order:
|
||||
row = run(strate, pair, mode)
|
||||
rows.append(row)
|
||||
if row["exit_code"] != 0 or row["whole_view_ready_s"] is None:
|
||||
break
|
||||
else:
|
||||
continue
|
||||
break
|
||||
if any(row["strate"] == strate and (row["exit_code"] != 0
|
||||
or row["whole_view_ready_s"] is None) for row in rows):
|
||||
break
|
||||
summary = OUT / "summary.json"
|
||||
summary.write_text(json.dumps(rows, indent=2) + "\n", encoding="utf-8")
|
||||
complete = len(rows) == 24 and all(
|
||||
row["exit_code"] == 0 and row["whole_view_ready_s"] is not None
|
||||
and row["whole_tiles"] is not None for row in rows)
|
||||
print(f"[L73Breakdown] runs={len(rows)}/24 complete={str(complete).lower()} "
|
||||
f"summary={summary.relative_to(ROOT)}", flush=True)
|
||||
return 0 if complete else 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in new issue
Block a user