clock() 时间精度.h

问题描述 投票:0回答:4

我正在尝试计算函数运行时使用的刻度数,并使用

clock()
函数来计算,如下所示:

clock_t time = clock();
myfunction();
clock_t time2 = clock() - time;
printf("time elapsed : %lu",time2);

但问题是它返回的值是10000的倍数,我认为是

CLOCKS_PER_SECOND
。有没有更精确的方法或等效函数值?

我使用的是 Ubuntu 64 位,但如果该解决方案可以在 Windows 和 Mac OS 等其他系统上运行,我会更喜欢。

c linux time clock
4个回答
11
投票

POSIX 中有许多更准确的计时器。

  • gettimeofday()
    - 官方已过时,但非常广泛可用;微秒分辨率。
  • clock_gettime()
    -
    gettimeofday()
    的替代品(但不一定如此广泛使用;在旧版本的 Solaris 上,需要
    -lposix4
    才能链接),具有纳秒分辨率。

还有其他或多或少具有历史性、便携性和分辨率的亚秒计时器,包括:

  • ftime()
    - 毫秒分辨率(在 POSIX 2004 中标记为“遗留”;不在 POSIX 2008 中)。
  • clock()
    - 你已经知道了。请注意,它测量的是 CPU 时间,而不是经过的(挂钟)时间。
  • times()
    -
    CLK_TCK
    HZ
    。 请注意,这测量父进程和子进程的 CPU 时间。

除非没有更好的办法,否则不要使用

ftime()
times()
。 最终的后备方案是

,但不能满足您的直接要求

clock()
函数以
CLOCKS_PER_SEC
为单位进行报告,POSIX要求其为1,000,000,但增量发生的频率可能较低(每秒100次是一种常见频率)。 返回值必须除以
CLOCKS_PER_SEC
才能得到以秒为单位的时间。


2
投票

测量时间最精确(但高度便携)的方法是计算 CPU 滴答数。

例如在 x86 上

 unsigned long long int asmx86Time ()
 {
   unsigned long long int realTimeClock = 0;
   asm volatile ( "rdtsc\n\t"         
                  "salq $32, %%rdx\n\t"    
                  "orq %%rdx, %%rax\n\t"   
                  "movq %%rax, %0"         
                  : "=r" ( realTimeClock ) 
                  : /* no inputs */
                  : "%rax", "%rdx" );
   return realTimeClock;
 }

 double cpuFreq ()
 {
   ifstream file ( "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" );
   string sFreq; if ( file ) file >> sFreq;
   stringstream ssFreq ( sFreq ); double freq = 0.;
   if ( ssFreq ) { ssFreq >> freq; freq *= 1000; } // kHz to Hz
   return freq;
 }

 // Timing

 unsigned long long int asmStart = asmx86Time ();
 doStuff ();
 unsigned long long int asmStop  = asmx86Time ();
 float asmDuration = ( asmStop - asmStart ) / cpuFreq ();

如果您没有 x86,则必须根据您的 CPU 重新编写汇编代码。如果您需要最大精度,不幸的是,这是唯一的方法......否则请使用clock_gettime()。


1
投票

根据clock()手册页,在POSIX平台上,CLOCKS_PER_SEC宏的值必须是1000000。正如你所说,从clock()获得的返回值是10000的倍数,这意味着分辨率是10女士

另请注意,Linux 上的 Clock() 返回程序使用的处理器时间的近似值。同样,在 Linux 上,调度程序统计信息会在调度程序以 CONFIG_HZ 频率运行时更新。因此,如果周期性计时器滴答频率为 100 Hz,您将获得分辨率为 10 ms 的进程 CPU 时间消耗统计信息。

Walltime 测量不受此限制,并且可以更加准确。现代 Linux 系统上的 Clock_gettime(CLOCK_MONOTONIC, ...) 提供纳秒分辨率。


0
投票

我同意乔纳森的解决方案。这是具有纳秒精度的clock_gettime() 的实现。

//Import 
 #define _XOPEN_SOURCE 500
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <time.h>
 #include <sys/time.h>


 int main(int argc, char *argv[])
 {   
     struct timespec ts;
     int ret;
     while(1)
     {
         ret = clock_gettime (CLOCK_MONOTONIC, &ts);
         if (ret) 
         {
             perror ("clock_gettime");
             return;
         }
         ts.tv_nsec += 20000; //goto sleep for 20000 n
         printf("Print before sleep tid%ld %ld\n",ts.tv_sec,ts.tv_nsec );
        // printf("going to sleep tid%d\n",turn );
         ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME,&ts, NULL);

     }
 }

虽然很难达到 ns 精度,但是可以用来获得小于一微秒(700-900 ns)的精度。上面的 printf 用于仅打印线程 # (打印一条语句肯定需要 2-3 微秒)。

© www.soinside.com 2019 - 2024. All rights reserved.