File: hash.cpp

package info (click to toggle)
pytorch 1.13.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 139,252 kB
  • sloc: cpp: 1,100,274; python: 706,454; ansic: 83,052; asm: 7,618; java: 3,273; sh: 2,841; javascript: 612; makefile: 323; xml: 269; ruby: 185; yacc: 144; objc: 68; lex: 44
file content (112 lines) | stat: -rw-r--r-- 3,023 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
 * This file is adapted from PyTorch/XLA
 * https://github.com/pytorch/xla/blob/e0e5f937a0ba8d904f9608137dc8c51ba439df2d/third_party/xla_client/util.h
 */
#include <iomanip>
#include <sstream>

#include <torch/csrc/lazy/core/hash.h>

namespace torch {
namespace lazy {
namespace {

hash_t LoadHash(const uint8_t** data, const uint8_t* top) {
  std::ptrdiff_t size = top - (*data);
  if (size >= (int)sizeof(hash_t)) {
    hash_t v;
    std::memcpy(&v, *data, sizeof(v));
    *data += sizeof(hash_t);
    return v;
  }
  union {
    hash_t h;
    std::array<uint8_t, sizeof(hash_t)> b;
#ifdef _MSC_VER
    // MSVC (or some versions we use) doesn't support C99 union field init
    // but it initializes the first member of the union.
  } uval = {hash_t(0)};
#else
  } uval = {.h = hash_t(0)};
#endif
  // use memcpy for compatibility with platforms not supporting unaligned access
  // note: compiled as single `movl` instr on x64.
  std::memcpy(uval.b.data(), *data, size);
  *data += size;
  return uval.h;
}

} // namespace

hash_t HashBlock(const void* data, size_t n, const hash_t& seed) {
  const hash_t m(static_cast<uint64_t>(0xc6a4a7935bd1e995));
  const int r = 47;

  const uint8_t* u8_data = reinterpret_cast<const uint8_t*>(data);
  const uint8_t* top = u8_data + n;
  hash_t h(seed ^ ((uint64_t)n * m));
  while (u8_data < top) {
    hash_t k = LoadHash(&u8_data, top);
    k *= m;
    k ^= k >> r;
    k *= m;

    h ^= k;
    h *= m;
  }
  h ^= h >> r;
  h *= m;
  h ^= h >> r;
  return h;
}

hash_t DataHash(const void* data, size_t size) {
  return HashBlock(
      data, size, hash_t(static_cast<uint64_t>(0xc2b2ae3d27d4eb4f)));
}

size_t StdDataHash(const void* data, size_t size) {
  return HashReduce(DataHash(data, size));
}

size_t StdHashCombine(uintmax_t a, uintmax_t b) {
  return a ^
      (b * 0x27d4eb2f165667c5 + 0x9e3779b97f4a7c15 + (a << 6) + (a >> 2));
}

hash_t HashCombine(const hash_t& a, const hash_t& b) {
  static const hash_t kb(101, 0x27d4eb2f165667c5);
  return hash_t(
      a ^ (b * kb + (uint64_t)0x9e3779b97f4a7c15 + (a << 6) + (a >> 2)));
}

size_t HashReduce(const hash_t& a) {
  return StdHashCombine(c10::Uint128Low64(a), c10::Uint128High64(a));
}

std::string HashToString(const hash_t& a) {
  std::stringstream ss;
  ss << std::hex << c10::Uint128High64(a) << std::setfill('0') << std::setw(16)
     << Uint128Low64(a);
  return ss.str();
}

hash_t Hash(const std::vector<bool>& values) {
  // We can't assume a DataHash size/dataptr approach here bc
  // vector<bool> can be optimized as vector<bit> and storage details
  // are decoupled from actual size of 'bool' type
  hash_t h(static_cast<uint64_t>(0xad2ed1983bbf2e28));
  static const hash_t h_true(static_cast<uint64_t>(0x74f6b5198daa2b2));
  static const hash_t h_false(static_cast<uint64_t>(0xe39f30789cab5382));
  for (const auto& b : values) {
    if (b) {
      h = HashCombine(h, h_true);
    } else {
      h = HashCombine(h, h_false);
    }
  }
  return h;
}

} // namespace lazy
} // namespace torch