【问题标题】:Measuring Time Spent Executing Function测量执行函数所花费的时间
【发布时间】:2018-05-23 00:11:58
【问题描述】:

编辑:我已经想通了。第二个算法运行得如此高效,以至于输入 时甚至都没有记录时间

我正在尝试测量我在函数中实现的某个算法需要多长时间才能执行。我已经包含了<time.h>,并且我将函数围绕在time_t 变量周围。它适用于我的第一次实现,但不适用于我的第二次。

我是否需要在使用之间关闭时钟流(想不出更好的工作)?有点像在 Java 程序中关闭 Scanner 流的方式。这是我的代码,以防我解释得不好。

switch(choice) {
    case 1:
        printf("Beginning prefixAverages1\n");
        clock_t begin1 = clock();
        int *a1 = prefixAverages1(input);
        clock_t end1 = clock();
        double time_spent1 = (double)(end1 - begin1) * 1000.0 / CLOCKS_PER_SEC;
        free(a1);
        printf("Algorithm took %f milliseconds to execute \n", time_spent1);
        break;
    case 2:
        printf("Beginning prefixAverages2\n");
        clock_t begin2 = clock();
        int *a2 = prefixAverages2(input);
        clock_t end2 = clock();
        double time_spent2 = (double)(end2 - begin2) * 1000.0 / CLOCKS_PER_SEC;
        free(a2);
        printf("Algorithm took %f milliseconds to execute \n", time_spent2);
        break;
    default:
        printf("Invalid input!");
        break;
}

在我的第一种情况下时间显示正确,但在第二种情况下没有。我已尝试进行一些研究,但找不到任何特定于我的场景的内容。

在运行案例 1 时,根据输入,我有 600-1000 毫秒的时间来运行(这听起来很正确)。当我运行案例 2 时,无论输入如何,我都会得到 00.000

如果有帮助,这是我的功能:

int* prefixAverages1(int input) {
    int x[input];
    int *a = malloc(input*sizeof(*a));
    srand(time(NULL));  

    for(int i = 0; i < input; i++) {
        int sum = 0;
        for(int j = 0; j < i; j++) {
            int r = rand() % 100;
            x[j] = r;
            sum = sum + x[j];
        }
        a[i] = sum / (i+1);
    }
    return a;
}

int* prefixAverages2(int input) {
    int sum = 0;
    int x[input];
    int *a = malloc(input*sizeof(*a));
    srand(time(NULL));  

    for(int i = 0; i < input; i++) {
        int r = rand() % 100;
        x[i] = r;
        sum = sum + x[i];
        a[i] = sum / (i+1);
    }
    return a;
}

【问题讨论】:

  • 第二种情况你怎么知道时间不合适呢?你从第一个和第二个得到什么?函数实际运行需要多长时间?如果它们低于 50 毫秒范围内的数字,则时间可能不可靠,IMO - 并且比这更长会更好。但是你真的需要展示你得到了什么。
  • @JonathanLeffler 你是对的。对于那个很抱歉。我已经编辑了帖子。
  • 看起来测量值应该是准确的。您是否尝试过执行第二个选择然后执行第一个? en.wikipedia.org/wiki/CPU_cache#CPU_stalls。尽管据我所知(一般而言),600ms 的内存时间远远超过现代 CPU 可以缓存的时间
  • begin2end2 之间添加一个睡眠 - 这会告诉你是时间问题还是第二种算法真的很快......
  • @InfoSecNick 我的意思是优化到编译器完全消除对prefixAverages2 的调用。由于代码从不使用返回值(除了释放它),如果prefixAverages2 没有副作用,编译器可能会完全消除调用。尝试使用和不使用优化进行编译。或者对a2 的内容做一些事情,比如打印它们。也许你应该告诉我们prefixAverages2

标签: c time execution-time


【解决方案1】:

虽然我不知道为什么第二个选择可能是 0,但由于这两个函数具有相同的签名,您可以通过使用函数指针来消除冗余代码。

void do_benchmark( const char *name, int*(*functionPtr)(int), int input ) {
    printf("Beginning %s\n", name);
    clock_t begin = clock();
    int *ret = (*functionPtr)(input);
    clock_t end = clock();
    double time_spent = (double)(end - begin) * 1000.0 / CLOCKS_PER_SEC;
    free(ret);
    printf("Algorithm took %f milliseconds to execute \n", time_spent);
}

然后这两个函数使用相同的时序代码运行,消除了作为罪魁祸首的基准测试代码的差异。

switch(choice) {
    case 1:
        do_benchmark("prefixAverages1", &prefixAverages1, input);
        break;
    case 2:
        do_benchmark("prefixAverages2", &prefixAverages2, input);
        break;
    default:
        printf("Invalid input!");
        break;
}

请注意,clock 可能会失败。

如果使用的处理器时间不可用或其值无法表示,则函数返回值 (clock_t)(-1)。

您需要检查该故障。

if( begin == (clock_t)-1 ) {
    fprintf(stderr, "Begin time not available.\n");
}
else if( end == (clock_t)-1 ) {
    fprintf(stderr, "End time not available.\n");
}
else {
    double time_spent = (double)(end - begin) * 1000.0 / CLOCKS_PER_SEC;
    printf("Algorithm took %f milliseconds to execute \n", time_spent);
}

【讨论】:

  • @InfoSecNick 我很想知道是什么。
【解决方案2】:

我更熟悉在 Windows 上使用 QueryPerformanceCounter 执行此操作,因此我可能在这里做了各种各样的坏事,但测量短循环的基本思想:

int main()
{
  printf("Beginning prefixAverages2\n");
  timespec begin, end;
  clock_gettime(CLOCK_REALTIME, &begin);
  int *a1 = prefixAverages2(50000);
  clock_gettime(CLOCK_REALTIME, &end);
  double time_spent = (end.tv_nsec - begin.tv_nsec) / 1000;
  time_spent += (end.tv_sec - begin.tv_sec) *1000000;

  free(a1);
  printf ("Time spent %f microseconds", time_spent);
}

输出:

Beginning prefixAverages2
Time spent 427.000000 microseconds

PS--原来clock() 不做壁时间:Calculate execution time when sleep() is used

【讨论】:

    猜你喜欢
    • 2010-09-23
    • 1970-01-01
    • 2010-12-13
    • 2014-05-25
    • 2020-07-30
    • 1970-01-01
    • 2014-09-05
    • 2016-03-26
    相关资源
    最近更新 更多