Generated from the full canonical file for this source snapshot. Line numbers match the library source.
Source SHA256: 52ce24fc72bed607301f29d5816fcce398498e277cd4708211d041e1698e9cf4
1"""Execute the canonical CUDA operator, validate it, and record actual artefacts.23No physical expression is reimplemented here: this runner chooses mathematical4stress inputs, invokes the library and its independent oracle, and plots records.5Generated records are private until the separate artefact/release checks accept6them. The warmed benchmark uses CUDA events and excludes setup and compilation.7"""89from __future__ import annotations1011import importlib12import json13import platform14import statistics15import struct16import subprocess17import sys18import tempfile19import time20from collections.abc import Callable21from dataclasses import asdict, dataclass22from decimal import Decimal, localcontext23from pathlib import Path24from typing import Any2526from dpt.experiments import (27RunRecorder,28experiment_parser,29experiment_sources,30private_output,31repository_root,32)33from dpt.transmission import (34TransmissionSpec,35optical_depth_from_removed,36prepare_transmission,37transmission_vjp,38transmit,39)40from dpt.validation.transmission import (41MIN_SUBNORMAL,42U32,43U64,44analytic_cases,45exact_input,46forward_reference,47inverse_reference,48value_error,49vjp_reference,50)5152ROOT = repository_root(__file__)53OUTPUT_NAMES = ("T", "counts", "log_T", "removed")54OUTPUT_ARGUMENTS = ("out_T", "out_counts", "out_log_T", "out_removed")555657@dataclass(frozen=True)58class Config:59schema_version: int60sweep_points: int61benchmark_sizes: list[int]62block_dims: list[int]63regimes: list[str]64batches: int65iterations: int66warmup_iterations: int6768def validate(self) -> None:69if self.schema_version != 1 or not 3 <= self.sweep_points <= 4097:70raise ValueError("schema_version must be 1; sweep_points must be 3..4097")71if not self.benchmark_sizes or any(72type(n) is not int or not 1 <= n <= 2**31 - 1 for n in self.benchmark_sizes73):74raise ValueError("benchmark sizes must be positive int32 lengths")75if not self.block_dims or any(n not in (128, 256) for n in self.block_dims):76raise ValueError("block_dims must contain only 128 and/or 256")77if not self.regimes or any(r not in ("ordinary", "tail", "mixed") for r in self.regimes):78raise ValueError("unknown benchmark numerical regime")79if self.batches < 5 or self.iterations < 1 or self.warmup_iterations < 1:80raise ValueError("use at least five batches and positive iteration counts")818283def write_json(path: Path, value: Any) -> None:84path.write_text(json.dumps(value, indent=2, allow_nan=False) + "\n", encoding="utf-8")858687def command_output(arguments: list[str]) -> str:88try:89result = subprocess.run(arguments, cwd=ROOT, capture_output=True, text=True, check=False)90except OSError as error:91return f"unavailable: {error}"92return result.stdout.strip() if result.returncode == 0 else result.stderr.strip()939495def metadata(wp: Any, device: Any, config: Config) -> dict[str, Any]:96runtime = device.runtime97return {98"command": sys.argv,99"source_commit": command_output(["git", "rev-parse", "HEAD"]),100"source_status": command_output(["git", "status", "--short"]),101"python": platform.python_version(),102"platform": platform.platform(),103"warp": wp.__version__,104"numpy": importlib.import_module("numpy").__version__,105"matplotlib": importlib.import_module("matplotlib").__version__,106"device": str(device),107"device_name": device.name,108"compute_capability": device.arch,109"cuda_toolkit": runtime.toolkit_version,110"cuda_driver_api": runtime.driver_version,111"nvcc": command_output(["nvcc", "--version"]),112"nvidia_smi": command_output(["nvidia-smi"]),113"numerics": {114"storage": "binary32",115"intermediates": "binary64 products, sums and exponential above optical depth 64",116"fast_math": False,117"fuse_fp": True,118"oracle_decimal_digits": 100,119"reduction_tile_size": 256,120},121"input_provenance": "deterministic mathematical stress inputs; no anatomical data",122}123124125# region book:transmission-experiment126def evaluate_sweep(wp: Any, np: Any, depths: Any, beam: float, device: Any) -> dict[str, Any]:127"""Execute all four canonical outputs, then check every stored value."""128workspace = prepare_transmission(129TransmissionSpec(beam="scalar"), device=str(device), max_pixels=len(depths)130)131optical_depth = wp.array(depths, dtype=wp.float32, device=device)132outputs = [wp.empty(len(depths), dtype=wp.float32, device=device) for _ in OUTPUT_NAMES]133transmit(134optical_depth,135beam,136workspace=workspace,137**dict(zip(OUTPUT_ARGUMENTS, outputs, strict=True)),138)139wp.synchronize_stream(workspace.stream)140measured = [output.numpy() for output in outputs]141cases: list[dict[str, Any]] = []142for index, depth in enumerate(depths):143reference = forward_reference(float(depth), beam)144checks = {}145for name, values in zip(OUTPUT_NAMES, measured, strict=True):146result = value_error(147float(values[index]), getattr(reference, name), counts=name == "counts"148)149exact_log = name != "log_T" or struct.pack("!f", float(values[index])) == struct.pack(150"!f", -float(depth)151)152checks[name] = {153"actual": float(values[index]),154"reference_decimal": str(getattr(reference, name)),155"ulps": result.ulps,156"allowed_ulps": 0 if name == "log_T" else result.allowed_ulps,157"passed": result.passed and exact_log,158}159if not result.passed or not exact_log:160raise AssertionError(f"{name} failed at optical depth {depth}: {checks[name]}")161cases.append({"optical_depth": float(depth), "checks": checks})162return {163"beam": float(np.float32(beam)),164"cases": cases,165"outputs": {166name: values.tolist() for name, values in zip(OUTPUT_NAMES, measured, strict=True)167},168"optical_depths": depths.tolist(),169}170171172# endregion book:transmission-experiment173174175def validation_run(wp: Any, np: Any, device: Any, config: Config) -> dict[str, Any]:176points = config.sweep_points177result: dict[str, Any] = {178"schema_version": 1,179"sweep": evaluate_sweep(wp, np, np.linspace(0, 20, points, dtype=np.float32), 1e6, device),180"weak": evaluate_sweep(181wp, np, np.geomspace(1e-12, 0.1, points, dtype=np.float32), 1.0, device182),183"tail": evaluate_sweep(184wp, np, np.linspace(80, 200, points, dtype=np.float32), 1e30, device185),186}187analytic = analytic_cases()188result["analytic"] = evaluate_sweep(189wp,190np,191np.array([float(case.optical_depth) for case in analytic], dtype=np.float32),1921.0,193device,194)195result["analytic"]["definitions"] = [asdict(case) for case in analytic]196for definition in result["analytic"]["definitions"]:197definition["optical_depth"] = str(definition["optical_depth"])198decrements = np.geomspace(1e-12, 0.9, points, dtype=np.float32)199workspace = prepare_transmission(device=str(device), max_pixels=points)200delta = wp.array(decrements, dtype=wp.float32, device=device)201restored = wp.empty(points, dtype=wp.float32, device=device)202optical_depth_from_removed(delta, out_L=restored, workspace=workspace)203measured = restored.numpy()204inverse_cases: list[dict[str, Any]] = []205for decrement, actual in zip(decrements, measured, strict=True):206expected = inverse_reference(float(decrement))207check = value_error(float(actual), expected)208if not check.passed:209raise AssertionError(f"inverse decrement failed for {decrement}")210inverse_cases.append(211{"decrement": float(decrement), "actual": float(actual), "ulps": check.ulps}212)213result["inverse"] = inverse_cases214# Diagnostic postprocessing of actual stored library output, deliberately215# showing cancellation. This is never used as a transport implementation.216stored_transmission = np.asarray(result["weak"]["outputs"]["T"], dtype=np.float32)217result["weak"]["diagnostic_one_minus_stored_T"] = (218np.float32(1.0) - stored_transmission219).tolist()220result["status"] = "passed"221return result222223224def render_figures(result: dict[str, Any], destination: Path) -> list[str]:225matplotlib = importlib.import_module("matplotlib")226matplotlib.use("Agg")227plt = importlib.import_module("matplotlib.pyplot")228np = importlib.import_module("numpy")229plt.rcParams.update(230{231"font.family": "sans-serif",232"font.size": 11,233"svg.fonttype": "none",234"svg.hashsalt": "dpt-transmission-v1",235"axes.spines.top": False,236"axes.spines.right": False,237"axes.grid": True,238"grid.alpha": 0.2,239"legend.frameon": False,240"lines.linewidth": 1.8,241}242)243files: list[str] = []244245def save(figure: Any, name: str) -> None:246figure.savefig(247destination / name, format="svg", metadata={"Date": None}, bbox_inches="tight"248)249figure.savefig(destination / Path(name).with_suffix(".png"), dpi=150, bbox_inches="tight")250plt.close(figure)251files.append(name)252253sweep = result["sweep"]254fig, axes = plt.subplots(1, 3, figsize=(12, 3.3), layout="constrained")255for ax, key, title in zip(256axes,257("T", "counts", "log_T"),258("Transmission", "Expected counts", "Log transmission"),259strict=True,260):261ax.plot(sweep["optical_depths"], sweep["outputs"][key], color="#0072B2")262ax.set(xlabel="Optical depth L", ylabel=title, title=title)263if key != "log_T":264ax.set_yscale("log")265fig.suptitle("Canonical CUDA execution · open-beam expectation = 10⁶")266save(fig, "transmission-sweep.svg")267268weak = result["weak"]269fig, axes = plt.subplots(1, 2, figsize=(10, 3.5), layout="constrained")270axes[0].loglog(271weak["optical_depths"],272weak["outputs"]["removed"],273color="#0072B2",274label="CUDA removed-primary fraction",275)276oracle = [float(case["checks"]["removed"]["reference_decimal"]) for case in weak["cases"]]277axes[0].loglog(278weak["optical_depths"][::8],279oracle[::8],280"o",281color="#D55E00",282markersize=4,283fillstyle="none",284label="100-digit reference",285)286axes[0].set(xlabel="Optical depth L", ylabel="Removed-primary fraction")287naive = np.asarray(weak["diagnostic_one_minus_stored_T"])288nonzero = naive > 0289axes[0].loglog(290np.asarray(weak["optical_depths"])[nonzero],291naive[nonzero],292linestyle="--",293color="#444444",294label="1 - stored T (FP32 diagnostic)",295)296zero_count = int(np.count_nonzero(~nonzero))297axes[0].text(2980.97,2990.05,300f"Subtraction gave zero at {zero_count} sampled depths\n(zeros omitted on log axes)",301transform=axes[0].transAxes,302ha="right",303va="bottom",304fontsize=9,305)306axes[0].legend(loc="upper left", fontsize=9)307inverse = result["inverse"]308axes[1].semilogx(309[row["decrement"] for row in inverse],310[row["ulps"] for row in inverse],311color="#009E73",312marker=".",313markersize=3,314)315axes[1].set(xlabel="Supplied decrement δ", ylabel="Inverse error (FP32 ULPs)")316maximum_ulp = max(row["ulps"] for row in inverse)317axes[1].set_ylim(-0.1, max(1, maximum_ulp + 0.5))318axes[1].set_yticks(range(maximum_ulp + 2))319fig.suptitle("Weak attenuation · direct decrement and independently checked inverse")320save(fig, "transmission-weak-attenuation.svg")321322tail = result["tail"]323fig, axes = plt.subplots(1, 2, figsize=(10, 3.5), layout="constrained")324for ax, key, title in zip(325axes, ("T", "counts"), ("Stored transmission", "Stored expected counts"), strict=True326):327values = np.asarray(tail["outputs"][key])328positive = values > 0329depths = np.asarray(tail["optical_depths"])330ax.semilogy(depths[positive], values[positive], color="#0072B2")331zero_depths = depths[~positive]332if zero_depths.size:333ax.axvline(float(zero_depths[0]), color="#D55E00", linestyle="--")334ax.text(3350.97,3360.96,337f"First stored zero in sweep: L = {zero_depths[0]:g}",338transform=ax.transAxes,339ha="right",340va="top",341fontsize=9,342)343ax.set(xlabel="Optical depth L", ylabel=title, xlim=(80, 200))344fig.suptitle("Tail range · open-beam expectation = 10³⁰ · zero values omitted from log axes")345save(fig, "transmission-tail-rescue.svg")346return files347348349def timed_batches(350wp: Any, stream: Any, operation: Callable[[], None], config: Config351) -> dict[str, Any]:352for _ in range(config.warmup_iterations):353operation()354wp.synchronize_stream(stream)355start = wp.Event(device=stream.device, enable_timing=True)356stop = wp.Event(device=stream.device, enable_timing=True)357samples: list[float] = []358for _ in range(config.batches):359stream.record_event(start)360for _ in range(config.iterations):361operation()362stream.record_event(stop)363samples.append(float(wp.get_event_elapsed_time(start, stop)) / config.iterations)364return {365"timing_kind": "CUDA event",366"cuda_event_ms_per_call": samples,367"median_ms": statistics.median(samples),368"min_ms": min(samples),369"max_ms": max(samples),370"batches": config.batches,371"iterations_per_batch": config.iterations,372"includes": "device work plus any host submission gaps between consecutive launches",373"excludes": "allocation, H2D upload, compilation, warmup, content validation",374}375376377def wall_batches(378wp: Any, stream: Any, operation: Callable[[], None], config: Config379) -> dict[str, Any]:380for _ in range(config.warmup_iterations):381operation()382wp.synchronize_stream(stream)383samples: list[float] = []384for _ in range(config.batches):385start = time.perf_counter_ns()386for _ in range(config.iterations):387operation()388wp.synchronize_stream(stream)389samples.append((time.perf_counter_ns() - start) / 1e6 / config.iterations)390return {391"timing_kind": "checked wall clock",392"wall_ms_per_call": samples,393"median_ms": statistics.median(samples),394"min_ms": min(samples),395"max_ms": max(samples),396"batches": config.batches,397"iterations_per_batch": config.iterations,398"includes": "host validation, device content scans, status readback and completed output",399"excludes": "allocation, input upload, compilation and warmup",400}401402403def benchmark_case(404wp: Any, np: Any, device: Any, size: int, block: int, regime: str, config: Config405) -> list[dict[str, Any]]:406# The same 256-value pattern supports a bounded independent correctness check407# before timing any size; this is a declared synthetic numerical workload.408ordinary = np.linspace(0, 20, 256, dtype=np.float32)409tail = np.linspace(64, 200, 256, dtype=np.float32)410pattern = ordinary if regime == "ordinary" else tail.copy()411if regime == "mixed":412pattern[::2] = ordinary[::2]413host_depth = np.resize(pattern, size)414depth = wp.array(host_depth, dtype=wp.float32, device=device)415outputs = [wp.empty(size, dtype=wp.float32, device=device) for _ in range(4)]416seed = wp.ones(size, dtype=wp.float32, device=device)417gradient = wp.empty(size, dtype=wp.float32, device=device)418rows: list[dict[str, Any]] = []419prechecks: dict[str, Any] = {}420references = [forward_reference(float(v), 1000.0) for v in pattern[: min(size, 256)]]421422def record(423label: str,424operation: Callable[[], None],425workspace: Any,426logical_bytes: int,427*,428checked: bool = False,429) -> None:430timer = wall_batches if checked else timed_batches431timing = timer(wp, workspace.stream, operation, config)432workspace.check_status()433rows.append(434{435"pixels": size,436"block_dim": block,437"regime": regime,438"operation": label,439"scratch_bytes": workspace.scratch_bytes,440"logical_array_bytes_estimate": logical_bytes,441"bytes_note": "minimum accesses; excludes caches/status/FP64 reduction scratch",442"precheck": prechecks.copy(),443**timing,444}445)446447for mode in ("scalar", "per-pixel", "device-scalar"):448prechecks.clear()449workspace = prepare_transmission(450TransmissionSpec(beam=mode, active_beam=mode != "scalar", block_dim=block),451device=str(device),452max_pixels=size,453)454beam = (4551000.0456if mode == "scalar"457else wp.full(4581 if mode == "device-scalar" else size, 1000.0, dtype=wp.float32, device=device459)460)461beam_gradient = (462None463if mode == "scalar"464else wp.empty(1 if mode == "device-scalar" else size, dtype=wp.float32, device=device)465)466kwargs = dict(zip(OUTPUT_ARGUMENTS, outputs, strict=True))467transmit(depth, beam, workspace=workspace, **kwargs)468for name, output in zip(OUTPUT_NAMES, outputs, strict=True):469# A diagnostic read occurs before timing; nothing is downloaded inside it.470values = output[: len(references)].numpy()471for actual, reference, input_depth in zip(472values, references, pattern[: len(references)], strict=True473):474check = value_error(475float(actual), getattr(reference, name), counts=name == "counts"476)477exact_log = name != "log_T" or struct.pack("!f", float(actual)) == struct.pack(478"!f", -float(input_depth)479)480if not check.passed or not exact_log:481raise AssertionError(f"benchmark precheck failed: {name}, {mode}, {regime}")482transmission_vjp(483depth,484beam,485seed_counts=seed,486out_grad_L=gradient,487out_grad_n0=beam_gradient,488workspace=workspace,489)490grad_values = gradient[: len(references)].numpy()491for actual, value in zip(grad_values, pattern[: len(references)], strict=True):492ref = vjp_reference(float(value), 1000.0, seed_counts=1.0)493if abs(exact_input(float(actual)) - ref.grad_L) > ref.budget_L:494raise AssertionError("benchmark VJP precheck failed")495if mode == "per-pixel":496assert beam_gradient is not None497for actual, value in zip(498beam_gradient[: len(references)].numpy(), pattern[: len(references)], strict=True499):500ref = vjp_reference(float(value), 1000.0, seed_counts=1.0)501if abs(exact_input(float(actual)) - ref.grad_n0) > ref.budget_n0:502raise AssertionError("per-pixel beam VJP precheck failed")503elif mode == "device-scalar":504assert beam_gradient is not None505# This positive repeated-pattern sum uses the oracle's contributions;506# its count-scaled bound avoids iterating over millions of host values.507with localcontext() as context:508context.prec = 100509whole, remainder = divmod(size, len(pattern))510contributions = [vjp_reference(float(v), seed_counts=1.0) for v in pattern]511expected = Decimal(whole) * sum((v.grad_n0 for v in contributions), Decimal(0))512expected += sum((v.grad_n0 for v in contributions[:remainder]), Decimal(0))513element_budget = Decimal(whole) * sum(514(v.budget_n0 for v in contributions), Decimal(0)515)516element_budget += sum((v.budget_n0 for v in contributions[:remainder]), Decimal(0))517count, levels = (size + 255) // 256, 1518while count > 1:519count = (count + 255) // 256520levels += 1521# Warp 1.17 tile_reduce.h combines each warp in five shuffle522# steps, then thread zero adds eight warp totals serially.523# The longest arithmetic path is therefore 5 + 7, not log2(256).524addition_depth = 12 * levels525product = addition_depth * U64526gamma = product / (1 - product)527# Seeds and factors here are positive, so magnitude == total.528budget = element_budget + gamma * expected + U32 * expected + MIN_SUBNORMAL / 2529if abs(exact_input(float(beam_gradient.numpy()[0])) - expected) > budget:530raise AssertionError("scalar beam VJP precheck failed")531prechecks.update(532{533"scalar_gradient_reference": str(expected),534"scalar_gradient_absolute_budget": str(budget),535"scalar_reduction_addition_depth": addition_depth,536}537)538prechecks.update(539{540"forward_and_depth_samples": len(references),541"log_transmission_check": "exact bits, including signed zero",542"status": "passed",543}544)545546def forward(beam: Any = beam, workspace: Any = workspace, kwargs: Any = kwargs) -> None:547transmit(depth, beam, workspace=workspace, validate=False, **kwargs)548549def backward(550beam: Any = beam, workspace: Any = workspace, beam_gradient: Any = beam_gradient551) -> None:552transmission_vjp(553depth,554beam,555seed_counts=seed,556out_grad_L=gradient,557out_grad_n0=beam_gradient,558workspace=workspace,559validate=False,560)561562def forward_backward(563forward: Callable[[], None] = forward, backward: Callable[[], None] = backward564) -> None:565forward()566backward()567568def checked_forward(569beam: Any = beam, workspace: Any = workspace, kwargs: Any = kwargs570) -> None:571transmit(depth, beam, workspace=workspace, **kwargs)572573def checked_backward(574beam: Any = beam, workspace: Any = workspace, beam_gradient: Any = beam_gradient575) -> None:576transmission_vjp(577depth,578beam,579seed_counts=seed,580out_grad_L=gradient,581out_grad_n0=beam_gradient,582workspace=workspace,583)584585record(586f"forward-fused-{mode}", forward, workspace, size * (24 if mode == "per-pixel" else 20)587)588record(f"vjp-counts-{mode}", backward, workspace, size * (12 if mode == "scalar" else 20))589record(590f"forward-plus-vjp-{mode}",591forward_backward,592workspace,593size * (32 if mode == "scalar" else (44 if mode == "per-pixel" else 40)),594)595with wp.ScopedCapture(stream=workspace.stream, force_module_load=False) as capture:596forward_backward()597598def graph_replay(graph: Any = capture.graph, stream: Any = workspace.stream) -> None:599wp.capture_launch(graph, stream=stream)600601record(602f"graph-forward-plus-vjp-{mode}",603graph_replay,604workspace,605size * (32 if mode == "scalar" else (44 if mode == "per-pixel" else 40)),606)607record(608f"checked-forward-{mode}",609checked_forward,610workspace,611size * (24 if mode == "per-pixel" else 20),612checked=True,613)614record(615f"checked-vjp-{mode}",616checked_backward,617workspace,618size * (12 if mode == "scalar" else 20),619checked=True,620)621if mode == "scalar":622623def matched_copy(stream: Any = workspace.stream) -> None:624wp.copy(outputs[0], depth, stream=stream)625626record("matched-device-copy", matched_copy, workspace, size * 8)627628def separate(beam: Any = beam, workspace: Any = workspace) -> None:629for argument, output in zip(OUTPUT_ARGUMENTS, outputs, strict=True):630transmit(depth, beam, workspace=workspace, validate=False, **{argument: output})631632record("forward-four-separate-launches", separate, workspace, size * 32)633for argument, output in zip(OUTPUT_ARGUMENTS, outputs, strict=True):634635def selected(636argument: str = argument,637output: Any = output,638beam: Any = beam,639workspace: Any = workspace,640) -> None:641transmit(depth, beam, workspace=workspace, validate=False, **{argument: output})642643record(f"forward-{argument}", selected, workspace, size * 8)644return rows645646647def main() -> int:648parser = experiment_parser(__file__, __doc__)649parser.add_argument("--benchmark", action="store_true")650parser.add_argument("--sizes", type=int, nargs="+", help="override benchmark pixel counts")651parser.add_argument("--iterations", type=int, help="override iterations per timing batch")652arguments = parser.parse_args()653config_data = json.loads(arguments.config.read_text(encoding="utf-8"))654if arguments.sizes is not None:655config_data["benchmark_sizes"] = arguments.sizes656if arguments.iterations is not None:657config_data["iterations"] = arguments.iterations658config = Config(**config_data)659config.validate()660destination = private_output(arguments.output, ROOT)661sources = experiment_sources(662__file__,663arguments.config,664extra={665name: ROOT / name666for name in (667"experiments/transmission-contract/profile_cuda.py",668"experiments/transmission-contract/config.json",669)670},671)672started = time.monotonic()673with RunRecorder(destination, configuration=asdict(config), sources=sources) as record:674wp, np = importlib.import_module("warp"), importlib.import_module("numpy")675wp.init()676device = wp.get_device(arguments.device)677if not device.is_cuda:678raise ValueError("this experiment requires actual CUDA execution")679record.set_metadata(**metadata(wp, device, config))680result = validation_run(wp, np, device, config)681record.write_json("validation.json", result)682with tempfile.TemporaryDirectory(prefix="dpt-figures-") as temporary:683figures = render_figures(result, Path(temporary))684for name in figures:685record.write_bytes(name, (Path(temporary) / name).read_bytes())686record.set_metadata(figures=figures)687print(f"Validated CUDA sweeps; figures and records: {destination}", flush=True)688if arguments.benchmark:689rows: list[dict[str, Any]] = []690for size in config.benchmark_sizes:691for block in config.block_dims:692for regime in config.regimes:693rows.extend(benchmark_case(wp, np, device, size, block, regime, config))694print(695f"Timed P={size}, block={block}, regime={regime}; {len(rows)} rows",696flush=True,697)698record.write_json("benchmark.json", {"schema_version": 1, "rows": rows})699record.set_metadata(benchmark_rows=len(rows))700record.set_metadata(elapsed_seconds=time.monotonic() - started)701return 0702703704if __name__ == "__main__":705raise SystemExit(main())706