保存多层地图最快的方法是什么?
what the the fastest way to save multi-layer map?
我想构建一个键值容器来保存数据。
我可以建一个三层的unordered_map
来映射,关键是<int, <int, <int>>>
,但是我觉得比较慢
所以,我想将 <int, int, int>
映射到唯一的 int
。然后我可以将它保存在一级 unordered_map
例如:
假设三个key叫a, b, c
,a的范围是[0, 1e4]
,b[0, 1e6]
c[0, 1e5]
我想写一个这样的函数:
int encode(int a, int b, int c) {
// return a unique int
}
我对时间很敏感,我认为按位可能是最快的方法,但我不知道如何实现它。你能帮忙吗?
你认为这会更快吗?还有,有没有比这更好的方法?
unordered_map
需要返回 size_t
的哈希函数,因此如果您正在编译 64 位应用程序(除了某些嵌入式环境外,大多数人都这样做),您可以简单地组合整数:
size_t encode(int a, int b, int c) {
return a + (b * 10'000) + (c * 10'000 * 1'000'000);
}
如果您的散列 table 使用质数桶(例如 GCC、clang),您可以考虑将上述数字四舍五入为最接近的 2 的幂,因为名义上乘以 2 的幂是CPU 可以更快地完成一个简单的左位移位操作。如果您的实现使用 2 的幂桶计数(例如 Visual C++),那么您应该不惜一切代价避免这种情况:因为当将数字修改为 2 的幂桶计数时,高阶位将被丢弃。例如,如果您有 256 个桶,则 8 个最低有效位确定桶,丢弃更高位。
或者,您可以使用 boost::hash_combine
采用的算法,该算法通常适用于散列多部分密钥:
template <class T>
inline void hash_combine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
你可以这样使用它:
size_t encode(int a, int b, int c) {
size_t seed = 0;
hash_combine(seed, a);
hash_combine(seed, b);
hash_combine(seed, c);
return seed;
}
另一种选择是在内存中并排排列字节(例如将它们复制到变量中 - int x[3]{ a, b, c};
),并应用任何写入的哈希函数来哈希任意内存块,即size_t (const std::byte* p, size_t n)
- 谷歌搜索会出现很多。
我想构建一个键值容器来保存数据。
我可以建一个三层的unordered_map
来映射,关键是<int, <int, <int>>>
,但是我觉得比较慢
所以,我想将 <int, int, int>
映射到唯一的 int
。然后我可以将它保存在一级 unordered_map
例如:
假设三个key叫a, b, c
,a的范围是[0, 1e4]
,b[0, 1e6]
c[0, 1e5]
我想写一个这样的函数:
int encode(int a, int b, int c) {
// return a unique int
}
我对时间很敏感,我认为按位可能是最快的方法,但我不知道如何实现它。你能帮忙吗?
你认为这会更快吗?还有,有没有比这更好的方法?
unordered_map
需要返回 size_t
的哈希函数,因此如果您正在编译 64 位应用程序(除了某些嵌入式环境外,大多数人都这样做),您可以简单地组合整数:
size_t encode(int a, int b, int c) {
return a + (b * 10'000) + (c * 10'000 * 1'000'000);
}
如果您的散列 table 使用质数桶(例如 GCC、clang),您可以考虑将上述数字四舍五入为最接近的 2 的幂,因为名义上乘以 2 的幂是CPU 可以更快地完成一个简单的左位移位操作。如果您的实现使用 2 的幂桶计数(例如 Visual C++),那么您应该不惜一切代价避免这种情况:因为当将数字修改为 2 的幂桶计数时,高阶位将被丢弃。例如,如果您有 256 个桶,则 8 个最低有效位确定桶,丢弃更高位。
或者,您可以使用 boost::hash_combine
采用的算法,该算法通常适用于散列多部分密钥:
template <class T>
inline void hash_combine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
你可以这样使用它:
size_t encode(int a, int b, int c) {
size_t seed = 0;
hash_combine(seed, a);
hash_combine(seed, b);
hash_combine(seed, c);
return seed;
}
另一种选择是在内存中并排排列字节(例如将它们复制到变量中 - int x[3]{ a, b, c};
),并应用任何写入的哈希函数来哈希任意内存块,即size_t (const std::byte* p, size_t n)
- 谷歌搜索会出现很多。