【问题标题】:boost::multi_index composite keys efficiencyboost::multi_index 复合键效率
【发布时间】:2013-12-01 14:18:02
【问题描述】:

长期读者第一次海报!我正在玩 boost::multi_index 容器的东西,并且有一个相当深入的问题,希望 boost 或 C++ 容器专家可能知道(我在 C++ 容器方面的知识非常基础)。作为参考,可以在此处找到有关复合键的 boost 文档:boost::multi_index composite keys.

当使用复合键时,文档指出“复合键按字典顺序排序,即按第一个键执行排序,如果第一个键相等,则按第二个键执行排序,等等”。这是否意味着存储结构以便查找特定的 2 部分复合键将花费 O(n=1) 时间,即容器是否已排序,以便有一个直接指向每个项目的指针,或者提升容器检索与组合键的第一部分匹配的列表,然后需要执行与键的第二部分匹配的项目的搜索,因此速度较慢?

例如,如果我要使用两个不同的索引手动维护两个容器,并且想要查找与特定的 2 部分查询匹配的项目,我可能会过滤第一个容器以查找与查询的第一部分匹配的所有项目,并且然后过滤与查询的第二部分匹配的项目的结果。因此,这种手动方法将有效地涉及两次搜索。 boost 是否有效地做到了这一点,或者它是否通过使用复合键以某种方式提高了效率?

希望我已经在这里解释了自己,但请提出问题,我会尽力澄清我的意思!

【问题讨论】:

  • 一个例子说 1000 个单词。它还让我们有机会快速进行一些测量并深入研究库的实现。
  • 我认为既然 boost::multi_index 文档中有一个示例(通过我输入的超链接),就不值得在这里重复了?

标签: c++ boost composite-key processing-efficiency multi-index


【解决方案1】:

涉及复合键的查找不会像您描述的那样经历任何两阶段过程。 composite_key-induced orderings 是正常的排序,唯一的特殊之处是它依赖于两个或多个元素键而不是一个。

也许一个例子会澄清。考虑使用composite_key

struct element
{
  int x,y,z;
};

typedef multi_index_container<
  element,
  indexed_by<
    ordered_unique<
      composite_key<
        element,
        member<element,int,&element::x>,
        member<element,int,&element::y>,
        member<element,int,&element::z>
      >
    >
  >
> multi_t;

生成的容器在某种意义上等同于:

struct element_cmp
{
  bool operator()(const element& v1, const element& v2)const
  {
    if(v1.x<v2.x)return true;
    if(v2.x<v1.x)return false;
    if(v1.y<v2.y)return true;
    if(v2.y<v1.y)return false;
    return v1.z<v2.z;
  }
};

typedef std::set<element,element_cmp> set_t;

composite_key 自动生成与element_cmp::operator() 中的代码等效的代码,并且还允许仅查找前 n 个键,但相对于使用 std::set 的情况,底层数据结构不会改变。

【讨论】:

  • 那么就查找时间而言,查找如何比较三个索引中的每一个?也就是说,你能比所有说 x=1、y=2、z=3 的键更快地检索所有说 x=1 的键吗?如果只查找 z=3 会怎样?顺便说一句,感谢您到目前为止的回复,我想我们正在磨练我的回答:)!
  • 提供的示例没有三个索引,而只有一个,凭借复合键,允许在 x、(x,y) 和 (x,y,z) 上查找所有其中(大致)具有相同的性能。要有效地查找 z 值,您需要在其上添加一个索引。
  • 啊,好吧,如果我有三个单独的索引并且包含所有三个索引的复合材料,使用复合材料会比仅使用 z 索引慢吗?这就是我的问题的重点,boost 复合键搜索的效率如何,它实际上是否比为单个索引之一获取迭代器更快,然后使用您检索到的迭代器在 multi_index 容器之外进行另一个过滤器。或者它是否有效地为您完成了所有这些工作,因此只是一种更好、更清洁的方式?抱歉,我知道我在问一个奇怪的问题。
  • 如果你想查找 x=1, y=2, z=3,使用composite_key 比查找x=1 和后过滤要快很多结果(通过线性扫描)。此外,没有办法分别在 x、y 和 z 上使用三个不同的索引来更有效地进行 (x=1,y=2,z=3) 查找。我认为您混淆了术语:在 (x,y,z) 上具有复合键的索引与 x、y 和 z 上的三个单独索引相同。
  • 好的,谢谢,这正是我想知道的:)!所以它确实创建了某种指针结构,这意味着对三个单独的索引有很好的加速。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-26
  • 1970-01-01
  • 2016-03-23
  • 2011-03-29
  • 1970-01-01
  • 2017-01-27
  • 1970-01-01
相关资源
最近更新 更多