簡體   English   中英

哈希一個32位整數比對3個16位整數進行哈希運算要慢?

[英]hashing a 32bit integer is slower than bitwise operation on hash of 3 16bit integers?

我正在研究對延遲敏感的軟件。 今天,我決定通過在聯合體內使用BitField結構來使結構更小,並讀取該BitField結構為整數,並將其用作哈希函數的唯一鍵。 我期望從我對唯一鍵的哈希中獲得的性能略好於(如果不是很多的話),比對類的屬性的哈希按位操作獲得更好的性能,但是事實證明,執行按位操作以獲取哈希鍵要快得多嗎? 我一直在試圖找出原因,但是我無法得出任何結論。

這是我的代碼: http : //quick-bench.com/OkNuVOxdVtW8g7OWUXjqcvYlNrs

#include <functional>

struct GroupTupleInformation {
  unsigned int src : 12;
  unsigned int dst : 12;
  unsigned int flow_id : 8;
};

union GroupTupleData {
  GroupTupleInformation info;
  uint32_t hash_key;
};

struct GroupTuple {
  constexpr void setSrc(uint16_t s) noexcept { data.info.src = s; }

  constexpr uint16_t getSrc() const noexcept { return data.info.src; }

  constexpr void setDst(uint16_t d) noexcept { data.info.dst = d; }

  constexpr uint16_t getDst() const noexcept { return data.info.dst; }

  constexpr void setFlowId(uint8_t f) noexcept { data.info.flow_id = f; }

  constexpr uint8_t getFlowId() const noexcept { return data.info.flow_id; }

  constexpr uint32_t getHashKey() const noexcept { return data.hash_key; }

 private:
  GroupTupleData data;
};

struct UnionHashFn {
  constexpr std::size_t operator()(const GroupTuple& gtup) const noexcept {
    return gtup.getHashKey();
  }
};

struct CombinedHashFn {
  std::size_t operator()(const GroupTuple& gtup) const noexcept {
    std::hash<uint16_t> hasher{};
    return hasher(gtup.getSrc()) ^ hasher(gtup.getDst()) ^
           hasher(gtup.getFlowId());
  }
};


static void UnionHashFnBench(benchmark::State& state) {
  unsigned long i = 0;
  UnionHashFn hasher;
  GroupTuple group_tuple;

  size_t key = 0;
  for (auto _ : state) {
    group_tuple.setSrc(i++ % 32);
    group_tuple.setDst(i++ % 32);
    group_tuple.setFlowId(i++ % 32);
    key = hasher(group_tuple);
    benchmark::DoNotOptimize(key);
  }
}
BENCHMARK(UnionHashFnBench);

static void CombinedHashFnBench(benchmark::State& state) {
  unsigned long i = 0;
  CombinedHashFn hasher;
  GroupTuple group_tuple;

  size_t key = 0;
  for (auto _ : state) {
    group_tuple.setSrc(i++ % 32);
    group_tuple.setDst(i++ % 32);
    group_tuple.setFlowId(i++ % 32);
    key = hasher(group_tuple);
    benchmark::DoNotOptimize(key);
  }
}
BENCHMARK(CombinedHashFnBench);

PS:我知道對基准圖或unordered_map進行基准測試要比對散列函數的基准進行基准測試更為復雜,而且我也知道我為從類中獲取散列所做的按位操作不是獲取散列的好方法,這只是為了有一個簡單的例子

std::hash<uint16_t>只是身份(說實話,這是有問題的),因此表達式:

hasher(gtup.getSrc()) ^ hasher(gtup.getDst()) ^ hasher(gtup.getFlowId())

將被優化為一個非常簡單的表達式。 它的代碼是:

   lea    -0x2(%rax),%ecx
   lea    -0x1(%rax),%edx
   xor    %ecx,%edx
   xor    %eax,%edx
   and    $0x1f,%edx

另一方面,計算hash_key需要付出更多努力:

   mov    %edx,%esi
   and    $0x1f,%esi
   mov    %ecx,%edi
   and    $0x1f000,%edi
   or     %rsi,%rdi
   add    $0x3,%rdx
   mov    %eax,%esi
   and    $0x1f000000,%esi
   or     %rdi,%rsi

因此, hash_key方法較慢並不奇怪。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM