You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by mo...@apache.org on 2021/04/07 04:19:52 UTC

[tvm] branch main updated: [FIX] Make HashCombine stable across platforms (#7801)

This is an automated email from the ASF dual-hosted git repository.

moreau 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 3ce74f0  [FIX] Make HashCombine stable across platforms (#7801)
3ce74f0 is described below

commit 3ce74f00a5168473578d7e420c3824eed91a1f62
Author: Tristan Konolige <tr...@gmail.com>
AuthorDate: Tue Apr 6 21:19:34 2021 -0700

    [FIX] Make HashCombine stable across platforms (#7801)
    
    * [FIX] Make HashCombine stable across platforms
    
    PR #7605 inadvertatly broke cross platform hashing when when it switched
    size_t to uint64_t. This cause a different specialization of HashCombine
    to be used. Unfortunately the new specialization used std::hash which is
    implementation dependent. I've added tests to make sure this doesn't
    happen again.
    
    * fix template specialization issues
---
 src/support/utils.h       | 19 ++++++++-----------
 tests/cpp/support_test.cc | 13 +++++++++++++
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/src/support/utils.h b/src/support/utils.h
index 91b9c13..2f55d40 100644
--- a/src/support/utils.h
+++ b/src/support/utils.h
@@ -165,22 +165,19 @@ inline int Execute(std::string cmd, std::string* err_msg) {
 #endif  // __hexagon__
 
 /*!
- * \brief Combine two hash values into a single one.
+ * \brief hash an object and combines uint64_t key with previous keys
+ *
+ * This hash function is stable across platforms.
+ *
  * \param key The left operand.
  * \param value The right operand.
  * \return the combined result.
  */
-inline size_t HashCombine(size_t key, size_t value) {
-  return key ^ (value + 0x9e3779b9 + (key << 6) + (key >> 2));
-}
-
-/*!
- * \brief hash an object and combines uint64_t key with previous keys
- */
-template <typename T>
+template <typename T, std::enable_if_t<std::is_convertible<T, uint64_t>::value, bool> = true>
 inline uint64_t HashCombine(uint64_t key, const T& value) {
-  std::hash<T> hash_func;
-  return key ^ (hash_func(value) + 0x9e3779b9 + (key << 6) + (key >> 2));
+  // XXX: do not use std::hash in this function. This hash must be stable
+  // across different platforms and std::hash is implementation dependent.
+  return key ^ (uint64_t(value) + 0x9e3779b9 + (key << 6) + (key >> 2));
 }
 
 }  // namespace support
diff --git a/tests/cpp/support_test.cc b/tests/cpp/support_test.cc
index bc9b944..7d523fe 100644
--- a/tests/cpp/support_test.cc
+++ b/tests/cpp/support_test.cc
@@ -21,6 +21,7 @@
 #include <gtest/gtest.h>
 
 #include "../../src/support/hexdump.h"
+#include "../../src/support/utils.h"
 
 namespace tvm {
 namespace test {
@@ -43,6 +44,18 @@ TEST(HexDumpTests, Unaligned) {
                               "\x01\x23\x45\x67\x89\xab\xcd\xef\x01"));
 }
 
+TEST(HashTests, HashStability) {
+  size_t a = 345292;
+  int b = 795620;
+  EXPECT_EQ(::tvm::support::HashCombine(a, b), 2677237020);
+  uint64_t c = 12345;
+  int d = 987654432;
+  EXPECT_EQ(::tvm::support::HashCombine(c, d), 3642871070);
+  size_t e = 1010101;
+  size_t f = 3030303;
+  EXPECT_EQ(::tvm::support::HashCombine(e, f), 2722928432);
+}
+
 }  // namespace test
 }  // namespace tvm