【问题标题】:Time a function in C++在 C++ 中为函数计时
【发布时间】:2015-10-25 22:58:13
【问题描述】:

我想计算一个函数在 C++ 中花费的时间(以毫秒为单位)。

这是我所拥有的:

#include<iostream>
#include<chrono>           
using timepoint = std::chrono::steady_clock::time_point;

float elapsed_time[100];

// Run function and count time
for(int k=0;k<100;k++) {

    // Start timer
    const timepoint clock_start = chrono::system_clock::now();

    // Run Function
    Recursive_Foo();

    // Stop timer
    const timepoint clock_stop = chrono::system_clock::now();

    // Calculate time in milliseconds
    chrono::duration<double,std::milli> timetaken = clock_stop - clock_start;
    elapsed_time[k] = timetaken.count();
}

for(int l=0;l<100;l++) {
    cout<<"Array: "<<l<<" Time: "<<elapsed_time[l]<<" ms"<<endl;
}

这可以编译,但我认为多线程会阻止它正常工作。输出以不规则的间隔产生时间,例如:

Array: 0 Time: 0 ms
Array: 1 Time: 0 ms
Array: 2 Time: 15.6 ms
Array: 3 Time: 0 ms
Array: 4 Time: 0 ms
Array: 5 Time: 0 ms
Array: 6 Time: 15.6 ms
Array: 7 Time: 0 ms
Array: 8 Time: 0 ms

我需要使用某种互斥锁吗?或者有没有更简单的方法来计算函数执行所需的毫秒数?

编辑

也许人们建议使用high_resolution_clocksteady_clock,但是这三个都会产生相同的不规则结果。

这个解决方案似乎产生了真正的结果:How to use QueryPerformanceCounter? 但我不清楚为什么。此外,https://gamedev.stackexchange.com/questions/26759/best-way-to-get-elapsed-time-in-miliseconds-in-windows 效果很好。似乎是 Windows 实现问题。

【问题讨论】:

  • 改用steady_clockhigh_resolution_clocksystem_clock 的粒度可能不够。
  • 是的,我已经尝试了所有 3 个,结果相同。我假设这是一个多线程问题,尽管很难指出。我也尝试过将 time_point 传递给函数,当函数结束时,返回差异,但这似乎也不起作用。
  • @OrdinaryHuman 也许这就是你的函数的工作原理?你试过测量睡眠吗?前任。 std::this_thread::sleep_for(std::chrono::milliseconds(15000));
  • 我相信问题在于您记录的是 CPU 时间而不是挂壁时间。如果您有权访问OpenMP,您应该能够使用函数omp_get_wtime() 获取挂钟时间。我确信在您使用的任何多线程语言中都有一个等价物。一般来说system_clock() 会返回 CPU 时间——不是你想要的。
  • @NoseKnowsAll 谢谢,但我不想要挂墙时间,我需要知道函数执行需要多少毫秒或微秒。测量墙上的时间会给我带来噪音——例如,如果有 15 个线程在运行,那么我的性能取决于其他获得 CPU 时间的东西。我正在寻找一个函数运行多长时间。我认为下面通过 Microsoft 提供的QueryPerformanceCounter 解决方案可能是 Windows 上唯一的方法。

标签: c++ multithreading timer mutex


【解决方案1】:

微软在微秒内提供了一个不错、干净的解决方案,通过:MSDN

#include <windows.h>

LONGLONG measure_activity_high_resolution_timing()
{
    LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
    LARGE_INTEGER Frequency;

    QueryPerformanceFrequency(&Frequency); 
    QueryPerformanceCounter(&StartingTime);

    // Activity to be timed

    QueryPerformanceCounter(&EndingTime);
    ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;


    //
    // We now have the elapsed number of ticks, along with the
    // number of ticks-per-second. We use these values
    // to convert to the number of elapsed microseconds.
    // To guard against loss-of-precision, we convert
    // to microseconds *before* dividing by ticks-per-second.
    //

    ElapsedMicroseconds.QuadPart *= 1000000;
    ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;
    return ElapsedMicroseconds.QuadPart;
}

【讨论】:

  • 我刚刚测试过它,它就像一个魅力。我做了一些小的编辑来为代码示例提供所需的头文件:默认情况下它不包含在我的 VS 项目中(可能是因为我正在重用控制台应用程序项目),并且 MSDN 文档在这一点上还不清楚。
【解决方案2】:

使用高分辨率计时器而不是系统时钟的配置文件代码;如您所见,它的粒度非常有限。

http://www.cplusplus.com/reference/chrono/high_resolution_clock/

typedef tp high_resolution_clock::time_point

const tp start = high_resolution_clock::now();
// do stuff
const tp end   = high_resolution_clock::now();

【讨论】:

  • 谢谢。我试过了,但 high_resolution_clock、system_clock 和 stable_clock 似乎都产生相同的不规则结果,大多数报告为 0。
  • @OrdinaryHuman 看看high_resolution_clock::time_point的成员,可能你的代码忽略了更高分辨率的值?
【解决方案3】:

如果您怀疑应用中的某些其他进程或线程占用过多 CPU 时间,请使用:

windows下的GetThreadTimes

linux下带有CLOCK_THREAD_CPUTIME_ID的clock_gettime

测量线程 CPU 时间您的函数正在执行。这将从您的测量时间中排除在分析期间执行其他线程/进程的时间。

【讨论】:

猜你喜欢
  • 2014-01-25
  • 2015-02-23
  • 2013-01-08
  • 2012-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-16
  • 1970-01-01
相关资源
最近更新 更多