如何在 Linux/Windows 上测量 CPU 时间和挂钟时间?

Posted

技术标签:

【中文标题】如何在 Linux/Windows 上测量 CPU 时间和挂钟时间?【英文标题】:How can I measure CPU time and wall clock time on both Linux/Windows? 【发布时间】:2013-06-30 05:29:28 【问题描述】:

我的意思是:如何测量 CPU 用于函数执行的时间以及运行函数所需的挂钟时间? (我对 Linux/Windows 以及 x86 和 x86_64 都感兴趣)。看看我想做什么(我在这里使用 C++,但我更喜欢 C 解决方案):

int startcputime, endcputime, wcts, wcte;

startcputime = cputime();
function(args);
endcputime = cputime();

std::cout << "it took " << endcputime - startcputime << " s of CPU to execute this\n";

wcts = wallclocktime();
function(args);
wcte = wallclocktime();

std::cout << "it took " << wcte - wcts << " s of real time to execute this\n";

另一个重要问题:这种时间测量架构是否独立?

【问题讨论】:

我知道您想在代码中以编程方式执行此操作,但无论如何:superuser.com/questions/228056/… @Huytard: 谢谢:) 我知道time 在 linux 但正如你所写,我需要直接在 C 代码中完成 @yak 在 Windows 上,clock() 提供挂墙时间,GetProcessTimes 提供 cpu 时间。在 Linux 上,gettimeofday() 提供了挂墙时间,clock() 提供了 cpu 时间。 @Mysticial:嗯!所以它有点复杂!稍后我将尝试编写一些代码并粘贴结果(对于win/lin)。但欢迎任何其他答案! :) 如果你会使用 C++,boost::auto_cpu_timer (boost.org/libs/timer) 就是你所需要的。你的代码变成了boost::auto_cpu_timer t; function(args);(是的,没有cout,没什么,就是这样,你得到了wall和cpu——我喜欢这个功能)。 【参考方案1】:

这是一个适用于 Windows 和 Linux 以及 C 和 C++ 的复制粘贴解决方案。

正如 cmets 中提到的,有一个 boost 库可以做到这一点。但如果你不能使用 boost,这应该可以工作:

//  Windows
#ifdef _WIN32
#include <Windows.h>
double get_wall_time()
    LARGE_INTEGER time,freq;
    if (!QueryPerformanceFrequency(&freq))
        //  Handle error
        return 0;
    
    if (!QueryPerformanceCounter(&time))
        //  Handle error
        return 0;
    
    return (double)time.QuadPart / freq.QuadPart;

double get_cpu_time()
    FILETIME a,b,c,d;
    if (GetProcessTimes(GetCurrentProcess(),&a,&b,&c,&d) != 0)
        //  Returns total user time.
        //  Can be tweaked to include kernel times as well.
        return
            (double)(d.dwLowDateTime |
            ((unsigned long long)d.dwHighDateTime << 32)) * 0.0000001;
    else
        //  Handle error
        return 0;
    


//  Posix/Linux
#else
#include <time.h>
#include <sys/time.h>
double get_wall_time()
    struct timeval time;
    if (gettimeofday(&time,NULL))
        //  Handle error
        return 0;
    
    return (double)time.tv_sec + (double)time.tv_usec * .000001;

double get_cpu_time()
    return (double)clock() / CLOCKS_PER_SEC;

#endif

有很多方法可以实现这些时钟。但是上面的 sn-p 是这样用的:

对于 Windows:

墙上时间:Performance Counters CPU 时间:GetProcessTimes()

对于 Linux:

墙上时间:gettimeofday() CPU 时间:clock()

这是一个小演示:

#include <math.h>
#include <iostream>
using namespace std;

int main()

    //  Start Timers
    double wall0 = get_wall_time();
    double cpu0  = get_cpu_time();

    //  Perform some computation.
    double sum = 0;
#pragma omp parallel for reduction(+ : sum)
    for (long long i = 1; i < 10000000000; i++)
        sum += log((double)i);
    

    //  Stop timers
    double wall1 = get_wall_time();
    double cpu1  = get_cpu_time();

    cout << "Wall Time = " << wall1 - wall0 << endl;
    cout << "CPU Time  = " << cpu1  - cpu0  << endl;

    //  Prevent Code Elimination
    cout << endl;
    cout << "Sum = " << sum << endl;


输出(12 个线程):

Wall Time = 15.7586
CPU Time  = 178.719

Sum = 2.20259e+011

【讨论】:

非常感谢您!还有两个问题:这些方法与架构无关吗?是否有可能使用内联组件(以及类似rdtsc 的功能?) @yak 不应该。它们是特定于操作系统的。 Windows 可能使用rdtsc() 来实现性能计数器。但如果它在不同的架构上,实现这些功能将是操作系统的工作。至于在内联汇编中做这些,这很棘手。请注意,rdtsc() 本身不足以获得挂壁时间,因为您仍然需要一些东西来告诉您一秒钟内有多少滴答声。而且我不知道操作系统之外的任何东西可以为您提供 CPU 时间。 是经过的时间 (wall1 - wall0) 以秒为单位吗? @llnk 是的,它们都在几秒钟内。 clock() 在 Linux 上运行良好,但不包括在子进程中花费的时间(例如,由 system() 调用启动)。如果您还需要测量在子进程中花费的时间,请查看times(),它为您提供当前进程和子进程的 cpu 时间和系统时间。注意这里的每秒时钟不是CLOCKS_PER_SEC,而是sysconf(_SC_CLK_TCK)【参考方案2】:

C++11。写起来容易多了!

std::chrono::system_clock 用于挂钟,std::clock 用于cpu 时钟 http://en.cppreference.com/w/cpp/chrono/system_clock

#include <cstdio>
#include <ctime>
#include <chrono>

.... 

std::clock_t startcputime = std::clock();
do_some_fancy_stuff();
double cpu_duration = (std::clock() - startcputime) / (double)CLOCKS_PER_SEC;
std::cout << "Finished in " << cpu_duration << " seconds [CPU Clock] " << std::endl;


auto wcts = std::chrono::system_clock::now();
do_some_fancy_stuff();
std::chrono::duration<double> wctduration = (std::chrono::system_clock::now() - wcts);
std::cout << "Finished in " << wctduration.count() << " seconds [Wall Clock]" << std::endl;

等等,简单便携!不需要#ifdef _WIN32 或LINUX!

如果您需要更高的精度,您甚至可以使用 chrono::high_resolution_clock http://en.cppreference.com/w/cpp/chrono/high_resolution_clock

【讨论】:

你为什么在wcts上使用auto,然后在wctduration上使用std::chrono::duration&lt;double&gt; 不幸的是 std::clock 在 Windows 上以非标准方式工作,所以“便携”有点过于乐观了。 @n.'pronouns'm。 std::clock 以非标准方式在 Windows 上以哪种方式工作?你能更详细地解释一下这个问题吗? @user561749 它测量挂钟时间而不是标准要求的 CPU 时间。这在其他 cmets 中讨论过,请阅读它们。【参考方案3】:

如果可以的话,举一个@lip 建议使用boost::timer 的具体例子(用Boost 1.51 测试):

#include <boost/timer/timer.hpp>

// this is wallclock AND cpu time
boost::timer::cpu_timer timer;

... run some computation ...

boost::timer::cpu_times elapsed = timer.elapsed();
std::cout << " CPU TIME: " << (elapsed.user + elapsed.system) / 1e9 << " seconds"
          << " WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds"
          << std::endl;

【讨论】:

总时间是哪一项? 'total' 是什么意思? CPU 时间通常是所有线程/内核的总和(每个 CPU 内核忙于执行代码的时间总和),挂钟时间是您必须等待代码完成的时间。对于在多个 CPU 内核上运行的代码,CPU 时间可以大于挂钟时间。 不,你没有发现两者都是“总”,一个是挂钟时间,另一个是 CPU 时间。【参考方案4】:

在time.h中使用clock方法:

clock_t start = clock();
/* Do stuffs */
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;

不幸的是,此方法在 Linux 上返回 CPU 时间,但 returns wall-clock time on Windows(感谢评论者提供此信息)。

【讨论】:

它给了我什么时间?挂钟时间还是 CPU 时间? 它测量 CPU 时间,而不是挂钟时间,如果那是你要找的。​​span> @syb0rg 实际上,clock() 在 Linux 上提供 cpu 时间,在 Windows 上提供时间。 我正在寻找两者;)为此欢呼,所以现在我只需要寻找一个挂钟时间:P @syb0rg: clock() 应该按照 ISO 标准返回 CPU 时间; MS documention 明确指出它会在 Windows 中返回挂钟时间,不过...

以上是关于如何在 Linux/Windows 上测量 CPU 时间和挂钟时间?的主要内容,如果未能解决你的问题,请参考以下文章

Windows 上程序的 CPU 使用率测量

如何计算理论上的最大 CPU-RAM 带宽?

测量同一服务器上特定 IIS 网站的 CPU 负载

如何实时测量 PC 组件(cpu、内存、磁盘等)的功率(瓦​​特)?

如何测量java程序中方法的cpu使用率[重复]

如何在 JMeter 中测量 Docker 容器 CPU 和内存并将其与其他 Docker 容器进行比较