为什么clock()被认为是不好的?

15

曾有人建议我使用平台相关的方法(Windows下的GetTickCount())来获取时间,而不是使用clock(),因为它很糟糕或不可靠。 为什么?还有许多人建议使用<chrono>头文件函数,但是我在我的IDE(VS 2010)中找不到它。

我的目标是游戏开发,如果这有影响。


3
可能会感兴趣:http://en.cppreference.com/w/cpp/chrono/c/clock - Galik
@Galik <chrono> 的函数看起来很不错,但我没有那个头文件。能下载到吗? - McLovin
1
如果您使用的是C++11,那么您就有了这个头文件。您可能需要设置编译器标志来启用C++11(对于GCC而言,标志为:-std=c++11)。 - Galik
2
VS2010对C++11只有部分支持,这就是为什么你没有<chrono>的原因。 - Alex
因为这是一个新的头文件,它能在旧机器上运行吗? - McLovin
显示剩余2条评论
2个回答

21

并不是说 clock() 是被视为不好的,而是它没有按人们通常想象的那样定义运行方式。换句话说,它没有指定生成墙钟时间或“真实”时间。

clock() 被定义为告诉您使用了多少 CPU 时间;使用更多线程会使用更多 CPU 时间,睡眠线程使用较少时间。

其次,并非所有平台都实现相同的行为;一些平台将 clock() 实现为应该给出墙钟时间。因此,可移植代码既不能用于一个目的也不能用于另一个目的。


然而,即使对于非可移植的用途,clock() 可能被认为是不好的原因之一是它具有“类型不安全”的 API,该 API 不区分时间点和时间持续时间,并且不能安全地管理时间单位。例如,使用其 API,一个人可能会轻易地混合表示微秒的值与表示毫秒的值。
C++11 的 <chrono> API 在这些方面要好得多。唯一的问题是 <chrono> 没有 CPU 时间时钟。如果您想要墙上时钟时间,那么 std::chrono::steady_clock 是最佳选择;它具有类型安全的 API,并且被定义为“以实时稳定速率前进”。

http://coliru.stacked-crooked.com/a/6df6c71a436092e3

每个线程休眠0.1秒。
经过的墙壁时间:0.101213秒。
经过的CPU时间:0秒。
每个线程旋转0.1秒。
经过的墙壁时间:0.100304秒。
经过的CPU时间:0.4秒。


以下是使用std::clock()<chrono>风格时钟,仅供娱乐:

#include <chrono>
#include <ratio>
#include <ctime>

struct cpu_clock {
    using rep = std::clock_t;
    using period = std::ratio<1, CLOCKS_PER_SEC>;
    using duration = std::chrono::duration<rep, period>;
    using time_point = std::chrono::time_point<cpu_clock, duration>;

    static const bool is_steady = false;

    static time_point now() noexcept {
        return time_point{duration{std::clock()}};
    }
};

1
"wall-clock time" 是什么意思? - McLovin
1
考虑以下代码:void func(void *x) { while(true) {} } void main() { _beginthread(func, 0, 0); while(true) cout << clock() << endl; }CPU 时间应该是正常速度的两倍,但实际上并不是。为什么? - McLovin
@Pilpel 最明显的答案是你的代码显然是在 Windows 上编写的,而 Visual Studios 中的 clock 函数出了问题。 - James Kanze
5
“wall-clock time” 正是指挂在你墙上的时钟所测量的时间。 - Martin Tournoij
1
@immibis 实际上,“墙钟时间”通常意味着单调时间;在使用墙钟计时任务时,您通常不会重置时钟。 墙钟时间与我们所谓的“日历”时间或系统时间形成对比,后者仅表示流行时间保持方案下的“当前”时间,并且由于各种原因而进行调整,因此在准确计时持续时间方面没有太大用处。 chrono :: steady_clock将允许您确定墙钟持续时间,而chrono :: system_clock将(可能)为您提供“日历”时间。 - bames53
显示剩余4条评论

9
根据cppreference.com: std::clock(),std::clock()函数返回的时间可能比墙上时钟快或慢,这取决于操作系统所赋予程序的执行资源。例如,如果CPU被其他进程共享,则std::clock()时间可能比墙上时钟慢。另一方面,如果当前进程是多线程的,并且有多个执行核心可用,则std::clock()时间可能比墙上时钟快。
此外,clock()函数返回的值在某些实现中可能会溢出。例如,在一个具有32位std::clock_t的机器上,它在2147秒或36分钟后溢出。
希望这能够帮助您。

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