如何在 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<double>
?
不幸的是 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 时间和挂钟时间?的主要内容,如果未能解决你的问题,请参考以下文章