在Windows上用C ++计算CPU时间

时间:2012-09-26 15:55:37

标签: c++ performance visual-studio-2008 windows-7 cpu-usage

C ++中是否有任何方法可以计算在CPU时间内运行给定程序或例程需要多长时间

我使用在Windows 7上运行的Visual Studio 2008。

5 个答案:

答案 0 :(得分:6)

如果您想知道进程使用的CPU总时间,clockrdtsc(直接或通过编译器内在)都不是最佳选择,至少是IMO。如果您需要可移植的代码,那么您可以使用clock,尽可能使用系统进行测试,并希望获得最佳效果(但如果您这样做,请注意{ {1}}是clock,可能是1000,也可能不是1000,即使它是,你的实际时间分辨率往往也不会那么好 - 它可能会给你几毫秒的时间,但至少通常一次提前几十毫秒。)

但是,由于您似乎不介意特定于Windows的代码,因此您可以做得更好。至少如果我对你正在寻找的东西的理解是正确的,你真正想要的可能是GetProcessTimes,它将(单独)告诉你进程的内核模式和用户模式CPU使用情况(以及作为开始时间和退出时间,您可以从中计算使用的时间,如果您愿意的话)。还有QueryProcessCycleTime,它将告诉您进程使用的CPU时钟周期总数(所有线程中用户和内核模式的总和)。就个人而言,我很难想象后者有多大用处 - 计算个别时钟周期对于部分代码有用,但需要进行深入优化,但我不太确定你是怎么做的d将它应用于一个完整的过程。 CLOCKS_PER_SEC使用FILETIME结构,它支持100纳秒的分辨率,但实际上大多数时候你会看到调度程序的时间片的倍数(随着窗口的版本而变化,但是大约为毫秒到几十毫秒)。

在任何情况下,如果你真的想要从开始到结束的时间,GetProcessTimes将允许你这样做 - 如果你产生程序(例如,GetProcessTimes),你会得到一个处理将在子进程退出时发出信号的进程。然后,您可以在该句柄上调用CreateProcess,并检索时间,即使该子项已经退出 - 只要该进程的至少一个句柄保持打开,该句柄将保持有效。

答案 1 :(得分:4)

这是一种方式。它以毫秒为单位测量常规测量时间。

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 << " \n\n";
}

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) \n\n";
    return 0;
}

答案 2 :(得分:2)

__rdtscp内在函数将为您提供CPU周期中的时间,并提供一些注意事项。 这是the MSDN article

这实际上取决于您想要衡量的内容。为了获得更好的结果,需要花费几百万(如果不是十亿次)迭代的平均值。

答案 3 :(得分:2)

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来测量块执行所需的时间。

答案 4 :(得分:0)

此代码是Process Cpu Usage

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);