C++ C++;11元组性能

C++ C++;11元组性能,c++,c++11,C++,C++11,我只是想通过在包括单个元素在内的许多情况下使用std::tuple使我的代码更加通用化。我的意思是,例如tuple,而不是double。但我决定检查这个特殊案例的性能 下面是简单的性能基准测试: #include <tuple> #include <iostream> using std::cout; using std::endl; using std::get; using std::tuple; int main(void) { #ifdef TUPLE

我只是想通过在包括单个元素在内的许多情况下使用
std::tuple
使我的代码更加通用化。我的意思是,例如
tuple
,而不是
double
。但我决定检查这个特殊案例的性能

下面是简单的性能基准测试:

#include <tuple>
#include <iostream>

using std::cout;
using std::endl;
using std::get;
using std::tuple;

int main(void)
{

#ifdef TUPLE
    using double_t = std::tuple<double>;
#else
    using double_t = double;
#endif

    constexpr int count = 1e9;
    auto array = new double_t[count];

    long long sum = 0;
    for (int idx = 0; idx < count; ++idx) {
#ifdef TUPLE
        sum += get<0>(array[idx]);
#else
        sum += array[idx];
#endif
    }
    delete[] array;
    cout << sum << endl; // just "external" side effect for variable sum.
}
我认为tuple是一个严格的静态编译模板,在这种情况下,所有get函数都只能执行普通的变量访问。顺便说一句,本测试中的内存分配大小相同。 为什么会出现这种执行时间差

编辑:问题出现在元组对象的初始化中。为了使测试更准确,必须更改一行:

     constexpr int count = 1e9;
-    auto array = new double_t[count];
+    auto array = new double_t[count]();

     long long sum = 0;
之后可以观察到类似的结果:

$ g++ -DTUPLE -g -O2 -std=c++11 test.cpp && (for i in $(seq 3); do time ./a.out; done) 2>&1 | grep real
real    0m3.342s
real    0m3.339s
real    0m3.343s

$ g++ -g -O2 -std=c++11 test.cpp && (for i in $(seq 3); do time ./a.out; done) 2>&1 | grep real
real    0m3.349s
real    0m3.339s
real    0m3.334s

tuple all default构造值(因此所有值都是0)double不会得到默认初始化

在生成的程序集中,以下初始化循环仅在使用元组时出现。否则,它们是等价的

.L2:
    movq    $0, (%rdx)
    addq    $8, %rdx
    cmpq    %rcx, %rdx
    jne .L2

你检查过程序集输出了吗?你运行过多次以确保结果一致吗?你的计算机运行速度有多快mine@koodawg是的,我有。元组的时间稳定在3.3s,w/o--2.9s。@aaronman我将
count
提高到10^9,只是为了让时间上的差异更加明显。我想你可以用10^8作为例子。在汇编中确认。它有两个循环,一个归零,一个求和
double
based one只做一个。@zch如果您愿意,您可以编辑我的答案,而不是在读取moodExcellent观察的程序集中。OP应该写
新的double\t[count]()。比较好,我同意他应该写一个新的测试,我喜欢证明C++和C一样快,并且你应该相信你。compiler@bames53:也许吧,但那真的离题了。如果您使用
vector
,一切都很好,因为您只有在拥有对象时才进行初始化。真正影响性能的是无意义地创建您不需要的对象。(不应使用动态原始数组的另一个原因。)
.L2:
    movq    $0, (%rdx)
    addq    $8, %rdx
    cmpq    %rcx, %rdx
    jne .L2