【问题标题】:How can I measure CPU time in C++ on windows and include calls of system()?如何在 Windows 上测量 C++ 中的 CPU 时间并包括 system() 调用?
【发布时间】:2013-11-27 10:03:23
【问题描述】:

我想在 C++ 算法上运行一些基准测试,并希望根据输入获得所需的 CPU 时间。我在 Windows 7 上使用 Visual Studio 2012。我已经发现了一种在 Windows 中计算 CPU 时间的方法:How can I measure CPU time and wall clock time on both Linux/Windows?

但是,我在我的算法中使用了system() 命令,但不是以这种方式测量的。那么,如何测量 CPU 时间并通过 system() 包含脚本调用的时间?

我应该添加一个小例子。这是我的 get_cpu_time 函数(来自上述链接):

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

到目前为止,它工作得很好,当我编写一个程序,对一些数组进行排序(或做一些其他需要一些时间的事情)时,它工作得很好。但是,当我在这种情况下使用 system()-command 时,它不会:

int main( int argc, const char* argv[] )
{
    double start = get_cpu_time();
    double end;
    system("Bla.exe");
    end = get_cpu_time();

    printf("Everything took %f seconds of CPU time", end - start);

    std::cin.get();

}

给定 exe 文件的执行以相同的方式测量,大约需要 5 秒。当我通过 system() 运行它时,整个过程占用了 0 秒的 CPU 时间,这显然不包括 exe 文件的执行。

一种可能性是在系统调用上获得 HANDLE,这可能吗?

【问题讨论】:

    标签: c++ windows cpu-time


    【解决方案1】:

    Linux:

    【讨论】:

    • 至于 Windows 上的 CPU 时间,您可能可以使用 GetProcessInformation() ,但它需要一个 HANDLE 给孩子,而您无法使用 system() - 其他方式似乎找到并阅读正确的性能计数器,这是非常重要的,我对它的了解还不够,无法回答那部分。
    【解决方案2】:

    它实际上会打印您的程序占用的 CPU 时间。但是如果您在程序中使用线程,它将无法正常工作。在完成 CPU 时间之前,您应该等待线程完成它的工作。所以基本上你应该这样写:

    WaitForSingleObject(threadhandle, INFINITE);
    

    如果你不知道你在你的程序中到底使用了什么(如果它是多线程的)你可以创建一个线程来完成这项工作并等待线程终止并测量时间。

    DWORD WINAPI MyThreadFunction( LPVOID lpParam );
    int main()
    {
    DWORD   dwThreadId;
    HANDLE  hThread;
    
    int startcputime, endcputime, wcts, wcte;
    
    startcputime = cputime();
    
    hThread = CreateThread( 
                NULL,                   // default security attributes
                0,                      // use default stack size  
                MyThreadFunction,       // thread function name
                NULL,                   // argument to thread function 
                0,                      // use default creation flags 
                dwThreadIdArray);
    
    WaitForSingleObject(hThread, INFINITE);
    
    endcputime = cputime();
    
    std::cout << "it took " << endcputime - startcputime << " s of CPU to execute this\n";
    
    return 0;
    }
    
    DWORD WINAPI MyThreadFunction( LPVOID lpParam ) 
    { 
        //do your job here
        return 0; 
    } 
    

    【讨论】:

      【解决方案3】:

      您可以尝试使用加速计时器。它具有跨平台能力。来自 boost 网站的示例代码:

      #include <boost/timer/timer.hpp>
      #include <cmath>
      
      int main() {
       boost::timer::auto_cpu_timer t;
      
        for (long i = 0; i < 100000000; ++i)
          std::sqrt(123.456L); // burn some time
      
       return 0;
      }
      

      【讨论】:

      • 但是它只返回调用进程使用的时间,问题的主题是子进程的测量。
      【解决方案4】:

      如果您使用 C++11(或可以访问它)std::chrono 拥有计算程序运行时长所需的所有功能。

      【讨论】:

      • 但它只返回调用进程使用的时间,问题的主题是测量子进程。
      【解决方案5】:

      在创建任何子进程之前,您需要将进程添加到 Job 对象。然后子进程将自动在同一个作业中运行,您想要的信息可以在JOBOBJECT_BASIC_ACCOUNTING_INFORMATION 结构的TotalUserTimeTotalKernelTime 成员中找到,可通过QueryInformationJobObject 函数获得。

      更多信息:

      从 Windows 8 开始,nested jobs are supported,因此即使某些程序已经依赖于作业对象,您也可以使用此方法。

      【讨论】:

        【解决方案6】:

        我认为没有跨平台机制。使用 CreateProcess 启动应用程序,使用 WaitForSingleObject 完成应用程序,将允许您获得直接后代时间。之后,您将需要工作对象来完成会计(如果您需要为孙子计时)

        【讨论】:

          【解决方案7】:

          您也可以试一试外部采样分析器。我在 Windows 下使用了免费赠品“Sleepy”[http://sleepy.sourceforge.net/]and 甚至更好的“Very Sleepy”[http://www.codersnotes.com/sleepy/] 分析器,并且对结果非常满意 - 几分钟内就可以轻松格式化信息。

          有一个类似的项目叫做“Shiny”[http://sourceforge.net/projects/shinyprofiler/],它应该可以在 Windows 和 *nix 上运行。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-06-30
            • 1970-01-01
            • 2013-12-08
            • 1970-01-01
            • 1970-01-01
            • 2013-03-21
            • 1970-01-01
            • 2023-03-03
            相关资源
            最近更新 更多