当前位置: 首页 > 面试题库 >

clock_gettime()是否适合亚微秒级计时?

梁学真
2023-03-14
问题内容

在我们的应用程序的Linux构建中,我需要一个用于嵌入式探查器的高分辨率计时器。我们的探查器可测量的范围与单个功能一样小,因此其计时器精度必须高于25纳秒。

以前,我们的实现使用内联汇编和rdtsc操作直接从CPU查询高频计时器,但这是有问题的,需要经常重新校准。

因此,我尝试使用该clock_gettime函数来查询CLOCK_PROCESS_CPUTIME_ID。文档声称这给了我纳秒级的计时,但是我发现单次调用的开销clock_gettime()超过了250ns。这使得不可能为事件设置100ns的时间,并且计时器功能的开销如此之大,严重降低了应用程序的性能,使配置文件超出了价值。(我们每秒有数十万个分析节点。)

有没有一种方法可以clock_gettime()使开销少于¼μs?还是有其他方法可以可靠地获得开销小于25ns的时间戳计数器?还是我坚持使用rdtsc

下面是我习惯的代码clock_gettime()

// calls gettimeofday() to return wall-clock time in seconds:
extern double Get_FloatTime();
enum { TESTRUNS = 1024*1024*4 };

// time the high-frequency timer against the wall clock
{
    double fa = Get_FloatTime();
    timespec spec; 
    clock_getres( CLOCK_PROCESS_CPUTIME_ID, &spec );
    printf("CLOCK_PROCESS_CPUTIME_ID resolution: %ld sec %ld nano\n", 
            spec.tv_sec, spec.tv_nsec );
    for ( int i = 0 ; i < TESTRUNS ; ++ i )
    {
        clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &spec );
    }
    double fb = Get_FloatTime();
    printf( "clock_gettime %d iterations : %.6f msec %.3f microsec / call\n",
        TESTRUNS, ( fb - fa ) * 1000.0, (( fb - fa ) * 1000000.0) / TESTRUNS );
}
// and so on for CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_THREAD_CPUTIME_ID.

结果:

CLOCK_PROCESS_CPUTIME_ID resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 3115.784947 msec 0.371 microsec / call
CLOCK_MONOTONIC resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2505.122119 msec 0.299 microsec / call
CLOCK_REALTIME resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2456.186031 msec 0.293 microsec / call
CLOCK_THREAD_CPUTIME_ID resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2956.633930 msec 0.352 microsec / call

这是在标准Ubuntu内核上。该应用程序是Windows应用程序的端口(我们的rdtsc内联程序集可以正常工作)。

附录:

x86-64 GCC是否具有__rdtsc()的内在等效项,因此至少可以避免内联汇编?


问题答案:

否。您必须使用特定于平台的代码来执行此操作。在x86和x86-64上,您可以使用’rdtsc’读取时间戳计数器。

只需移植您正在使用的rdtsc程序集。

__inline__ uint64_t rdtsc(void) {
  uint32_t lo, hi;
  __asm__ __volatile__ (      // serialize
  "xorl %%eax,%%eax \n        cpuid"
  ::: "%rax", "%rbx", "%rcx", "%rdx");
  /* We cannot use "=A", since this would use %rax on x86_64 and return only the lower 32bits of the TSC */
  __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
  return (uint64_t)hi << 32 | lo;
}


 类似资料:
  • 我正试图通过服务提供者API在运行时由加载一个jar。然而,结果却是失败的。 以下是我所做的: null 我尝试了抽象类而不是我的SPI接口的接口,当我无法实现我的目标时,将它改回接口; 我已尝试获取资源并将我的作为输入参数传递,但没有工作; 我尝试了Apache实现的,但它也找不到适当的资源; 我的问题是如何通过从外部jar加载资源?SPI可能是一种解决方案吗?

  • 问题内容: JavaScript中是否有具有微秒分辨率的计时功能? 我知道Chrome的timer.js,希望能够为其他友好的浏览器提供解决方案,例如Firefox,Safari,Opera,Epiphany,Konqueror等。我对支持任何IE均不感兴趣,但可以提供包括 IE 在内的_ 答案受欢迎的。 (鉴于JS中毫秒级计时的准确性很差,因此我不屏息!) 更新:timer.js宣传微秒分辨率,

  • 问题内容: 我正在将一个最初为Win32 API编写的游戏移植到Linux(很好,是将Win32端口的OS X端口移植到Linux)。 自程序启动以来,我已经通过提供uSeconds来实现: 再加上恒定的1000000作为频率,可以 在我的机器上 很好地工作,并为我提供了一个自程序启动以来包含的64位变量。 这 是便携式的吗? 我不想发现以某种方式或类似方式编译内核时,它的工作原理有所不同。我可以

  • 本文向大家介绍nodeJS代码实现计算交社保是否合适,包括了nodeJS代码实现计算交社保是否合适的使用技巧和注意事项,需要的朋友参考一下 按一个普通程序员8000的月收入算就是1800的社保金,而且要延迟到65岁退休,我过完年就是30岁,这笔账和余额宝比对一下,我顿时明白了 结果: {  "all": "1070226.48",  "year15": "458919.44" } 结果15年后可以

  • 问题内容: 用Java编写了一个随机模拟,该模拟从磁盘上的几个CSV文件加载数据(总计约100MB),并将结果写入另一个输出文件(数据不多,只有布尔值和几个数字)。还有一个参数文件,对于不同的参数,模拟输出的分布可能会发生变化。为了确定正确/最佳的输入参数,我需要针对多个输入参数配置运行多个模拟,并查看每组中输出的分布。根据参数和随机性,每次仿真需要0.1-10分钟。 我一直在阅读有关Hadoop

  • 区分度不高的字段不适合做索引,因为索引页是需要有开销的,需要存储的,不过这类字段可以做联合索引的一部分。