Improve node and node argument name generation (#3649)

This commit is contained in:
Wei-Sheng Chin 2020-04-27 13:57:24 -07:00 committed by GitHub
parent 635bc9cd04
commit 7627e6bcc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 79 additions and 26 deletions

View file

@ -1106,6 +1106,14 @@ class Graph {
// Graph value_info.
std::vector<const NodeArg*> value_info_;
// Strings which have been used as node names.
// New node name should not conflict with this set.
std::unordered_set<std::string> 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<std::string> generated_node_arg_names_;
// All node args owned by <*this> graph. Key is node arg name.
std::unordered_map<std::string, std::unique_ptr<NodeArg>> node_args_;

View file

@ -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<Node>& 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;
}

View file

@ -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<typename T>
Status Clip_6<T>::Compute(OpKernelContext* ctx) const {
const auto* X = ctx->Input<Tensor>(0);
Tensor* Y = ctx->Output(0, X->Shape());
EigenVectorMap<T>(Y->template MutableData<T>(), Y->Shape().Size()) =
ConstEigenVectorMap<T>(X->template Data<T>(), X->Shape().Size())
.cwiseMax(this->min_)
.cwiseMin(this->max_);
return Status::OK();
}
template <typename T>
struct Clip::ComputeImpl {
void operator()(const Tensor* X, const Tensor* min, const Tensor* max, Tensor* Y) const {

View file

@ -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<T>, public OpKernel {
explicit Clip_6(const OpKernelInfo& info) : clip_internal::Clip_6Base<T>(info), OpKernel(info) {
}
Status Compute(OpKernelContext* ctx) const override {
const auto* X = ctx->Input<Tensor>(0);
Tensor* Y = ctx->Output(0, X->Shape());
EigenVectorMap<T>(Y->template MutableData<T>(), Y->Shape().Size()) =
ConstEigenVectorMap<T>(X->template Data<T>(), 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

View file

@ -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)