我试图使用时间()来测量我的程序的各个点。
我不明白的是为什么前后的值是一样的?我知道这不是分析我的程序的最佳方式,我只是想看看需要多长时间。
printf("**MyProgram::before time= %ld\n", time(NULL));
doSomthing();
doSomthingLong();
printf("**MyProgram::after time= %ld\n", time(NULL));
我试过:
struct timeval diff, startTV, endTV;
gettimeofday(&startTV, NULL);
doSomething();
doSomethingLong();
gettimeofday(&endTV, NULL);
timersub(&endTV, &startTV, &diff);
printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);
我如何读取**时间花费= 0 26339的结果?这是否意味着26339纳秒= 26.3毫秒?
**时间= 4 45025,这是否意味着4秒25毫秒?
c++ std::chrono具有跨平台的明显优势。
然而,与POSIX clock_gettime()相比,它也引入了显著的开销。
在我的Linux机器上,所有std::chrono::xxx_clock::now()味道的执行大致相同:
std::chrono::system_clock::now()
std::chrono::steady_clock::now()
std::chrono::high_resolution_clock::now()
虽然POSIX clock_gettime(CLOCK_MONOTONIC, &time)应该与steady_clock::now()相同,但它要快x3倍以上!
这是我的测试,为了完整性。
#include <stdio.h>
#include <chrono>
#include <ctime>
void print_timediff(const char* prefix, const struct timespec& start, const
struct timespec& end)
{
double milliseconds = end.tv_nsec >= start.tv_nsec
? (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3
: (start.tv_nsec - end.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec - 1) * 1e3;
printf("%s: %lf milliseconds\n", prefix, milliseconds);
}
int main()
{
int i, n = 1000000;
struct timespec start, end;
// Test stopwatch
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < n; ++i) {
struct timespec dummy;
clock_gettime(CLOCK_MONOTONIC, &dummy);
}
clock_gettime(CLOCK_MONOTONIC, &end);
print_timediff("clock_gettime", start, end);
// Test chrono system_clock
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < n; ++i)
auto dummy = std::chrono::system_clock::now();
clock_gettime(CLOCK_MONOTONIC, &end);
print_timediff("chrono::system_clock::now", start, end);
// Test chrono steady_clock
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < n; ++i)
auto dummy = std::chrono::steady_clock::now();
clock_gettime(CLOCK_MONOTONIC, &end);
print_timediff("chrono::steady_clock::now", start, end);
// Test chrono high_resolution_clock
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < n; ++i)
auto dummy = std::chrono::high_resolution_clock::now();
clock_gettime(CLOCK_MONOTONIC, &end);
print_timediff("chrono::high_resolution_clock::now", start, end);
return 0;
}
这是我用gcc7.2 -O3编译时得到的输出:
clock_gettime: 24.484926 milliseconds
chrono::system_clock::now: 85.142108 milliseconds
chrono::steady_clock::now: 87.295347 milliseconds
chrono::high_resolution_clock::now: 84.437838 milliseconds
正如其他人已经注意到的,C标准库中的time()函数的分辨率不超过1秒。唯一可以提供更好分辨率的完全可移植的C函数似乎是clock(),但它测量的是处理器时间而不是wallclock时间。如果一个人满足于将自己局限于POSIX平台(例如Linux),那么clock_gettime()函数是一个很好的选择。
从c++ 11开始,就有了更好的计时工具,以一种可以在不同编译器和操作系统间移植的形式提供了更好的分辨率。类似地,boost::datetime库提供了良好的高分辨率计时类,这些类应该是高度可移植的。
One challenge in using any of these facilities is the time-delay introduced by querying the system clock. From experimenting with clock_gettime(), boost::datetime and std::chrono, this delay can easily be a matter of microseconds. So, when measuring the duration of any part of your code, you need to allow for there being a measurement error of around this size, or try to correct for that zero-error in some way. Ideally, you may well want to gather multiple measurements of the time taken by your function, and compute the average, or maximum/minimum time taken across many runs.
为了帮助解决所有这些可移植性和统计数据收集问题,我一直在Github上开发cxx-rtimers库,它试图为c++代码的计时块提供一个简单的API,计算零错误,并从代码中嵌入的多个计时器报告统计数据。如果你有一个c++ 11编译器,你只需简单地#include <rtimers/cxx11.hpp>,并使用如下代码:
void expensiveFunction() {
static rtimers::cxx11::DefaultTimer timer("expensiveFunc");
auto scopedStartStop = timer.scopedStart();
// Do something costly...
}
在程序退出时,你会得到一个写入std::cerr的时间统计摘要,例如:
Timer(expensiveFunc): <t> = 6.65289us, std = 3.91685us, 3.842us <= t <= 63.257us (n=731)
它显示了平均时间,它的标准偏差,上限和下限,以及这个函数被调用的次数。
如果你想使用特定于linux的计时函数,你可以#include <rtimers/posix.hpp>,或者如果你有Boost库但是一个旧的c++编译器,你可以#include <rtimers/ Boost .hpp>。这些计时器类也有不同版本,可以跨多个线程收集统计计时信息。还有一些方法允许您估计与两个立即连续的系统时钟查询相关的零错误。