From f8343c458623da71e0a24835df12d583db1010f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zientkiewicz?= Date: Wed, 22 Apr 2026 20:55:40 +0200 Subject: [PATCH 1/8] Add schema aliases. Use aliases in rename-only deprecations. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Zientkiewicz --- dali/operators/audio/resample.cc | 14 ++-- dali/operators/decoder/image_decoder.cc | 43 ++++--------- dali/operators/decoder/inflate/inflate.cc | 5 +- .../generic/resize/tensor_resize_cpu.cc | 14 ++-- dali/operators/reader/file_reader_op.cc | 10 +-- dali/operators/reader/mxnet_reader_op.cc | 12 ++-- dali/operators/reader/numpy_reader_op.cc | 12 ++-- dali/operators/reader/sequence_reader_op.cc | 13 ++-- dali/operators/reader/tfrecord_reader_op.cc | 8 +-- .../video/decoder/video_decoder_cpu.cc | 10 +-- dali/pipeline/operator/op_schema.cc | 64 +++++++++++++++++-- dali/pipeline/operator/op_schema.h | 14 +++- dali/pipeline/operator/operator.cc | 6 +- dali/pipeline/operator/operator_factory.h | 31 +++++---- 14 files changed, 135 insertions(+), 121 deletions(-) diff --git a/dali/operators/audio/resample.cc b/dali/operators/audio/resample.cc index 86ed2b7d50b..70db9da10bc 100644 --- a/dali/operators/audio/resample.cc +++ b/dali/operators/audio/resample.cc @@ -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. @@ -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 { diff --git a/dali/operators/decoder/image_decoder.cc b/dali/operators/decoder/image_decoder.cc index 2e0fa7c8bce..f7ddcdc6c32 100644 --- a/dali/operators/decoder/image_decoder.cc +++ b/dali/operators/decoder/image_decoder.cc @@ -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 diff --git a/dali/operators/decoder/inflate/inflate.cc b/dali/operators/decoder/inflate/inflate.cc index 355f9239e10..c334ffe593c 100644 --- a/dali/operators/decoder/inflate/inflate.cc +++ b/dali/operators/decoder/inflate/inflate.cc @@ -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(); diff --git a/dali/operators/generic/resize/tensor_resize_cpu.cc b/dali/operators/generic/resize/tensor_resize_cpu.cc index 59624b2a4bf..a71569e7a03 100644 --- a/dali/operators/generic/resize/tensor_resize_cpu.cc +++ b/dali/operators/generic/resize/tensor_resize_cpu.cc @@ -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. @@ -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); diff --git a/dali/operators/reader/file_reader_op.cc b/dali/operators/reader/file_reader_op.cc index 64a3560f3c0..0d6b77223f2 100644 --- a/dali/operators/reader/file_reader_op.cc +++ b/dali/operators/reader/file_reader_op.cc @@ -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 diff --git a/dali/operators/reader/mxnet_reader_op.cc b/dali/operators/reader/mxnet_reader_op.cc index fb6e34523d4..d0bcba04405 100644 --- a/dali/operators/reader/mxnet_reader_op.cc +++ b/dali/operators/reader/mxnet_reader_op.cc @@ -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. @@ -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 diff --git a/dali/operators/reader/numpy_reader_op.cc b/dali/operators/reader/numpy_reader_op.cc index db22b98de9d..2e23572afcc 100644 --- a/dali/operators/reader/numpy_reader_op.cc +++ b/dali/operators/reader/numpy_reader_op.cc @@ -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. @@ -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 diff --git a/dali/operators/reader/sequence_reader_op.cc b/dali/operators/reader/sequence_reader_op.cc index cfcb05d2953..1910812ce8a 100644 --- a/dali/operators/reader/sequence_reader_op.cc +++ b/dali/operators/reader/sequence_reader_op.cc @@ -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. @@ -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 diff --git a/dali/operators/reader/tfrecord_reader_op.cc b/dali/operators/reader/tfrecord_reader_op.cc index fcb3e8c8d93..9ba99ffa8a7 100644 --- a/dali/operators/reader/tfrecord_reader_op.cc +++ b/dali/operators/reader/tfrecord_reader_op.cc @@ -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 diff --git a/dali/operators/video/decoder/video_decoder_cpu.cc b/dali/operators/video/decoder/video_decoder_cpu.cc index 9b376da2368..51198a9221e 100644 --- a/dali/operators/video/decoder/video_decoder_cpu.cc +++ b/dali/operators/video/decoder/video_decoder_cpu.cc @@ -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 { public: diff --git a/dali/pipeline/operator/op_schema.cc b/dali/pipeline/operator/op_schema.cc index 55db17eabdb..0df599ef31c 100644 --- a/dali/pipeline/operator/op_schema.cc +++ b/dali/pipeline/operator/op_schema.cc @@ -27,11 +27,20 @@ namespace dali { -std::map> &SchemaRegistry::registry() { +namespace { + +std::map> ®istry() { static std::map> schema_map; return schema_map; } +std::map> &aliases() { + static std::map> alias_map; + return alias_map; +} + +} // namespace + OpSchema &SchemaRegistry::RegisterSchema(std::string_view name) { auto &schema_map = registry(); @@ -46,20 +55,50 @@ 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()) { + auto &alias_map = aliases(); + auto alias_it = alias_map.find(name); + if (alias_it != alias_map.end()) + name = alias_it->second; + } + + if (it == schema_map.end()) + return nullptr; + + return &it->second; +} + +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 &actual = alias_map[std::string(alias_name)]; + if (!actual.empty()) + throw std::invalid_argument(make_string("\"", alias_name, + "\" is already used as a schema alias name for \"", actual, "\"")); + + 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; + } + actual = actual_name; } + const OpSchema &OpSchema::Default() { static OpSchema default_schema(DefaultSchemaTag{}); return default_schema; @@ -380,6 +419,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; @@ -826,6 +873,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_; diff --git a/dali/pipeline/operator/op_schema.h b/dali/pipeline/operator/op_schema.h index db2ade83ebe..d06901bd77a 100644 --- a/dali/pipeline/operator/op_schema.h +++ b/dali/pipeline/operator/op_schema.h @@ -416,6 +416,9 @@ class DLL_PUBLIC OpSchema { std::string in_favor_of = "", std::string explanation = ""); + /** Marks that this schema is actually just an alias */ + OpSchema &AliasFor(std::string_view actual_name); + /** Notes that this operator cannot be serialized */ OpSchema &Unserializable(); @@ -735,6 +738,9 @@ used with DALIDataType, to avoid confusion with `AddOptionalArg(name, doc, /** What operator replaced the current one. */ const std::string &DeprecatedInFavorOf() const; + /** Whether this schema is just an alias for another one */ + const std::string &AliasFor() const; + /** Additional deprecation message */ const std::string &DeprecationMessage() const; @@ -1011,6 +1017,7 @@ used with DALIDataType, to avoid confusion with `AddOptionalArg(name, doc, std::string deprecated_in_favor_of_; std::string deprecation_message_; std::string deprecation_version_; + std::string alias_for_; }; @@ -1020,10 +1027,9 @@ class SchemaRegistry { DLL_PUBLIC static const OpSchema &GetSchema(std::string_view name); DLL_PUBLIC static const OpSchema *TryGetSchema(std::string_view name); - private: - inline SchemaRegistry() {} + DLL_PUBLIC static void AddAlias(std::string_view alias_name, std::string_view actual_name); - DLL_PUBLIC static std::map> ®istry(); + SchemaRegistry() = delete; }; template @@ -1061,6 +1067,8 @@ inline T OpSchema::GetDefaultValueForArgument(std::string_view name) const { #define DALI_SCHEMA(OpName) DALI_SCHEMA_REG(OpName) #endif +#define DALI_SCHEMA_ALIAS(AliasName, OpName) DALI_SCHEMA(AliasName).AliasFor(#OpName) + } // namespace dali #endif // DALI_PIPELINE_OPERATOR_OP_SCHEMA_H_ diff --git a/dali/pipeline/operator/operator.cc b/dali/pipeline/operator/operator.cc index 3c68fc700c7..a11a15776cf 100644 --- a/dali/pipeline/operator/operator.cc +++ b/dali/pipeline/operator/operator.cc @@ -158,11 +158,11 @@ std::unique_ptr InstantiateOperator(const OpSpec &spec) { string device = spec.GetArgument("device"); // traverse devices by likelihood (gpu, cpu, mixed) if (device == "gpu") { - return GPUOperatorRegistry::Registry().Create(spec.SchemaName(), spec, &device); + return GPUOperatorRegistry::Registry().Create(spec.SchemaName(), spec, device); } else if (device == "cpu") { - return CPUOperatorRegistry::Registry().Create(spec.SchemaName(), spec, &device); + return CPUOperatorRegistry::Registry().Create(spec.SchemaName(), spec, device); } else if (device == "mixed") { - return MixedOperatorRegistry::Registry().Create(spec.SchemaName(), spec, &device); + return MixedOperatorRegistry::Registry().Create(spec.SchemaName(), spec, device); } else { DALI_FAIL("Unknown device: " + device); } diff --git a/dali/pipeline/operator/operator_factory.h b/dali/pipeline/operator/operator_factory.h index 8d1aa5c00c2..5a04011e93c 100644 --- a/dali/pipeline/operator/operator_factory.h +++ b/dali/pipeline/operator/operator_factory.h @@ -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. @@ -23,6 +23,7 @@ #include #include "dali/core/common.h" +#include "dali/core/string_map.h" #include "dali/core/error_handling.h" #include "dali/pipeline/operator/op_schema.h" @@ -34,25 +35,33 @@ template class OperatorRegistry { public: typedef std::function (const OpSpec &spec)> Creator; - typedef std::unordered_map CreatorRegistry; + typedef unordered_string_map CreatorRegistry; OperatorRegistry() {} - void Register(const std::string &name, Creator creator, const std::string &devName = "") { + void Register(const std::string &name, Creator creator, std::string_view devName = "") { std::lock_guard lock(mutex_); - DALI_ENFORCE(registry_.count(name) == 0, - "Operator \"" + name + "\" already registered" + - (!devName.empty() ? (" for " + devName) : "") + "."); + DALI_ENFORCE(registry_.count(name) == 0, make_string( + "Operator \"", name, "\" already registered", + (!devName.empty() ? make_string(" for ", devName) : ""), ".")); registry_[name] = creator; } std::unique_ptr Create( - const std::string &name, const OpSpec &spec, const std::string *devName = NULL) { + std::string_view name, const OpSpec &spec, std::optional devName = {}) { std::lock_guard lock(mutex_); - auto creator_it = registry_.find(name); - DALI_ENFORCE(creator_it != registry_.end(), - "Operator \"" + name + "\" not registered" + (devName? (" for " + *devName) : "") + "."); - return registry_[name](spec); + auto it = registry_.find(name); + if (it == registry_.end()) { + // Maybe we got an alias? Check the schema's actual name. + if (auto *schema = SchemaRegistry::TryGetSchema(name)) { + it = registry_.find(schema->name()); + } + } + DALI_ENFORCE(it != registry_.end(), make_string( + "Operator \"", name, "\" not registered", + (devName ? make_string(" for ", *devName) : ""), + ".")); + return it->second(spec); } vector RegisteredNames(bool internal_ops) { From 3209848b656019f702050be06f32df7a05227a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zientkiewicz?= Date: Wed, 22 Apr 2026 21:36:06 +0200 Subject: [PATCH 2/8] Fix chained alias logic. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Zientkiewicz --- dali/pipeline/operator/op_schema.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dali/pipeline/operator/op_schema.cc b/dali/pipeline/operator/op_schema.cc index 0df599ef31c..b3eddeb529c 100644 --- a/dali/pipeline/operator/op_schema.cc +++ b/dali/pipeline/operator/op_schema.cc @@ -67,8 +67,10 @@ const OpSchema *SchemaRegistry::TryGetSchema(std::string_view name) { if (it == schema_map.end()) { auto &alias_map = aliases(); auto alias_it = alias_map.find(name); - if (alias_it != alias_map.end()) + if (alias_it != alias_map.end()) { name = alias_it->second; + it = schema_map.find(name); + } } if (it == schema_map.end()) From a798cc27be1ac61f7d362936141445b24ba1891a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zientkiewicz?= Date: Wed, 22 Apr 2026 21:38:32 +0200 Subject: [PATCH 3/8] Missing file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Zientkiewicz --- include/dali/core/string_map.h | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 include/dali/core/string_map.h diff --git a/include/dali/core/string_map.h b/include/dali/core/string_map.h new file mode 100644 index 00000000000..cd973cf4606 --- /dev/null +++ b/include/dali/core/string_map.h @@ -0,0 +1,39 @@ +// Copyright (c) 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. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef DALI_CORE_STRING_MAP_H_ +#define DALI_CORE_STRING_MAP_H_ + +#include +#include +#include +#include +#include + +namespace dali { + +struct string_hash : public std::hash { + using is_transparent = void; +}; + +template +using unordered_string_map = std::unordered_map>; + +template +using string_map = std::map>; + +} // namespace dali + +#endif // DALI_CORE_STRING_MAP_H_ From faba1a2c9adeaad360667b83a080d7ce06f2c33e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zientkiewicz?= Date: Wed, 22 Apr 2026 21:48:38 +0200 Subject: [PATCH 4/8] Convert if to while in operator lookup. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Zientkiewicz --- dali/pipeline/operator/operator_factory.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dali/pipeline/operator/operator_factory.h b/dali/pipeline/operator/operator_factory.h index 5a04011e93c..5c943bf9435 100644 --- a/dali/pipeline/operator/operator_factory.h +++ b/dali/pipeline/operator/operator_factory.h @@ -51,10 +51,12 @@ class OperatorRegistry { std::string_view name, const OpSpec &spec, std::optional devName = {}) { std::lock_guard lock(mutex_); auto it = registry_.find(name); + std::string_view lookup_name = name; if (it == registry_.end()) { // Maybe we got an alias? Check the schema's actual name. - if (auto *schema = SchemaRegistry::TryGetSchema(name)) { - it = registry_.find(schema->name()); + while (auto *schema = SchemaRegistry::TryGetSchema(lookup_name)) { + lookup_name = schema->name(); + it = registry_.find(lookup_name); } } DALI_ENFORCE(it != registry_.end(), make_string( From 7575f39887e62d8c49ae8784266b145044197f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zientkiewicz?= Date: Wed, 22 Apr 2026 22:22:38 +0200 Subject: [PATCH 5/8] Fix alias handling in schema.cc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Zientkiewicz --- dali/pipeline/operator/op_schema.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dali/pipeline/operator/op_schema.cc b/dali/pipeline/operator/op_schema.cc index b3eddeb529c..c728bfc11cf 100644 --- a/dali/pipeline/operator/op_schema.cc +++ b/dali/pipeline/operator/op_schema.cc @@ -64,7 +64,7 @@ const OpSchema &SchemaRegistry::GetSchema(std::string_view name) { const OpSchema *SchemaRegistry::TryGetSchema(std::string_view name) { auto &schema_map = registry(); auto it = schema_map.find(name); - if (it == schema_map.end()) { + 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()) { From 285ca8a0563b9ff13f79fab612c9e373d95ed9b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zientkiewicz?= Date: Wed, 22 Apr 2026 22:37:53 +0200 Subject: [PATCH 6/8] Another shot at op construction from alias schema. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Zientkiewicz --- dali/pipeline/operator/operator_factory.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dali/pipeline/operator/operator_factory.h b/dali/pipeline/operator/operator_factory.h index 5c943bf9435..b0424a3a9f1 100644 --- a/dali/pipeline/operator/operator_factory.h +++ b/dali/pipeline/operator/operator_factory.h @@ -52,11 +52,13 @@ class OperatorRegistry { std::lock_guard lock(mutex_); auto it = registry_.find(name); std::string_view lookup_name = name; - if (it == registry_.end()) { + while (it == registry_.end()) { // Maybe we got an alias? Check the schema's actual name. - while (auto *schema = SchemaRegistry::TryGetSchema(lookup_name)) { + if (auto *schema = SchemaRegistry::TryGetSchema(lookup_name)) { lookup_name = schema->name(); it = registry_.find(lookup_name); + } else { + break; } } DALI_ENFORCE(it != registry_.end(), make_string( From 69be8b7a037cc16b84cd09c4473ac1e0c02ab77b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zientkiewicz?= Date: Thu, 23 Apr 2026 04:27:50 +0200 Subject: [PATCH 7/8] Fix alias lookup in operator factory. Remove side-effects of failed alias insertions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Zientkiewicz --- dali/pipeline/operator/op_schema.cc | 8 ++++---- dali/pipeline/operator/operator_factory.h | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dali/pipeline/operator/op_schema.cc b/dali/pipeline/operator/op_schema.cc index c728bfc11cf..8a87a669a90 100644 --- a/dali/pipeline/operator/op_schema.cc +++ b/dali/pipeline/operator/op_schema.cc @@ -84,10 +84,10 @@ void SchemaRegistry::AddAlias(std::string_view alias_name, std::string_view actu throw std::invalid_argument("Schema name self-aliasing is forbidden"); auto &alias_map = aliases(); - auto &actual = alias_map[std::string(alias_name)]; - if (!actual.empty()) + 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 \"", actual, "\"")); + "\" is already used as a schema alias name for \"", previous_target_it->second, "\"")); for (;;) { auto redir = alias_map.find(actual_name); @@ -97,7 +97,7 @@ void SchemaRegistry::AddAlias(std::string_view alias_name, std::string_view actu throw std::invalid_argument("Cycle detected while adding schema alias."); actual_name = redir->second; } - actual = actual_name; + alias_map[std::string(alias_name)] = actual_name; } diff --git a/dali/pipeline/operator/operator_factory.h b/dali/pipeline/operator/operator_factory.h index b0424a3a9f1..549181a2265 100644 --- a/dali/pipeline/operator/operator_factory.h +++ b/dali/pipeline/operator/operator_factory.h @@ -55,7 +55,10 @@ class OperatorRegistry { while (it == registry_.end()) { // Maybe we got an alias? Check the schema's actual name. if (auto *schema = SchemaRegistry::TryGetSchema(lookup_name)) { - lookup_name = schema->name(); + std::string_view new_name = schema->name(); + if (new_name == lookup_name) + break; // no alias found + lookup_name = new_name; it = registry_.find(lookup_name); } else { break; From 8fb4cd3bbc7e328560e88c3b6d92a7c774cddf93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zientkiewicz?= Date: Thu, 23 Apr 2026 04:44:36 +0200 Subject: [PATCH 8/8] Add missing include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Zientkiewicz --- dali/pipeline/operator/operator_factory.h | 1 + 1 file changed, 1 insertion(+) diff --git a/dali/pipeline/operator/operator_factory.h b/dali/pipeline/operator/operator_factory.h index 549181a2265..5ad72dfac40 100644 --- a/dali/pipeline/operator/operator_factory.h +++ b/dali/pipeline/operator/operator_factory.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include