experiments/transmission-contract/run.py

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 (27    RunRecorder,28    experiment_parser,29    experiment_sources,30    private_output,31    repository_root,32)33from dpt.transmission import (34    TransmissionSpec,35    optical_depth_from_removed,36    prepare_transmission,37    transmission_vjp,38    transmit,39)40from dpt.validation.transmission import (41    MIN_SUBNORMAL,42    U32,43    U64,44    analytic_cases,45    exact_input,46    forward_reference,47    inverse_reference,48    value_error,49    vjp_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:59    schema_version: int60    sweep_points: int61    benchmark_sizes: list[int]62    block_dims: list[int]63    regimes: list[str]64    batches: int65    iterations: int66    warmup_iterations: int6768    def validate(self) -> None:69        if self.schema_version != 1 or not 3 <= self.sweep_points <= 4097:70            raise ValueError("schema_version must be 1; sweep_points must be 3..4097")71        if not self.benchmark_sizes or any(72            type(n) is not int or not 1 <= n <= 2**31 - 1 for n in self.benchmark_sizes73        ):74            raise ValueError("benchmark sizes must be positive int32 lengths")75        if not self.block_dims or any(n not in (128, 256) for n in self.block_dims):76            raise ValueError("block_dims must contain only 128 and/or 256")77        if not self.regimes or any(r not in ("ordinary", "tail", "mixed") for r in self.regimes):78            raise ValueError("unknown benchmark numerical regime")79        if self.batches < 5 or self.iterations < 1 or self.warmup_iterations < 1:80            raise ValueError("use at least five batches and positive iteration counts")818283def write_json(path: Path, value: Any) -> None:84    path.write_text(json.dumps(value, indent=2, allow_nan=False) + "\n", encoding="utf-8")858687def command_output(arguments: list[str]) -> str:88    try:89        result = subprocess.run(arguments, cwd=ROOT, capture_output=True, text=True, check=False)90    except OSError as error:91        return f"unavailable: {error}"92    return result.stdout.strip() if result.returncode == 0 else result.stderr.strip()939495def metadata(wp: Any, device: Any, config: Config) -> dict[str, Any]:96    runtime = device.runtime97    return {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."""128    workspace = prepare_transmission(129        TransmissionSpec(beam="scalar"), device=str(device), max_pixels=len(depths)130    )131    optical_depth = wp.array(depths, dtype=wp.float32, device=device)132    outputs = [wp.empty(len(depths), dtype=wp.float32, device=device) for _ in OUTPUT_NAMES]133    transmit(134        optical_depth,135        beam,136        workspace=workspace,137        **dict(zip(OUTPUT_ARGUMENTS, outputs, strict=True)),138    )139    wp.synchronize_stream(workspace.stream)140    measured = [output.numpy() for output in outputs]141    cases: list[dict[str, Any]] = []142    for index, depth in enumerate(depths):143        reference = forward_reference(float(depth), beam)144        checks = {}145        for name, values in zip(OUTPUT_NAMES, measured, strict=True):146            result = value_error(147                float(values[index]), getattr(reference, name), counts=name == "counts"148            )149            exact_log = name != "log_T" or struct.pack("!f", float(values[index])) == struct.pack(150                "!f", -float(depth)151            )152            checks[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            }159            if not result.passed or not exact_log:160                raise AssertionError(f"{name} failed at optical depth {depth}: {checks[name]}")161        cases.append({"optical_depth": float(depth), "checks": checks})162    return {163        "beam": float(np.float32(beam)),164        "cases": cases,165        "outputs": {166            name: 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]:176    points = config.sweep_points177    result: 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(181            wp, np, np.geomspace(1e-12, 0.1, points, dtype=np.float32), 1.0, device182        ),183        "tail": evaluate_sweep(184            wp, np, np.linspace(80, 200, points, dtype=np.float32), 1e30, device185        ),186    }187    analytic = analytic_cases()188    result["analytic"] = evaluate_sweep(189        wp,190        np,191        np.array([float(case.optical_depth) for case in analytic], dtype=np.float32),192        1.0,193        device,194    )195    result["analytic"]["definitions"] = [asdict(case) for case in analytic]196    for definition in result["analytic"]["definitions"]:197        definition["optical_depth"] = str(definition["optical_depth"])198    decrements = np.geomspace(1e-12, 0.9, points, dtype=np.float32)199    workspace = prepare_transmission(device=str(device), max_pixels=points)200    delta = wp.array(decrements, dtype=wp.float32, device=device)201    restored = wp.empty(points, dtype=wp.float32, device=device)202    optical_depth_from_removed(delta, out_L=restored, workspace=workspace)203    measured = restored.numpy()204    inverse_cases: list[dict[str, Any]] = []205    for decrement, actual in zip(decrements, measured, strict=True):206        expected = inverse_reference(float(decrement))207        check = value_error(float(actual), expected)208        if not check.passed:209            raise AssertionError(f"inverse decrement failed for {decrement}")210        inverse_cases.append(211            {"decrement": float(decrement), "actual": float(actual), "ulps": check.ulps}212        )213    result["inverse"] = inverse_cases214    # Diagnostic postprocessing of actual stored library output, deliberately215    # showing cancellation. This is never used as a transport implementation.216    stored_transmission = np.asarray(result["weak"]["outputs"]["T"], dtype=np.float32)217    result["weak"]["diagnostic_one_minus_stored_T"] = (218        np.float32(1.0) - stored_transmission219    ).tolist()220    result["status"] = "passed"221    return result222223224def render_figures(result: dict[str, Any], destination: Path) -> list[str]:225    matplotlib = importlib.import_module("matplotlib")226    matplotlib.use("Agg")227    plt = importlib.import_module("matplotlib.pyplot")228    np = importlib.import_module("numpy")229    plt.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    )243    files: list[str] = []244245    def save(figure: Any, name: str) -> None:246        figure.savefig(247            destination / name, format="svg", metadata={"Date": None}, bbox_inches="tight"248        )249        figure.savefig(destination / Path(name).with_suffix(".png"), dpi=150, bbox_inches="tight")250        plt.close(figure)251        files.append(name)252253    sweep = result["sweep"]254    fig, axes = plt.subplots(1, 3, figsize=(12, 3.3), layout="constrained")255    for ax, key, title in zip(256        axes,257        ("T", "counts", "log_T"),258        ("Transmission", "Expected counts", "Log transmission"),259        strict=True,260    ):261        ax.plot(sweep["optical_depths"], sweep["outputs"][key], color="#0072B2")262        ax.set(xlabel="Optical depth L", ylabel=title, title=title)263        if key != "log_T":264            ax.set_yscale("log")265    fig.suptitle("Canonical CUDA execution · open-beam expectation = 10⁶")266    save(fig, "transmission-sweep.svg")267268    weak = result["weak"]269    fig, axes = plt.subplots(1, 2, figsize=(10, 3.5), layout="constrained")270    axes[0].loglog(271        weak["optical_depths"],272        weak["outputs"]["removed"],273        color="#0072B2",274        label="CUDA removed-primary fraction",275    )276    oracle = [float(case["checks"]["removed"]["reference_decimal"]) for case in weak["cases"]]277    axes[0].loglog(278        weak["optical_depths"][::8],279        oracle[::8],280        "o",281        color="#D55E00",282        markersize=4,283        fillstyle="none",284        label="100-digit reference",285    )286    axes[0].set(xlabel="Optical depth L", ylabel="Removed-primary fraction")287    naive = np.asarray(weak["diagnostic_one_minus_stored_T"])288    nonzero = naive > 0289    axes[0].loglog(290        np.asarray(weak["optical_depths"])[nonzero],291        naive[nonzero],292        linestyle="--",293        color="#444444",294        label="1 - stored T (FP32 diagnostic)",295    )296    zero_count = int(np.count_nonzero(~nonzero))297    axes[0].text(298        0.97,299        0.05,300        f"Subtraction gave zero at {zero_count} sampled depths\n(zeros omitted on log axes)",301        transform=axes[0].transAxes,302        ha="right",303        va="bottom",304        fontsize=9,305    )306    axes[0].legend(loc="upper left", fontsize=9)307    inverse = result["inverse"]308    axes[1].semilogx(309        [row["decrement"] for row in inverse],310        [row["ulps"] for row in inverse],311        color="#009E73",312        marker=".",313        markersize=3,314    )315    axes[1].set(xlabel="Supplied decrement δ", ylabel="Inverse error (FP32 ULPs)")316    maximum_ulp = max(row["ulps"] for row in inverse)317    axes[1].set_ylim(-0.1, max(1, maximum_ulp + 0.5))318    axes[1].set_yticks(range(maximum_ulp + 2))319    fig.suptitle("Weak attenuation · direct decrement and independently checked inverse")320    save(fig, "transmission-weak-attenuation.svg")321322    tail = result["tail"]323    fig, axes = plt.subplots(1, 2, figsize=(10, 3.5), layout="constrained")324    for ax, key, title in zip(325        axes, ("T", "counts"), ("Stored transmission", "Stored expected counts"), strict=True326    ):327        values = np.asarray(tail["outputs"][key])328        positive = values > 0329        depths = np.asarray(tail["optical_depths"])330        ax.semilogy(depths[positive], values[positive], color="#0072B2")331        zero_depths = depths[~positive]332        if zero_depths.size:333            ax.axvline(float(zero_depths[0]), color="#D55E00", linestyle="--")334            ax.text(335                0.97,336                0.96,337                f"First stored zero in sweep: L = {zero_depths[0]:g}",338                transform=ax.transAxes,339                ha="right",340                va="top",341                fontsize=9,342            )343        ax.set(xlabel="Optical depth L", ylabel=title, xlim=(80, 200))344    fig.suptitle("Tail range · open-beam expectation = 10³⁰ · zero values omitted from log axes")345    save(fig, "transmission-tail-rescue.svg")346    return files347348349def timed_batches(350    wp: Any, stream: Any, operation: Callable[[], None], config: Config351) -> dict[str, Any]:352    for _ in range(config.warmup_iterations):353        operation()354    wp.synchronize_stream(stream)355    start = wp.Event(device=stream.device, enable_timing=True)356    stop = wp.Event(device=stream.device, enable_timing=True)357    samples: list[float] = []358    for _ in range(config.batches):359        stream.record_event(start)360        for _ in range(config.iterations):361            operation()362        stream.record_event(stop)363        samples.append(float(wp.get_event_elapsed_time(start, stop)) / config.iterations)364    return {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(378    wp: Any, stream: Any, operation: Callable[[], None], config: Config379) -> dict[str, Any]:380    for _ in range(config.warmup_iterations):381        operation()382    wp.synchronize_stream(stream)383    samples: list[float] = []384    for _ in range(config.batches):385        start = time.perf_counter_ns()386        for _ in range(config.iterations):387            operation()388            wp.synchronize_stream(stream)389        samples.append((time.perf_counter_ns() - start) / 1e6 / config.iterations)390    return {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(404    wp: 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.408    ordinary = np.linspace(0, 20, 256, dtype=np.float32)409    tail = np.linspace(64, 200, 256, dtype=np.float32)410    pattern = ordinary if regime == "ordinary" else tail.copy()411    if regime == "mixed":412        pattern[::2] = ordinary[::2]413    host_depth = np.resize(pattern, size)414    depth = wp.array(host_depth, dtype=wp.float32, device=device)415    outputs = [wp.empty(size, dtype=wp.float32, device=device) for _ in range(4)]416    seed = wp.ones(size, dtype=wp.float32, device=device)417    gradient = wp.empty(size, dtype=wp.float32, device=device)418    rows: list[dict[str, Any]] = []419    prechecks: dict[str, Any] = {}420    references = [forward_reference(float(v), 1000.0) for v in pattern[: min(size, 256)]]421422    def record(423        label: str,424        operation: Callable[[], None],425        workspace: Any,426        logical_bytes: int,427        *,428        checked: bool = False,429    ) -> None:430        timer = wall_batches if checked else timed_batches431        timing = timer(wp, workspace.stream, operation, config)432        workspace.check_status()433        rows.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        )446447    for mode in ("scalar", "per-pixel", "device-scalar"):448        prechecks.clear()449        workspace = prepare_transmission(450            TransmissionSpec(beam=mode, active_beam=mode != "scalar", block_dim=block),451            device=str(device),452            max_pixels=size,453        )454        beam = (455            1000.0456            if mode == "scalar"457            else wp.full(458                1 if mode == "device-scalar" else size, 1000.0, dtype=wp.float32, device=device459            )460        )461        beam_gradient = (462            None463            if mode == "scalar"464            else wp.empty(1 if mode == "device-scalar" else size, dtype=wp.float32, device=device)465        )466        kwargs = dict(zip(OUTPUT_ARGUMENTS, outputs, strict=True))467        transmit(depth, beam, workspace=workspace, **kwargs)468        for name, output in zip(OUTPUT_NAMES, outputs, strict=True):469            # A diagnostic read occurs before timing; nothing is downloaded inside it.470            values = output[: len(references)].numpy()471            for actual, reference, input_depth in zip(472                values, references, pattern[: len(references)], strict=True473            ):474                check = value_error(475                    float(actual), getattr(reference, name), counts=name == "counts"476                )477                exact_log = name != "log_T" or struct.pack("!f", float(actual)) == struct.pack(478                    "!f", -float(input_depth)479                )480                if not check.passed or not exact_log:481                    raise AssertionError(f"benchmark precheck failed: {name}, {mode}, {regime}")482        transmission_vjp(483            depth,484            beam,485            seed_counts=seed,486            out_grad_L=gradient,487            out_grad_n0=beam_gradient,488            workspace=workspace,489        )490        grad_values = gradient[: len(references)].numpy()491        for actual, value in zip(grad_values, pattern[: len(references)], strict=True):492            ref = vjp_reference(float(value), 1000.0, seed_counts=1.0)493            if abs(exact_input(float(actual)) - ref.grad_L) > ref.budget_L:494                raise AssertionError("benchmark VJP precheck failed")495        if mode == "per-pixel":496            assert beam_gradient is not None497            for actual, value in zip(498                beam_gradient[: len(references)].numpy(), pattern[: len(references)], strict=True499            ):500                ref = vjp_reference(float(value), 1000.0, seed_counts=1.0)501                if abs(exact_input(float(actual)) - ref.grad_n0) > ref.budget_n0:502                    raise AssertionError("per-pixel beam VJP precheck failed")503        elif mode == "device-scalar":504            assert 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.507            with localcontext() as context:508                context.prec = 100509                whole, remainder = divmod(size, len(pattern))510                contributions = [vjp_reference(float(v), seed_counts=1.0) for v in pattern]511                expected = Decimal(whole) * sum((v.grad_n0 for v in contributions), Decimal(0))512                expected += sum((v.grad_n0 for v in contributions[:remainder]), Decimal(0))513                element_budget = Decimal(whole) * sum(514                    (v.budget_n0 for v in contributions), Decimal(0)515                )516                element_budget += sum((v.budget_n0 for v in contributions[:remainder]), Decimal(0))517                count, levels = (size + 255) // 256, 1518                while count > 1:519                    count = (count + 255) // 256520                    levels += 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).524                addition_depth = 12 * levels525                product = addition_depth * U64526                gamma = product / (1 - product)527                # Seeds and factors here are positive, so magnitude == total.528                budget = element_budget + gamma * expected + U32 * expected + MIN_SUBNORMAL / 2529                if abs(exact_input(float(beam_gradient.numpy()[0])) - expected) > budget:530                    raise AssertionError("scalar beam VJP precheck failed")531                prechecks.update(532                    {533                        "scalar_gradient_reference": str(expected),534                        "scalar_gradient_absolute_budget": str(budget),535                        "scalar_reduction_addition_depth": addition_depth,536                    }537                )538        prechecks.update(539            {540                "forward_and_depth_samples": len(references),541                "log_transmission_check": "exact bits, including signed zero",542                "status": "passed",543            }544        )545546        def forward(beam: Any = beam, workspace: Any = workspace, kwargs: Any = kwargs) -> None:547            transmit(depth, beam, workspace=workspace, validate=False, **kwargs)548549        def backward(550            beam: Any = beam, workspace: Any = workspace, beam_gradient: Any = beam_gradient551        ) -> None:552            transmission_vjp(553                depth,554                beam,555                seed_counts=seed,556                out_grad_L=gradient,557                out_grad_n0=beam_gradient,558                workspace=workspace,559                validate=False,560            )561562        def forward_backward(563            forward: Callable[[], None] = forward, backward: Callable[[], None] = backward564        ) -> None:565            forward()566            backward()567568        def checked_forward(569            beam: Any = beam, workspace: Any = workspace, kwargs: Any = kwargs570        ) -> None:571            transmit(depth, beam, workspace=workspace, **kwargs)572573        def checked_backward(574            beam: Any = beam, workspace: Any = workspace, beam_gradient: Any = beam_gradient575        ) -> None:576            transmission_vjp(577                depth,578                beam,579                seed_counts=seed,580                out_grad_L=gradient,581                out_grad_n0=beam_gradient,582                workspace=workspace,583            )584585        record(586            f"forward-fused-{mode}", forward, workspace, size * (24 if mode == "per-pixel" else 20)587        )588        record(f"vjp-counts-{mode}", backward, workspace, size * (12 if mode == "scalar" else 20))589        record(590            f"forward-plus-vjp-{mode}",591            forward_backward,592            workspace,593            size * (32 if mode == "scalar" else (44 if mode == "per-pixel" else 40)),594        )595        with wp.ScopedCapture(stream=workspace.stream, force_module_load=False) as capture:596            forward_backward()597598        def graph_replay(graph: Any = capture.graph, stream: Any = workspace.stream) -> None:599            wp.capture_launch(graph, stream=stream)600601        record(602            f"graph-forward-plus-vjp-{mode}",603            graph_replay,604            workspace,605            size * (32 if mode == "scalar" else (44 if mode == "per-pixel" else 40)),606        )607        record(608            f"checked-forward-{mode}",609            checked_forward,610            workspace,611            size * (24 if mode == "per-pixel" else 20),612            checked=True,613        )614        record(615            f"checked-vjp-{mode}",616            checked_backward,617            workspace,618            size * (12 if mode == "scalar" else 20),619            checked=True,620        )621        if mode == "scalar":622623            def matched_copy(stream: Any = workspace.stream) -> None:624                wp.copy(outputs[0], depth, stream=stream)625626            record("matched-device-copy", matched_copy, workspace, size * 8)627628            def separate(beam: Any = beam, workspace: Any = workspace) -> None:629                for argument, output in zip(OUTPUT_ARGUMENTS, outputs, strict=True):630                    transmit(depth, beam, workspace=workspace, validate=False, **{argument: output})631632            record("forward-four-separate-launches", separate, workspace, size * 32)633            for argument, output in zip(OUTPUT_ARGUMENTS, outputs, strict=True):634635                def selected(636                    argument: str = argument,637                    output: Any = output,638                    beam: Any = beam,639                    workspace: Any = workspace,640                ) -> None:641                    transmit(depth, beam, workspace=workspace, validate=False, **{argument: output})642643                record(f"forward-{argument}", selected, workspace, size * 8)644    return rows645646647def main() -> int:648    parser = experiment_parser(__file__, __doc__)649    parser.add_argument("--benchmark", action="store_true")650    parser.add_argument("--sizes", type=int, nargs="+", help="override benchmark pixel counts")651    parser.add_argument("--iterations", type=int, help="override iterations per timing batch")652    arguments = parser.parse_args()653    config_data = json.loads(arguments.config.read_text(encoding="utf-8"))654    if arguments.sizes is not None:655        config_data["benchmark_sizes"] = arguments.sizes656    if arguments.iterations is not None:657        config_data["iterations"] = arguments.iterations658    config = Config(**config_data)659    config.validate()660    destination = private_output(arguments.output, ROOT)661    sources = experiment_sources(662        __file__,663        arguments.config,664        extra={665            name: ROOT / name666            for name in (667                "experiments/transmission-contract/profile_cuda.py",668                "experiments/transmission-contract/config.json",669            )670        },671    )672    started = time.monotonic()673    with RunRecorder(destination, configuration=asdict(config), sources=sources) as record:674        wp, np = importlib.import_module("warp"), importlib.import_module("numpy")675        wp.init()676        device = wp.get_device(arguments.device)677        if not device.is_cuda:678            raise ValueError("this experiment requires actual CUDA execution")679        record.set_metadata(**metadata(wp, device, config))680        result = validation_run(wp, np, device, config)681        record.write_json("validation.json", result)682        with tempfile.TemporaryDirectory(prefix="dpt-figures-") as temporary:683            figures = render_figures(result, Path(temporary))684            for name in figures:685                record.write_bytes(name, (Path(temporary) / name).read_bytes())686        record.set_metadata(figures=figures)687        print(f"Validated CUDA sweeps; figures and records: {destination}", flush=True)688        if arguments.benchmark:689            rows: list[dict[str, Any]] = []690            for size in config.benchmark_sizes:691                for block in config.block_dims:692                    for regime in config.regimes:693                        rows.extend(benchmark_case(wp, np, device, size, block, regime, config))694                        print(695                            f"Timed P={size}, block={block}, regime={regime}; {len(rows)} rows",696                            flush=True,697                        )698            record.write_json("benchmark.json", {"schema_version": 1, "rows": rows})699            record.set_metadata(benchmark_rows=len(rows))700        record.set_metadata(elapsed_seconds=time.monotonic() - started)701    return 0702703704if __name__ == "__main__":705    raise SystemExit(main())706