改进价值哈希
Improving value hashing
本文关键字:哈希 更新时间:2023-10-16
目前我有以下几种:
class Transform
{
int N; // set in other functions
std::unordered_map<int,float> cache;
float Wn(int n)
{
std::unordered_map<int,float>::const_iterator got = cache.find(n);
if(got == cache.end())
return cache[n] = sin((M_PI / (2 * N)) * (n + 0.5f));
return cache[n];
}
由于函数Wn
被称为LOT,并且只有n
参数发生了更改,所以我尝试缓存它们。我的问题是,在许多情况下,该函数比没有缓存的情况下需要更长的时间,有时甚至需要25%的时间。有没有优化的方法?
假设输入整数通常在某个小范围内,只需使用一个数组作为缓存即可。即使有些值不能缓存,它也会比哈希更高效。
我仔细查看了您的代码以及可以做些什么来改进它
下面是函数wN()的3个注释版本:
在这种情况下,这并不重要(优化器负责冗余查找),有一种可以说更惯用的正确方法来编写Wn()
首先是原始版本:
float original_cached_wN(int n)
{
// compute hash and search
std::unordered_map<int,float>::const_iterator got = cache.find(n);
if(got == cache.end())
// recompute hash
// search again
// default construct
// overwrite
return cache[n] = compute_wN(n);
// recompute hash
// search again
// default construct
// overwrite
return cache[n];
}
一个惯用的改进版本,考虑到迭代器为我们提供了访问值的权限,这意味着我们不需要使用名义上昂贵的operator[]
float improved_cached_wN(int n)
{
// search
std::unordered_map<int,float>::const_iterator got = cache.find(n);
if(got == cache.end())
{
// emplace the computed value and recover its location
// from the returned pair<iterator, bool>
got = cache.emplace(n, compute_wN(n)).first;
}
// got is an iterator. got->first is the index, got->second is the value
return got->second;
}
最后在不缓存的情况下简单地计算Wn:
float compute_wN(int n) const
{
return sin((M_PI / (2 * N)) * (n + 0.5f));
}
下面是一个测试程序,它允许查看由以下3种方法产生的编译源代码:
#include <iostream>
#include <cmath>
#include <unordered_map>
#include <sstream>
#include <vector>
class Transform
{
int N;
std::unordered_map<int,float> cache;
public:
Transform(int N) : N(N) {}
float original_cached_wN(int n)
{
std::unordered_map<int,float>::const_iterator got = cache.find(n);
if(got == cache.end())
return cache[n] = compute_wN(n);
return cache[n];
}
float improved_cached_wN(int n)
{
std::unordered_map<int,float>::const_iterator got = cache.find(n);
if(got == cache.end())
{
got = cache.emplace(n, compute_wN(n)).first;
}
return got->second;
}
float compute_wN(int n) const
{
return sin((M_PI / (2 * N)) * (n + 0.5f));
}
};
int main()
{
using namespace std;
// this is to defeat the optimiser
// and prefent compile-time evaluation of Wn
std::istringstream ss ("5 4 6 7");
int N = 10, n1 = 0, n2 = 1, n3 = 2;
ss >> N >> n1 >> n2 >> n3;
Transform t1(N);
std::vector<float> v = {
t1.original_cached_wN(n1),
t1.improved_cached_wN(n2),
t1.compute_wN(n3)
};
std::copy(v.begin(), v.end(), std::ostream_iterator<float>(cout, ", "));
std::cout << std::endl;
return 0;
}
预期输出:
0.987688, 0.891007, 0.707107,
从编译后的输出来看,在我看来,搜索和更新地图的成本实际上超过了计算W(n)
的成本
以下是apple clang 7在使用选项-O3 -march=native
编译后为compute_wN()
发出的代码
movl (%rdi), %eax
addl %eax, %eax
vcvtsi2sdl %eax, %xmm0, %xmm0
vmovsd LCPI2_0(%rip), %xmm1 ## xmm1 = mem[0],zero
vdivsd %xmm0, %xmm1, %xmm0
vcvtsi2ssl %r15d, %xmm0, %xmm1
vaddss LCPI2_1(%rip), %xmm1, %xmm1
vcvtss2sd %xmm1, %xmm1, %xmm1
vmulsd %xmm0, %xmm1, %xmm0
callq _sin
老实说,这比地图操作少了很多代码。
相关文章:
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 使用Qt C++计算类似Git的SHA1哈希
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 用C++将哈希表写入文件并从文件中恢复
- c++找不到具有相同哈希的无序集合元素
- 哈希文件递归并保存到矢量Cryptopp中
- 对 pair<pair<int,int>pair<int,int unordered_map进行哈希处理>>
- 直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象
- 如何为字符串生成唯一但一致的 N 位哈希(小于 64 位)?
- 使用对象的基类部分模板专用化对对象进行哈希处理::哈希
- boost::包含提升单元的元组的哈希值
- 使用 Key 对 C++ 中的哈希映射进行排序. 无法排序
- C++中的并发哈希表
- 哈希映射使用 nullptr c++ 初始化节点的动态数组
- 在具有开放寻址的哈希表中插入节点 [优化逻辑]
- 与C++哈希表的基础知识混淆
- 如何为位集找到/实现一个好的哈希函数
- 对于短字符串来说,这是一个很好的哈希函数吗?
- 调整大小和复制哈希表数组中的元素