时序算法:C++中的clock()与time()函数比较

68

对于测量算法时间(大约以毫秒为单位),以下两种方法哪种更好:

clock_t start = clock();
algorithm();
clock_t end = clock();
double time = (double) (end-start) / CLOCKS_PER_SEC * 1000.0;

或者,

time_t start = time(0);
algorithm();
time_t end = time(0);
double time = difftime(end, start) * 1000.0;

此外,从Freenode的C++频道的一些讨论中,我了解到clock的分辨率非常差,因此对于(相对)快速的算法,计时将为零。但是,time()和clock()哪个具有更好的分辨率?或者它们是相同的吗?


您的参数顺序错误,导致difftime函数无法正常运行。 - Steinin
5个回答

60

<chrono> 如果你使用 C++11,那么它会是一个更好的库。

#include <iostream>
#include <chrono>
#include <thread>

void f()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

int main()
{
    auto t1 = std::chrono::high_resolution_clock::now();
    f();
    auto t2 = std::chrono::high_resolution_clock::now();
    std::cout << "f() took "
              << std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count()
              << " milliseconds\n";
}

以下示例取自此处


47

这取决于您想要什么: time 是实际时间的测量,而clock则是当前进程所花费的处理时间。如果您的进程睡眠了相当长的时间,或者系统正在执行其他进程,则两者将非常不同。

http://en.cppreference.com/w/cpp/chrono/c/clock


5
clock 还受本地并行性的影响。在并行区域使用 N 个线程的 OpenMP 将导致所有 clock 返回值增加(约)N 倍快。 - Dan

10

time_t 结构体很可能是一个整数,这意味着它的精度为秒。

第一段代码:它只记录 CPU 在执行任务时所用的时间,因此当您使用 sleep()函数时,它不会记录任何内容。虽然可以通过计算 sleep() 函数的时间来避开这个问题,但是随着时间的推移,这种方法可能会出现偏差。

第二段代码:仅能获得秒级别的时间分辨率,如果需要亚秒级别的时间读取,则不太适用。

要获得最高分辨率的时间读数,您应该像这样进行操作:

double getUnixTime(void)
{
    struct timespec tv;

    if(clock_gettime(CLOCK_REALTIME, &tv) != 0) return 0;

    return (tv.tv_sec + (tv.tv_nsec / 1000000000.0));
}

double start_time = getUnixTime();
double stop_time, difference;

doYourStuff();

stop_time = getUnixTime();
difference = stop_time - start_time;

在大多数系统上,它的分辨率将降至几微秒,但它可能因不同的CPU甚至主要内核版本而有所不同。


4
return 行中的显式转换为 double 是多余的,因为两个算术运算符都至少对一个 double 参数进行操作(即字面量,然后是除法的结果)。此外,您应该使用更简洁的文字表示法:我认为 return tv.tv_sec + tv.tv_nsec / 1.0e9; 更易读。 - Stefan Majewsky
“所以当你执行sleep()时,它不会计算任何东西”这是真的吗?我测试了sleep,它在时钟中得到计算。 - user1633272

2
"

<chrono> 是最好的。Visual Studio 2013 提供了这个功能。就我个人而言,我尝试过上面提到的所有方法。我强烈推荐使用 <chrono> 库。它可以跟踪墙上时间,并且具有很好的分辨率(远低于一秒)。

"

0

gettimeofday()怎么样?当它被调用时,它会更新两个结构体(timevaltimezone),其中包含时间信息。通常,传递一个timeval结构体就足够了,而timezone结构体可以设置为NULL。更新后的timeval结构体将有两个成员tv_sectv_usectv_sec是自1970年1月1日00:00:00(Unix纪元)以来的秒数,而tv_usec是相对于tv_sec的附加微秒数。因此,可以获得非常高分辨率的时间。

可以按以下方式使用:

#include <time.h>

struct timeval start_time;
double mtime, seconds, useconds;
gettimeofday(&start_time, NULL); //timeval is usually enough
int seconds  = start_time.tv_sec; //time in seconds
int useconds = start_time.tv_usec; //further time in microseconds
int desired_time = seconds * 1000000 + useconds; //time in microseconds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接