Skip to content

Allow passing tensor arguments in reader constructors#6252

Merged
rostan-t merged 24 commits into
NVIDIA:mainfrom
rostan-t:ndd-reader-tensor-args
Apr 16, 2026
Merged

Allow passing tensor arguments in reader constructors#6252
rostan-t merged 24 commits into
NVIDIA:mainfrom
rostan-t:ndd-reader-tensor-args

Conversation

@rostan-t
Copy link
Copy Markdown
Collaborator

Category:

New feature (non-breaking change which adds functionality)

Description:

Currently, it is necessary to invoke readers in order to pass tensor arguments. The recommended way to use readers is with next_epoch and the __call__ API is not even documented.

This PR allows constructing readers with tensor arguments.

Additional information:

Affected modules and functionalities:

Dynamic mode.

Key points relevant for the review:

Tests:

  • Existing tests apply
  • New tests added
    • Python tests
    • GTests
    • Benchmark
    • Other
  • N/A

Checklist

Documentation

  • Existing documentation applies
  • Documentation updated
    • Docstring
    • Doxygen
    • RST
    • Jupyter
    • Other
  • N/A

DALI team only

Requirements

  • Implements new requirements
  • Affects existing requirements
  • N/A

REQ IDs: N/A

JIRA TASK: DALI-4600

@review-notebook-app
Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 11, 2026

Greptile Summary

This PR allows tensor arguments (numpy arrays, PyTorch tensors, ndd.Tensor) to be passed directly in reader constructors (e.g., resize_x=ndd.tensor(108)), in addition to scalars. Non-scalar tensor args are extracted from the constructor kwargs, converted to Tensor objects via to_tensor, stored in _raw_tensor_args, and broadcast to Batch objects of the appropriate size at iteration time via the new _process_tensor_args helper. The __call__ path merges stored tensor args into raw_kwargs before processing. Previous issues from review threads have been addressed — notably the .value() typo, caller_depth override, _raw_tensor_args vs _tensor_args field confusion, and moving the Batch guard to the constructor.

Confidence Score: 4/5

  • PR is safe to merge; the core feature works correctly and all previously flagged critical issues have been resolved. One niche interaction between get_metadata(None) and batched next_epoch may produce a confusing internal error when tensor constructor args are present.
  • All P0/P1 issues from prior review threads have been addressed (.values() typo, _raw_tensor_args field, Batch guard placement, caller_depth revert). The remaining finding is P2: the get_metadata(None) → batched iteration path is an undocumented internal scenario that the PyTorch caller already avoids. No correctness issue exists on the documented user-facing paths.
  • _ops.py (Reader._process_tensor_args / get_metadata interaction) and _op_builder.py (constructor tensor-arg extraction logic) are the most impactful changed files.

Important Files Changed

Filename Overview
dali/python/nvidia/dali/experimental/dynamic/_ops.py Core reader changes: adds _raw_tensor_args/_tensor_args/_previous_batch_size fields, new _process_tensor_args and _get_batch_size helpers, updates _samples/_batches to pass tensor args, makes get_metadata accept optional batch_size. Logic is sound but get_metadata(None) before next_epoch(batch_size=X) can hit a _check_compatible mismatch (Tensor vs Batch metadata) when tensor constructor args are present.
dali/python/nvidia/dali/experimental/dynamic/_op_builder.py Constructor generation updated to separate scalar vs tensor args for readers; tensor args are extracted, converted via to_tensor, and stored in _raw_tensor_args after base __init__. __call__ guard correctly prevents duplicate tensor args. actual_tensor_arg_names computed before mutations. Looks correct.
dali/python/nvidia/dali/experimental/dynamic/_invocation.py Minor cleanup: changed caller_depth default from None to 4 (with comment that a proper fix comes in PR #6262), updated import to _ops, and simplified the conditional to a ternary. Correct and clean.
dali/python/nvidia/dali/experimental/dynamic/pytorch/nodes.py Updated get_metadata() call to pass self._batch_size, ensuring backend is initialized with Batch (not Tensor) metadata. Also fixed _stream keyword argument. Both changes are correct.
dali/python/nvidia/dali/ops/_signatures.py Type stub generation updated: __init__ now uses allow_data_node_kwargs=False, allow_batch_kwargs=False instead of include_inputs/include_kwarg_inputs=False, and the __call__ overload gains input_annotation_gen=lambda _: _TensorLike. Parameters match the existing _call_signature signature.
dali/test/python/experimental_mode/test_reader_decoder.py Three new tests: tensor args with and without batch_size, partial (scalar-only) constructor args with __call__, and duplicate-arg rejection. Covers the main paths well. Previously flagged shape assertion in test_video_resize_tensor_args_partial appears resolved (uses resize_x=144 scalar, asserts width=144).
dali/test/python/type_annotations/test_typing_dynamic.py Adds test_numpy_reader_roi to verify ROI args work in a reader constructor. Clean, straightforward test.
docs/examples/general/data_loading/numpy_reader/dynamic_mode.ipynb Updated notebook to use next_epoch() iterator API instead of the old reader() direct call, and added ROI constructor-arg example. Documentation improvements only.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Reader.__init__(resize_x=tensor, resize_y=108)"] --> B{is tensor arg?}
    B -- "non-scalar\n(Tensor/ndarray/etc)" --> C["to_tensor(arg, dtype)\n→ _raw_tensor_args"]
    B -- "scalar\n(int/float/str…)" --> D["stays in kwargs\n→ _init_args / OpSpec"]
    B -- "Batch" --> E["raise ValueError"]
    C --> F["super().__init__(**kwargs)\nReader.__init__ sets _raw_tensor_args={}…"]
    D --> F
    F --> G["_tensor_arg_names = actual_tensor_arg_names\n_raw_tensor_args = tensor_args"]

    G --> H{API path}
    H -- "__call__()" --> I["merge _raw_tensor_args\ninto raw_kwargs\n→ _process_params → Invocation"]
    H -- "next_epoch(batch_size=None)" --> J["_samples()\n_process_tensor_args(1)\n→ Batch.broadcast(Tensor, 1)"]
    H -- "next_epoch(batch_size=N)" --> K["_batches(N)\n_process_tensor_args(N)\n→ Batch.broadcast(Tensor, N)"]
    H -- "get_metadata(batch_size)" --> L["_process_tensor_args(batch_size)\n→ _init_backend(…, tensor_args)"]

    J --> M["super()._run(ctx, **tensor_args)\nAddArgumentInput per tensor arg"]
    K --> M
    I --> M
Loading

Fix All in Claude Code

Reviews (18): Last reviewed commit: "Make batch_size optional in get_metadata..." | Re-trigger Greptile

Comment thread dali/python/nvidia/dali/experimental/dynamic/_op_builder.py Outdated
Comment thread dali/python/nvidia/dali/experimental/dynamic/_invocation.py Outdated
@rostan-t rostan-t force-pushed the ndd-reader-tensor-args branch 2 times, most recently from ed9a066 to c498545 Compare March 11, 2026 11:08
@rostan-t
Copy link
Copy Markdown
Collaborator Author

!build

Comment thread dali/python/nvidia/dali/experimental/dynamic/_op_builder.py Outdated
Comment thread dali/python/nvidia/dali/experimental/dynamic/_ops.py
@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [45875629]: BUILD STARTED

Comment thread dali/python/nvidia/dali/experimental/dynamic/_ops.py Outdated
Comment thread dali/test/python/experimental_mode/test_reader_decoder.py
Comment thread dali/python/nvidia/dali/experimental/dynamic/_ops.py
Comment thread dali/python/nvidia/dali/experimental/dynamic/_ops.py Outdated
@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [45875629]: BUILD FAILED

Comment thread dali/python/nvidia/dali/experimental/dynamic/_invocation.py Outdated
Comment thread dali/python/nvidia/dali/experimental/dynamic/_op_builder.py Outdated
Comment thread dali/python/nvidia/dali/experimental/dynamic/_ops.py Outdated
Copy link
Copy Markdown
Contributor

@mzient mzient left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To change:

  • make a copy tensor arguments
  • do not promote non-tensor arguments to tensors
  • simplify caller_depth logic

Comment thread dali/python/nvidia/dali/experimental/dynamic/_ops.py
@rostan-t rostan-t force-pushed the ndd-reader-tensor-args branch from 51fb904 to f283da0 Compare March 13, 2026 17:00
Comment thread dali/python/nvidia/dali/experimental/dynamic/_op_builder.py Dismissed
Comment thread dali/python/nvidia/dali/experimental/dynamic/_op_builder.py Outdated
@rostan-t
Copy link
Copy Markdown
Collaborator Author

the init stub change must be scoped to reader operators only

@greptileai This is not necessary. Readers are now the only operators publicly exposed as classes.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 16, 2026

That makes sense - if readers are the only operators exposed as classes, then the change is already naturally scoped correctly. Thanks for the clarification!

@rostan-t
Copy link
Copy Markdown
Collaborator Author

!build

@rostan-t rostan-t requested a review from mzient March 16, 2026 10:11
@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [46240320]: BUILD STARTED

@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [46240320]: BUILD PASSED

Comment thread dali/python/nvidia/dali/experimental/dynamic/_op_builder.py Outdated
Comment thread dali/python/nvidia/dali/experimental/dynamic/_ops.py Outdated
rostan-t added 10 commits March 19, 2026 12:40
…al tensors

Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
… _process_tensor_args

Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
PR NVIDIA#6262 fixes the caller depth properly.

Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
@rostan-t rostan-t force-pushed the ndd-reader-tensor-args branch from da6080c to 0a640ea Compare March 19, 2026 13:33
Comment thread dali/python/nvidia/dali/experimental/dynamic/_invocation.py Dismissed
@rostan-t
Copy link
Copy Markdown
Collaborator Author

!build

@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [46597957]: BUILD STARTED

@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [46597957]: BUILD PASSED

Comment thread dali/test/python/experimental_mode/test_reader_decoder.py Outdated
Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
@rostan-t
Copy link
Copy Markdown
Collaborator Author

!build

@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [48420838]: BUILD STARTED

@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [48420838]: BUILD FAILED

…batch_size if None

Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
@rostan-t rostan-t force-pushed the ndd-reader-tensor-args branch from 54ac4db to 0b312d3 Compare April 14, 2026 08:44
@rostan-t
Copy link
Copy Markdown
Collaborator Author

!build

@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [48484543]: BUILD STARTED

@dali-automaton
Copy link
Copy Markdown
Collaborator

CI MESSAGE: [48484543]: BUILD PASSED

@rostan-t rostan-t merged commit b21472e into NVIDIA:main Apr 16, 2026
7 checks passed
@rostan-t rostan-t deleted the ndd-reader-tensor-args branch April 16, 2026 08:19
stiepan pushed a commit that referenced this pull request Apr 16, 2026
* Support constructing readers with tensor args
* Detect when default values are passed when invoking a reader
* Add tests passing tensor arguments
* Disallow constructing a reader with batch kwargs
* Update signature of reader constructors to allow tensor arguments
* Update NumpyReader example to pass ROI in the reader constructor
* Prevent processing again tensor args when not necessary in batch processing
* Cache processed tensor args passed in the constructor
* Fix caller_depth handling. Remove special case for readers
* Pass scalar arguments directly to reader constructors and copy external tensors
* Properly use reader tensor args in TorchData integration
* Copy all tensors passed to constructors and perform only broadcast in _process_tensor_args
* Perform dtype conversion of reader constructor arguments
---------

Signed-off-by: Rostan Tabet <rtabet@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants