【问题标题】:Boost tuple performance提高元组性能
【发布时间】:2010-11-29 08:33:43
【问题描述】:

根据boost::tuple documentation,访问元组的单个元素与访问成员变量具有相同的性能。例如,给定以下声明:

tuple<A, B, C> t1(A(), B(), C());
struct T { A a; B b; C c; }
T t2;

这两个语句的性能应该相同(或差异可以忽略不计):

t1.get<2>();
t2.c;

我查看了 boost::tuple 的来源,如果我理解正确(我不确定我是否理解),get&lt;N&gt; 函数实际上执行了这个操作:

C get<2>(tuple<A, B, C>& t)
{
    return t.tail.tail.head;
    //Generally:  return t.tail. <<N times>> .head;
}

这更像是在链表中查找而不是直接访问,并且据我所知,它具有 O(N) 复杂度,而不是 O(1),这是成员访问所期望的。从我过去使用 boost 的经验来看,我认为我理解错了。但我的错误是什么? get 到底是如何工作的?

【问题讨论】:

  • 我猜这很大程度上依赖于编译时优化

标签: c++ templates boost boost-tuples


【解决方案1】:

您对类似列表的性能是正确的。但是,它可以在编译时解决,因此在运行时归结为 O(1)。 (给定一个足够好的优化编译器。)

【讨论】:

  • 你的意思是,如果我在 for 循环中遍历“尾部”,它是计算运行时间的,但如果我只写t.tail.tail.tail.tail.tail.tail.tail.head,那么现代编译器可以将其优化为直接访问最终物品?有没有一种简单的方法可以知道我的编译器用它做了什么?
  • 哪些编译器实际上会执行该优化?
  • 如果优化器可以正确展开循环,那么它也可以很好地展开。请注意,您在这里处理的是编译时常量结构,而不是普通的动态数据结构。
  • 要了解您的编译器是否优化了链式成员访问,您可以查看生成的汇编代码。
  • 我刚刚检查过了。 MSVC 确实将链式访问折叠为一个操作(无论如何,对于一个八成员元组)。您可以检查项目属性对话框的输出文件部分的“程序集和源代码”属性。我认为给 GCC 提供 -S 选项会起到类似的作用。
【解决方案2】:

请记住,在 C++ 中,点运算符不是指针引用,而是直接偏移计算。一般的答案是肯定的,所有 n 的 i1.i2.i3.in 是一个可在编译时计算的常数时间操作。

如果您想在不深入挖掘的情况下了解一些关于编译器内部的知识,请查看 LLVM getelementptr http://llvm.org/docs/LangRef.html#i_getelementptr 这正是像 CLANG 这样的 C++ 编译器在编译结构引用时针对 LLVM 的方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 2013-02-12
    • 2021-12-18
    相关资源
    最近更新 更多