0

编辑:在写完这篇解释每一个小细节的长篇文章后,我才发现我的问题......如果有人能给我一个很好的答案,说明我做错了什么以及如何以秒为单位获得执行时间(使用带有 5 的浮点数小数位左右),我将其标记为已接受。提示:问题在于我如何解释 clock_getttime() 手册页。

你好,

假设我有一个名为的函数myOperation,我需要测量它的执行时间。为了测量它,我正在使用其中一条评论clock_gettime()中推荐方法。

我的老师建议我们测量它N的时间,这样我们就可以获得最终报告的平均值、标准差和中位数。他还建议我们执行myOperation M时间,而不仅仅是一个。如果myOperation是一个非常快的操作,测量它M的时间可以让我们了解它所花费的“实时”;导致正在使用的时钟可能没有测量此类操作所需的精度。因此,myOperation只执行一次或M多次真的取决于操作本身是否需要足够长的时间来满足我们使用的时钟精度。

我在处理那次M执行时遇到了麻烦。增加M会降低(很多)最终平均值。这对我来说没有意义。就像这样,从 A 点到 B 点平均需要 3 到 5 秒。但是从 A 点到 B 点再回到 A 点需要 5 次(这就是 10 次,因为 A 到 B 点与 B 点相同)到 A) 然后你测量它。除了除以 10,你得到的平均值应该与你从 A 点到 B 点的平均时间相同,也就是 3 到 5 秒。

这就是我希望我的代码执行的操作,但它不起作用。如果我不断增加从 A 到 B 再返回 A 的次数,每次的平均值都会越来越低,这对我来说毫无意义。

足够的理论,这是我的代码:

#include <stdio.h>
#include <time.h>

#define MEASUREMENTS 1
#define OPERATIONS   1

typedef struct timespec TimeClock;

TimeClock diffTimeClock(TimeClock start, TimeClock end) {
    TimeClock aux;

    if((end.tv_nsec - start.tv_nsec) < 0) {
        aux.tv_sec = end.tv_sec - start.tv_sec - 1;
        aux.tv_nsec = 1E9 + end.tv_nsec - start.tv_nsec;
    } else {
        aux.tv_sec = end.tv_sec - start.tv_sec;
        aux.tv_nsec = end.tv_nsec - start.tv_nsec;
    }

    return aux;
}

int main(void) {
    TimeClock sTime, eTime, dTime;
    int i, j;

    for(i = 0; i < MEASUREMENTS; i++) {
        printf(" » MEASURE %02d\n", i+1);

        clock_gettime(CLOCK_REALTIME, &sTime);

        for(j = 0; j < OPERATIONS; j++) {
            myOperation();
        }

        clock_gettime(CLOCK_REALTIME, &eTime);

        dTime = diffTimeClock(sTime, eTime);

        printf("   - NSEC (TOTAL): %ld\n", dTime.tv_nsec);
        printf("   - NSEC (OP): %ld\n\n", dTime.tv_nsec / OPERATIONS);
    }

    return 0;
}

注:以上diffTimeClock功​​能来自这篇文。我替换了我的实际操作,myOperation()因为发布我的实际功能没有任何意义,因为我必须发布长代码块,myOperation()如果你愿意,你可以轻松地用任何你喜欢的代码来编写代码。

如您所见,OPERATIONS = 1结果是:

 » MEASURE 01
   - NSEC (TOTAL): 27456580
   - NSEC (OP): 27456580

OPERATIONS = 100结果是:

 » MEASURE 01
   - NSEC (TOTAL): 218929736
   - NSEC (OP): 2189297

OPERATIONS = 1000结果是:

 » MEASURE 01
   - NSEC (TOTAL): 862834890
   - NSEC (OP): 862834

OPERATIONS = 10000结果是:

 » MEASURE 01
   - NSEC (TOTAL): 574133641
   - NSEC (OP): 57413

现在,我不是数学天才,实际上远非如此,但这对我来说没有任何意义。我已经和一个和我一起做这个项目的朋友讨论过这个问题,他也无法理解这些差异。我不明白为什么当我增加时价值越来越低OPERATIONS。无论我执行多少次,操作本身都应该花费相同的时间(当然,平均而言,不是完全相同的时间)。

您可以告诉我,这实际上取决于操作本身、正在读取的数据以及某些数据可能已经在缓存中等等,但我认为这不是问题所在。就我而言,myOperation是从 CSV 文件中读取 5000 行文本,通过分隔值;并将这些值插入到数据结构中。对于每次迭代,我都会破坏数据结构并再次对其进行初始化。

现在我想起来了,我也认为用 测量时间有问题clock_gettime(),也许我没有正确使用它。我的意思是,看最后一个例子,其中OPERATIONS = 10000. 总共花费了 574133641ns,大概是 0.5s;那是不可能的,花了几分钟,因为我无法忍受看着屏幕等待并去吃东西。

4

4 回答 4

1

看起来 TimeClock 类型有两个字段,一个是秒,一个是纳秒。仅将 nanosec 字段除以操作数是没有意义的。您需要划分总时间。

于 2010-05-12T19:49:09.770 回答
1

如果您使用的是具有 gettimeofday() 函数的 POSIX 系统,则可以使用类似这样的方法来获取以微秒为单位的当前时间:

long long timeInMicroseconds(void) {
    struct timeval tv;

    gettimeofday(&tv,NULL);
    return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
}

这非常方便的原因是为了计算你的函数需要多少时间,你需要这样做:

long long start = timeInMicroseconds();
... do your task N times ...
printf("Total microseconds: %lld", timeInMicroseconds()-start);

所以你不必处理两个整数,一个是秒,一个是微秒。添加和减去时间将以一种明显的方式起作用。

于 2010-05-12T20:44:22.913 回答
1

您只需要更改diffTimeClock()函数以返回秒数差异,如下所示double

double diffTimeClock(TimeClock start, TimeClock end) {
    double diff;

    diff = (end.tv_nsec - start.tv_nsec) / 1E9;
    diff += (end.tv_sec - start.tv_sec);

    return diff;
}

并在主程序中更改dTime为 adouble和 printfs 以适应:

printf("   - SEC (TOTAL): %f\n", dTime);
printf("   - SEC (OP): %f\n\n", dTime / OPERATIONS);
于 2010-05-12T23:28:36.853 回答
0

我通常为此使用 time() 函数。它显示挂钟时间,但这才是我最终关心的。

性能测试的一个问题是操作系统可能会缓存与文件系统相关的操作。所以第二次(及以后)运行可能比第一次运行快得多。您通常需要测试可能的操作并对结果进行平均,以便对您所做的任何更改的结果有一个好的感觉。有很多变量可以帮助您过滤掉噪音。

于 2010-05-12T19:44:07.370 回答