Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions dali/operators/audio/resample.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -97,18 +97,14 @@ type. Example::
nullptr, false);

// Deprecated alias
DALI_SCHEMA(experimental__AudioResample)
.AddParent("AudioResample")
.DocStr("Legacy alias for :meth:`audio_resample`.")
.NumInput(1)
.NumOutput(1)
.MakeDocHidden()
DALI_SCHEMA_ALIAS(experimental__AudioResample, AudioResample)
.Deprecate(
"1.18",
"AudioResample",
"This operator was moved out from the experimental phase, "
"and is now a regular DALI operator. This is just an deprecated "
"alias kept for backward compatibility.");
"and is now a regular DALI operator. This is just a deprecated "
"alias kept for backward compatibility.")
.MakeDocHidden();

namespace audio {

Expand Down
43 changes: 13 additions & 30 deletions dali/operators/decoder/image_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -317,59 +317,42 @@ interpreted as absolute or relative coordinates, depending on the value of

// Deprecated aliases

DALI_SCHEMA(ImageDecoder)
.DocStr("Legacy alias for :meth:`decoders.image`.")
.NumInput(1)
.NumOutput(1)
.AddParent("decoders__Image")
.MakeDocHidden()
DALI_SCHEMA_ALIAS(ImageDecoder, decoders__Image)
.Deprecate(
"1.0",
"decoders__Image",
R"code(In DALI 1.0 all decoders were moved into a dedicated :mod:`~nvidia.dali.fn.decoders`
submodule and renamed to follow a common pattern. This is a placeholder operator with identical
functionality to allow for backward compatibility.)code");
functionality to allow for backward compatibility.)code")
.MakeDocHidden();

// Fused

DALI_SCHEMA(ImageDecoderCrop)
.DocStr("Legacy alias for :meth:`decoders.image_crop`.")
.NumInput(1)
.NumOutput(1)
.AddParent("decoders__ImageCrop")
.MakeDocHidden()
DALI_SCHEMA_ALIAS(ImageDecoderCrop, decoders__ImageCrop)
.Deprecate(
"1.0",
"decoders__ImageCrop",
R"code(In DALI 1.0 all decoders were moved into a dedicated :mod:`~nvidia.dali.fn.decoders`
submodule and renamed to follow a common pattern. This is a placeholder operator with identical
functionality to allow for backward compatibility.)code");

DALI_SCHEMA(ImageDecoderRandomCrop)
.DocStr("Legacy alias for :meth:`decoders.image_random_crop`.")
.NumInput(1)
.NumOutput(1)
.AddParent("decoders__ImageRandomCrop")
.MakeDocHidden()
functionality to allow for backward compatibility.)code")
.MakeDocHidden();

DALI_SCHEMA_ALIAS(ImageDecoderRandomCrop, decoders__ImageRandomCrop)
.Deprecate(
"1.0",
"decoders__ImageRandomCrop",
R"code(In DALI 1.0 all decoders were moved into a dedicated :mod:`~nvidia.dali.fn.decoders`
submodule and renamed to follow a common pattern. This is a placeholder operator with identical
functionality to allow for backward compatibility.)code");

functionality to allow for backward compatibility.)code")
.MakeDocHidden();

DALI_SCHEMA(ImageDecoderSlice)
.DocStr("Legacy alias for :meth:`decoders.image_slice`.")
.NumInput(1, 3)
.NumOutput(1)
.AddParent("decoders__ImageSlice")
.MakeDocHidden()
DALI_SCHEMA_ALIAS(ImageDecoderSlice, decoders__ImageSlice)
.Deprecate(
"1.0",
"decoders__ImageSlice",
R"code(In DALI 1.0 all decoders were moved into a dedicated :mod:`~nvidia.dali.fn.decoders`
submodule and renamed to follow a common pattern. This is a placeholder operator with identical
functionality to allow for backward compatibility.)code");
functionality to allow for backward compatibility.)code")
.MakeDocHidden();

} // namespace dali
5 changes: 1 addition & 4 deletions dali/operators/decoder/inflate/inflate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,7 @@ The value is ignored if the `layout` is not specified or the input is not a sequ
.OutputLayout(0, std::nullopt)
.OutputNDim(0, std::nullopt);

DALI_SCHEMA(experimental__Inflate)
.AddParent("decoders__Inflate")
.NumInput(1)
.NumOutput(1)
DALI_SCHEMA_ALIAS(experimental__Inflate, decoders__Inflate)
.Deprecate("2.0", "decoders__Inflate")
.MakeDocHidden();

Expand Down
14 changes: 4 additions & 10 deletions dali/operators/generic/resize/tensor_resize_cpu.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -46,20 +46,14 @@ DALI_SCHEMA(TensorResize)
.AddParent("TensorResizeAttr");

// Deprecated alias
DALI_SCHEMA(experimental__TensorResize)
.AddParent("TensorResize")
.DocStr("Legacy alias for :meth:`tensor_resize`.")
.NumInput(1)
.NumOutput(1)
.MakeDocHidden()
.SupportVolumetric()
.AllowSequences()
DALI_SCHEMA_ALIAS(experimental__TensorResize, TensorResize)
.Deprecate(
"2.0",
"TensorResize",
"This operator was moved out from the experimental phase, "
"and is now a regular DALI operator. This is just a deprecated "
"alias kept for backward compatibility.");
"alias kept for backward compatibility.")
.MakeDocHidden();

// Kept for backwards compatibility
DALI_REGISTER_OPERATOR(experimental__TensorResize, tensor_resize::TensorResizeCPU, CPU);
Expand Down
10 changes: 3 additions & 7 deletions dali/operators/reader/file_reader_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,17 +146,13 @@ case-sensitively, otherwise case-insensitively.)", false)
// Deprecated alias
DALI_REGISTER_OPERATOR(FileReader, FileReader, CPU);

DALI_SCHEMA(FileReader)
.DocStr("Legacy alias for :meth:`readers.file`.")
.NumInput(0)
.NumOutput(2) // (Images, Labels)
.AddParent("readers__File")
.MakeDocHidden()
DALI_SCHEMA_ALIAS(FileReader, readers__File)
.Deprecate(
"1.0",
"readers__File",
R"code(In DALI 1.0 all readers were moved into a dedicated :mod:`~nvidia.dali.fn.readers`
submodule and renamed to follow a common pattern. This is a placeholder operator with identical
functionality to allow for backward compatibility.)code");
functionality to allow for backward compatibility.)code")
.MakeDocHidden();

} // namespace dali
12 changes: 4 additions & 8 deletions dali/operators/reader/mxnet_reader_op.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2017-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2017-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -64,17 +64,13 @@ properties.
// Deprecated alias
DALI_REGISTER_OPERATOR(MXNetReader, MXNetReader, CPU);

DALI_SCHEMA(MXNetReader)
.DocStr("Legacy alias for :meth:`readers.mxnet`.")
.NumInput(0)
.NumOutput(2)
.AddParent("readers__MXNet")
.MakeDocHidden()
DALI_SCHEMA_ALIAS(MXNetReader, readers__MXNet)
.Deprecate(
"1.0",
"readers__MXNet",
R"code(In DALI 1.0 all readers were moved into a dedicated :mod:`~nvidia.dali.fn.readers`
submodule and renamed to follow a common pattern. This is a placeholder operator with identical
functionality to allow for backward compatibility.)code");
functionality to allow for backward compatibility.)code")
.MakeDocHidden();

} // namespace dali
12 changes: 4 additions & 8 deletions dali/operators/reader/numpy_reader_op.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -238,18 +238,14 @@ Mutually exclusive with ``dont_use_mmap=False``.)code",
// Deprecated alias
DALI_REGISTER_OPERATOR(NumpyReader, NumpyReaderCPU, CPU);

DALI_SCHEMA(NumpyReader)
.DocStr("Legacy alias for :meth:`readers.numpy`.")
.NumInput(0)
.NumOutput(1) // (Arrays)
.AddParent("readers__Numpy")
.MakeDocHidden()
DALI_SCHEMA_ALIAS(NumpyReader, readers__Numpy)
.Deprecate(
"1.0",
"readers__Numpy",
R"code(In DALI 1.0 all readers were moved into a dedicated :mod:`~nvidia.dali.fn.readers`
submodule and renamed to follow a common pattern. This is a placeholder operator with identical
functionality to allow for backward compatibility.)code");
functionality to allow for backward compatibility.)code")
.MakeDocHidden();

NumpyReaderCPU::~NumpyReaderCPU() {
// Stop the prefetch thread as it uses the thread pool from this class. So before we can
Expand Down
13 changes: 4 additions & 9 deletions dali/operators/reader/sequence_reader_op.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2018-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2018-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -90,18 +90,13 @@ For reading video sequences, one of :meth:`nvidia.dali.fn.readers.video`,
// Deprecated alias
DALI_REGISTER_OPERATOR(SequenceReader, SequenceReader, CPU);

DALI_SCHEMA(SequenceReader)
.DocStr("Legacy alias for :meth:`readers.sequence`.")
.NumInput(0)
.NumOutput(1) // ([Frames])
.AllowSequences()
.AddParent("readers__Sequence")
.MakeDocHidden()
DALI_SCHEMA_ALIAS(SequenceReader, readers__Sequence)
.Deprecate(
"1.0",
"readers__Sequence",
R"code(In DALI 1.0 all readers were moved into a dedicated :mod:`~nvidia.dali.fn.readers`
submodule and renamed to follow a common pattern. This is a placeholder operator with identical
functionality to allow for backward compatibility.)code");
functionality to allow for backward compatibility.)code")
.MakeDocHidden();

} // namespace dali
8 changes: 3 additions & 5 deletions dali/operators/reader/tfrecord_reader_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,14 @@ functionality to allow for backward compatibility.)code");


// Deprecated alias
DALI_SCHEMA(TFRecordReader)
.DocStr("Legacy alias for :meth:`readers.tfrecord`.")
.AddParent("readers__TFRecord")
.MakeDocHidden()
DALI_SCHEMA_ALIAS(TFRecordReader, readers__TFRecord)
.Deprecate(
"1.0",
"readers__TFRecord",
R"code(In DALI 1.0 all readers were moved into a dedicated :mod:`~nvidia.dali.fn.readers`
submodule and renamed to follow a common pattern. This is a placeholder operator with identical
functionality to allow for backward compatibility.)code");
functionality to allow for backward compatibility.)code")
.MakeDocHidden();

void TFRecordReader::Prefetch() {
// We actually prepare the next batch
Expand Down
10 changes: 3 additions & 7 deletions dali/operators/video/decoder/video_decoder_cpu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,14 @@ apart or starting playback from a frame deep into the video.)code",
.OutputDType(0, DALI_UINT8)
.OutputLayout(0, "FHWC");

DALI_SCHEMA(experimental__decoders__Video)
.AddParent("decoders__Video")
.DocStr("Legacy alias for :meth:`decoders.video`.")
.NumInput(1)
.NumOutput(1)
.MakeDocHidden()
DALI_SCHEMA_ALIAS(experimental__decoders__Video, decoders__Video)
.Deprecate(
"2.0",
"decoders__Video",
"This operator was moved out from the experimental phase, "
"and is now a regular DALI operator. This is just a deprecated "
"alias kept for backward compatibility.");
"alias kept for backward compatibility.")
.MakeDocHidden();

class VideoDecoderCpu : public VideoDecoderBase<CPUBackend, FramesDecoderCpu> {
public:
Expand Down
66 changes: 59 additions & 7 deletions dali/pipeline/operator/op_schema.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,20 @@

namespace dali {

std::map<string, OpSchema, std::less<>> &SchemaRegistry::registry() {
namespace {

std::map<string, OpSchema, std::less<>> &registry() {
static std::map<string, OpSchema, std::less<>> schema_map;
return schema_map;
}

std::map<string, string, std::less<>> &aliases() {
static std::map<string, string, std::less<>> alias_map;
return alias_map;
}

} // namespace

OpSchema &SchemaRegistry::RegisterSchema(std::string_view name) {
auto &schema_map = registry();

Expand All @@ -46,20 +55,52 @@ OpSchema &SchemaRegistry::RegisterSchema(std::string_view name) {
}

const OpSchema &SchemaRegistry::GetSchema(std::string_view name) {
auto &schema_map = registry();
auto it = schema_map.find(name);
if (it == schema_map.end())
if (auto *schema = TryGetSchema(name))
return *schema;
else
throw invalid_key("Schema for operator '" + std::string(name) + "' not registered");

return it->second;
}

const OpSchema *SchemaRegistry::TryGetSchema(std::string_view name) {
auto &schema_map = registry();
auto it = schema_map.find(name);
return it != schema_map.end() ? &it->second : nullptr;
if (it == schema_map.end() || !it->second.AliasFor().empty()) {
auto &alias_map = aliases();
auto alias_it = alias_map.find(name);
if (alias_it != alias_map.end()) {
name = alias_it->second;
it = schema_map.find(name);
}
}

if (it == schema_map.end())
return nullptr;

return &it->second;
Comment thread
mzient marked this conversation as resolved.
}
Comment thread
mzient marked this conversation as resolved.

void SchemaRegistry::AddAlias(std::string_view alias_name, std::string_view actual_name) {
if (alias_name == actual_name)
throw std::invalid_argument("Schema name self-aliasing is forbidden");

auto &alias_map = aliases();
auto previous_target_it = alias_map.find(alias_name);
if (previous_target_it != alias_map.end())
throw std::invalid_argument(make_string("\"", alias_name,
"\" is already used as a schema alias name for \"", previous_target_it->second, "\""));

for (;;) {
auto redir = alias_map.find(actual_name);
if (redir == alias_map.end())
break;
if (redir->second == alias_name)
throw std::invalid_argument("Cycle detected while adding schema alias.");
actual_name = redir->second;
}
Comment on lines +92 to +99

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Alias path-compression only works for aliases added after their targets

The for (;;) chain-following loop in AddAlias flattens chains at insertion time: AddAlias(A, B) when B → C already exists stores A → C directly. However, if A → B is registered before B → C, then A stays pointing to B and is never updated when B is later aliased. With TryGetSchema fixed to re-look up via schema_map.find(alias_it->second), an alias-to-alias chain would result in nullptr for the intermediate name if that intermediate is itself only an alias (not a real schema entry).

This is not a problem today because DALI_SCHEMA_ALIAS is always used to point to a real schema (not to another alias), but it is worth documenting or asserting that actual_name must be a real schema name, not itself an alias.

@mzient mzient Apr 22, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@greptileai Path compression might fail - but will cycle detection still work?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, cycle detection still works correctly regardless of insertion order.

The loop traverses alias_map directly at each step using the current state of the map, so it always follows the full chain:

Consider the failure case for path compression:

  1. AddAlias(A, B) — stored as A → B (B→C doesn't exist yet)
  2. AddAlias(B, C) — stored as B → C
  3. AddAlias(C, A) — cycle attempt

In step 3, the loop does:

  • find(A)A → B, so actual_name = B; check B == C? No
  • find(B)B → C, so actual_name = C; check C == C? Yes → throws

The loop doesn't rely on pre-compressed paths — it re-walks alias_map live each time. So even when path compression is incomplete (due to out-of-order registration), the cycle check is exhaustive and correct.

The only real outstanding issue is that TryGetSchema doesn't re-look up it in schema_map after updating name. That's a separate bug from cycle detection.

alias_map[std::string(alias_name)] = actual_name;
}


const OpSchema &OpSchema::Default() {
static OpSchema default_schema(DefaultSchemaTag{});
return default_schema;
Expand Down Expand Up @@ -380,6 +421,14 @@ OpSchema &OpSchema::Deprecate(std::string version, std::string in_favor_of,
return *this;
}

OpSchema &OpSchema::AliasFor(std::string_view actual_name) {
DALI_ENFORCE(alias_for_.empty(), make_string(
"The schema \"", name_, "\" is already an alias for \"", alias_for_, "\""));

alias_for_ = actual_name;
SchemaRegistry::AddAlias(name_, actual_name);
return *this;
}

OpSchema &OpSchema::Unserializable() {
serializable_ = false;
Expand Down Expand Up @@ -826,6 +875,9 @@ const std::string &OpSchema::DeprecatedInFavorOf() const {
return deprecated_in_favor_of_;
}

const std::string &OpSchema::AliasFor() const {
return alias_for_;
}

const std::string &OpSchema::DeprecationMessage() const {
return deprecation_message_;
Expand Down
Loading
Loading