如何在Windows上测量C++中的CPU时间并包括system()函数的调用?

7
我想在一个C++算法上运行一些基准测试,并希望根据输入获取它所需的CPU时间。我在Windows 7上使用Visual Studio 2012。我已经发现了一种在Windows上计算CPU时间的方法:如何在Linux/Windows上测量CPU时间和墙钟时间? 然而,我在我的算法中使用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()命令时,就像在这种情况下一样,它就不起作用了:

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,有什么办法可以做到吗?
7个回答

0

它实际上会打印出程序所需的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; 
} 

0

我认为没有跨平台的机制。使用CreateProcess启动应用程序,并使用WaitForSingleObject等待应用程序完成,可以让您获得直接子代的时间。之后,如果您需要计时孙子辈,您将需要使用作业对象进行完整的计时。


0

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

更多信息:

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


0
如果你使用C++11(或者有访问权限),std::chrono拥有所有你需要计算程序运行时间的函数。

但它只返回调用进程使用的时间,而问题的主题是子进程的测量。 - Ben Voigt

0

2
对于Windows上的CPU时间,您可以使用GetProcessInformation(),但它需要一个子进程的句柄,而您使用system()不会得到该句柄 - 另一种方法似乎是查找和读取适当的性能计数器,这是非平凡的,我对此部分的回答不够了解。 - nos

0

-1

你可以尝试使用boost计时器。它具有跨平台能力。以下是来自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;
}

但它只返回调用进程使用的时间,而问题的主题是子进程的测量。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接