在 Windows 上以C++计算 CPU 时间
Computing CPU time in C++ on Windows
C++有什么方法可以计算在CPU时间内运行给定程序或例程需要多长时间?
我使用在Windows 7上运行的Visual Studio 2008。
如果你想知道一个进程使用的CPU时间总量,clock
和rdtsc
(无论是直接还是通过编译器内部函数)都不是最好的选择,至少IMO是这样。如果您需要代码可移植,您能做的最好的事情就是使用clock
,尽可能静态地测试系统,并希望最好(但如果您这样做,请注意clock
的分辨率是CLOCKS_PER_SEC
,可能是也可能不是 1000,即使它是, 你的实际计时分辨率通常不会那么好——它可能会给你以毫秒为单位的时间,但至少通常一次前进几十毫秒)。
但是,由于您似乎不介意特定于Windows的代码,因此您可以做得更好。至少如果我对你正在寻找的东西的理解是正确的,你真正想要的可能是GetProcessTimes
,这将(分别)告诉你进程的内核模式和用户模式 CPU 使用率(以及开始时间和退出时间,如果你关心的话,你可以从中计算使用的墙时间)。还有QueryProcessCycleTime
,它将告诉您进程使用的 CPU 时钟周期总数(所有线程中的用户和内核模式的总和)。就我个人而言,我很难想象后者有多大用处——计算单个时钟周期对于需要密集优化的小段代码很有用,但我不太确定如何将其应用于完整的过程。GetProcessTimes
使用 FILETIME 结构,它支持 100 纳秒的分辨率,但实际上大多数时候你会看到调度程序时间片的倍数(随 Windows 版本而异,但在毫秒到几十毫秒的数量级)。
无论如何,如果你真的想要从头到尾的时间,GetProcessTimes
会让你这样做——如果你生成程序(例如,使用CreateProcess
),你将得到一个进程的句柄,当子进程退出时,它会发出信号。然后,可以在该句柄上调用GetProcessTimes
,并检索时间,即使子句柄已经退出 - 只要进程的至少一个句柄保持打开状态,句柄将保持有效。
这是一种方法。它以毫秒为单位测量常规执行时间。
clock_t begin=clock();
在执行路由之前开始,clock_t end=clock();
在例程退出后立即开始。
然后将两个时间集相互减去,结果是毫塞科德值。
#include <stdio.h>
#include <iostream>
#include <time.h>
using namespace std;
double get_CPU_time_usage(clock_t clock1,clock_t clock2)
{
double diffticks=clock1-clock2;
double diffms=(diffticks*1000)/CLOCKS_PER_SEC;
return diffms;
}
void test_CPU_usage()
{
cout << "Standby.. measuring exeution time: ";
for (int i=0; i<10000;i++)
{
cout << "b\" << std::flush;
cout << "b|" << std::flush;
cout << "b/" << std::flush;
cout << "b-" << std::flush;
}
cout << " nn";
}
int main (void)
{
clock_t begin=clock();
test_CPU_usage();
clock_t end=clock();
cout << "Time elapsed: " << double(get_CPU_time_usage(end,begin)) << " ms ("<<double(get_CPU_time_usage(end,begin))/1000<<" sec) nn";
return 0;
}
clock() 函数 [由 Visual C++ 2008 提供] 不返回程序使用的处理器时间,而它应该返回(根据 C 标准和/或 C++ 标准)。也就是说,为了测量Windows上的CPU时间,我有这个帮助程序类(不可避免地是不可移植的):
class ProcessorTimer
{
public:
ProcessorTimer() { start(); }
void start() { ::GetProcessTimes(::GetCurrentProcess(), &ft_[3], &ft_[2], &ft_[1], &ft_[0]); }
std::tuple<double, double> stop()
{
::GetProcessTimes(::GetCurrentProcess(), &ft_[5], &ft_[4], &ft_[3], &ft_[2]);
ULARGE_INTEGER u[4];
for (size_t i = 0; i < 4; ++i)
{
u[i].LowPart = ft_[i].dwLowDateTime;
u[i].HighPart = ft_[i].dwHighDateTime;
}
double user = (u[2].QuadPart - u[0].QuadPart) / 10000000.0;
double kernel = (u[3].QuadPart - u[1].QuadPart) / 10000000.0;
return std::make_tuple(user, kernel);
}
private:
FILETIME ft_[6];
};
class ScopedProcessorTimer
{
public:
ScopedProcessorTimer(std::ostream& os = std::cerr) : timer_(ProcessorTimer()), os_(os) { }
~ScopedProcessorTimer()
{
std::tuple<double, double> t = timer_.stop();
os_ << "user " << std::get<0>(t) << "n";
os_ << "kernel " << std::get<1>(t) << "n";
}
private:
ProcessorTimer timer_;
std::ostream& os_;
}
例如,可以通过在该 {} 块的开头定义一个 ScopedProcessorTimer 来测量执行块需要多长时间。
__rdtscp
内函数将为您提供 CPU 周期中的时间,但需要注意一些。 这是 MSDN 文章
这实际上取决于您要测量的内容。为了获得更好的结果,取几百万次(如果不是十亿次)迭代的平均值。
此代码是进程 CPU 使用情况
ULONGLONG LastCycleTime = NULL;
LARGE_INTEGER LastPCounter;
LastPCounter.QuadPart = 0; // LARGE_INTEGER Init
// cpu get core number
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
int numProcessors = sysInfo.dwNumberOfProcessors;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, Process::pid);
if (hProcess == NULL)
nResult = 0;
int count = 0;
while (true)
{
ULONG64 CycleTime;
LARGE_INTEGER qpcLastInt;
if (!QueryProcessCycleTime(hProcess, &CycleTime))
nResult = 0;
ULONG64 cycle = CycleTime - LastCycleTime;
if (!QueryPerformanceCounter(&qpcLastInt))
nResult = 0;
double Usage = cycle / ((double)(qpcLastInt.QuadPart - LastPCounter.QuadPart));
// Scaling
Usage *= 1.0 / numProcessors;
Usage *= 0.1;
LastPCounter = qpcLastInt;
LastCycleTime = CycleTime;
if (count > 3)
{
printf("%.1f", Usage);
break;
}
Sleep(1); // QueryPerformanceCounter Function Resolution is 1 microsecond
count++;
}
CloseHandle(hProcess);
- 分别测量每个线程上花费的 CPU 时间(C++)
- 超过CPU时间限制:当MPI_Sent一个非常大的int*时
- 如何测量一组特定线程的 CPU 时间?
- 如何以C++而不是 CPU 时间测量挂钟时间
- 将返回 CPU 时间提升为 0
- C++中的双感叹号(!!)会花费更多的CPU时间吗
- 即使使用睡眠,线程也不会放弃CPU时间
- 以C++为单位测量程序的 CPU 时间和挂钟时间
- 在 Windows 上以C++计算 CPU 时间
- 时间短函数与 CPU 时间使用 RTEMS 操作系统
- PDH 无法通过 PdhAddCounter() 访问总 CPU 时间
- 二叉搜索真的是在 0 时钟 CPU 时间内执行的吗?
- 我应该检查什么:cpu时间还是墙时间
- 使用MPI时计算CPU时间
- 堆排序CPU时间
- rusage的进程/线程的Cpu时间不可能
- 如何在 Windows 上以 C++ 为单位测量 CPU 时间并包括 system() 的调用
- 在 Ubuntu 中获取 CPU 时间
- 为什么使用 clock() 在测量 CPU 时间时得到减号
- 使用 GetProcessTimes 测量 Windows 上的 CPU 时间