使用相同的密钥加速对许多std :: maps的访问

时间:2013-01-16 07:52:22

标签: c++ performance boost

假设您有std::vector<std::map<std::string, T> >。您知道所有map都具有相同的密钥。它们可能已经用

初始化
typedef std::map<std::string, int> MapType;
std::vector<MapType> v;
const int n = 1000000;
v.reserve(n);
for (int i=0;i<n;i++)
{
    std::map<std::string, int> m;
    m["abc"] = rand();
    m["efg"] = rand();
    m["hij"] = rand();
    v.push_back(m);
}

给定一个密钥(例如"efg"),我想提取给定密钥的地图的所有值(绝对存在于每个地图中)。

是否可以加快以下代码?

std::vector<int> efgValues;
efgValues.reserve(v.size());
BOOST_FOREACH(MapType const& m, v)
{
    efgValues.push_back(m.find("efg")->second);
}

请注意,值不一定是int。由于分析确认大部分时间花在find函数上,我在考虑是否存在(GCC和MSVC兼容的C ++ 03)方法,以避免再次根据每个映射的键在地图中定位元素,因为所有地图的结构都是相同的。

如果不是,是否可以使用boost::unordered_map(使用上面的代码在我的机器上慢15%)?是否可以缓存字符串的哈希值?

P.S。:我知道拥有std::map<std::string, std::vector<T> >可以解决我的问题。但是,我无法更改数据结构(这实际上比我在此处显示的更复杂)。

1 个答案:

答案 0 :(得分:2)

您可以使用有状态比较器缓存和回放比较结果序列。但这只是令人讨厌的;解决方案是调整数据结构。没有“不能”。实际上,添加有状态比较器正在改变数据结构。这个要求几乎排除了任何东西。

另一种可能性是在T类型的对象之间创建链接列表,这样您就可以从每个地图到另一个地图而无需另外查找。如果您可能从任何地图开始(请重新构建结构),那么循环或双向链接列表就可以解决问题。

  

由于分析确认大部分时间都花在了查找功能

保持树数据结构并优化比较只能加快比较速度。除非在operator< (std::string const&, std::string const&)中花费时间,否则您需要更改它链接在一起的方式。