我有一个C程序,目的是在几个处理器上并行运行。我需要能够记录执行时间(可以从1秒到几分钟不等)。我已经搜索了答案,但它们似乎都建议使用clock()函数,然后涉及计算程序所用的时钟数除以Clocks_per_second值。
我不确定Clocks_per_second值是如何计算的?
在Java中,我只是在执行前后以毫秒为单位获取当前时间。
C语言中也有类似的东西吗?我看了一下,但我似乎找不到比第二次分辨率更好的方法。
我也知道一个分析器将是一个选项,但我希望自己实现一个定时器。
谢谢
您必须考虑到,测量程序执行所花费的时间在很大程度上取决于机器在特定时刻的负载。
我们知道,在C语言中获取当前时间的方法有不同的方法,更简单的方法是:
#include <time.h>
#define CPU_TIME (getrusage(RUSAGE_SELF,&ruse), ruse.ru_utime.tv_sec + \
ruse.ru_stime.tv_sec + 1e-6 * \
(ruse.ru_utime.tv_usec + ruse.ru_stime.tv_usec))
int main(void) {
time_t start, end;
double first, second;
// Save user and CPU start time
time(&start);
first = CPU_TIME;
// Perform operations
...
// Save end time
time(&end);
second = CPU_TIME;
printf("cpu : %.2f secs\n", second - first);
printf("user : %d secs\n", (int)(end - start));
}
希望能有所帮助。
的问候!
CLOCKS_PER_SEC是一个在<time.h>中声明的常量。要获得C应用程序中任务使用的CPU时间,请使用:
clock_t begin = clock();
/* here, do your time-consuming job */
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
注意,这将以浮点类型返回时间。这可以比一秒更精确(例如,你测量的是4.52秒)。精度取决于架构;在现代系统上,你很容易得到10毫秒或更低,但在老式的Windows机器上(从Win98时代开始),它接近60毫秒。
clock()是标准C;它“无处不在”。有一些系统特定的函数,比如类unix系统上的getrusage()。
Java的System.currentTimeMillis()没有测量相同的东西。它是一个“挂钟”:它可以帮助您测量程序执行所花费的时间,但它不会告诉您使用了多少CPU时间。在多任务系统(即所有系统)上,这些可能有很大的不同。
很多答案都建议使用clock(),然后是time.h中的CLOCKS_PER_SEC。这可能是一个坏主意,因为这是我的/bits/time.h文件所写的:
/* ISO/IEC 9899:1990 7.12.1: <time.h>
The macro `CLOCKS_PER_SEC' is the number per second of the value
returned by the `clock' function. */
/* CAE XSH, Issue 4, Version 2: <time.h>
The value of CLOCKS_PER_SEC is required to be 1 million on all
XSI-conformant systems. */
# define CLOCKS_PER_SEC 1000000l
# if !defined __STRICT_ANSI__ && !defined __USE_XOPEN2K
/* Even though CLOCKS_PER_SEC has such a strange value CLK_TCK
presents the real value for clock ticks per second for the system. */
# include <bits/types.h>
extern long int __sysconf (int);
# define CLK_TCK ((__clock_t) __sysconf (2)) /* 2 is _SC_CLK_TCK */
# endif
因此,CLOCKS_PER_SEC可能定义为1000000,这取决于用于编译的选项,因此它似乎不是一个好的解决方案。
冒泡排序和选择排序执行时间的比较
我有一个程序,比较冒泡排序和选择排序的执行时间。
要找出一个代码块的执行时间,计算该代码块之前和之后的时间
clock_t start=clock();
…
clock_t end=clock();
CLOCKS_PER_SEC is constant in time.h library
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int a[10000],i,j,min,temp;
for(i=0;i<10000;i++)
{
a[i]=rand()%10000;
}
//The bubble Sort
clock_t start,end;
start=clock();
for(i=0;i<10000;i++)
{
for(j=i+1;j<10000;j++)
{
if(a[i]>a[j])
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
end=clock();
double extime=(double) (end-start)/CLOCKS_PER_SEC;
printf("\n\tExecution time for the bubble sort is %f seconds\n ",extime);
for(i=0;i<10000;i++)
{
a[i]=rand()%10000;
}
clock_t start1,end1;
start1=clock();
// The Selection Sort
for(i=0;i<10000;i++)
{
min=i;
for(j=i+1;j<10000;j++)
{
if(a[min]>a[j])
{
min=j;
}
}
temp=a[min];
a[min]=a[i];
a[i]=temp;
}
end1=clock();
double extime1=(double) (end1-start1)/CLOCKS_PER_SEC;
printf("\n");
printf("\tExecution time for the selection sort is %f seconds\n\n", extime1);
if(extime1<extime)
printf("\tSelection sort is faster than Bubble sort by %f seconds\n\n", extime - extime1);
else if(extime1>extime)
printf("\tBubble sort is faster than Selection sort by %f seconds\n\n", extime1 - extime);
else
printf("\tBoth algorithms have the same execution time\n\n");
}
(如果您的系统管理员更改了系统时间,或者您的时区有不同的冬季和夏季时间,这里就没有所有的答案。因此…)
在linux上使用:clock_gettime(clock_单调ic_raw, &time_variable);
如果系统管理员改变了时间,或者你生活在一个冬季和夏季不同的国家,等等,它不会受到影响。
#include <stdio.h>
#include <time.h>
#include <unistd.h> /* for sleep() */
int main() {
struct timespec begin, end;
clock_gettime(CLOCK_MONOTONIC_RAW, &begin);
sleep(1); // waste some time
clock_gettime(CLOCK_MONOTONIC_RAW, &end);
printf ("Total time = %f seconds\n",
(end.tv_nsec - begin.tv_nsec) / 1000000000.0 +
(end.tv_sec - begin.tv_sec));
}
Man clock_gettime声明:
CLOCK_MONOTONIC
Clock that cannot be set and represents monotonic time since some unspecified starting point. This clock is not affected by discontinuous jumps in the system time
(e.g., if the system administrator manually changes the clock), but is affected by the incremental adjustments performed by adjtime(3) and NTP.
有些人可能会发现另一种输入方式很有用:我在大学课程中用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来得到适合你需要的测量单位。
我发现通常的clock(),这里每个人都推荐,由于某种原因在一次运行中严重偏离,即使对于静态代码也没有任何副作用,如绘制到屏幕或读取文件。这可能是因为CPU改变了功耗模式,操作系统给出了不同的优先级,等等…
因此,每次使用clock()都可靠地获得相同结果的唯一方法是在循环中多次运行测量的代码(持续几分钟),并采取预防措施防止编译器对其进行优化:现代编译器可以预先计算在循环中运行的代码而不会产生副作用,并将其移出循环。例如,每次迭代都使用随机输入。
在一个数组中收集了足够多的样本后,对数组进行排序,并取中间的元素,称为中位数。中位数比平均值好,因为它排除了极端偏差,比如反病毒病毒占用了所有CPU或操作系统进行了一些更新。
这里有一个简单的实用程序来测量C/ c++代码的执行性能,平均值接近中值:https://github.com/saniv/gauge
我自己仍然在寻找一种更健壮、更快的方法来度量代码。人们可能会尝试在没有任何操作系统的情况下在受控条件下运行代码,但这会产生不切实际的结果,因为在现实中操作系统确实涉及到。
x86有这些硬件性能计数器,包括实际执行的指令数量,但是如果没有操作系统的帮助,它们很难访问,很难解释,并且有自己的问题(http://archive.gamedev.net/archive/reference/articles/article213.html)。尽管如此,他们仍然可以帮助调查瓶颈的性质(数据访问或对数据的实际计算)。