Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.cirron.com/llms.txt

Use this file to discover all available pages before exploring further.

Attach the profiler to the current process. Call once. Subsequent calls are no-ops and log a warning. Returns a Profiler handle most callers discard. Calling ci.shutdown() clears the singleton; ci.profile() after that starts a fresh profiler. This is the supported way to reset state between tests.

Signature

def profile(
    config: dict | None = None,
    frameworks: list[str] | None = None,
    snapshots: Literal["stats", "sampled", "full"] | None = None,
    sample_rate: float | None = None,
    flush_interval: float | None = None,
    enabled: bool = True,
    path: str | None = None,
    output: str | list[str] | None = None,
) -> Profiler

Parameters

NameTypeDefaultPurpose
configdict?NoneRuntime feature flags read by your code via config.get(...)
frameworkslist[str]?NoneSkip autodetect and install hooks for the named frameworks
snapshotsstr?"stats""stats", "sampled", or "full" weight/gradient capture
sample_ratefloat?0.01Fraction of epoch boundaries that serialize raw tensors
flush_intervalfloat?1.0Background flush thread wake interval in seconds
enabledboolTrueSet False to build a no-op profiler (zero overhead, no hooks)
pathstr?NoneOverride the local spool directory (./.cirron/ by default)
outputstr or list[str]"spool"Local sink fan-out: "spool", "log", "stdout", "none"
None for snapshots / sample_rate / flush_interval means “use the Cirron instance default”. Pass an explicit value to override per-call.

What it does

  1. Resolves config (explicit config= → platform global → SDK defaults).
  2. Reads platform context from CIRRON_RUN_ID, CIRRON_PIPELINE_ID, CIRRON_DEPLOYMENT_ID, CIRRON_WORKSPACE_ID.
  3. Selects a transport: kernel event stream (inside a Cirron pipeline or deployment), HTTP (with an API key), or file-only (neither).
  4. Autodetects installed frameworks unless frameworks= is explicit.
  5. Installs hooks for every detected framework. When multiple are present, the priority order transformers > tensorflow > torch determines which one owns the semantic epoch and step scopes via a shared HookContext.owned_scopes map; lower-priority hooks yield on those names and still produce their own lower-level scopes (torch still emits forward / backward / optimizer_step / data_load under the transformers-owned step).
  6. Starts the background flush thread.
  7. Registers atexit, SIGTERM, and SIGINT handlers for clean shutdown.
  8. Opens the cirron.session root scope with framework, device, cuda_count, and mixed_precision attributes.

Snapshot modes

ModeCost per epoch boundaryWhat’s captured
"stats"≤ 50 ms (typical model){mean, std, min, max, norm, histogram[16]} per tensor
"sampled"≤ 200 ms on sampled stepsStats + raw tensor values for random() < sample_rate epochs
"full"unbounded; debug-onlyStats + raw tensor values every epoch
"full" is not recommended for models over 100M parameters. At 7B+, even "sampled" is expensive; drop the sample_rate.

Output sinks

The output= parameter selects which local sinks the flush thread writes each batch to. It is independent of the platform transport: when CIRRON_RUN_ID is set, batches still flow over the kernel event stream regardless of output. Sinks control the local experience (disk, logs, terminal), which is why output="none" is safe even inside a Cirron pipeline.
ValueBehavior
"spool"(Default.) Write each batch as a JSON file under ./.cirron/spool/. Public spool format.
"log"Emit one logging.INFO line per closed span on the cirron.trace logger.
"stdout"Print one line per closed span to stdout. Same format as "log", no logging configuration.
"none"No spool, no log, no print. Traces stay in the in-memory buffer for ci.trace() only.
list[str]Multiple sinks fan-out simultaneously, e.g. ["spool", "log"].
Invalid values raise ValueError at ci.profile() time, before any hook is installed.
ci.profile(output="log")               # stream lines to the cirron.trace logger
ci.profile(output=["spool", "stdout"]) # disk + live terminal feed
ci.profile(output="none")              # in-memory only; pair with ci.trace()
A live span line looks like:
[cirron] epoch[0] - 142us {epoch_loss=0.5234}

Returns

A Profiler handle exposing health, flush, trace, and shutdown.

Examples

Zero-touch

import cirron as ci
ci.profile()

trainer.train()   # HF Trainer, Keras model.fit, or torch + DataLoader

Explicit snapshot mode

ci.profile(snapshots="sampled", sample_rate=0.05)
sample_rate is the fraction of epoch boundaries that serialize raw tensors. Higher values give more fidelity for debugging (e.g. you can inspect the actual weight values at epoch 7 when loss spiked); lower values keep storage and flush cost bounded. The default 0.01 (1 %) is conservative. For small models or short runs, 0.050.1 is reasonable; at 7 B+ parameters, stay at 0.01 or lower.

Disable hooks selectively

ci.profile(frameworks=["torch"])   # ignore transformers / tensorflow even if importable

Dev-only kill switch

ci.profile(enabled=os.environ.get("ENABLE_PROFILE") == "1")

Notebook-friendly inspection

ci.profile(output="none")    # no disk writes, no log noise
trainer.train()
ci.trace()                   # render the scope tree in the cell
See ci.trace for the full read-back surface.

Distributed training

Every rank calls ci.profile(). The SDK reads RANK, LOCAL_RANK, and WORLD_SIZE from the environment and tags every span with its rank. The platform merges views at query time.

Profiling guide

Narrative walk-through of training instrumentation.

Lifecycle

flush, health, and shutdown.