众所周知,clock()显示的值可能小于或大于实时值--这两种情况都显示在下面的示例1和2中。
对于C++11中时间的高精度测量,我们可以使用:
std::chrono::high_resolution_clock::now(); -保证高精度std::chrono::steady_clock::now(); -保证测量的实时性clock(); -保证高精度,但测量CPU周期而不是时间。time(&t_start); -不是高精度的,而是实时测量。1-,例如:http://ideone.com/SudWTM
#include <stdio.h>
#include <time.h>
#include <thread>
#include <iostream>
#include <chrono>
int main(void) {
std::cout << "sleep(3) took: \n\n";
clock_t c_start, c_end;
time_t t_start, t_end;
std::chrono::high_resolution_clock::time_point h_start, h_end;
std::chrono::steady_clock::time_point steady_start, steady_end;
time(&t_start); // less precise than clock() but always get the real actual time
c_start = clock(); // clock() get only CPU-time, it can be more than real or less - sleep(3); took 0.00 seconds
h_start = std::chrono::high_resolution_clock::now();
steady_start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(std::chrono::seconds(3));
steady_end = std::chrono::steady_clock::now();
h_end = std::chrono::high_resolution_clock::now();
c_end = clock();
time(&t_end);
std::cout << "highres = " << std::chrono::duration<double>(h_end - h_start).count() << " s \n";
std::cout << "steady = " << std::chrono::duration<double>(steady_end - steady_start).count() << " s \n";
printf("clock() = %.2lf seconds \n", (c_end - c_start) / (double)CLOCKS_PER_SEC);
printf("time() = %.2lf seconds \n", difftime(t_end, t_start));
return 0;
}g++上的结果(Debian4.9.2-10) 4.9.2:clock() = 0.00秒
sleep(3) took:
highres = 3.00098 s
steady = 3.00098 s
clock() = 0.00 seconds
time() = 3.00 seconds C++ MSVS 2013 v120 (Windows7x64)的结果:
sleep(3) took:
highres = 3.00017 s
steady = 3.00017 s
clock() = 3.00 seconds
time() = 3.00 seconds2-第二个示例OpenMP或<thread>:http://coliru.stacked-crooked.com/a/2922c85385d197e1
#include <stdio.h>
#include <time.h>
#include <thread>
#include <iostream>
#include <chrono>
#include <vector>
int main(void) {
std::cout << "for-loop took: \n\n";
clock_t c_start, c_end;
time_t t_start, t_end;
std::chrono::high_resolution_clock::time_point h_start, h_end;
std::chrono::steady_clock::time_point steady_start, steady_end;
time(&t_start); // less precise than clock() but always get the real actual time
c_start = clock(); // clock() get only CPU-time, it can be more than real or less - sleep(3); took 0.00 seconds
h_start = std::chrono::high_resolution_clock::now();
steady_start = std::chrono::steady_clock::now();
#pragma omp parallel num_threads(10)
{
for (volatile int i = 0; i < 200000000; ++i);
}
steady_end = std::chrono::steady_clock::now();
h_end = std::chrono::high_resolution_clock::now();
c_end = clock();
time(&t_end);
std::cout << "highres = " << std::chrono::duration<double>(h_end - h_start).count() << " s \n";
std::cout << "steady = " << std::chrono::duration<double>(steady_end - steady_start).count() << " s \n";
printf("clock() = %.2lf seconds \n", (c_end - c_start) / (double)CLOCKS_PER_SEC);
printf("time() = %.2lf seconds \n", difftime(t_end, t_start));
int b = getchar();
return 0;
}g++上的结果(Debian4.9.2-10) 4.9.2:clock() =1.35秒
for-loop took:
highres = 0.213906 s
steady = 0.213905 s
clock() = 1.35 seconds
time() = 0.00 seconds C++ MSVS 2013 v120 (Windows7x64)的结果:
for-loop took:
highres = 1.49109 s
steady = 1.49109 s
clock() = 1.49 seconds
time() = 2.00 seconds简历:
clock()在g++ 4.9.2上并不测量时间,与其他函数不同。<thread> (链接)进行多线程处理时,g++ 4.9.2上的clock()会测量所有线程的CPU周期。同样,在Windows 2013中,clock()测量在这两种情况下都需要实时,但这并不能保证clock()在其他平台上的测量相同(在linux g++上,睡眠为0,多线程为x折叠)。
基于此,如果在Windows 2013和g++ 4.9.2两种情况下都需要实时测量,这是否保证它将在所有其他平台上测量真正的高分辨率时间,以及它是否保证标准C++11/14?
发布于 2016-07-07 18:55:16
简短的回答:根据C++14标准,high_resolution_clock没有明确提供您想要的保证。
目前,steady_clock和system_clock提供了更好和更明确的保证。然而,大多数实现可能会确保HRC在线程处于休眠状态时继续前进。尽管如此,它可能是更好的做你自己的类型混叠。请参阅下面的“编辑”部分和评论中的讨论。
较长的答覆:
实际上,标准草案确实隐式地承认(注30.2.4“定时规范”,注5)时钟对象是而不是,因为它们的关联线程处于休眠状态。对于上下文,本节解释标准库计时器对象是如何工作的;定时器的行为是基于用来设置它的时钟的行为。
注意:如果时钟与稳定的时钟(例如CPU时钟)不同步,这些超时可能无法提供有用的功能。-尾注
请注意,在这种情况下,“超时可能无法提供有用的功能”意味着,如果您使用一个计时器使用一个不同步(非实时)时钟sleep_until特定时钟时间,您的线程将不会唤醒。所以上面的注释有点轻描淡写。
而且,实际上,时钟规范(20.13.3)中没有任何实际需要与稳定时钟同步的东西。
然而,在20.13.7.3中的定义中,该标准似乎含蓄地容忍了high_resolution_clock的两个潜在别名:
high_resolution_clock可以是system_clock或steady_clock的同义词。
当然,steady_clock是稳定的。system_clock是而不是,因为程序运行时系统时间可能会改变(例如,NTP更新的结果)。
然而,system_clock (20.13.7.1) 仍然是一个“实时”时钟:
类
system_clock对象表示来自系统范围的实时时钟的挂钟时间.
因此,当线程休眠时,system_clock 不会停止前进。这证实了Nicol的观点,即is_steady对于high_resolution_clock来说可能是错误的,即使时钟的行为与您预期的一样(也就是说,无论其关联线程的状态如何,它都会前进)。
基于此,期望大多数主流实现为high_resolution_clock使用某种类型的实时(即同步)时钟似乎是合理的。毕竟,实现被设计成有用的,如果时钟不是实时的,那么它通常就不太有用了,特别是按照上面关于“有用功能”的说明,它与定时器一起使用时更是如此。
但是,由于不能保证这一点,所以您应该检查要使用的每个实现的行为和/或文档。
编辑:--我已经在这个问题上启动了一个国际标准化组织C++标准组的探讨,这表明这是标准中的一个bug。霍华德·辛南特( Howard Hinnant )提出的第一个答复值得引用:
我不反对反对
high_resolution_clock,目的是在一段适当的反对期之后删除它。实际情况是,它总是steady_clock或system_clock的类型,程序员最好选择这两种中的一种,并知道自己得到了什么,而不是选择high_resolution_clock并按骰子获得其他时钟。
根据辛纳特的说法,high_resolution_clock**.**的寓意是不使用
编辑2:
根据Hinnant的说法,high_resolution_clock的问题不在于你很可能在HRC中遇到问题(尽管按照上面的论点,即使使用符合标准的编译器也是可能的),但是由于您通常没有获得比其他两个时钟中的一个更低的分辨率(尽管您需要手动比较它们的分辨率(别名或类型)以获得“最大分辨率”而不是睡眠时钟),所以没有任何具体的好处。因此,您需要权衡让线程永远睡在一致性实现上的风险,而不是名称high_resolution_clock的语义好处,以及避免只使用您自己的type或类型别名所带来的简单/简洁的好处。
以下是各种方法的实际代码:
static_assert检查high_resolution_clock是否实际上是一个真正的时钟。这可能永远不会触发,这意味着您将自动获得最高分辨率的“实时”时钟,而不会干扰您自己的字体:
static_assert( std::is_same::value the std::is_same::value,"high_resolution_clock不是其他标准时钟的别名!“);high_resolution_clock::is_steady为真,则使用HRC;否则更喜欢system_clock和steady_clock之间的高分辨率时钟。注意到,如果high_resolution_clock::is_steady是false,这可能只是意味着HRC被别名为system_clock,在这种情况下,最终您将得到一个新的类型--别名实际上与high_resolution_clock的类型相同。但是,创建自己的类型别名可以显式地说明这一点,并保证即使是符合恶意但符合条件的实现也不会出现上述问题。
使用maxres_sys_or_steady = std::conditional< system_clock::period::den <= steady_clock::period::den,system_clock,steady_clock >:type;使用maxres_nonsleeping_clock = std::conditional< high_resolution_clock::is_steady,high_resolution_clock,maxres_sys_or_steady >:type;发布于 2016-07-07 18:14:15
标准没有从它的时钟中指定这种行为。不完全同意。
时钟具有is_steady静态属性,可以对其进行检查。任何is_steady返回true的时钟都不能仅仅因为使线程处于休眠状态而停止运行。然而,由于各种原因,该值为假的时钟可能是不稳定的。它可能不是稳定的,因为如果系统时间发生变化,这是一个会改变的挂钟。或者是因为滴答之间的周期是一个平均值,而不是一个确切的数字。
所以is_steady并没有真正回答你的问题。
标准没有指定high_resolution_clock::is_steady,但它确实要求实现来回答这个问题。如果它是稳定的,那么你可以保证线程的睡眠不会停止时钟。但如果不稳定..。你根本得不到保证。
https://stackoverflow.com/questions/38252022
复制相似问题