Skip to content

Forward PreRun/PostRun to all operands in composing operators#1200

Merged
cliffburdick merged 1 commit into
mainfrom
tbenson/fix-operators-missing-prerun-forwarding
Jun 5, 2026
Merged

Forward PreRun/PostRun to all operands in composing operators#1200
cliffburdick merged 1 commit into
mainfrom
tbenson/fix-operators-missing-prerun-forwarding

Conversation

@tbensonatl
Copy link
Copy Markdown
Collaborator

Several operators that accept operator-valued operands forwarded PreRun() and PostRun() to only a subset of their operands. The dropped operands were still read lazily in the operator's kernel.

When a dropped operand is a transform-style operator that allocates and fills temporary storage during PreRun, that temporary was never allocated or computed, so the consuming operator read uninitialized memory.

Operators fixed (each now forwards both PreRun and PostRun to the previously-dropped operand, guarded by is_matx_op<>()):

  • polyval : coefficient operand
  • interp1 : sample points, sample values, and query points (the default LINEAR method's PreRun was otherwise a no-op)
  • remap : index operand
  • shift : shift-amount operand
  • sar_bp : voxel_locations and range_to_mcp

Each fix adds a self-contained regression test that composes the operator with a new prerun_tester operator that validates PreRun forwarding of the parent operator.

Several operators that accept operator-valued operands forwarded PreRun()
and PostRun() to only a subset of their operands. The dropped operands were
still read lazily in the operator's kernel.

When a dropped operand is a transform-style operator that allocates and fills
temporary storage during PreRun, that temporary was never allocated or computed,
so the consuming operator read uninitialized memory.

Operators fixed (each now forwards both PreRun and PostRun to the
previously-dropped operand, guarded by is_matx_op<>()):

  - polyval : coefficient operand
  - interp1 : sample points, sample values, and query points (the default
              LINEAR method's PreRun was otherwise a no-op)
  - remap   : index operand
  - shift   : shift-amount operand
  - sar_bp  : voxel_locations and range_to_mcp

Each fix adds a self-contained regression test that composes the operator with
a new prerun_tester operator that validates PreRun forwarding of the parent
operator.

Signed-off-by: Thomas Benson <tbenson@nvidia.com>
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented Jun 4, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 4, 2026

Greptile Summary

Several composing operators (polyval, interp1, remap, shift, sar_bp) were not forwarding PreRun/PostRun to all their operands, causing uninitialized memory reads when a dropped operand was a transform-style operator that allocates temporary storage during PreRun. This PR adds the missing forwarding calls (guarded by is_matx_op<>()) and updates combine_capabilities / get_capability to reflect the newly tracked operands.

  • Each fixed operator now calls PreRun/PostRun on every operator-valued operand before and after its own resource lifecycle, matching the pattern already used for the previously forwarded operands.
  • A new PreRunTesterOp test utility (transparent pass-through with lifecycle counters) is introduced to verify forwarding contracts, and each fixed operator gets a self-contained regression test exercising the new paths.

Confidence Score: 5/5

Safe to merge. All five operators now correctly forward PreRun/PostRun to every operator-valued operand, eliminating the uninitialized-memory reads described in the PR. The capability bookkeeping is updated consistently.

The fix is surgical and follows the well-established forwarding pattern already used for the previously forwarded operands in each operator. The new PreRunTesterOp infrastructure cleanly validates the forwarding contract without coupling to operator internals. The sar_bp two-level PreRun design (InnerPreRun → PreRun) is preserved correctly. No regressions are expected.

The interp1 regression test only exercises the CUDA executor path — a pre-existing static_assert in interp.h triggers for non-CUDA executors even when the LINEAR method is selected, so the LINEAR fix on host executors is not directly covered by the new test.

Important Files Changed

Filename Overview
include/matx/operators/interp.h Adds PreRun/PostRun forwarding for x_, v_, and xq_ operands before SPLINE allocation. Correct ordering. All three uses of std::forward(shape) and std::forward(ex) in sequence follow pre-existing codebase pattern.
include/matx/operators/polyval.h Adds PreRun/PostRun forwarding for coeffs_ operand and includes coeffs_ in SUPPORTS_JIT combine_capabilities. Straightforward and correct.
include/matx/operators/remap.h Adds PreRun/PostRun forwarding for idx_ operand and includes idx_ in SUPPORTS_JIT combine_capabilities. Correct fix.
include/matx/operators/sar_bp.h Adds voxel_locations_ and range_to_mcp_ to InnerPreRun forwarding and PostRun forwarding; also adds voxel_locations_ to get_capability. Clean two-level PreRun design preserved.
include/matx/operators/shift.h Adds shift_ to SUPPORTS_JIT combine_capabilities (shift_ was already handled in all other Cap branches) and adds PreRun/PostRun forwarding to shift_. Correct and consistent.
test/include/prerun_tester.h New test-only lifecycle probe operator. Well-designed: transparent element access, raw pointer for device-copy safety, separate PreRun/PostRun counters to detect both missing and duplicated forwarding.
test/00_operators/interp_test.cu New InterpOperatorInput test validates lifecycle forwarding for all three interp1 operands. CUDA-only due to pre-existing static_assert in interp.h that fires even for LINEAR on non-CUDA executors.

Sequence Diagram

sequenceDiagram
    participant R as run()
    participant C as ComposingOp
    participant A as Operand A (previously forwarded)
    participant B as Operand B (newly forwarded)

    R->>C: PreRun(shape, ex)
    C->>A: "is_matx_op<A>? PreRun(shape, ex)"
    Note over A: allocates/fills temp storage
    C->>B: "is_matx_op<B>? PreRun(shape, ex) NEW"
    Note over B: allocates/fills temp storage (was skipped before fix)
    C->>C: own allocations
    R->>C: Exec(shape, ex)
    C->>A: operator()(indices)
    C->>B: operator()(indices) reads valid temp storage now
    R->>C: PostRun(shape, ex)
    C->>A: "is_matx_op<A>? PostRun(shape, ex)"
    C->>B: "is_matx_op<B>? PostRun(shape, ex) NEW"
    C->>C: matxFree own allocations
Loading

Reviews (1): Last reviewed commit: "Forward PreRun/PostRun to all operands i..." | Re-trigger Greptile

@tbensonatl tbensonatl requested a review from cliffburdick June 4, 2026 20:54
@tbensonatl
Copy link
Copy Markdown
Collaborator Author

/build

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage is 93.581%tbenson/fix-operators-missing-prerun-forwarding into main. No base build found for main.

@cliffburdick cliffburdick merged commit a2b6780 into main Jun 5, 2026
1 check passed
@cliffburdick cliffburdick deleted the tbenson/fix-operators-missing-prerun-forwarding branch June 5, 2026 16:41
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.

3 participants