【问题标题】:fast elapsed time on linuxlinux上的快速运行时间
【发布时间】:2010-11-25 16:38:21
【问题描述】:

我正在寻找一种快速的方法来获取 C 中函数的两次调用之间经过的时间。

我考虑过使用 jiffies,但它们在用户空间中不可用。那么,我应该使用 getimeofday() 还是有最快的方法来做到这一点。

我只对两次调用之间经过的时间感兴趣,以便在基准工具中使用。

【问题讨论】:

    标签: c linux time


    【解决方案1】:

    如果您使用的是 x86/x64 架构,并且在单个 CPU 上运行,则可以考虑读取 CPU 上的时间戳计数器以获取循环计数。维基百科有more information。请注意,如果您的应用程序在多个 CPU 上运行,则此方法不太有用,因为每个 CPU 都有自己的 TSC。如果您决定要转换周期 -> 时间单位,请注意频率缩放。

    【讨论】:

      【解决方案2】:

      是的,如果您想找到实际经过的时间,gettimeofday() 就足够了。如果需要查找 CPU 时间,则可以使用 clock()。在许多情况下,这两种方法都会给出相似的结果(除非代码中有睡眠或某种等待)。可以在此处找到 clock() 的示例:
      http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_19.html

      【讨论】:

        【解决方案3】:

        查看clock_gettime,它提供对高分辨率计时器的访问。

        【讨论】:

        • clock_gettime() 最好使用 CLOCK_MONOTONIC 源来进行相对计时。如果用户或进程可以更改当前时间,gettimeofday() 很容易出错。
        【解决方案4】:

        我将通过clock()time.h 获取处理器时间。要获得有用的值,请通过CLOCKS_PER_SEC 转换为毫秒:

        clock_t start = clock();
        // [...]
        clock_t end = clock();
        unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;
        

        【讨论】:

        • clock() 时间似乎不等于实时。 stackoverflow.com/questions/556405/…
        • 在测试clock()时间后返回系统+用户时间,但不是实时时间。改用 gettimeofday
        • @xhan:取决于您的用例 - 对于基准测试工具,处理器时间可能是比挂钟时间更好的指标
        【解决方案5】:

        如果您的内核支持 gettimeofday() 作为 vsyscall(虚拟系统调用),那么使用它会比调用常规系统调用(例如 clock())更快。有关 vsyscall 工作原理的一些信息,请参阅 Andrea Arcangeli's presentation

        【讨论】:

          【解决方案6】:

          添加的有点晚,但是任何 linux/unix 上可用的时间实用程序可能是实现您想要的更轻量级的方式。这里有两个例子

          time ls -l stuff*
          ls: stuff*: No such file or directory
              0.01s real     0.00s user     0.00s system
          
          
           time -c run_script.csh` 
          
          ...
          
          real    1m22.38s
          user    0m14.67s
          sys     0m1.06s
          

          【讨论】:

            【解决方案7】:

            以下在 CentOS 6 上适用于我:

            #include <stdio.h>
            #include <stdlib.h>
            #include <time.h>
            
            #if ! defined(_POSIX_C_SOURCE)
            #  error "_POSIX_C_SOURCE undefined"
            #endif
            
            #if _POSIX_C_SOURCE < 199309L
            #  error "_POSIX_C_SOURCE < 199309L"
            #endif
            
            int main(int, char**){
              struct timespec start, stop;
              struct timespec stop;
              if(clock_gettime(CLOCK_MONOTONIC, &start )) goto err_out;
              if(clock_gettime(CLOCK_MONOTONIC, &stop  )) goto err_out;
              printf("start == {tv_sec: %d, tv_nsec: %d}\n", start.tv_sec, start.tv_nsec);
              printf("stop  == {tv_sec: %d, tv_nsec: %d}\n", stop.tv_sec,  stop.tv_nsec );
              printf("stop.tv_nsec - start.tv_nsec == %d\n", stop.tv_nsec - start.tv_nsec);
              return EXIT_SUCCESS;
             err_out:
              perror("clock_gettime");
              return EXIT_FAILURE ;
            }
            

            ...虽然它确实需要librt:

            $ make dur
            cc     dur.c   -o dur
            /tmp/cc1yF58x.o: In function `main':
            dur.c:(.text+0x1c): undefined reference to `clock_gettime'
            dur.c:(.text+0x4e): undefined reference to `clock_gettime'
            collect2: ld returned 1 exit status
            make: *** [dur] Error 1
            $ LDFLAGS="-lrt" make dur
            cc   -lrt  dur.c   -o dur
            $ ./dur
            start == {tv_sec: 206247, tv_nsec: 411717209}
            stop  == {tv_sec: 206247, tv_nsec: 411759791}
            stop.tv_nsec - start.tv_nsec == 42582
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-04-11
              • 1970-01-01
              • 2016-04-12
              • 2016-01-11
              • 2014-01-22
              • 2016-06-01
              • 2013-06-03
              相关资源
              最近更新 更多