diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index f08df584ba..12245aeb51 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -1106,6 +1106,14 @@ class Graph { // Graph value_info. std::vector value_info_; + // Strings which have been used as node names. + // New node name should not conflict with this set. + std::unordered_set generated_node_names_; + + // Strings which have been used as node_arg names. + // New node_arg name should not conflict this this set. + std::unordered_set generated_node_arg_names_; + // All node args owned by <*this> graph. Key is node arg name. std::unordered_map> node_args_; diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index a5e4c3c73f..d939d25876 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -2378,28 +2378,57 @@ Node& Graph::AddNode(const NodeProto& node_proto, } std::string Graph::GenerateNodeArgName(const std::string& base_name) { - std::string new_name; - do { + std::string new_name = base_name; + // Check if new_name has been used in as any of node_args_' names. + // Check if new_name has been generated by this function. + // If both are not, add new_name into name set and return the new_name + // as the generated name. Otherwise, keep generating new names. + while (node_args_.find(new_name) != node_args_.end() || + generated_node_arg_names_.find(new_name) != generated_node_arg_names_.end()) { std::ostringstream str; - str << base_name << "_" << name_generator_++; + str << base_name << "_token_" << name_generator_++; new_name = str.str(); - } while (node_args_.find(new_name) != node_args_.end()); + } + + generated_node_arg_names_.insert(new_name); return new_name; } std::string Graph::GenerateNodeName(const std::string& base_name) { - std::string new_name; - bool keep_going = true; + // Define name-checking function for node name. + // Return true if the input name hasn't been used. Otherwise, return false. + auto name_is_ok = [&] (const std::string name) { + for (auto it = nodes_.begin(); it != nodes_.end(); ++it) { + if (*it == nullptr) { + continue; + } + if (it->get()->Name() != name) { + continue; + } + // Find a matched name so we cannot reuse the input name. + return false; + } - do { + if (generated_node_names_.find(name) != generated_node_names_.end()) { + // Find a matched name so we cannot reuse the input name. + return false; + } + + // The input name can be reused. + return true; + }; + + // Start with the input name. + std::string new_name = base_name; + + while (!name_is_ok(new_name)) { std::ostringstream str; - str << base_name << "_" << name_generator_++; + str << base_name << "_token_" << name_generator_++; new_name = str.str(); + } - keep_going = std::find_if(nodes_.cbegin(), nodes_.cend(), [&new_name](const std::unique_ptr& n) { - return (n != nullptr) && (n->Name() == new_name); - }) != nodes_.end(); - } while (keep_going); + // Make sure this new_name is not going to be reused. + generated_node_names_.insert(new_name); return new_name; } diff --git a/onnxruntime/core/providers/cpu/math/clip.cc b/onnxruntime/core/providers/cpu/math/clip.cc index 75ae6d4cdd..92c7590d53 100644 --- a/onnxruntime/core/providers/cpu/math/clip.cc +++ b/onnxruntime/core/providers/cpu/math/clip.cc @@ -3,6 +3,7 @@ #include "core/providers/cpu/math/clip.h" #include "core/framework/data_types_internal.h" +#include "core/util/math_cpuonly.h" namespace onnxruntime { @@ -31,6 +32,17 @@ ONNX_CPU_OPERATOR_VERSIONED_KERNEL( REG_KERNEL_NONTEMPL(Clip, 12, Clip, float, double, int8_t, uint8_t, int64_t, uint64_t); +template +Status Clip_6::Compute(OpKernelContext* ctx) const { + const auto* X = ctx->Input(0); + Tensor* Y = ctx->Output(0, X->Shape()); + EigenVectorMap(Y->template MutableData(), Y->Shape().Size()) = + ConstEigenVectorMap(X->template Data(), X->Shape().Size()) + .cwiseMax(this->min_) + .cwiseMin(this->max_); + return Status::OK(); +} + template struct Clip::ComputeImpl { void operator()(const Tensor* X, const Tensor* min, const Tensor* max, Tensor* Y) const { diff --git a/onnxruntime/core/providers/cpu/math/clip.h b/onnxruntime/core/providers/cpu/math/clip.h index b365aa33fd..b7c6032c6b 100644 --- a/onnxruntime/core/providers/cpu/math/clip.h +++ b/onnxruntime/core/providers/cpu/math/clip.h @@ -5,7 +5,6 @@ #include "core/common/common.h" #include "core/framework/op_kernel.h" -#include "core/util/math_cpuonly.h" namespace onnxruntime { @@ -33,15 +32,7 @@ class Clip_6 final : public clip_internal::Clip_6Base, public OpKernel { explicit Clip_6(const OpKernelInfo& info) : clip_internal::Clip_6Base(info), OpKernel(info) { } - Status Compute(OpKernelContext* ctx) const override { - const auto* X = ctx->Input(0); - Tensor* Y = ctx->Output(0, X->Shape()); - EigenVectorMap(Y->template MutableData(), Y->Shape().Size()) = - ConstEigenVectorMap(X->template Data(), X->Shape().Size()) - .cwiseMax(this->min_) - .cwiseMin(this->max_); - return Status::OK(); - } + Status Compute(OpKernelContext* ctx) const override; }; // Since version 11. Min and Max are inputs diff --git a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/GraphDescBuilder.cpp b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/GraphDescBuilder.cpp index 622b7b96cb..b07eed9fd8 100644 --- a/onnxruntime/core/providers/dml/DmlExecutionProvider/src/GraphDescBuilder.cpp +++ b/onnxruntime/core/providers/dml/DmlExecutionProvider/src/GraphDescBuilder.cpp @@ -14,8 +14,21 @@ namespace Dml::GraphDescBuilder // mismatch is fixed (WindowsAI: 21114358, Lotus: 1953), this workaround should be removed. static std::string GetFusedNodeArgNameMatchingGraph(const std::string& fusedNodeArgeName) { - // The suffix used when inserting mem copies is equal to the below, followed by an incrementing number. - const char* suffix = strstr(fusedNodeArgeName.c_str(), "_DmlExecutionProvider_"); + const char* suffix = nullptr; + + // The suffix used when inserting mem copies is equal to the below, probably followed by an incrementing number. + if (!suffix) { + suffix = strstr(fusedNodeArgeName.c_str(), "_DmlExecutionProvider_"); + } + + // The suffix used when inserting mem copies is equal to the below, not followed by an incrementing number. + if (!suffix) { + suffix = strstr(fusedNodeArgeName.c_str(), "_DmlExecutionProvider"); + } + + if (!suffix) { + suffix = strstr(fusedNodeArgeName.c_str(), "_token_"); + } if (suffix) { @@ -23,9 +36,9 @@ namespace Dml::GraphDescBuilder fusedNodeArgeName.begin(), fusedNodeArgeName.begin() + (suffix - fusedNodeArgeName.c_str()) ); + } else { + return fusedNodeArgeName; } - - return fusedNodeArgeName; } const std::string& GetUniqueNodeName(const onnxruntime::Node& node)