C++ 标准C++;11保证高分辨率时钟测量实时性(非CPU周期)?

C++ 标准C++;11保证高分辨率时钟测量实时性(非CPU周期)?,c++,multithreading,performance,c++11,performance-testing,C++,Multithreading,Performance,C++11,Performance Testing,众所周知,clock()可能显示小于或大于实时值-以下示例1和2中显示了这两种情况 对于C++11中的高精度时间测量,我们可以使用: std::chrono::高分辨率时钟::现在()-保证高精度 std::chrono::staid_clock::now()-保证测量的实时性 clock()-保证高精度,但测量CPU周期而不是时间 时间(&t\u开始)-不是高精度,而是实时测量 1-例如: 结果:C++ MMSS 2013 V120(Windows 7x64): 2-第二个示例OpenMP

众所周知,
clock()
可能显示小于或大于实时值-以下示例1和2中显示了这两种情况

对于C++11中的高精度时间测量,我们可以使用:

  • std::chrono::高分辨率时钟::现在()-保证高精度
  • std::chrono::staid_clock::now()-保证测量的实时性
  • clock()-保证高精度,但测量CPU周期而不是时间
  • 时间(&t\u开始)-不是高精度,而是实时测量
1-例如:

<>结果:C++ MMSS 2013 V120(Windows 7x64):

2-第二个示例OpenMP或

<>结果:C++ MMSS 2013 V120(Windows 7x64):

简历:

  • 当线程休眠时,与其他函数不同,g++4.9.2上的
    clock()
    不会测量时间

  • 当我们使用OpenMP或
    ()使用多线程时,g++4.9.2上的
    clock()
    会测量所有线程的CPU周期

  • 同样在Windows MSVS 2013上,在这两种情况下
    clock()
    测量所需的实时性,但这并不保证
    clock()
    在其他平台上测量相同的时间(在linux上,g++的睡眠时间为0,多线程时间为x倍)


    基于此,if
    std::chrono::high_resolution_clock::now()
    在Windows MSVS 2013和g++4.9.2上测量这两种情况下所需的实时性,这是否保证它将在所有其他平台上测量真实的高分辨率时间,是否保证标准C++11/14?

    该标准没有从其时钟中指定此行为。不完全是

    时钟具有静态特性,可以检查。任何
    稳定的
    返回true的时钟都不能是那种仅仅因为你让线程休眠而停止运行的时钟。然而,该值为false的时钟可能由于各种原因而不稳定。它可能不稳定,因为它是一个挂钟,如果系统时间改变,它就会改变。或者因为滴答声之间的周期是一个平均值,而不是一个精确的数字

    所以,
    是稳定的
    并不能真正回答你的问题


    该标准没有规定
    高分辨率时钟::是稳定的
    ,但它确实需要实现来回答这个问题。如果它是稳定的,那么你就可以保证睡眠线程不会停止时钟。但如果它不稳定。。。你根本得不到任何保证。

    简短回答:在C++14标准中,
    高分辨率时钟
    没有明确提供你想要的保证。 目前,
    稳定时钟
    系统时钟
    提供了更好、更明确的保证。然而,大多数实现可能会确保HRC在其线程处于休眠状态时进行。不过,最好还是自己做类型别名。请参阅下面的“编辑”部分和评论中的讨论

    长答覆: 事实上,确实隐含地承认(在注释30.2.4“计时规范”,注释5中)时钟对象在其相关线程处于休眠状态时不需要前进。对于上下文,本节将解释标准库计时器对象是如何工作的;计时器的行为基于用于设置计时器的时钟的行为

    [注:如果时钟与稳定时钟不同步,例如 CPU时钟,这些超时可能无法提供有用的功能。 -[完注]

    请注意,在这种情况下,“超时可能不会提供有用的功能”意味着,如果使用未同步(非实时)时钟使用计时器在特定时钟时间之前
    睡眠,\u线程将不会唤醒。所以上面的注释有点轻描淡写

    事实上,时钟规范(20.13.3)中没有任何内容需要与稳定时钟同步

    然而,在20.13.7.3中的定义中,本标准似乎隐含了两个潜在的别名:

    高分辨率时钟
    可能是系统时钟
    的同义词,或者
    稳定的时钟

    稳定\u时钟
    当然是稳定的<代码>系统时钟
    ,因为程序运行时系统时间可能会发生变化(例如,由于NTP更新)

    但是,
    系统时钟(20.13.7.1)仍然是一个“实时”时钟:

    system\u clock
    的对象表示从 全系统实时时钟

    因此,当线程休眠时,
    系统时钟将不会停止前进。
    这证实了Nicol Bolas的观点,即
    是稳定的
    对于
    高分辨率时钟
    可能是错误的,即使时钟的行为与您预期的一样(即,无论其关联线程的状态如何,它都会前进)

    基于此,期望大多数主流实现为
    高分辨率时钟使用某种实时(即同步)时钟似乎是合理的。毕竟,实现是为了有用而设计的,如果时钟不是实时的,那么它通常就不那么有用,特别是如果按照上面关于“有用功能”的注释,它与计时器一起使用的话

    但是,由于不能保证,您应该检查要使用的每个实现的行为和/或文档

    编辑:我已经开始讨论这个问题,表明这是标准中的一个缺陷。霍华德·希南特(Howard Hinnant)的第一个回答值得一提,他因将其纳入标准而受到赞扬:

    我不反对使用高分辨率时钟,因为
    #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;
    }
    
    sleep(3) took: 
    
    highres = 3.00098 s 
    steady = 3.00098 s 
    clock() = 0.00 seconds 
    time() = 3.00 seconds 
    
    sleep(3) took:
    
    highres = 3.00017 s
    steady = 3.00017 s
    clock() = 3.00 seconds
    time() = 3.00 seconds
    
    #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;
    }
    
    for-loop took: 
    
    highres = 0.213906 s 
    steady = 0.213905 s 
    clock() = 1.35 seconds 
    time() = 0.00 seconds 
    
    for-loop took:
    
    highres = 1.49109 s
    steady = 1.49109 s
    clock() = 1.49 seconds
    time() = 2.00 seconds
    
     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!");
    
    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;