C程序的执行时间

Rog*_*ger 194 c benchmarking

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

我不确定如何Clocks_per_second计算价值?

在Java中,我只是在执行之前和之后以毫秒为单位.

C中有类似的东西吗?我看过了,但我似乎无法找到比第二种解决方案更好的方法.

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

谢谢

Tho*_*nin 315

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;
Run Code Online (Sandbox Code Playgroud)

请注意,这会将时间作为浮点类型返回.这可能比一秒钟更精确(例如,您测量4.52秒).精度取决于架构; 在现代系统上你很容易获得10毫秒或更低,但在较旧的Windows机器上(从Win98时代)它接近60毫秒.

clock()是标准C; 它"无处不在".有系统特定的功能,例如getrusage()类Unix系统.

Java System.currentTimeMillis()并没有衡量同样的事情.它是一个"挂钟":它可以帮助您测量程序执行所花费的时间,但它并不能告诉您使用了多少CPU时间.在多任务系统(即所有这些系统)上,这些系统可能大不相同.

  • 大警告:clock()返回操作系统运行过程所花费的时间,而不是实际经过的时间.但是,这适用于对一段代码进行计时,但不能测量现实世界中流逝的时间. (12认同)
  • 是:`clock()`返回称为"时钟"的内部标度的时间,"CLOCKS_PER_SEC"是每秒的时钟数,因此除以"CLOCKS_PER_SEC"会产生以秒为单位的时间.在上面的代码中,值是一个"double",因此您可以随意缩放它. (3认同)
  • 他说他想测量一个多线程程序。我不确定clock()是否适合此操作,因为它会汇总所有线程的运行时间,因此结果看起来像是代码按顺序运行。对于此类事情,我使用omp_get_wtime(),但是我当然需要确保系统不忙于其他进程。 (2认同)
  • 我应该提到一些事情,即使这个线程一年前更相关:“CLOCKS_PER_SEC”是一个“long int”,其值为“1000000”,在不除时给出以微秒为单位的时间;不是CPU时钟周期。因此,它不需要考虑动态频率,因为这里的时钟以微秒为单位(可能是 1 MHz CPU 的时钟周期?)我编写了一个简短的 C 程序来打印该值,在我的 i7-2640M 笔记本电脑上它是 1000000,动态频率允许 800 MHz 至 2.8 GHz,甚至使用睿频加速可高达 3.5 GHz。 (2认同)
  • @Leos313:“CLOCKS_PER_SEC”用于通过定时器中断递增的软件时钟,或对其进行进一步处理的结果。例如,正如 DDPWNAGE 所评论的,“clock()”通常只是微秒。它与现代系统上的实际 CPU 频率或核心时钟周期完全无关。为此,请使用 Linux“perf stat ./a.out”,它默认对“cycles”硬件事件进行计数,例如最新 Intel CPU 上的“cpu_clk_unhalted.thread”。与“rdtsc”“参考时钟”相反,“rdtsc”实际上是固定频率并且即使 CPU 进入睡眠状态也不会停止。 (2认同)

S..*_*..K 107

如果您使用Unix shell运行,则可以使用time命令.

$ time ./a.out
Run Code Online (Sandbox Code Playgroud)

假设a.out,因为可执行文件将给你运行它的时间

  • @acgtyrant但仅适用于简单程序,因为它将占用整个程序时间,包括输入,输出等. (3认同)
  • 如果您使用的是 Linux,并且您已将(微)基准测试减少到启动开销可以忽略不计的程序,例如运行热循环几秒钟的静态可执行文件,则可以使用 `perf stat ./a.out ` 获取缓存未命中和分支错误预测的硬件性能计数器以及 IPC。 (2认同)

Wes*_*ker 58

你在功能上想要这个:

#include <sys/time.h>

struct timeval  tv1, tv2;
gettimeofday(&tv1, NULL);
/* stuff to do! */
gettimeofday(&tv2, NULL);

printf ("Total time = %f seconds\n",
         (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 +
         (double) (tv2.tv_sec - tv1.tv_sec));
Run Code Online (Sandbox Code Playgroud)

请注意,这是以微秒为单位,而不仅仅是秒.

  • 是的,它适用于支持gettimeofday调用的ac库的Windows.实际上编译器是什么并不重要,你只需将它与一个体面的libc库链接起来.在mingw的情况下,它不是默认的窗口之一. (11认同)
  • 这个比接受的更好,更可靠. (6认同)
  • 为什么不?它适用于我的Windows 8,MinGW编译器. (3认同)
  • `gettimeofday` 已过时,不建议用于新代码。它的 POSIX 手册页建议改为 [clock_gettime](http://pubs.opengroup.org/onlinepubs/009696899/functions/clock_getres.html),它可以让您请求不受系统时钟更改影响的“CLOCK_MONOTONIC” ,因此最好作为间隔时间。(参见[JohnSll的回答](/sf/ask/367424081/#41959179))。例如,在现代Linux系统上,gettimeofday基本上是clock_gettime的包装器,它将纳秒转换为微秒。 (3认同)
  • MinGW编译器基于GCC。这样就可以了。但是,如果使用Visual C编译器,则会出现错误。 (2认同)

Ale*_* C. 54

在普通香草C:

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

int main()
{
    clock_t tic = clock();

    my_expensive_function_which_can_spawn_threads();

    clock_t toc = clock();

    printf("Elapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 我一段时间以来见过的最好的变量名称。tic =“时钟时间”,toc =“时钟超时”。而且 tic-toc =“滴答”。从现在开始,我就是这样标记时间争夺的。 (22认同)
  • 请注意,“tic”和“toc”是 MATLAB 中标准秒表定时器函数的名称,用法相同。因此,我不确定原创性是否值得赞扬,但这增加了它们被认可和理解的可能性。 (8认同)
  • @CodyGray 哦,我不知道。我在某个地方看到了这些变量名,大概是 10 多年前了:) 2022 年我仍然使用 `tic` 和 `toc`,所以下次我让同事在代码审查中眨眼时,我可以解释它们的来源:) (3认同)

adi*_*moh 12

大多数简单程序的计算时间以毫秒为单位.所以,我想,你会发现这很有用.

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

int main(){
    clock_t start = clock();
    // Execuatable code
    clock_t stop = clock();
    double elapsed = (double)(stop - start) * 1000.0 / CLOCKS_PER_SEC;
    printf("Time elapsed in ms: %f", elapsed);
}
Run Code Online (Sandbox Code Playgroud)

如果要计算整个程序的运行时并且在Unix系统上,请使用如下的time命令运行程序time ./a.out

  • 这个答案没有添加任何不在[Alexandre C]中的内容(http://stackoverflow.com/users/373025/alexandre-c)的[答案](http://stackoverflow.com/a/5249129/15168)从两年前开始. (5认同)
  • @boctulus:在Windows上,1s *总是* 1000ms。 (3认同)

小智 9

(这里没有所有答案,如果您的系统管理员更改了系统时间,或者您的时区有不同的冬季和夏季时间。因此...)

linux使用:clock_gettime(CLOCK_MONOTONIC_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));

}
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

  • (糟糕,纳秒部分的减法可能需要带入秒部分,因此使用 double 并让它为负数可以避免该问题。要使用纯整数格式字符串,您需要一个类似“timeval_subtract”的“timespec_subtract” ` 在 glibc 手册中建议:https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html) (2认同)

Ste*_*hen 8

很多答案一直在建议clock(),然后CLOCKS_PER_SEC来自time.h.这可能是一个坏主意,因为这是我的/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
Run Code Online (Sandbox Code Playgroud)

因此CLOCKS_PER_SEC可能被定义为1000000,具体取决于您用于编译的选项,因此它似乎不是一个好的解决方案.

  • 这不是一个实际问题:是的Posix系统总是有`CLOCK_PER_SEC == 1000000`,但同时,它们的clock()实现都使用1-μs精度; 顺便说一句,它具有减少共享问题的好处.如果你想测量可能非常快的事件,比如低于1毫秒,那么你应该首先担心clock()函数的准确性(或分辨率),它必须比Posix中的1μs更粗糙,但也常常*很多*粗糙; 通常的解决方案是多次运行测试; 但问到的问题似乎并不需要它. (3认同)

hkl*_*lel 8

Thomas Pornin作为宏的答案:

#define TICK(X) clock_t X = clock()
#define TOCK(X) printf("time %s: %g sec.\n", (#X), (double)(clock() - (X)) / CLOCKS_PER_SEC)
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

TICK(TIME_A);
functionA();
TOCK(TIME_A);

TICK(TIME_B);
functionB();
TOCK(TIME_B);
Run Code Online (Sandbox Code Playgroud)

输出:

time TIME_A: 0.001652 sec.
time TIME_B: 0.004028 sec.
Run Code Online (Sandbox Code Playgroud)


Rav*_*dav 5

    #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);
    }
Run Code Online (Sandbox Code Playgroud)

这个程序将会像魅力一样发挥作用。