Linux 时钟()在 time.h 中的精度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8594277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:46:29  来源:igfitidea点击:

clock() precision in time.h

clinuxtimeclock

提问by mteffaha

I am trying to calculate the number of ticks a function uses to run and to do so an using the clock()function like so:

我正在尝试计算函数用于运行的滴答数,并使用如下clock()函数执行此操作:

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

But the problem is that the value it returns is a multiple of 10000, which I think is the CLOCK_PER_SECOND. Is there a way or an equivalent function value that is more precise?

但问题是它返回的值是 10000 的倍数,我认为是CLOCK_PER_SECOND. 有没有更精确的方法或等效的函数值?

I am using Ubuntu 64-bit, but would prefer if the solution can work on other systems like Windows & Mac OS.

我使用的是 64 位 Ubuntu,但希望该解决方案可以在 Windows 和 Mac OS 等其他系统上运行。

采纳答案by Jonathan Leffler

There are a number of more accurate timers in POSIX.

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

  • gettimeofday()- officially obsolescent, but very widely available; microsecond resolution.
  • clock_gettime()- the replacement for gettimeofday()(but not necessarily so widely available; on an old version of Solaris, requires -lposix4to link), with nanosecond resolution.
  • gettimeofday()- 正式过时,但非常广泛可用;微秒分辨率。
  • clock_gettime()- 替换gettimeofday()(但不一定如此广泛可用;在旧版本的 Solaris 上,需要-lposix4链接),具有纳秒分辨率。

There are other sub-second timers of greater or lesser antiquity, portability, and resolution, including:

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

  • ftime()- millisecond resolution (marked 'legacy' in POSIX 2004; not in POSIX 2008).
  • clock()- which you already know about. Note that it measures CPU time, not elapsed (wall clock) time.
  • times()- CLK_TCKor HZ. Note that this measures CPU time for parent and child processes.
  • ftime()- 毫秒分辨率(在 POSIX 2004 中标记为“legacy”;在 POSIX 2008 中没有)。
  • clock()- 你已经知道了。请注意,它测量的是 CPU 时间,而不是经过(挂钟)时间。
  • times()-CLK_TCKHZ。请注意,这会测量父进程和子进程的 CPU 时间。

Do not use ftime()or times()unless there is nothing better. The ultimate fallback, but not meeting your immediate requirements, is

不要使用ftime()times()除非没有更好的。最终的回退,但不能满足您的直接要求,是

  • time()- one second resolution.

The clock()function reports in units of CLOCKS_PER_SEC, which is required to be 1,000,000by POSIX, but the increment may happen less frequently (100 times per second was one common frequency). The return value must be defined by CLOCKS_PER_SECto get time in seconds.

clock()函数以 为单位报告,POSIXCLOCKS_PER_SEC要求其为1,000,000,但增量发生的频率可能较低(每秒 100 次是一种常见频率)。返回值必须定义为CLOCKS_PER_SEC以秒为单位获取时间。

回答by janneb

Per the clock() manpage, on POSIX platforms the value of the CLOCKS_PER_SEC macro must be 1000000. As you say that the return value you're getting from clock() is a multiple of 10000, that would imply that the resolution is 10 ms.

根据 clock() 联机帮助页,在 POSIX 平台上,CLOCKS_PER_SEC 宏的值必须为 1000000。正如您所说,从 clock() 获得的返回值是 10000 的倍数,这意味着分辨率为 10 ms .

Also note that clock() on Linux returns an approximation of the processor time used by the program. On Linux, again, scheduler statistics are updated when the scheduler runs, at CONFIG_HZ frequency. So if the periodic timer tick is 100 Hz, you get process CPU time consumption statistics with 10 ms resolution.

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

Walltime measurements are not bound by this, and can be much more accurate. clock_gettime(CLOCK_MONOTONIC, ...) on a modern Linux system provides nanosecond resolution.

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

回答by FGH

The most precise (but highly notportable) way to measure time is to count CPU ticks.

测量时间的最精确(但高度不可移植)的方法是计算 CPU 滴答数。

For instance on x86

例如在 x86 上

 unsigned long long int asmx86Time ()
 {
   unsigned long long int realTimeClock = 0;
   asm volatile ( "rdtsc\n\t"         
                  "salq , %%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 ();

If you don't have an x86, you'll have to re-write the assembler code accordingly to your CPU. If you needmaximum precision, that's unfortunatelly the only way to go... otherwise use clock_gettime().

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

回答by Scissor

I agree with the solution of Jonathan. Here is the implementation of clock_gettime() with nanoseconds of precision.

我同意乔纳森的解决方案。这是具有纳秒精度的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);

     }
 }

Although It's difficult to achieve ns precision, but this can be used to get precision for less than a microseconds (700-900 ns). printf above is used to just print the thread # (it'll definitely take 2-3 micro seconds to just print a statement).

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