Added hash to type_info (#8175)
* Added hash to type_info * Fast hash * Fixed tests * Added new tests * Fixed build * Fix centos * Fixed segfault * Fixed test * Fixed build * Revert "Fix centos" This reverts commitc739e923aa
. * Try to fix cent os * Fixed style * Fixed GCC 4.8 * Try to fix build * Fixed code style * remove constexpr from type construction * Fixed tests * Revert "Fixed tests" This reverts commit50aec37f95
. * Revert "remove constexpr from type construction" This reverts commit6c22d7ecfa
.
This commit is contained in:
parent
abc554513f
commit
0017ec71fd
@ -27,10 +27,15 @@ namespace ov {
|
||||
/// A user-defined function.
|
||||
class OPENVINO_API Function : public std::enable_shared_from_this<Function> {
|
||||
public:
|
||||
static constexpr ov::DiscreteTypeInfo type_info{"Function", 0};
|
||||
const ov::DiscreteTypeInfo& get_type_info() const {
|
||||
static const ::ov::DiscreteTypeInfo& get_type_info_static() {
|
||||
static const ::ov::DiscreteTypeInfo type_info{"Function", 0};
|
||||
return type_info;
|
||||
}
|
||||
const ::ov::DiscreteTypeInfo& get_type_info() const {
|
||||
return get_type_info_static();
|
||||
}
|
||||
OPENVINO_DEPRECATED("This member was deprecated. Please use ::get_type_info_static() instead.")
|
||||
static const ov::DiscreteTypeInfo type_info;
|
||||
Function(const ov::NodeVector& results, const ov::ParameterVector& parameters, const std::string& name = "");
|
||||
|
||||
Function(const ov::OutputVector& results, const ov::ParameterVector& parameters, const std::string& name = "");
|
||||
|
@ -147,14 +147,11 @@ OPENVINO_API std::int64_t width_idx(const Layout& layout);
|
||||
template <>
|
||||
class OPENVINO_API AttributeAdapter<Layout> : public ValueAccessor<std::string> {
|
||||
public:
|
||||
OPENVINO_RTTI("AttributeAdapter<Layout>");
|
||||
explicit AttributeAdapter(Layout& value) : m_ref(value) {}
|
||||
|
||||
const std::string& get() override;
|
||||
void set(const std::string& value) override;
|
||||
static constexpr DiscreteTypeInfo type_info{"AttributeAdapter<Layout>", 0};
|
||||
const DiscreteTypeInfo& get_type_info() const override {
|
||||
return type_info;
|
||||
}
|
||||
explicit operator Layout&() {
|
||||
return m_ref;
|
||||
}
|
||||
|
@ -11,13 +11,14 @@
|
||||
|
||||
#define _OPENVINO_RTTI_WITH_TYPE(TYPE_NAME) _OPENVINO_RTTI_WITH_TYPE_VERSION(TYPE_NAME, "util")
|
||||
|
||||
#define _OPENVINO_RTTI_WITH_TYPE_VERSION(TYPE_NAME, VERSION_NAME) \
|
||||
static const ::ov::DiscreteTypeInfo& get_type_info_static() { \
|
||||
static const ::ov::DiscreteTypeInfo type_info{TYPE_NAME, 0, VERSION_NAME}; \
|
||||
return type_info; \
|
||||
} \
|
||||
const ::ov::DiscreteTypeInfo& get_type_info() const override { \
|
||||
return get_type_info_static(); \
|
||||
#define _OPENVINO_RTTI_WITH_TYPE_VERSION(TYPE_NAME, VERSION_NAME) \
|
||||
static const ::ov::DiscreteTypeInfo& get_type_info_static() { \
|
||||
static ::ov::DiscreteTypeInfo type_info{TYPE_NAME, 0, VERSION_NAME}; \
|
||||
type_info.hash(); \
|
||||
return type_info; \
|
||||
} \
|
||||
const ::ov::DiscreteTypeInfo& get_type_info() const override { \
|
||||
return get_type_info_static(); \
|
||||
}
|
||||
|
||||
#define _OPENVINO_RTTI_WITH_TYPE_VERSION_PARENT(TYPE_NAME, VERSION_NAME, PARENT_CLASS) \
|
||||
@ -25,10 +26,11 @@
|
||||
|
||||
#define _OPENVINO_RTTI_WITH_TYPE_VERSIONS_PARENT(TYPE_NAME, VERSION_NAME, PARENT_CLASS, OLD_VERSION) \
|
||||
static const ::ov::DiscreteTypeInfo& get_type_info_static() { \
|
||||
static const ::ov::DiscreteTypeInfo type_info{TYPE_NAME, \
|
||||
OLD_VERSION, \
|
||||
VERSION_NAME, \
|
||||
&PARENT_CLASS::get_type_info_static()}; \
|
||||
static ::ov::DiscreteTypeInfo type_info{TYPE_NAME, \
|
||||
OLD_VERSION, \
|
||||
VERSION_NAME, \
|
||||
&PARENT_CLASS::get_type_info_static()}; \
|
||||
type_info.hash(); \
|
||||
return type_info; \
|
||||
} \
|
||||
const ::ov::DiscreteTypeInfo& get_type_info() const override { \
|
||||
|
@ -39,7 +39,8 @@ struct OPENVINO_API DiscreteTypeInfo {
|
||||
: name(_name),
|
||||
version(_version),
|
||||
version_id(nullptr),
|
||||
parent(_parent) {}
|
||||
parent(_parent),
|
||||
hash_value(0) {}
|
||||
|
||||
constexpr DiscreteTypeInfo(const char* _name,
|
||||
uint64_t _version,
|
||||
@ -48,22 +49,12 @@ struct OPENVINO_API DiscreteTypeInfo {
|
||||
: name(_name),
|
||||
version(_version),
|
||||
version_id(_version_id),
|
||||
parent(_parent) {}
|
||||
parent(_parent),
|
||||
hash_value(0) {}
|
||||
|
||||
bool is_castable(const DiscreteTypeInfo& target_type) const {
|
||||
return *this == target_type || (parent && parent->is_castable(target_type));
|
||||
}
|
||||
bool is_castable(const DiscreteTypeInfo& target_type) const;
|
||||
|
||||
std::string get_version() const {
|
||||
if (version_id) {
|
||||
return std::string(version_id);
|
||||
}
|
||||
return std::to_string(version);
|
||||
}
|
||||
|
||||
operator std::string() const {
|
||||
return std::string(name) + "_" + get_version();
|
||||
}
|
||||
std::string get_version() const;
|
||||
|
||||
// For use as a key
|
||||
bool operator<(const DiscreteTypeInfo& b) const;
|
||||
@ -72,6 +63,14 @@ struct OPENVINO_API DiscreteTypeInfo {
|
||||
bool operator>=(const DiscreteTypeInfo& b) const;
|
||||
bool operator==(const DiscreteTypeInfo& b) const;
|
||||
bool operator!=(const DiscreteTypeInfo& b) const;
|
||||
|
||||
operator std::string() const;
|
||||
|
||||
size_t hash() const;
|
||||
size_t hash();
|
||||
|
||||
private:
|
||||
size_t hash_value;
|
||||
};
|
||||
|
||||
OPENVINO_API
|
||||
|
@ -31,7 +31,8 @@ protected:
|
||||
|
||||
public:
|
||||
static const ::ov::Node::type_info_t& get_type_info_static() {
|
||||
static const ::ov::Node::type_info_t info{"Op", 0, "util"};
|
||||
static ::ov::Node::type_info_t info{"Op", 0, "util"};
|
||||
info.hash();
|
||||
return info;
|
||||
}
|
||||
const ::ov::Node::type_info_t& get_type_info() const override {
|
||||
|
@ -87,6 +87,10 @@ ngraph::ParameterVector auto_detect_parameters(const std::vector<std::shared_ptr
|
||||
|
||||
} // namespace
|
||||
|
||||
OPENVINO_SUPPRESS_DEPRECATED_START
|
||||
const ov::DiscreteTypeInfo ov::Function::type_info = ov::Function::get_type_info_static();
|
||||
OPENVINO_SUPPRESS_DEPRECATED_END
|
||||
|
||||
ov::Function::Function(const ResultVector& results, const ngraph::ParameterVector& parameters, const std::string& name)
|
||||
: m_name(name),
|
||||
m_unique_name("Function_" + to_string(m_next_instance_id.fetch_add(1))),
|
||||
|
@ -346,8 +346,6 @@ std::int64_t width_idx(const Layout& layout) {
|
||||
|
||||
} // namespace layout
|
||||
|
||||
constexpr DiscreteTypeInfo AttributeAdapter<ov::Layout>::type_info;
|
||||
|
||||
const std::string& AttributeAdapter<ov::Layout>::get() {
|
||||
m_dump = m_ref.to_string();
|
||||
return m_dump;
|
||||
|
@ -4,20 +4,47 @@
|
||||
|
||||
#include "ngraph/type.hpp"
|
||||
|
||||
#include "ngraph/util.hpp"
|
||||
#include "openvino/util/common_util.hpp"
|
||||
|
||||
namespace std {
|
||||
size_t std::hash<ngraph::DiscreteTypeInfo>::operator()(const ngraph::DiscreteTypeInfo& k) const {
|
||||
NGRAPH_SUPPRESS_DEPRECATED_START
|
||||
size_t name_hash = hash<string>()(string(k.name));
|
||||
size_t version_hash = hash<decltype(k.version)>()(k.version);
|
||||
// don't use parent for hash calculation, it is not a part of type (yet)
|
||||
return ngraph::hash_combine(vector<size_t>{name_hash, version_hash});
|
||||
NGRAPH_SUPPRESS_DEPRECATED_END
|
||||
return k.hash();
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
namespace ov {
|
||||
|
||||
size_t DiscreteTypeInfo::hash() const {
|
||||
if (hash_value != 0)
|
||||
return hash_value;
|
||||
size_t name_hash = name ? std::hash<std::string>()(std::string(name)) : 0;
|
||||
size_t version_hash = std::hash<decltype(version)>()(version);
|
||||
size_t version_id_hash = version_id ? std::hash<std::string>()(std::string(version_id)) : 0;
|
||||
|
||||
return ov::util::hash_combine(std::vector<size_t>{name_hash, version_hash, version_id_hash});
|
||||
}
|
||||
|
||||
size_t DiscreteTypeInfo::hash() {
|
||||
if (hash_value == 0)
|
||||
hash_value = static_cast<const DiscreteTypeInfo*>(this)->hash();
|
||||
return hash_value;
|
||||
}
|
||||
|
||||
bool DiscreteTypeInfo::is_castable(const DiscreteTypeInfo& target_type) const {
|
||||
return *this == target_type || (parent && parent->is_castable(target_type));
|
||||
}
|
||||
|
||||
std::string DiscreteTypeInfo::get_version() const {
|
||||
if (version_id) {
|
||||
return std::string(version_id);
|
||||
}
|
||||
return std::to_string(version);
|
||||
}
|
||||
|
||||
DiscreteTypeInfo::operator std::string() const {
|
||||
return std::string(name) + "_" + get_version();
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& s, const DiscreteTypeInfo& info) {
|
||||
std::string version_id = info.version_id ? info.version_id : "(empty)";
|
||||
s << "DiscreteTypeInfo{name: " << info.name << ", version_id: " << version_id << ", old_version: " << info.version
|
||||
@ -33,22 +60,26 @@ std::ostream& operator<<(std::ostream& s, const DiscreteTypeInfo& info) {
|
||||
|
||||
// parent is commented to fix type relaxed operations
|
||||
bool DiscreteTypeInfo::operator<(const DiscreteTypeInfo& b) const {
|
||||
if (version_id == nullptr || b.version_id == nullptr)
|
||||
return version < b.version ||
|
||||
(version == b.version && strcmp(name, b.name) < 0); // ||
|
||||
// (version == b.version && strcmp(name, b.name) ==
|
||||
// 0 && parent && b.parent && *parent < *b.parent);
|
||||
else
|
||||
return strcmp(version_id, b.version_id) < 0 ||
|
||||
(strcmp(version_id, b.version_id) == 0 && strcmp(name, b.name) < 0); // ||
|
||||
// (strcmp(version_id, b.version_id) == 0 && strcmp(name, b.name) == 0 && parent && b.parent &&
|
||||
// *parent < *b.parent);
|
||||
if (version < b.version)
|
||||
return true;
|
||||
if (version == b.version && name != nullptr && b.name != nullptr) {
|
||||
int cmp_status = strcmp(name, b.name);
|
||||
if (cmp_status < 0)
|
||||
return true;
|
||||
if (cmp_status == 0) {
|
||||
std::string v_id(version_id == nullptr ? "" : version_id);
|
||||
std::string bv_id(b.version_id == nullptr ? "" : b.version_id);
|
||||
if (v_id < bv_id)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool DiscreteTypeInfo::operator==(const DiscreteTypeInfo& b) const {
|
||||
if (version_id == nullptr || b.version_id == nullptr)
|
||||
return version == b.version && strcmp(name, b.name) == 0; // && parent == b.parent;
|
||||
else
|
||||
return strcmp(version_id, b.version_id) == 0 && strcmp(name, b.name) == 0; // && parent == b.parent;
|
||||
if (hash_value != 0 && b.hash_value != 0)
|
||||
return hash() == b.hash();
|
||||
return version == b.version && strcmp(name, b.name) == 0;
|
||||
}
|
||||
bool DiscreteTypeInfo::operator<=(const DiscreteTypeInfo& b) const {
|
||||
return *this == b || *this < b;
|
||||
|
@ -78,11 +78,7 @@ vector<string> ngraph::split(const string& src, char delimiter, bool do_trim) {
|
||||
}
|
||||
|
||||
size_t ngraph::hash_combine(const std::vector<size_t>& list) {
|
||||
size_t seed = 0;
|
||||
for (size_t v : list) {
|
||||
seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
return seed;
|
||||
return ov::util::hash_combine(list);
|
||||
}
|
||||
|
||||
void* ngraph::ngraph_malloc(size_t size) {
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "openvino/core/type.hpp"
|
||||
#include "openvino/opsets/opset.hpp"
|
||||
#include "openvino/util/common_util.hpp"
|
||||
|
||||
TEST(type_info, compare_old_type) {
|
||||
ov::DiscreteTypeInfo type1("type1", 0);
|
||||
@ -47,3 +49,75 @@ TEST(type_info, compare_new_with_old_type) {
|
||||
ov::DiscreteTypeInfo type1_o("type1", 0);
|
||||
ASSERT_TRUE(type1 == type1_o);
|
||||
}
|
||||
|
||||
TEST(type_info, check_hash_value) {
|
||||
const auto& hash_val = [](const char* name, const char* version_id, uint64_t version) -> size_t {
|
||||
size_t name_hash = name ? std::hash<std::string>()(std::string(name)) : 0;
|
||||
size_t version_hash = std::hash<decltype(version)>()(version);
|
||||
size_t version_id_hash = version_id ? std::hash<std::string>()(std::string(version_id)) : 0;
|
||||
// don't use parent for hash calculation, it is not a part of type (yet)
|
||||
return ov::util::hash_combine(std::vector<size_t>{name_hash, version_hash, version_id_hash});
|
||||
};
|
||||
ov::DiscreteTypeInfo type("type1", 0, "version1");
|
||||
ov::DiscreteTypeInfo type_old("type1", 1);
|
||||
ov::DiscreteTypeInfo type_with_version("type1", 1, "version1");
|
||||
ov::DiscreteTypeInfo type_empty_name("", 0);
|
||||
ov::DiscreteTypeInfo type_empty_ver("type", 0, "");
|
||||
EXPECT_EQ(hash_val(type.name, type.version_id, type.version), type.hash());
|
||||
EXPECT_EQ(hash_val(type_old.name, type_old.version_id, type_old.version), type_old.hash());
|
||||
EXPECT_EQ(hash_val(type_with_version.name, type_with_version.version_id, type_with_version.version),
|
||||
type_with_version.hash());
|
||||
EXPECT_EQ(hash_val(type_empty_name.name, type_empty_name.version_id, type_empty_name.version),
|
||||
type_empty_name.hash());
|
||||
EXPECT_EQ(hash_val(type_empty_ver.name, type_empty_ver.version_id, type_empty_ver.version), type_empty_ver.hash());
|
||||
}
|
||||
|
||||
TEST(type_info, find_in_map) {
|
||||
std::vector<std::string> vector_names;
|
||||
ov::DiscreteTypeInfo a("Mod", 1, "opset1");
|
||||
ov::DiscreteTypeInfo b("Prelu", 0, "opset1");
|
||||
ov::DiscreteTypeInfo c("Vector", 0);
|
||||
ov::DiscreteTypeInfo d("Mod", 1, "opset3");
|
||||
ov::DiscreteTypeInfo f("Mod", 2);
|
||||
|
||||
std::map<ov::DiscreteTypeInfo, int> test_map;
|
||||
test_map[a] = 1;
|
||||
test_map[b] = 1;
|
||||
test_map[c] = 1;
|
||||
|
||||
const auto& opset = ov::get_opset8();
|
||||
// Reserve memory to avoid reallocation and copy of strings
|
||||
// because type info uses pointers from the original memory
|
||||
vector_names.reserve(opset.size() * 3);
|
||||
for (const auto& type : opset.get_types_info()) {
|
||||
test_map[type] = 2;
|
||||
std::string name = type.name;
|
||||
vector_names.emplace_back(name);
|
||||
ov::DiscreteTypeInfo t(vector_names.rbegin()->c_str(), 1000);
|
||||
ov::DiscreteTypeInfo t2(vector_names.rbegin()->c_str(), 0);
|
||||
test_map[t] = 3;
|
||||
test_map[t2] = 4;
|
||||
std::string name1 = "a" + name;
|
||||
vector_names.emplace_back(name1);
|
||||
ov::DiscreteTypeInfo t3(vector_names.rbegin()->c_str(), 1000);
|
||||
ov::DiscreteTypeInfo t4(vector_names.rbegin()->c_str(), 0);
|
||||
test_map[t3] = 5;
|
||||
test_map[t4] = 6;
|
||||
std::string name2 = name + "z";
|
||||
vector_names.emplace_back(name2);
|
||||
ov::DiscreteTypeInfo t5(vector_names.rbegin()->c_str(), 1000);
|
||||
ov::DiscreteTypeInfo t6(vector_names.rbegin()->c_str(), 0);
|
||||
test_map[t5] = 7;
|
||||
test_map[t6] = 8;
|
||||
}
|
||||
|
||||
for (const auto& it : test_map) {
|
||||
ASSERT_NE(test_map.end(), test_map.find(it.first));
|
||||
}
|
||||
|
||||
ASSERT_NE(test_map.end(), test_map.find(a));
|
||||
ASSERT_NE(test_map.end(), test_map.find(b));
|
||||
ASSERT_NE(test_map.end(), test_map.find(c));
|
||||
ASSERT_EQ(test_map.end(), test_map.find(d));
|
||||
ASSERT_EQ(test_map.end(), test_map.find(f));
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ std::string to_lower(const std::string& s);
|
||||
|
||||
std::string to_upper(const std::string& s);
|
||||
|
||||
size_t hash_combine(const std::vector<size_t>& list);
|
||||
|
||||
/**
|
||||
* @brief trim from start (in place)
|
||||
* @param s - string to trim
|
||||
|
@ -40,3 +40,11 @@ std::vector<std::string> ov::util::split(const std::string& src, char delimiter,
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
size_t ov::util::hash_combine(const std::vector<size_t>& list) {
|
||||
size_t seed = 0;
|
||||
for (size_t v : list) {
|
||||
seed ^= v + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user