Skip to content

Implement offline correlation between profiler rows and captured FX regions - #17

Open
aryan5v wants to merge 50 commits into
RightNow-AI:mainfrom
aryan5v:universal-ws2-fx-ranking
Open

Implement offline correlation between profiler rows and captured FX regions#17
aryan5v wants to merge 50 commits into
RightNow-AI:mainfrom
aryan5v:universal-ws2-fx-ranking

Conversation

@aryan5v

@aryan5v aryan5v commented Jul 31, 2026

Copy link
Copy Markdown

Summary

  • Implemented offline correlation between FastVideo profiler operator rows and FX graph regions captured from Task 2
  • Added scope-based matching using parent_module hierarchy and operation names
  • Implemented exclusive CUDA time calculation to avoid double-counting nested scopes
  • Added region deduplication using stable graph fingerprints
  • Implemented aggregation of timing data, call counts, and shape frequencies
  • Added confidence scoring based on safety, profiler matches, and call frequency
  • Implemented end-to-end impact estimation using Amdahl-style optimistic improvement
  • Added tracking of unmatched profiler rows and capture failures

Key Changes

  • New module: autokernel/discovery/correlation.py with correlation logic
  • Updated autokernel/discovery/__init__.py to export correlation functions
  • Enhanced autokernel/discovery/profiler_export.py to support optional FX capture blocks
  • Added comprehensive test suite in tests/test_correlation.py (11 tests)
  • Enhanced tests/test_ranking_fx.py with FX capture block tests (4 tests)

Acceptance Criteria

✅ Synthetic CPU fixtures produce non-zero timed regions
✅ Repeated equivalent regions aggregate correctly by fingerprint
✅ Region shares use exclusive time without nested double-counting
✅ Unmatched profiler rows and capture failures remain visible
✅ All existing tests pass (433 CPU tests)

Test Plan

  • All 11 new correlation tests pass
  • All 433 existing CPU tests pass
  • Tested with synthetic CPU fixtures
  • Verified deduplication logic
  • Verified exclusive time calculation
  • Verified unmatched row tracking

Generated with Devin

aryan5v and others added 30 commits July 29, 2026 10:24
Introduce the importable core of the downstream platform: a typed KernelSpec
that owns everything the harness needs for one operation, and a small explicit
registry to hold them.

- autokernel/specs/types.py: Tolerance, EdgeCase, KernelSpec and validation.
  Validation rejects non-identifier names, duplicate size labels, unknown
  dtypes, missing/negative tolerances, size keys that disagree with shape_keys,
  inconsistent shape aliases, missing starter-kernel files and non-callable
  references; every message names the spec and the field.
- autokernel/specs/dtypes.py: canonical dtype strings (float16, bfloat16,
  float32) with static byte widths, so specs stay serializable and CPU-friendly.
  torch.dtype translation is lazy and runtime-only.
- autokernel/specs/accounting.py: FLOP/byte accounting as a small expression
  tree that both evaluates and serializes back to a safe numeric expression.
  This replaces storing Python function bodies as source strings.
- autokernel/specs/lazy.py: lazily resolved callables so specification
  discovery does not import torch.
- autokernel/specs/registry.py: KernelRegistry with deterministic ordering,
  duplicate-registration errors, and create_builtin_registry() for a fresh,
  isolated registry per command or test.

No behavior change yet: nothing imports this package.
Describe all nine built-in operations as KernelSpec objects, so sizes, dtypes,
tolerances, edge cases, FLOP/byte accounting, profiler shape aliases, starter
kernels and speedup estimates have exactly one home.

- autokernel/specs/inputs.py: the deterministic input generators, moved out of
  bench.py with identical tensor creation order and seeding. torch is imported
  inside the generators so discovery stays torch-free.
- autokernel/specs/builtins.py: matmul, softmax, layernorm, flash_attention,
  fused_mlp, cross_entropy, rotary_embedding, rmsnorm, reduce -- in the same
  order KERNEL_CONFIGS declared them. Reference implementations still live in
  reference.py and are resolved lazily; the math is not duplicated.

Metadata previously duplicated in extract.py (SHAPE_ALIAS_MAP, TOLERANCES_MAP,
FLOPS_FN_SRC, BYTES_FN_SRC, SPEEDUP_ESTIMATES, default shapes) is folded into
the specs. Two notes on faithfulness:

- extract.py::SHAPE_KEYS was dead code holding profiler key spellings; those
  spellings are already covered by shape_aliases, so nothing is lost.
  KernelSpec.shape_keys now means "the canonical size keys of this operation".
- 'reduce' keeps default_shape={"M": 4096, "N": 4096} because extraction fell
  back to that shape (not its 8192x8192 'large' size) before this change.
Allow an operation to be supplied from outside the repository through a
locator, so a new op needs no edit to any central map.

Supported forms:

    package.module:SPEC
    /absolute/path/to/spec.py:SPEC
    relative/path/to/spec.py:SPEC

The attribute may be a KernelSpec or a zero-argument callable returning one.
Rejected with actionable errors that always echo the original locator: missing
module, missing file, missing attribute, wrong type, factory failure, invalid
spec, missing starter kernel, and a name that collides with an already
registered operation unless an override is requested.

File locators are imported through importlib.util.spec_from_file_location under
a unique module name; sys.path is never permanently mutated and specification
content is never passed to eval.

resolve_spec() applies the command-line precedence (locator first, then name)
and registers the loaded spec into a caller-supplied, isolated registry rather
than a process-wide global.

Trust boundary: loading a spec executes the Python file it names, like
`python that_file.py`. This is documented for callers.
bench.py and extract.py now read operation metadata from KernelSpec instead of
their own tables.

bench.py:
- KERNEL_CONFIGS, the input generators and the reference wrappers are gone;
  a deprecated KERNEL_CONFIGS view is derived from the registry for any
  out-of-tree caller.
- run_correctness / run_performance / run_profile take a KernelSpec. Console
  output is unchanged: torch dtypes are still resolved at the runtime boundary
  and printed the same way, and all five correctness stages behave identically.
- stage 5 now iterates EdgeCase objects, which adds optional per-case dtype,
  seed and input transforms. Built-ins declare none of those, so their edge
  coverage is byte-for-byte the same.
- new --spec LOCATOR and --spec-override. Precedence is --spec, then --kernel,
  then kernel.py::KERNEL_TYPE (resolve_operation_name). Specs are loaded after
  argument parsing, so --help never imports external code, and registered into
  a per-invocation registry.
- BENCH_DEVICE makes the harness device injectable so CPU tests can exercise
  the correctness stages; the default is unchanged ("cuda").

extract.py:
- SHAPE_KEYS, SHAPE_ALIAS_MAP, TOLERANCES_MAP, FLOPS_FN_SRC, BYTES_FN_SRC,
  SPEEDUP_ESTIMATES and the hard-coded default shapes are removed.
- generated kernel files now emit accounting from the serialized expression
  tree; an opaque external callable is referenced through its spec instead of
  being guessed or eval'd.
- new --spec LOCATOR/--spec-override. With --spec and no matching report entry,
  the target is synthesized from the spec's default shape so an external op can
  be extracted without profiling a model first.
- an op_type with no registered spec is skipped with a clear message.
Example:
- examples/custom_ops/add.py exports SPEC for an out-of-tree "custom_add"
  operation, and examples/custom_ops/add_kernel.py is its starter Triton kernel.
  It runs through the same bench.py/extract.py path as a built-in with no edit
  to any central operation map.

Tests (215 CPU tests, `uv run pytest -m "not gpu"`):
- test_spec_registry.py: registration, retrieval, deterministic ordering,
  duplicate errors, registry isolation, every documented validation error,
  accounting evaluation/serialization and dtype helpers.
- test_spec_loader.py: module, absolute and relative file locators, callable
  factories, bad module/path/attribute/type/factory errors, collision and
  override behavior, sys.path is untouched, unique module names, and discovery
  of the shipped example.
- test_builtin_specs.py: freezes the pre-refactor built-in names and order, size
  labels, large-size values, dtypes, tolerances, edge cases, shape aliases,
  extraction shapes, speedup estimates, starter-kernel existence, FLOP/byte
  values, deterministic inputs, and that discovery imports no torch.
- test_cli_compat.py: the pre-existing flags still exist, --help does not import
  an external spec, bad specs fail with actionable messages that keep the
  greppable "correctness: FAIL"/"throughput_tflops: 0.000" contract, precedence,
  and extraction consuming an external spec.
- test_bench_harness.py: all five correctness stages on CPU via BENCH_DEVICE,
  including per-edge-case dtype and input transforms, plus the spec-driven
  performance accounting.
- test_gpu_smoke.py: GPU-marked runs of built-in and external starter kernels.

Packaging and docs:
- pyproject: `dev` extra with pytest, testpaths and the `gpu` marker.
- CI: a cpu-tests job running `uv sync --extra dev` and `uv run pytest -m "not gpu"`.
- README: a custom-operation quick start covering the spec contract, locators,
  precedence, validation rules and the trust boundary.
An infinite atol or rtol makes every correctness comparison pass, which
silently disables the Week 1 correctness gate. Tolerance now rejects
non-finite values at construction time (NaN and negative values were
already rejected), and the brief's validation list records the
requirement. Also freeze the pre-existing NaN rejection with a test.
Add autokernel/verification/outputs.py: an output-tree comparator that
flattens tensors, tuples, lists, dicts (sorted-key order) and named
tuples into leaves with stable diagnostic paths, then compares leaf by
leaf with per-dtype tolerances, NaN/Inf detection per path, exact
non-tensor metadata comparison, and bitwise determinism checking.

KernelSpec gains optional OutputSpec/BackwardSpec/CompileSpec policies
(defaults preserve single-tensor behavior), and bench.py's five
correctness stages consume the comparator with console output unchanged
for single-tensor operations. Per-leaf details are collected for the
structured result artifact.

Add examples/custom_ops/affine.py, a structured-output external
operation (dict of tensor + (tensor, metadata)) that proves the
framework on CPU.
Add autokernel/verification/corpus.py: a versioned JSON shape-corpus
loader (schema_version 1) carrying metadata-only benchmark cases --
names, sizes, dtypes, weights, tags; never tensor data. Validation
rejects unknown fields, bad schema versions, duplicate names, non-
positive sizes/weights, and (against the selected spec) operation
mismatch, undeclared shape keys/dtypes, and resolved duplicate
configurations.

bench.py gains --shape-corpus PATH and --shape-corpus-only. Corpus
validation runs before the candidate module is imported whenever the
operation is explicitly selected, and always before GPU detection.
Validated cases join the stage-2 correctness sweep and are benchmarked
once each in the performance loop; weights feed per-dtype weighted
aggregate latency and speedup reporting, never loop repetition.

Add examples/custom_ops/affine_corpus.json and CPU tests for schema
validation, spec compatibility, merge/corpus-only behavior, weighted
aggregation, and CLI failure ordering.
Add autokernel/verification/backward.py: opt-in gradient verification
per the spec's BackwardSpec. One canonical input mapping is generated,
tensor inputs are deep-cloned for the reference and candidate paths
(requires_grad only on declared differentiable inputs), both forward
passes run independently, and torch.autograd.grad compares every
requested gradient against deterministic fixed-seed upstream gradients
(randn, never only output.sum()). Missing, unexpected, mismatched and
NaN/Inf gradients are reported per input; nothing accumulates between
checks.

A spec without backward_spec is forward-only: --check-backward then
fails with an actionable unsupported message instead of silently
skipping. bench.py wires --check-backward (plus the
enabled_by_default escape hatch) with a BACKWARD_CORRECTNESS verdict
line; backward execution is correctness-only and never timed.

CPU tests cover gradient parity on the affine fixture, per-input
mismatch statistics, missing/unexpected gradients, deterministic
upstreams, output_paths selection, tolerance overrides, unsupported
declarations and the bench wiring.
Establish downstream project foundation
Add an extensible kernel specification registry
Generalize kernel correctness verification
Add model optimization campaign workflow
aryan5v and others added 20 commits July 30, 2026 09:20
Introduce the shared generation workload schema that MotionKernel and FastVideo
use for baseline measurement, profiling, and end-to-end validation. Ship Wan
and LTX manifests, result classification, a resume-friendly launcher bridge,
and CPU tests. GPU execution depends on the paired FastVideo generation
launcher.
Introduce metadata-only profiling/graph-capture contracts: stable graph
fingerprints, operator hotspot ranking, graph-break records, and a pure-tensor
allowlist that fails closed on collectives and data-dependent ops. Foundation
for universal capture without model-specific annotations.
CPU-only discovery continuation: impact-floor ranking with Amdahl ceilings,
FX symbolic-trace region capture, and torch.profiler key-average parsers.
CUDA timing still requires a GPU profiling run.
Expose discovery report validation and region ranking through a real CLI entry
point used by overnight orchestration and local CPU checks.
Validate launcher resume state JSON, pass mode_env into child processes,
reject unknown A/B modes, guard zero optimized medians, reject null
wall_seconds, share validators via _validate, and drop machine-local paths
from the plan doc.
Extend discovery capture so hooked modules yield metadata-only GraphRegion
records with ops, dependencies, signatures, safe scalars, call aggregation,
graph breaks, and fail-closed rejection of mutation/collectives/custom ops.
Never serializes weights, prompts, tensor values, or source.
…egions.

This implementation adds correlation logic to match FastVideo profiler operator
rows with FX graph regions captured from Task 2, enabling offline analysis
without requiring live model execution.

Key features:
- Scope-based matching using parent_module hierarchy and operation names
- Exclusive CUDA time calculation to avoid double-counting nested scopes
- Region deduplication using stable graph fingerprints
- Aggregation of timing data, call counts, and shape frequencies
- Confidence scoring based on safety, profiler matches, and call frequency
- End-to-end impact estimation using Amdahl-style optimistic improvement
- Tracking of unmatched profiler rows and capture failures

The correlation module provides:
- correlate_profiler_to_regions(): Main correlation function
- correlate_discovery_report(): High-level report integration
- ScopeMatch dataclass for match metadata
- RegionAccumulator for aggregating equivalent regions

Acceptance criteria met:
- Synthetic CPU fixtures produce non-zero timed regions
- Repeated equivalent regions aggregate correctly by fingerprint
- Region shares use exclusive time without nested double-counting
- Unmatched profiler rows and capture failures remain visible
- All existing tests pass (433 CPU tests)

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Require explicit --trust-specs before campaign.py run loads Python
  spec locators, matching the prepare gate
- Record a terminal agent_launch_failed receipt and morning report when
  the agent process cannot be spawned
- Map non-success terminal statuses to CAMPAIGN_RUN: FAIL with a
  non-zero exit code so unattended callers can gate on the CLI

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015dGTVqeg1AohwtT6PN1nYe
- Normalize profiler op keys and region operations before strategy-2
  matching so overload-qualified rows correlate
- Return unmatched profiler rows through a separate channel instead of a
  synthetic region that cannot survive serialization
- Preserve operator namespaces in UnsupportedOpRecord op names
- Truncate capture names after the r. prefix so hook-generated names
  always satisfy the region name pattern
- Reject capture payloads that arrive without their capture version block
- Fix the correlation test tensor helper annotation and derive strides
  from shapes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015dGTVqeg1AohwtT6PN1nYe
Complete Wan overnight optimization pack
- README: record GB200 validation of all three Wan targets, describe the
  workloads/discovery CLIs, and extend the project structure tree
- CHANGELOG: add the universal workload and discovery foundation section

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015dGTVqeg1AohwtT6PN1nYe
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants