函数的执行时间在运行时减少。 (C ++)为什么?

时间:2012-09-25 20:55:25

标签: c++ qt posix qmake timespec

出于某些测试目的,我编写了一段代码,用于测量实时视频处理代码中几个快速操作的执行时间。事情很好。我得到了非常逼真的结果,但我注意到了一个有趣的特点。

我正在使用带有clock_gettime属性的 POSIX 函数CLOCK_MONOTONIC。所以我得到的是具有纳秒精度(1 / 1000000000sec)的timespecs,并且据说以这种方式获得一个timespec值只需要几个处理器滴答。

以下是我用于保存timespecs的两个函数。我还添加了正在使用的数据结构的定义:

QVector<long> timeMemory;
QVector<std::string> procMemory;
timespec moment;

void VisionTime::markBegin(const std::string& action) {
    if(measure){
    clock_gettime(CLOCK_MONOTONIC, &moment);
    procMemory.append(action + ";b");
    timeMemory.append(moment.tv_nsec);
    }
}

void VisionTime::markEnd(const std::string& action) {
    if(measure){
    clock_gettime(CLOCK_MONOTONIC, &moment);
    procMemory.append(action + ";e");
    timeMemory.append(moment.tv_nsec);
    }
}

我正在将结果收集到稍后使用的几个QVectors中。

我注意到当这两个函数第一次执行时(彼此之后,它们之间没有任何内容),两个保存的时间规格之间的差异是~34000ns。下次差异大约小2倍。等等。如果我执行它们数百次,那么平均差异是~2000ns。 因此,这些函数的平均循环执行时间比第一个函数少大约17000倍。 由于我连续进行了数百次测量,对我来说,一些首次执行的持续时间要长一点并不重要。但无论如何它只是让我感兴趣,为什么会这样?

我有各种Java经验,但我对c ++很新。我不太清楚这里有什么工作。 我正在使用O3标志进行优化级别。 我的QMake conf: QMAKE_CXXFLAGS += -O3 -march=native

那么,任何人都可以说,这个小代码的哪一部分在运行时变得更快,如何以及为什么?我怀疑附加到QVector。优化会以某种方式影响这个吗?

这是我在stackoverflow上的第一个问题,希望它不会太长:)非常感谢您的所有回复!

2 个答案:

答案 0 :(得分:2)

这可能是由于分支预测。 http://en.wikipedia.org/wiki/Branch_predictor

答案 1 :(得分:2)

您的测量代码中有相当多的潜在首次成本,这里有一对以及如何测试它们。

内存分配:这些QVectors在第一次使用它们之前不会在堆上分配任何内存。

此外,向量很可能通过分配少量内存开始,然后在添加更多数据时以指数方式分配(对于像这样的容器的标准折衷)。因此,在运行时开始时将有许多内存分配,然后频率会随着时间的推移而减少。

您可以通过查看QVector::capacity()的返回值来验证是否发生这种情况,然后按QVector::reserve(int)调整行为 - 例如如果您执行timeMemory.reserve(10000);procMemory.reserve(10000);,则可以在测量开始之前为前一万次测量预留足够的空间。

延迟符号绑定:默认情况下,动态链接器不会解析来自Qt(或其他共享库)的符号,直到需要它们为止。因此,如果这些测量函数是代码中第一个调用某些QVectorstd::string函数的函数,那么动态链接器将需要做一些一次性的工作来解决这些函数,这需要时间

如果确实如此,您可以通过在Linux上设置环境变量LD_BIND_NOW=1或在Mac上设置DYLD_BIND_AT_LAUNCH=1来禁用延迟加载。