Linux中的代码执行时间

时间:2014-03-11 01:27:33

标签: c++ c linux performance

我试图获取特定代码段的执行时间(可能是循环或函数等)。我听说命令time或函数clock()完成了这项工作。但我的要求是毫秒/微秒的准确度。所以我写了这样的东西。

int main()
{
    struct timeval ts1, ts2;
    long long time1, time2, diff;
    int i,var;

    scanf("%d",&var);
    gettimeofday(&ts1, NULL);
    time1 = (ts1.tv_sec * 1000000) + ts1.tv_usec;

    for (i=0; i<var; i++); // <-- Trying to measure execution time for the loop

    gettimeofday(&ts2, NULL);
    time2 = (ts2.tv_sec * 1000000) + ts2.tv_usec;

    printf("-------------------------\n");
    diff = time2 - time1;
    printf("total %ld microseconds\n", diff);
    printf("%ld seconds\n", diff/1000000);
    diff %= 1000000;
    printf("%ld milliseconds\n", diff/1000);
    diff %= 1000;
    printf("%ld microseconds\n", diff);
    printf("-------------------------\n");
    return 0;
}

我有两个问题

  1. 以上代码是否可靠,我的意图是什么?我不太确定;)
  2. 当我使用优化级别-O2编译代码时,这根本不起作用。我知道-O2会应用一些化妆但我怎么看才会发生什么?如果我愿意选择1,那么有人可以建议如何恢复O2问题吗?
  3. 感谢您的帮助!感谢。

4 个答案:

答案 0 :(得分:1)

您显示的上述代码是为了获得自gettimeofday()返回挂钟时间以来的实际时间。至于不使用优化级别-O2,请将i声明为volatile int i,这将阻止优化到i

答案 1 :(得分:1)

这个NanoTimer类(头文件)应该可以完成这项工作。 使用startTimer()/ stopTimer()。请注意,计算此相对分辨率的已用时间需要一段时间,因此如果只执行startTimer(),则永远不会有0值; stopTimer();中间没有任何代码。 此外还有许多其他因素会影响已用时间,因此您应多次重复特定度量并取最低值。

class NanoTimer
{
    struct timespec ts_;
    u_int64_t startTimer_;
    u_int64_t totalTimer_;
public:
    NanoTimer()
    {
        totalTimer_ = 0;
        startTimer_ = 0;
    }

    u_int64_t getNanoSecTimer(void)
    {
        clock_gettime(CLOCK_REALTIME, &ts_);
        return ts_.tv_sec * 1000000000 +  ts_.tv_nsec;
    }

    void startTimer(void)
    {
        startTimer_ = getNanoSecTimer();
    }
    void stopTimer(void)
    {
        //assert(startTimer_ > 0);
        totalTimer_ += getNanoSecTimer() - startTimer_;
        startTimer_ = 0;
    }
    inline u_int32_t getTotalSeconds()
    {
        return totalTimer_/1000000000;
    }
    inline u_int32_t getTotalMilliseconds()
    {
        return totalTimer_/1000000;
    }
    inline u_int32_t getTotalMicroseconds()
    {
        return totalTimer_/1000;
    }
    inline u_int32_t getTotalNanoseconds()
    {
        return totalTimer_;
    }
    inline u_int32_t getCurrentSeconds()
    {
        return (totalTimer_ + (startTimer_ > 0 ? getNanoSecTimer() - startTimer_ : 0)) / 1000000000;
    }
};

答案 2 :(得分:0)

您可以使用示例代码!!该代码导致计算成本无开销

#include <sys/time.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/resource.h>

void timing(double* wcTime, double* cputime)
{
    struct timeval tp;

    gettimeofday(&tp, NULL);
    *wcTime=(double) (tp.tv_sec + tp.tv_usec/1000000.0);

    struct rusage ruse;
    getrusage(RUSAGE_SELF, &ruse);
    *cpuTime=(double)(ruse.ru_utime.tv_sec+ruse.ru_utime.tv_usec / 1000000.0);
}

使用:

double  wcs,    //  Wall Clock Start
        wce,    //  Wall Clock End
        ccs,    //  CPU Clock Start
        cce;    //  CPU Clock End
timing(&wcs, &ccs);

//  COMPUTATION CODE

timing(&wce, &cce);

cout << "CPU RUNTIME:       " << cce - ccs << endl
     << "WALL CLOCK TIME:   " << wce - wcs << endl;

答案 3 :(得分:0)

可变速率CPU时钟和热余量的利用使我越来越怀疑,对于运行时间不够长以加热核心的功能而言,挂钟时间以秒为单位可能不如循环计数有用。

如果我正在使用我自己的代码,我倾向于选择以下内容:

static __inline__ uint64_t rdtsc(void)
{
    uint32_t hi, lo;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
    return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 );
}

使用它,我可以在函数调用之前和之后记录TSC值,减去这两个值,并获得所花费的周期数。

如果您需要挂钟时间,可以使用clock_gettime()中的time.h,如果不准确,将为您提供纳秒分辨率,并使用以下内容减去两者(之前和之后){{ 1}}对象:

struct timespec

那就是说,我倾向于使用#define NSEC_PER_SEC 1000000000 static int timespec_subtract(result, x, y) struct timespec *result, *x, *y; { /* Perform the carry for the later subtraction by updating y. */ if (x->tv_nsec < y->tv_nsec) { int nsec = (y->tv_nsec - x->tv_nsec) / NSEC_PER_SEC + 1; y->tv_nsec -= NSEC_PER_SEC * nsec; y->tv_sec += nsec; } if (x->tv_nsec - y->tv_nsec > NSEC_PER_SEC) { int nsec = (x->tv_nsec - y->tv_nsec) / NSEC_PER_SEC; y->tv_nsec += NSEC_PER_SEC * nsec; y->tv_sec -= nsec; } /* Compute the time remaining to wait. tv_nsec is certainly positive. */ result->tv_sec = x->tv_sec - y->tv_sec; result->tv_nsec = x->tv_nsec - y->tv_nsec; /* Return 1 if result is negative. */ return x->tv_sec < y->tv_sec; } 并完全避免使用仪器。