在MinGW GCC 8.2.0中正确实现了clock_gettime()吗?

时间:2020-02-01 20:45:47

标签: c mingw iso c11

我偶然发现了Linux系统上clock_gettime()函数的存在。由于我正在寻找一种衡量函数执行时间的方法,因此我在Windows 10 64位计算机上的MinGW gcc 8.2.0版本中进行了尝试:

#include <time.h>
#include <stdio.h>

int main() {
    struct timespec tstart, tend;
    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tstart);
    for (int i = 0; i < 100000; ++i);
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tend);
    printf("It takes %li nanoseconds for 100,000 empty iterations.\n", tend.tv_nsec - tstart.tv_nsec);
    return 0;
}

该代码段编译时不会发出警告/错误,也没有运行时失败(至少没有写入stdout)。

输出:

It takes 0 nanoseconds for 100,000 empty iterations.

我不相信这是真的。

您能发现缺陷吗?


还有一件事:

根据ISO / IEC 9899:201x的N1570 Committee draft(2011年4月12日),timespec_get()是否应该代替clock_gettime()的角色?

2 个答案:

答案 0 :(得分:2)

该循环应该完全没有优化,因此使用低分辨率时钟(分辨率不一定是单个纳秒;它可以以更大的单位前进,clock_getres应该可以告诉您)0是一个合理的结果。但是您的代码中还有一些其他错误,例如将CLOCK_THREAD_CPUTIME_IDCLOCK_PROCESS_CPUTIME_ID混合在一起,而不检查clock_gettime的返回值(这可能表明您不支持这些时钟)。 / p>

答案 1 :(得分:2)

首先,您的代码正在查询两个不同的时钟(CLOCK_THREAD_CPUTIME_ID的{​​{1}}和tstart的{​​{1}}),因此比较这两个值没有任何意义。其次,您仅查看CLOCK_PROCESS_CPUTIME_ID返回的tend的{​​{1}}字段,即使两次查询相同的时钟,您的差异也可能是错误的。另外,您的编译器可能正在优化空的tv_nsec循环,但是如果不查看生成的二进制文件就无法说这句话,但是除非您使用struct timespec或{{1}进行编译,否则我发现这不太可能}(例如,参见here,仅用clock_gettime()消除了循环)。

此外,Windows根本不兼容POSIX,MinGW只能在某种程度上模拟for的行为,因此我真的不相信它能返回精确的值。对于mingw-w64 looking at the source code来说似乎还可以,但是我不知道那是您使用的版本。即使-O1对象以纳秒分辨率描述时间,可用分辨率也取决于系统,甚至可能大于1秒。您可能要检查-O2的内容。

根据ISO / IEC 9899:201x的N1570 Committee draft(2011年4月12日),-O2是否应该代替clock_gettime()的角色?

C标准对任何功能应扮演其他角色一无所知。 struct timespec函数肯定不具有与clock_getres()相同的语义。 timespec_get()函数仅在“日历时间”上起作用(使用clock_gettime()时,该时间应与timespec_get()相同)。