我有一个C程序,目的是在几个处理器上并行运行。我需要能够记录执行时间(可以从1秒到几分钟不等)。我已经搜索了答案,但它们似乎都建议使用clock()函数,然后涉及计算程序所用的时钟数除以Clocks_per_second值。

我不确定Clocks_per_second值是如何计算的?

在Java中,我只是在执行前后以毫秒为单位获取当前时间。

C语言中也有类似的东西吗?我看了一下,但我似乎找不到比第二次分辨率更好的方法。

我也知道一个分析器将是一个选项,但我希望自己实现一个定时器。

谢谢


当前回答

我发现通常的clock(),这里每个人都推荐,由于某种原因在一次运行中严重偏离,即使对于静态代码也没有任何副作用,如绘制到屏幕或读取文件。这可能是因为CPU改变了功耗模式,操作系统给出了不同的优先级,等等…

因此,每次使用clock()都可靠地获得相同结果的唯一方法是在循环中多次运行测量的代码(持续几分钟),并采取预防措施防止编译器对其进行优化:现代编译器可以预先计算在循环中运行的代码而不会产生副作用,并将其移出循环。例如,每次迭代都使用随机输入。

在一个数组中收集了足够多的样本后,对数组进行排序,并取中间的元素,称为中位数。中位数比平均值好,因为它排除了极端偏差,比如反病毒病毒占用了所有CPU或操作系统进行了一些更新。

这里有一个简单的实用程序来测量C/ c++代码的执行性能,平均值接近中值:https://github.com/saniv/gauge

我自己仍然在寻找一种更健壮、更快的方法来度量代码。人们可能会尝试在没有任何操作系统的情况下在受控条件下运行代码,但这会产生不切实际的结果,因为在现实中操作系统确实涉及到。

x86有这些硬件性能计数器,包括实际执行的指令数量,但是如果没有操作系统的帮助,它们很难访问,很难解释,并且有自己的问题(http://archive.gamedev.net/archive/reference/articles/article213.html)。尽管如此,他们仍然可以帮助调查瓶颈的性质(数据访问或对数据的实际计算)。

其他回答

    #include<time.h>
    #include<stdio.h>
    int main(){
      clock_t begin=clock();

      int i;
      for(i=0;i<100000;i++){
        printf("%d",i);
      }
      clock_t end=clock();

      printf("Time taken:%lf",(double)(end-begin)/CLOCKS_PER_SEC);
    }

这个程序会很有效。

如果你的程序使用GPU或者使用sleep(),那么clock() diff给出的持续时间小于实际持续时间。这是因为clock()返回CPU时钟滴答数。它只能用于计算CPU使用时间(CPU负载),而不能用于计算执行持续时间。我们不应该使用clock()来计算持续时间。在C语言中,我们仍然应该使用gettimeofday()或clock_gettime()来表示持续时间。

Perf工具更准确地用于收集和分析正在运行的程序。使用性能统计显示与正在执行的程序相关的所有信息。

有些人可能会发现另一种输入方式很有用:我在大学课程中用NVidia CUDA进行gpgpu编程时学过这种测量时间的方法(课程描述)。它结合了在以前的文章中看到的方法,我只是简单地发布它,因为需求赋予它可信度:

unsigned long int elapsed;
struct timeval t_start, t_end, t_diff;
gettimeofday(&t_start, NULL);

// perform computations ...

gettimeofday(&t_end, NULL);
timeval_subtract(&t_diff, &t_end, &t_start);
elapsed = (t_diff.tv_sec*1e6 + t_diff.tv_usec);
printf("GPU version runs in: %lu microsecs\n", elapsed);

我认为你可以乘以1.0 / 1000.0来得到适合你需要的测量单位。

ANSI C只指定秒精度时间函数。但是,如果您在POSIX环境中运行,则可以使用gettimeofday()函数,该函数提供自UNIX纪元以来经过的时间的微秒分辨率。

作为旁注,我不建议使用clock(),因为它在许多(如果不是所有?)系统上实现得很糟糕,而且不准确,此外,它只指程序在CPU上花费了多长时间,而不是程序的总生命周期,根据您的问题,我认为您想测量的是总生命周期。