![](/img/trans.png)
[英]Is there a way to get a 32bit C++ compiler to follow 16bit integer promotion rules?
[英]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.