This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new 012d6a72f6 [IR] Platform-independent SHash (#14204)
012d6a72f6 is described below
commit 012d6a72f661113ae1ccfae38e5fc848296d76d8
Author: Junru Shao <[email protected]>
AuthorDate: Mon Mar 6 17:37:27 2023 -0800
[IR] Platform-independent SHash (#14204)
This PR introduces the necessary change to make structural-hash
platform-independent. The change includes:
- Explicitly require the hash type to be `uint64_t` rather than
platform-dependent `size_t`.
- Implement structural hash for POD types including `double`, `int`
by unioning them with `uint64_t` explicitly.
- Implement a platform-independent fast hashing algorithm for `std::string`
---
include/tvm/node/reflection.h | 2 +-
include/tvm/node/structural_hash.h | 74 ++++++++++++++++--------------
include/tvm/runtime/container/string.h | 73 +++++++++++++++++++++++++++---
src/node/structural_hash.cc | 82 +++++++++++++++++-----------------
src/relay/backend/utils.h | 2 +-
5 files changed, 151 insertions(+), 82 deletions(-)
diff --git a/include/tvm/node/reflection.h b/include/tvm/node/reflection.h
index f547b5a707..2cfb50e1a2 100644
--- a/include/tvm/node/reflection.h
+++ b/include/tvm/node/reflection.h
@@ -244,7 +244,7 @@ class ReflectionVTable::Registry {
* static constexpr const std::nullptr_t VisitAttrs = nullptr;
*
* static void SHashReduce(const runtime::StringObj* key, SHashReducer
hash_reduce) {
- *
hash_reduce->SHashReduceHashedValue(runtime::String::HashBytes(key->data,
key->size));
+ *
hash_reduce->SHashReduceHashedValue(runtime::String::StableHashBytes(key->data,
key->size));
* }
*
* static bool SEqualReduce(const runtime::StringObj* lhs,
diff --git a/include/tvm/node/structural_hash.h
b/include/tvm/node/structural_hash.h
index 8b8a403326..4d822e68d3 100644
--- a/include/tvm/node/structural_hash.h
+++ b/include/tvm/node/structural_hash.h
@@ -36,52 +36,60 @@ namespace tvm {
* \brief Hash definition of base value classes.
*/
class BaseValueHash {
- public:
- size_t operator()(const double& key) const { return
std::hash<double>()(key); }
-
- size_t operator()(const int64_t& key) const { return
std::hash<int64_t>()(key); }
-
- size_t operator()(const uint64_t& key) const { return
std::hash<uint64_t>()(key); }
-
- size_t operator()(const int& key) const { return std::hash<int>()(key); }
-
- size_t operator()(const bool& key) const { return std::hash<bool>()(key); }
-
- size_t operator()(const std::string& key) const { return
std::hash<std::string>()(key); }
-
- size_t operator()(const runtime::DataType& key) const {
- return std::hash<int32_t>()(static_cast<int32_t>(key.code()) |
- (static_cast<int32_t>(key.bits()) << 8) |
- (static_cast<int32_t>(key.lanes()) << 16));
+ protected:
+ template <typename T, typename U>
+ uint64_t Reinterpret(T value) const {
+ union Union {
+ T a;
+ U b;
+ } u;
+ static_assert(sizeof(Union) == sizeof(T), "sizeof(Union) != sizeof(T)");
+ static_assert(sizeof(Union) == sizeof(U), "sizeof(Union) != sizeof(U)");
+ u.b = 0;
+ u.a = value;
+ return u.b;
}
+ public:
+ uint64_t operator()(const float& key) const { return Reinterpret<float,
uint32_t>(key); }
+ uint64_t operator()(const double& key) const { return Reinterpret<double,
uint64_t>(key); }
+ uint64_t operator()(const int64_t& key) const { return Reinterpret<int64_t,
uint64_t>(key); }
+ uint64_t operator()(const uint64_t& key) const { return key; }
+ uint64_t operator()(const int& key) const { return Reinterpret<int,
uint32_t>(key); }
+ uint64_t operator()(const bool& key) const { return key; }
+ uint64_t operator()(const runtime::DataType& key) const {
+ return Reinterpret<DLDataType, uint32_t>(key);
+ }
template <typename ENum, typename = typename
std::enable_if<std::is_enum<ENum>::value>::type>
- bool operator()(const ENum& key) const {
- return std::hash<size_t>()(static_cast<size_t>(key));
+ uint64_t operator()(const ENum& key) const {
+ return Reinterpret<int64_t, uint64_t>(static_cast<int64_t>(key));
+ }
+ uint64_t operator()(const std::string& key) const {
+ return runtime::String::StableHashBytes(key.data(), key.length());
}
};
/*!
- * \brief Content-aware structural hasing.
+ * \brief Content-aware structural hashing.
*
* The structural hash value is recursively defined in the DAG of IRNodes.
* There are two kinds of nodes:
*
* - Normal node: the hash value is defined by its content and type only.
* - Graph node: each graph node will be assigned a unique index ordered by
the
- * first occurence during the visit. The hash value of a graph node is
+ * first occurrence during the visit. The hash value of a graph node is
* combined from the hash values of its contents and the index.
*/
class StructuralHash : public BaseValueHash {
public:
- // inheritate operator()
+ // inherit operator()
using BaseValueHash::operator();
/*!
* \brief Compute structural hashing value for an object.
* \param key The left operand.
* \return The hash value.
*/
- TVM_DLL size_t operator()(const ObjectRef& key) const;
+ TVM_DLL uint64_t operator()(const ObjectRef& key) const;
};
/*!
@@ -109,23 +117,23 @@ class SHashReducer {
*
* \param hashed_value The hashed value
*/
- virtual void SHashReduceHashedValue(size_t hashed_value) = 0;
+ virtual void SHashReduceHashedValue(uint64_t hashed_value) = 0;
/*!
* \brief Append hash value of key to the current sequence of hashes.
*
* \param key The object to compute hash from.
- * \param map_free_vars Whether to map free variables by their occurence
number.
+ * \param map_free_vars Whether to map free variables by their occurrence
number.
*/
virtual void SHashReduce(const ObjectRef& key, bool map_free_vars) = 0;
/*!
- * \brief Apppend a hash value of free variable to the current sequence of
hashes.
+ * \brief Append a hash value of free variable to the current sequence of
hashes.
*
* \param var The var of interest.
- * \param map_free_vars Whether to map free variables by their occurence
number.
+ * \param map_free_vars Whether to map free variables by their occurrence
number.
*
* \note If map_free_vars is set to be true,
* internally the handler can maintain a counter to encode free
variables
- * by their order of occurence. This helps to resolve variable
+ * by their order of occurrence. This helps to resolve variable
* mapping of function parameters and let binding variables.
*
* If map_free_vars is set to be false, the address of the variable
will be used.
@@ -139,7 +147,7 @@ class SHashReducer {
*
* \return Whether there is already a pre-computed hash value.
*/
- virtual bool LookupHashedValue(const ObjectRef& key, size_t* hashed_value)
= 0;
+ virtual bool LookupHashedValue(const ObjectRef& key, uint64_t*
hashed_value) = 0;
/*!
* \brief Mark current comparison as graph node in hashing.
* Graph node hash will depends on the graph structure.
@@ -193,7 +201,7 @@ class SHashReducer {
/*! \brief Internal class pointer. */
Handler* handler_;
/*!
- * \brief Whether or not to map free variables by their occurence
+ * \brief Whether or not to map free variables by their occurrence
* If the flag is false, then free variables will be mapped
* by their in-memory address.
*/
@@ -210,10 +218,10 @@ class SHashHandlerDefault : public SHashReducer::Handler {
SHashHandlerDefault();
virtual ~SHashHandlerDefault();
- void SHashReduceHashedValue(size_t hashed_value) override;
+ void SHashReduceHashedValue(uint64_t hashed_value) override;
void SHashReduce(const ObjectRef& key, bool map_free_vars) override;
void SHashReduceFreeVar(const runtime::Object* var, bool map_free_vars)
override;
- bool LookupHashedValue(const ObjectRef& key, size_t* hashed_value) override;
+ bool LookupHashedValue(const ObjectRef& key, uint64_t* hashed_value)
override;
void MarkGraphNode() override;
/*!
@@ -222,7 +230,7 @@ class SHashHandlerDefault : public SHashReducer::Handler {
* \param map_free_vars Whether or not to remap variables if possible.
* \return The hash result.
*/
- virtual size_t Hash(const ObjectRef& object, bool map_free_vars);
+ virtual uint64_t Hash(const ObjectRef& object, bool map_free_vars);
protected:
/*!
diff --git a/include/tvm/runtime/container/string.h
b/include/tvm/runtime/container/string.h
index 5ecd89e9f5..c6382506b3 100644
--- a/include/tvm/runtime/container/string.h
+++ b/include/tvm/runtime/container/string.h
@@ -24,6 +24,7 @@
#ifndef TVM_RUNTIME_CONTAINER_STRING_H_
#define TVM_RUNTIME_CONTAINER_STRING_H_
+#include <dmlc/endian.h>
#include <dmlc/logging.h>
#include <tvm/runtime/container/base.h>
#include <tvm/runtime/logging.h>
@@ -247,10 +248,70 @@ class String : public ObjectRef {
* \param size The size of the bytes.
* \return the hash value.
*/
- static size_t HashBytes(const char* data, size_t size) {
- // This function falls back to string copy with c++11 compiler and is
- // recommended to be compiled with c++14
- return std::hash<std::string_view>()(std::string_view(data, size));
+ static uint64_t StableHashBytes(const char* data, size_t size) {
+ const constexpr uint64_t kMultiplier = 1099511628211ULL;
+ const constexpr uint64_t kMod = 2147483647ULL;
+ union Union {
+ uint8_t a[8];
+ uint64_t b;
+ } u;
+ static_assert(sizeof(Union) == sizeof(uint64_t), "sizeof(Union) !=
sizeof(uint64_t)");
+ const char* it = data;
+ const char* end = it + size;
+ uint64_t result = 0;
+ for (; it + 8 <= end; it += 8) {
+ if (DMLC_IO_NO_ENDIAN_SWAP) {
+ u.a[0] = it[0];
+ u.a[1] = it[1];
+ u.a[2] = it[2];
+ u.a[3] = it[3];
+ u.a[4] = it[4];
+ u.a[5] = it[5];
+ u.a[6] = it[6];
+ u.a[7] = it[7];
+ } else {
+ u.a[0] = it[7];
+ u.a[1] = it[6];
+ u.a[2] = it[5];
+ u.a[3] = it[4];
+ u.a[4] = it[3];
+ u.a[5] = it[2];
+ u.a[6] = it[1];
+ u.a[7] = it[0];
+ }
+ result = (result * kMultiplier + u.b) % kMod;
+ }
+ if (it < end) {
+ u.b = 0;
+ uint8_t* a = u.a;
+ if (it + 4 <= end) {
+ a[0] = it[0];
+ a[1] = it[1];
+ a[2] = it[2];
+ a[3] = it[3];
+ it += 4;
+ a += 4;
+ }
+ if (it + 2 <= end) {
+ a[0] = it[0];
+ a[1] = it[1];
+ it += 2;
+ a += 2;
+ }
+ if (it + 1 <= end) {
+ a[0] = it[0];
+ it += 1;
+ a += 1;
+ }
+ if (!DMLC_IO_NO_ENDIAN_SWAP) {
+ std::swap(u.a[0], u.a[7]);
+ std::swap(u.a[1], u.a[6]);
+ std::swap(u.a[2], u.a[5]);
+ std::swap(u.a[3], u.a[4]);
+ }
+ result = (result * kMultiplier + u.b) % kMod;
+ }
+ return result;
}
TVM_DEFINE_NOTNULLABLE_OBJECT_REF_METHODS(String, ObjectRef, StringObj);
@@ -448,7 +509,7 @@ inline int String::memncmp(const char* lhs, const char*
rhs, size_t lhs_count, s
inline size_t ObjectHash::operator()(const ObjectRef& a) const {
if (const auto* str = a.as<StringObj>()) {
- return String::HashBytes(str->data, str->size);
+ return String::StableHashBytes(str->data, str->size);
}
return ObjectPtrHash()(a);
}
@@ -476,7 +537,7 @@ namespace std {
template <>
struct hash<::tvm::runtime::String> {
std::size_t operator()(const ::tvm::runtime::String& str) const {
- return ::tvm::runtime::String::HashBytes(str.data(), str.size());
+ return ::tvm::runtime::String::StableHashBytes(str.data(), str.size());
}
};
} // namespace std
diff --git a/src/node/structural_hash.cc b/src/node/structural_hash.cc
index fa77b47bd2..6cf796d344 100644
--- a/src/node/structural_hash.cc
+++ b/src/node/structural_hash.cc
@@ -39,7 +39,7 @@
namespace tvm {
-// Define the dispatch functio here since primary user is in this file.
+// Define the dispatch function here since primary user is in this file.
void ReflectionVTable::SHashReduce(const Object* self, SHashReducer reducer)
const {
uint32_t tindex = self->type_index();
if (tindex >= fshash_reduce_.size() || fshash_reduce_[tindex] == nullptr) {
@@ -50,7 +50,7 @@ void ReflectionVTable::SHashReduce(const Object* self,
SHashReducer reducer) con
}
// Hash handler that handles free vars
-// by assigning an unique counter in the order of their ocurrence.
+// by assigning an unique counter in the order of their occurrence.
//
// This algorithm depends on the determinism of the traversal of SHash
function.
// In particular, when we traverse unordered_map, we should first sort
@@ -69,9 +69,9 @@ class SHashHandlerDefault::Impl {
*/
ObjectRef object;
/*! \brief The partially reduce hash value.*/
- size_t reduced_hash;
+ uint64_t reduced_hash;
/*! \brief The expected location in the result stack. */
- size_t result_stack_index = std::numeric_limits<size_t>::max();
+ uint64_t result_stack_index = std::numeric_limits<uint64_t>::max();
/*! \brief Whether the children has been expanded via SEqualReduce */
bool children_expanded{false};
/*! \brief Whether the node is graph node. */
@@ -80,7 +80,7 @@ class SHashHandlerDefault::Impl {
bool map_free_vars;
Task() = default;
- explicit Task(ObjectRef object, size_t reduced_hash, bool map_free_vars)
+ explicit Task(ObjectRef object, uint64_t reduced_hash, bool map_free_vars)
: object(object), reduced_hash(reduced_hash),
map_free_vars(map_free_vars) {}
};
@@ -90,7 +90,7 @@ class SHashHandlerDefault::Impl {
task_stack_.back().graph_node_hash = true;
}
- bool LookupHashedValue(const ObjectRef& key, size_t* hash_value) {
+ bool LookupHashedValue(const ObjectRef& key, uint64_t* hash_value) {
auto it = hash_memo_.find(key);
if (it != hash_memo_.end()) {
hash_value[0] = it->second;
@@ -99,7 +99,7 @@ class SHashHandlerDefault::Impl {
return false;
}
- void SHashReduceHashedValue(size_t hashed_value) {
+ void SHashReduceHashedValue(uint64_t hashed_value) {
pending_tasks_.emplace_back(Task(ObjectRef(nullptr), hashed_value, false));
}
@@ -107,18 +107,18 @@ class SHashHandlerDefault::Impl {
ICHECK(!hash_memo_.count(GetRef<ObjectRef>(var)));
if (map_free_vars) {
// use counter value.
- size_t value = std::hash<size_t>()(free_var_counter_++);
+ uint64_t value = std::hash<uint64_t>()(free_var_counter_++);
pending_tasks_.emplace_back(Task(ObjectRef(nullptr), value, false));
} else {
// use pointer hash
- size_t value = std::hash<const runtime::Object*>()(var);
+ uint64_t value = std::hash<const runtime::Object*>()(var);
pending_tasks_.emplace_back(Task(ObjectRef(nullptr), value, false));
}
}
void SHashReduce(const ObjectRef& object, bool map_free_vars) {
// Directly push the result
- // Note: it is still important to push the result to pendng tasks
+ // Note: it is still important to push the result to pending tasks
// so that the reduction order of hash values stays the same.
if (!object.defined()) {
pending_tasks_.emplace_back(Task(ObjectRef(nullptr), 0, false));
@@ -133,7 +133,7 @@ class SHashHandlerDefault::Impl {
}
}
- size_t Hash(const ObjectRef& object, bool map_free_vars) {
+ uint64_t Hash(const ObjectRef& object, bool map_free_vars) {
ICHECK_EQ(task_stack_.size(), 0U);
ICHECK_EQ(pending_tasks_.size(), 0U);
ICHECK_EQ(result_stack_.size(), 0U);
@@ -147,7 +147,7 @@ class SHashHandlerDefault::Impl {
this->RunTasks();
ICHECK_EQ(result_stack_.size(), 1U);
- size_t ret = result_stack_.back();
+ uint64_t ret = result_stack_.back();
result_stack_.pop_back();
return ret;
}
@@ -170,13 +170,13 @@ class SHashHandlerDefault::Impl {
* \brief Compute the reduced hash value for the task.
* \param task The indicated task.
*/
- size_t ReduceHash(const Task& task) {
- size_t stack_begin = task.result_stack_index;
+ uint64_t ReduceHash(const Task& task) {
+ uint64_t stack_begin = task.result_stack_index;
ICHECK_LE(stack_begin, result_stack_.size());
// combine in the reverse order of the stack.
- size_t reduced_hash = task.reduced_hash;
- for (size_t i = result_stack_.size(); i != stack_begin; --i) {
+ uint64_t reduced_hash = task.reduced_hash;
+ for (uint32_t i = result_stack_.size(); i != stack_begin; --i) {
reduced_hash = support::HashCombine(reduced_hash, result_stack_[i - 1]);
}
result_stack_.resize(stack_begin);
@@ -201,7 +201,7 @@ class SHashHandlerDefault::Impl {
// so that we can distinguish DAG from trees.
if (entry.graph_node_hash) {
entry.reduced_hash = support::HashCombine(entry.reduced_hash,
-
std::hash<size_t>()(graph_node_counter_++));
+
std::hash<uint64_t>()(graph_node_counter_++));
}
hash_memo_[entry.object] = entry.reduced_hash;
}
@@ -241,27 +241,27 @@ class SHashHandlerDefault::Impl {
// The owner of this impl
SHashHandlerDefault* parent_;
// free var counter.
- size_t free_var_counter_{0};
+ uint32_t free_var_counter_{0};
// graph node counter.
- size_t graph_node_counter_{0};
+ uint32_t graph_node_counter_{0};
// record current stack top
bool allow_push_to_stack_{true};
// list of pending tasks to be pushed to the stack.
std::vector<Task> pending_tasks_;
// Internal task stack to executed the task
std::vector<Task> task_stack_;
- // Internal stack to store the result poped from the task stack.
- std::vector<size_t> result_stack_;
+ // Internal stack to store the result popped from the task stack.
+ std::vector<uint64_t> result_stack_;
// reflection vtable
ReflectionVTable* vtable_ = ReflectionVTable::Global();
// map from lhs to rhs
- std::unordered_map<ObjectRef, size_t, ObjectPtrHash, ObjectPtrEqual>
hash_memo_;
+ std::unordered_map<ObjectRef, uint64_t, ObjectPtrHash, ObjectPtrEqual>
hash_memo_;
};
SHashHandlerDefault::SHashHandlerDefault() { impl = new Impl(this); }
SHashHandlerDefault::~SHashHandlerDefault() { delete impl; }
-void SHashHandlerDefault::SHashReduceHashedValue(size_t hashed_value) {
+void SHashHandlerDefault::SHashReduceHashedValue(uint64_t hashed_value) {
return impl->SHashReduceHashedValue(hashed_value);
}
@@ -273,13 +273,13 @@ void SHashHandlerDefault::SHashReduceFreeVar(const
runtime::Object* var, bool ma
impl->SHashReduceFreeVar(var, map_free_vars);
}
-bool SHashHandlerDefault::LookupHashedValue(const ObjectRef& key, size_t*
hashed_value) {
+bool SHashHandlerDefault::LookupHashedValue(const ObjectRef& key, uint64_t*
hashed_value) {
return impl->LookupHashedValue(key, hashed_value);
}
void SHashHandlerDefault::MarkGraphNode() { impl->MarkGraphNode(); }
-size_t SHashHandlerDefault::Hash(const ObjectRef& object, bool map_free_vars) {
+uint64_t SHashHandlerDefault::Hash(const ObjectRef& object, bool
map_free_vars) {
return impl->Hash(object, map_free_vars);
}
@@ -289,11 +289,11 @@ void SHashHandlerDefault::DispatchSHash(const ObjectRef&
key, bool map_free_vars
TVM_REGISTER_GLOBAL("node.StructuralHash")
.set_body_typed([](const ObjectRef& object, bool map_free_vars) -> int64_t
{
- size_t hashed_value = SHashHandlerDefault().Hash(object, map_free_vars);
+ uint64_t hashed_value = SHashHandlerDefault().Hash(object,
map_free_vars);
return static_cast<int64_t>(hashed_value);
});
-size_t StructuralHash::operator()(const ObjectRef& object) const {
+uint64_t StructuralHash::operator()(const ObjectRef& object) const {
return SHashHandlerDefault().Hash(object, false);
}
@@ -302,7 +302,7 @@ struct StringObjTrait {
static constexpr const std::nullptr_t VisitAttrs = nullptr;
static void SHashReduce(const runtime::StringObj* key, SHashReducer
hash_reduce) {
- hash_reduce->SHashReduceHashedValue(runtime::String::HashBytes(key->data,
key->size));
+
hash_reduce->SHashReduceHashedValue(runtime::String::StableHashBytes(key->data,
key->size));
}
static bool SEqualReduce(const runtime::StringObj* lhs, const
runtime::StringObj* rhs,
@@ -371,7 +371,7 @@ void NDArrayHash(const runtime::NDArray::Container* arr,
SHashReducer* hash_redu
}
if (hash_data) {
(*hash_reduce)
- ->SHashReduceHashedValue(runtime::String::HashBytes(
+ ->SHashReduceHashedValue(runtime::String::StableHashBytes(
static_cast<const char*>(arr->dl_tensor.data),
runtime::GetDataSize(arr->dl_tensor)));
}
}
@@ -405,7 +405,7 @@ struct ArrayNodeTrait {
static void SHashReduce(const ArrayNode* key, SHashReducer hash_reduce) {
hash_reduce(static_cast<uint64_t>(key->size()));
- for (size_t i = 0; i < key->size(); ++i) {
+ for (uint32_t i = 0; i < key->size(); ++i) {
hash_reduce(key->at(i));
}
}
@@ -416,7 +416,7 @@ struct ArrayNodeTrait {
}
if (lhs->size() != rhs->size()) return false;
- for (size_t i = 0; i < lhs->size(); ++i) {
+ for (uint32_t i = 0; i < lhs->size(); ++i) {
if (!equal(lhs->at(i), rhs->at(i))) return false;
}
return true;
@@ -425,10 +425,10 @@ struct ArrayNodeTrait {
private:
static bool SEqualReduceTraced(const ArrayNode* lhs, const ArrayNode* rhs,
const SEqualReducer& equal) {
- size_t min_size = std::min(lhs->size(), rhs->size());
+ uint32_t min_size = std::min(lhs->size(), rhs->size());
const ObjectPathPair& array_paths = equal.GetCurrentObjectPaths();
- for (size_t index = 0; index < min_size; ++index) {
+ for (uint32_t index = 0; index < min_size; ++index) {
ObjectPathPair element_paths = {array_paths->lhs_path->ArrayIndex(index),
array_paths->rhs_path->ArrayIndex(index)};
if (!equal(lhs->at(index), rhs->at(index), element_paths)) {
@@ -491,7 +491,7 @@ struct ShapeTupleObjTrait {
static void SHashReduce(const ShapeTupleObj* self, SHashReducer hash_reduce)
{
hash_reduce(self->size);
- for (size_t i = 0; i < self->size; ++i) {
+ for (uint32_t i = 0; i < self->size; ++i) {
hash_reduce(self->data[i]);
}
}
@@ -499,7 +499,7 @@ struct ShapeTupleObjTrait {
static bool SEqualReduce(const ShapeTupleObj* lhs, const ShapeTupleObj* rhs,
SEqualReducer equal) {
if (lhs->size != rhs->size) return false;
- for (size_t i = 0; i < lhs->size; ++i) {
+ for (uint32_t i = 0; i < lhs->size; ++i) {
if (!equal(lhs->data[i], rhs->data[i])) return false;
}
return true;
@@ -539,10 +539,10 @@ struct MapNodeTrait {
// This resolves common use cases where we want to store
// Map<Var, Value> where Var is defined in the function
// parameters.
- using KV = std::pair<size_t, ObjectRef>;
+ using KV = std::pair<uint64_t, ObjectRef>;
std::vector<KV> temp;
for (const auto& kv : *key) {
- size_t hashed_value;
+ uint64_t hashed_value;
if (hash_reduce->LookupHashedValue(kv.first, &hashed_value)) {
temp.emplace_back(hashed_value, kv.second);
}
@@ -553,11 +553,11 @@ struct MapNodeTrait {
// add size to the hash
hash_reduce(static_cast<uint64_t>(key->size()));
// hash the content
- for (size_t i = 0; i < temp.size();) {
- size_t k = i + 1;
+ for (uint32_t i = 0; i < temp.size();) {
+ uint32_t k = i + 1;
for (; k < temp.size() && temp[k].first == temp[i].first; ++k) {
}
- // ties are rare, but we need to skip them to make the hash determinsitic
+ // ties are rare, but we need to skip them to make the hash deterministic
if (k == i + 1) {
hash_reduce->SHashReduceHashedValue(temp[i].first);
hash_reduce(temp[i].second);
@@ -583,7 +583,7 @@ struct MapNodeTrait {
// add size to the hash after sorting.
hash_reduce(static_cast<uint64_t>(key->size()));
// hash the content
- for (size_t i = 0; i < temp.size(); ++i) {
+ for (uint32_t i = 0; i < temp.size(); ++i) {
hash_reduce(temp[i].first);
hash_reduce(temp[i].second);
}
diff --git a/src/relay/backend/utils.h b/src/relay/backend/utils.h
index d5cf4baf72..acaea425d1 100644
--- a/src/relay/backend/utils.h
+++ b/src/relay/backend/utils.h
@@ -696,7 +696,7 @@ struct TargetStrHash {
*/
size_t operator()(const Target& target) const {
std::string s(target->kind->name);
- return String::HashBytes(s.c_str(), s.size());
+ return String::StableHashBytes(s.c_str(), s.size());
}
};