如何在 Windows 上以 C++ 为单位测量 CPU 时间并包括 system() 的调用

How can I measure CPU time in C++ on windows and include calls of system()?

本文关键字:system 包括 调用 时间 CPU Windows 上以 C++ 测量 为单位      更新时间:2023-10-16

我想在C++算法上运行一些基准测试,并希望根据输入获得所需的CPU时间。我在Windows 7上使用Visual Studio 2012。我已经发现了一种在 Windows 中计算 CPU 时间的方法:如何在 Linux/Windows 上测量 CPU 时间和挂钟时间?

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

我应该补充一个小例子。这是我的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()-命令时,它不会:

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 文件的执行。

一种可能性是在系统调用上获取句柄,这可能以某种方式吗?

Linux:

  • 对于挂钟时间,请使用 gettimeofday() 或 clock_gettime()
  • 对于 CPU 时间,请使用 getrusage() 或 times()

它实际上会打印程序占用的 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 thisn";
return 0;
}
DWORD WINAPI MyThreadFunction( LPVOID lpParam ) 
{ 
    //do your job here
    return 0; 
} 

>如果您使用 C++11(或有权访问它),std::chrono具有计算程序运行时间所需的所有功能。

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

更多信息:

  • 作业的资源核算
  • JOBOBJECT_BASIC_ACCOUNTING_INFORMATION结构

从 Windows 8 开始,支持嵌套作业,因此即使某些程序已依赖于作业对象,也可以使用此方法。

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

您也可以尝试外部采样探查器。 我在Windows下使用了免费赠品"Sleepy"[http://sleepy.sourceforge.net/]甚至更好的"Very Sleepy"[http://www.codersnotes.com/sleepy/]分析器,并且对结果非常满意 - 在几分钟内几乎没有任何努力地格式化了信息。

有一个名为"Shiny"[http://sourceforge.net/projects/shinyprofiler/]的类似项目应该可以在Windows和*nix上运行。

您可以尝试使用加速计时器。 它具有跨平台功能。 来自 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;
}