Ale*_*lex 17 c++ performance multithreading performance-testing c++11
如已知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;
}
Run Code Online (Sandbox Code Playgroud)
关于g ++的结果(Debian 4.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
Run Code Online (Sandbox Code Playgroud)
C++ MSVS 2013 v120(Windows 7x64)上的结果:
sleep(3) took:
highres = 3.00017 s
steady = 3.00017 s
clock() = 3.00 seconds
time() = 3.00 seconds
Run Code Online (Sandbox Code Playgroud)
2-第二个例子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;
}
Run Code Online (Sandbox Code Playgroud)
结果g ++(Debian 4.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
Run Code Online (Sandbox Code Playgroud)
C++ MSVS 2013 v120(Windows 7x64)上的结果:
for-loop took:
highres = 1.49109 s
steady = 1.49109 s
clock() = 1.49 seconds
time() = 2.00 seconds
Run Code Online (Sandbox Code Playgroud)
恢复:
当线程休眠然后clock()在g ++ 4.9.2上测量时间与其他函数不同.
当我们使用OpenMP或使用<thread>(链接)使用多线程时,然后clock()在g ++ 4.9.2上测量所有线程的CPU周期.
同样在Windows上,MSVS 2013 clock()在两种情况下都需要实时测量,但这并不能保证clock()其他平台上的测量值相同(在linux g ++上,睡眠为0,多线程为x倍).
基于此,如果std::chrono::high_resolution_clock::now();在Windows MSVS 2013和g ++ 4.9.2两种情况下都需要实时测量,这是否可以保证它将在所有其他平台上测量真正的高分辨率时间,并确保它是否保证标准C++ 11/14 ?
Kyl*_*and 20
high_resolution_clock没有明确提供您正在寻找的保证.目前,steady_clock并system_clock提供更好,更明确的保证.但是,大多数实现可能会确保HRC在其线程处于休眠状态时前进.尽管如此,最好还是进行自己的类型别名.请参阅下面的"编辑"部分和评论中的讨论.
该标准草案做其实隐含确认(附注30.2.4"时序规范",注1)是时钟对象不是必需的,而其相关的线程休眠推进.对于上下文,本节将解释标准库计时器对象的工作方式; 计时器的行为基于用于设置它的时钟的行为.
[ 注意:如果时钟与稳定时钟不同步,例如CPU时钟,则这些超时可能无法提供有用的功能.- 结束说明 ]
请注意,在这种情况下,"超时可能无法提供有用的功能"意味着如果使用非同步(非实时)时钟将计时器用于sleep_until特定时钟时间,则线程将不会被唤醒.所以上面的说明有点轻描淡写.
事实上,时钟规范(20.13.3)中没有任何内容实际上需要与稳定时钟同步.
但是,该标准似乎暗含high_resolution_clock了20.13.7.3中定义的两个潜在别名:
high_resolution_clock可能是system_clock或 的同义词steady_clock.
steady_clock当然是稳定的.system_clock是不是,因为程序运行时,系统时间可以改变(例如,作为NTP更新的结果).
然而,system_clock(20.13.7.1)是依然是"实时"时钟:
类的对象
system_clock表示来自系统范围实时时钟的挂钟时间.
所以当你的线程睡觉时system_clock 不会停止前进.这证实了尼科尔流星锤的点,一个is_steady可能是假的high_resolution_clock,即使如你所期望的时钟的行为(即它不考虑推进其相关线程的状态).
基于此,期望大多数主流实现使用某种实时(即同步)时钟似乎是合理的high_resolution_clock.毕竟,实现被设计为有用,并且如果时钟不是实时的话通常不太有用,特别是如果它按照上面"有用功能"的注释与定时器一起使用.
但是,由于无法保证,您应该检查要使用的每个实现的行为和/或文档.
编辑:我已经就此问题开始讨论ISO C++标准组,这表明这是标准中的一个错误.第一个回复,从霍华德Hinnant(欣南特),谁需要信贷把它的标准,是值得引用:
我不反对弃用
high_resolution_clock,意图在适当的弃用期后删除它.现实情况是,它始终是一个typedef要么steady_clock或者system_clock,而程序员是最好选择这两个中的一个,并知道他得到,不是选择high_resolution_clock并通过掷骰子得到一些其他的时钟.
......所以根据Hinnant的说法,道德是不要使用的high_resolution_clock.
编辑2:
这个问题high_resolution_clock根据Hinnant(欣南特)是没有这么多,你可能会碰到与HRC的问题(虽然这是可能的,即使使用符合标准的编译,按照上面的说法),但因为你通常不会实际得到分辨率低于其他两个时钟之一的分辨率(虽然你需要在类型别名或typedef中手动比较它们的分辨率以获得"最大分辨率"非休眠时钟),但没有具体的好处.因此,您需要权衡线程在符合实现方面永远睡眠的风险与名称的语义优势high_resolution_clock以及避免仅创建自己的typedef或type-alias的简单/简洁优势.
以下是各种方法的一些实际代码:
使用static_assert以检查是否high_resolution_clock真正化名为一个真正的时钟.这可能永远不会触发,这意味着您将自动获得最高分辨率的"实时"时钟而不会弄乱您自己的typedef:
static_assert(
std::is_same<high_resolution_clock, steady_clock>::value
|| std::is_same<high_resolution_clock, system_clock>::value,
"high_resolution_clock IS NOT aliased to one of the other standard clocks!");
Run Code Online (Sandbox Code Playgroud)使用HRC如果high_resolution_clock::is_steady是真的话; 否则更喜欢system_clock和之间的更高分辨率的时钟steady_clock.注意,如果high_resolution_clock::is_steady为false,这可能仅仅意味着HRC具有别名system_clock,在这种情况下,您最终会得到一个新的类型别名,实际上与其类型相同high_resolution_clock.但是,创建自己的类型别名会使其明确,并保证即使是恶意但符合要求的实现也不会出现上述问题.
using maxres_sys_or_steady =
std::conditional<
system_clock::period::den <= steady_clock::period::den,
system_clock, steady_clock
>::type;
using maxres_nonsleeping_clock =
std::conditional<
high_resolution_clock::is_steady,
high_resolution_clock, maxres_sys_or_steady
>::type;
Run Code Online (Sandbox Code Playgroud)该标准未从其时钟中指定此行为.不完全是.
时钟具有is_steady静态属性,可以检查.任何is_steady返回true 的时钟都不能是因为你让一个线程进入休眠而停止运行的时钟.然而,由于各种原因,该值为假的时钟可能是不稳定的.它可能不稳定,因为它是一个挂钟,如果系统时间改变,它会改变.或者因为滴答之间的时间段是平均值,而不是确切的数字.
所以is_steady不能真正回答你的问题.
该标准没有规定high_resolution_clock::is_steady,但确实需要实施来回答这个问题.如果它是稳定的,那么你可以保证睡眠线程不会停止时钟.但如果它不稳定......你根本得不到任何保证.
| 归档时间: |
|
| 查看次数: |
4441 次 |
| 最近记录: |