Source code for track_gen.pipeline.producer

"""The :class:`Producer` protocol: what a ``Course`` drives."""
from __future__ import annotations

from typing import TYPE_CHECKING, Protocol

if TYPE_CHECKING:  # pragma: no cover
    import warp as wp

    from ..exec.context import LaunchContext
    from ..results import Layout

__all__ = ["Producer"]


[docs] class Producer(Protocol): """The generator surface ``track_gen.course.Course`` drives (documentation only: the library duck-types it and never ``isinstance``-checks it). ``TrackGenerator`` / ``GateGenerator`` (through their ``program``) and a built :class:`~track_gen.pipeline.Program` implement it; a third-party producer (e.g. a mixed batch of several generators writing views of one result) implements the required members, and the optional ones it needs. Required: - ``result``: the result every generation writes (a ``Track``, a ``GateSequence`` or another result the components read), the same instance with the same array addresses for the producer's lifetime; its ``valid`` (when present) is ``StepResult.valid``. - ``layout``: the result's :class:`~track_gen.results.Layout` (``num_envs``, the stride, the device). - ``enqueue(ctx, *, advance=False, mask=None)``: one generation on ``ctx`` (a :class:`~track_gen.exec.LaunchContext`), allocation-free and host-sync free. With ``advance``: bump each env's epoch first (every env, or the masked ones). With ``mask`` (``[E]`` int32, read on device): the unmasked envs' result rows end the generation bit for bit as they were (a masked commit), and an all-zero mask is an exact no-op. It may run inside a CUDA conditional-node body (the course's masked regeneration): kernels, fills and device-to-device copies on ``ctx``'s stream only. Optional (read when present): - ``seeds``: its :class:`~track_gen.seeds.SeedState` (``course.seeds``; ``Course.generate(seeds=)`` sets owned seeds through it). - ``capture_class``: a :class:`~track_gen.plugin.CaptureClass` (default ``STATIC``); ``HOST`` runs eagerly outside a capture and is refused inside one (``NotCapturableError``). - ``prepared`` and ``prepare()``: an unprepared producer is prepared first (its own warm-up, loading every module ``enqueue`` uses). Without them, the producer must have loaded every module its ``enqueue`` uses before it reaches a Course (e.g. one real ``enqueue`` at its construction). - ``default_stream``: the course's default stream when ``Course(..., stream=)`` is not given. - ``capacity`` and ``bounds`` (``name -> number`` mappings): the static capacities (``max_loop_length``) and declared bounds (``size_hi``) a plan would give, read by :meth:`ComponentContext.for_producer <track_gen.tools.ComponentContext.for_producer>` before the plan. - ``inputs`` and ``input_info``: its persistent device inputs (listed, never bound by the course: write them in place). """ @property def result(self) -> object: """The result that every generation writes (the same instance, with the same array addresses, for the producer's lifetime).""" ... @property def layout(self) -> "Layout": """The result's :class:`~track_gen.results.Layout`.""" ...
[docs] def enqueue(self, ctx: "LaunchContext", *, advance: bool = False, mask: "wp.array | None" = None) -> object: """Enqueue one generation on ``ctx``: allocation-free and host-sync free; with ``advance``, bump the epochs first; with ``mask``, leave the unmasked envs' rows bit for bit as they were (see the class docstring).""" ...