Computing CPU time in C++ on Windows

后端 未结 5 898
無奈伤痛
無奈伤痛 2021-02-03 14:50

Is there any way in C++ to calculate how long does it take to run a given program or routine in CPU time?

I work with Visual Studio 2008 running on Wind

相关标签:
5条回答
  • 2021-02-03 15:07

    The __rdtscp intrinsic will give you the time in CPU cycles with some caveats. Here's the MSDN article

    It depends really what you want to measure. For better results take the average of a few million (if not billion) iterations.

    0 讨论(0)
  • 2021-02-03 15:08

    The clock() function [as provided by Visual C++ 2008] doesn't return processor time used by the program, while it should (according to the C standard and/or C++ standard). That said, to measure CPU time on Windows, I have this helper class (which is inevitably non-portable):

    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_;
    }
    

    For example, one can measure how long it takes a block to execute, by defining a ScopedProcessorTimer at the beginning of that {} block.

    0 讨论(0)
  • 2021-02-03 15:13

    This Code is 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);
    
    0 讨论(0)
  • 2021-02-03 15:14

    Here's one way. It measures routine exeution time in milliseconds.

    clock_t begin=clock(); starts before the route is executed and clock_t end=clock(); starts right after the routine exits.

    The two time sets are then subtracted from each other and the result is a millisecod value.

    #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;
    }
    
    0 讨论(0)
  • 2021-02-03 15:29

    If you want to know the total amount of CPU time used by a process, neither clock nor rdtsc (either directly or via a compiler intrinsic) is really the best choice, at least IMO. If you need the code to be portable, about the best you can do is use clock, test with the system as quiescent as possible, and hope for the best (but if you do, be aware that the resolution of clock is CLOCKS_PER_SEC, which may or may not be 1000, and even if it is, your actual timing resolution often won't be that good -- it may give you times in milliseconds, but at least normally advance tens of milliseconds at a time).

    Since, however, you don't seem to mind the code being specific to Windows, you can do quite a bit better. At least if my understanding of what you're looking for is correctly, what you really want is probably GetProcessTimes, which will (separately) tell you both kernel-mode and user-mode CPU usage of the process (as well as the start time and exit time, from which you can compute wall time used, if you care). There's also QueryProcessCycleTime, which will tell you the total number of CPU clock cycles used by the process (total of both user and kernel mode in all threads). Personally, I have a hard time imagining much use for the latter though -- counting individual clock cycles can be useful for small sections of code subject to intensive optimization, but I'm less certain about how you'd apply it to a complete process. GetProcessTimes uses FILETIME structures, which support resolutions of 100 nanoseconds, but in reality most times you'll see will be multiples of the scheduler's time slice (which varies with the version of windows, but is on the order of milliseconds to tens of milliseconds).

    In any case, if you truly want time from beginning to end, GetProcessTimes will let you do that -- if you spawn the program (e.g., with CreateProcess), you'll get a handle to the process which will be signaled when the child process exits. You can then call GetProcessTimes on that handle, and retrieve the times even though the child has already exited -- the handle will remain valid as long as at least one handle to the process remains open.

    0 讨论(0)
提交回复
热议问题