寻找基准测试的代码片段(C++)

25

我的程序中有一些加载例程需要太长时间才能完成。我想要一个快速的小片段来检查函数执行的时间,尽量不使用第三方库。

也许简单地获取系统时间就可以了吗?

start = current_system_time()
load_something()
delta = current_system_time()-start
log_debug("load took "+delta)

编辑: 问题中的目标操作系统是Windows。


这个问题不会得到任何答案,因为“是”太短了无法发布。 - Chris Becke
2
我希望能得到一个“是”的回答,然后是一个更加清晰/更好的想法,即... - Mizipzor
5个回答

18

你的回答:是的

注意:那种方法 不适用于多线程代码或多核机器,你需要一个强大的挂钟计时器。因此,我建议你使用omp的wallclock。OMP已经包含在VC和GCC中,它是大多数编译器和标准,你不需要担心它会消失。

#include <omp.h>

// Starting the time measurement
double start = omp_get_wtime();
// Computations to be measured
...
// Measuring the elapsed time
double end = omp_get_wtime();
// Time calculation (in seconds)

4
请确保链接到-lgomp。 - Roger Collins

14
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)

namespace win32 {
    #include <windows.h>
}

class timer
{
    win32::LARGE_INTEGER start_time_;
public:
    timer() { QueryPerformanceCounter( &start_time_ ); }
    void   restart() { QueryPerformanceCounter( &start_time_ ); }
    double elapsed() const
    {
        win32::LARGE_INTEGER end_time, frequency;
        QueryPerformanceCounter( &end_time );
        QueryPerformanceFrequency( &frequency );
        return double( end_time.QuadPart - start_time_.QuadPart )
            / frequency.QuadPart;
    }
};

#else

#include <ctime>

class timer
{
    clock_t _start_time;
public:
    timer() { _start_time = clock(); }
    void   restart() { _start_time = clock(); }
    double elapsed() const
    {
        return double(clock() - _start_time) / CLOCKS_PER_SEC;
    }
};

#endif

template< typename Func >
double measure_time( Func f )
{
    timer t;
    f();
    return t.elapsed();
}

5

这是一种快速而简单的方法来计时 C/C++ 代码块。您需要 #include <sys/time.h>,这应该是一个标准头文件...

struct timeval start, end;
gettimeofday(&start, NULL);
// benchmark code
gettimeofday(&end, NULL);
long long time =   (end.tv_sec * (unsigned int)1e6 +   end.tv_usec) - 
                 (start.tv_sec * (unsigned int)1e6 + start.tv_usec);

这应该能够在现代 Linux 系统上提供 1-2 微秒的分辨率(您使用的是哪个操作系统?),这意味着它并不适合学习需要少于 10 微秒的项目。但是,您似乎不处于这种情况下。
更新:根据指定的操作系统... Windows 实现 gettimeofday()

1

我使用一个类来实现这个功能,它设计用于测量执行函数所用的时间,并将其写入到一个UTF-16LE文本文件中(我需要更新为使用新类,但无需理会)。

在函数顶部创建一个新的实例,例如jProfiler(L"myFunction"),并且在函数结束后清除,如果您想要确保自己进行新建和删除。对于小型测试来说可能有点过度,但可以提高效率:

// start header

/* jProfiler class by Semi Essessi
 *
 * (class description goes here)
 *
 */

#ifndef __JPROFILER_H
#define __JPROFILER_H

#include <stdio.h>
#include <windows.h>

class jProfiler
{
private:
    wchar_t*        str;
    LARGE_INTEGER   start;
    LARGE_INTEGER   tps;
    LARGE_INTEGER   buf;

    static FILE*    f;
    static int      instCount;

    static void     Initialise();
    static void     Shutdown();
public:
    jProfiler(const wchar_t* msg);
    ~jProfiler();
};

#endif

// - end header

/* jProfiler class by Semi Essessi
 *
 * (class description goes here)
 *
 */

#include "jProfiler.h"

#include <windows.h>

FILE* jProfiler::f = 0;
int jProfiler::instCount = 0;

jProfiler::jProfiler(const wchar_t* msg)
{
    // constructor code for menuVar
    int i = (int)wcslen(msg)+1;
    str = new wchar_t[i];
    memcpy(str, msg, sizeof(wchar_t)*i);
    str[i-1] =  0;

    QueryPerformanceFrequency(&tps);
    QueryPerformanceCounter(&start);

    instCount++;
    Initialise();
}

jProfiler::~jProfiler()
{
    // destructor code for menuVar
    QueryPerformanceCounter(&buf);
    // work out change in time
    double dt=((float)buf.QuadPart - (float)start.QuadPart)/(float)tps.QuadPart;
    fwprintf(f, L"%s : %.20f\r\n", str, dt);

    if(str) delete[] str;
    instCount--;
    Shutdown();
}

void jProfiler::Initialise()
{
    if(!f)
    {
        f = _wfopen(L"profilerlog.txt", L"wb");
        unsigned short a = 0xFEFF;
        fwrite(&a, sizeof(unsigned short), 1, f);
    }
}

void jProfiler::Shutdown()
{
    if(instCount==0) if(f) fclose(f);
}

1
我有一个名为benchmark.hpp的头文件在我的sweet.hpp库中。它有两个基准测试工具。第一个是一个简单的手动开始停止计时器。
Bench b;
...
b.stop();
b.milli(); // returns an uint with passed millisec. Also has sec and micro sec

另一个稍微复杂一些。您可以像这样编写函数或块语句。
void myFunc() {
    BENCH(someName);
    ...
}

最后,调用sweet::Benchmark::printResults();函数,以打印所花费的时间和调用次数。
编辑: 我添加了一个函数,你可以像这样调用它。
double c = BENCHMARK_CNT(25, yourFunctionCallHere());

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