1

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

我正在使用带有属性的POSIX函数。所以我得到了纳秒精度(1/1000000000sec)的时间规格,据说以这种方式获得时间规格值只需要几个处理器滴答声。clock_gettimeCLOCK_MONOTONIC

这是我用来保存时间规格的两个函数。我还添加了正在使用的数据结构的定义:

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);
    }
}

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

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

我在 Java 方面有各种经验,但我对 c++ 还是很陌生。我不太了解这里的情况。我正在使用 O3 标志进行优化级别。我的 QMake 配置: QMAKE_CXXFLAGS += -O3 -march=native

那么,谁能告诉我,这段小代码的哪一部分在运行时变得更快,如何以及为什么?我怀疑附加到 QVector。优化是否会以某种方式影响这一点?

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

4

2 回答 2

3

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

于 2012-09-25T21:06:53.037 回答
3

您的测量代码中有很多潜在的首次成本,这里有几个以及如何测试它们。

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

此外,该向量很可能会从分配少量内存开始,然后随着您添加更多数据而以指数方式分配更多内存(此类容器的标准折衷方案)。因此,您将在运行时开始时分配许多内存,然后频率会随着时间的推移而降低。

您可以通过查看 的返回值来验证这是否正在发生QVector::capacity(),并通过以下方式调整行为QVector::reserve(int)- 例如,如果您这样做timeMemory.reserve(10000);procMemory.reserve(10000);您可以在测量开始之前为前一万次测量保留足够的空间。

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

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

于 2012-09-26T03:30:46.397 回答