寻找一个高分辨率计时器。

5

在Linux下的C++中,我正在尝试每微秒/纳秒做一些事情,目前使用如下的nanosleep函数。它可以工作,但如果代码循环数百万次,那么这将变得很耗费资源。我正在寻找一个高分辨率计时器,以便能够实现非常精确的计时(应用为音频/视频)。有任何想法吗?

struct timespec req = {0};
req.tv_sec = 0;
req.tv_nsec = 1000000000L / value;

for(long i = 0; i < done; i++)
{
    printf("Hello world");            
    nanosleep(&req, (struct timespec *)NULL);
}

2
<chrono> 有什么问题吗? - chris
2
如果你的 CPU 时钟频率为 4 GHz,那么你在一纳秒内有 4 个时钟周期。即使以这样的速度,每一纳秒也不能做太多事情。 - Jonathan Leffler
我们在谈论什么样的Linux和处理器?对于非实时系统,高于毫秒级别的精度已经相当雄心勃勃了。微秒(更不用说纳秒)级别的精度在大多数实时系统上甚至都不会去追求。 - MikeMB
3个回答

4

使用 C++11

#include <chrono>
#include <thread>

...

for (long i = 0; i < done; i++) {
    std::cout << "Hello world" << std::endl;            
    std::this_thread::sleep_for(std::chrono::nanoseconds(1e9 / value));
}

记得使用-std=c++11标志进行编译。


我比较了这两种方法,它们的计算开销似乎非常相似(系统调用需要很长时间)。这真的是最好的选择吗?还是可能直接从内核使用特殊的定时器之类的东西? - Josh
@Josh 我认为这是用户端能做到的最好的了。 - Shreevardhan

1
对于音频/视频,通常不需要纳秒/微秒级别的精确计时器,毫秒就足够了。音频中最常见的包间隔是20毫秒。可以使用nanosleep来实现这个目的。
此外,除非您使用实时操作系统,否则无法保证从内核获得如此好的定时。
使用睡眠在实时通信中的陷阱是:它们不保持适当的频率(对于具有20ms间隔的音频为50Hz)。因为在每个滴答声上,您都会将处理时间添加到睡眠间隔中。因此,睡眠间隔必须基于先前的滴答声时间戳和下一个预期的滴答声时间戳进行计算。
您可以使用睡眠实现短间隔计时器(例如10ms),并在计时器警报上处理应在此计时器警报之间发生的事件。如果这样做,您将优化操作系统资源使用(最小化进程/线程上下文切换)。

0

请注意,POSIX标记setitimer()getitimer()为过时函数,并表示首选替代函数是timer_settime()timer_gettime()getitimer()setitimer()函数不会立即消失,但这已经是明摆着的事实了。 - Jonathan Leffler
另一方面,Mac OS X 10.10.4没有timer_settime()timer_gettime(),但它有getitimer()setitimer()。因此,“过时”的函数在可用性方面具有优势。类似的评论也适用于gettimeofday()clock_gettime() - Mac OS X有前者,但POSIX更喜欢后者,并将前者标记为过时。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接