C 或 C++ 中的亚毫秒级精度计时

2021-12-23 00:00:00 time c c++

有哪些技术/方法可以在 C 或 C++ 中获取亚毫秒级精度的计时数据,它们提供什么样的精度和准确度?我正在寻找不需要额外硬件的方法.该应用程序需要等待大约 50 微秒 +/- 1 微秒,而某些外部硬件会收集数据.

What techniques / methods exist for getting sub-millisecond precision timing data in C or C++, and what precision and accuracy do they provide? I'm looking for methods that don't require additional hardware. The application involves waiting for approximately 50 microseconds +/- 1 microsecond while some external hardware collects data.

操作系统是 Wndows,可能是 VS2010.如果我可以在 Linux 上获得硬件的驱动程序和 SDK,我可以使用最新的 GCC 去那里.

OS is Wndows, probably with VS2010. If I can get drivers and SDK's for the hardware on Linux, I can go there using the latest GCC.

推荐答案

在处理现成的操作系统时,准确计时是一项极其困难且复杂的任务.如果您确实需要保证时间,唯一真正的选择是完整的实时操作系统.但是,如果几乎总是"足够好,那么您可以使用以下一些技巧,这些技巧将在商品 Windows 和 Windows 下提供良好的准确性.Linux

When dealing with off-the-shelf operating systems, accurate timing is an extremely difficult and involved task. If you really need guaranteed timing, the only real option is a full real-time operating system. However if "almost always" is good enough, here are a few tricks you can use that will provide good accuracy under commodity Windows & Linux

  1. 使用 屏蔽 CPU 基本上,这意味着关闭所选 CPU 的 IRQ 关联为机器上的所有其他进程设置处理器关联掩码以忽略您的目标 CPU.在您的应用程序上,将 CPU 关联设置为仅在受防护的 CPU 上运行.实际上,这应该可以防止操作系统暂停您的应用,因为它始终是该 CPU 的唯一可运行进程.
  2. 永远不要让您的进程自愿将控制权交给操作系统(这对于非实时操作系统来说本质上是不确定的).没有内存分配,没有套接字,没有互斥锁,nada.使用 RDTSC 在等待目标时间到达的 while 循环中旋转.它会消耗 100% 的 CPU,但这是最准确的方法.
  3. 如果数字 2 有点过于严厉,您可以少睡一会儿",然后将 CPU 消耗到您的目标时间.在这里,您可以利用操作系统按设定的时间间隔调度 CPU 的事实.通常每秒 100 次或每秒 1000 次,具体取决于您的操作系统和配置(在 Windows 上,您可以使用多媒体 API 将默认调度周期从 100/s 更改为 1000/s).这可能有点难以正确,但本质上您需要确定操作系统调度周期何时发生并在您的目标唤醒时间之前计算该周期.在此期间睡眠,然后在醒来时旋转 RDTSC(如果您在单个 CPU 上……如果不是,请使用 QueryPerformanceCounter 或 Linux 等效项),直到您的目标时间到达.有时,操作系统调度会导致您错过,但总的来说,这种机制效果很好.
  1. Use a Sheilded CPU Basically, this means turn off IRQ affinity for a selected CPU & set the processor affinity mask for all other processes on the machine to ignore your targeted CPU. On your app, set the CPU affinity to run only on your shielded CPU. Effectively, this should prevent the OS from ever suspending your app as it will always be the only runnable process for that CPU.
  2. Never allow let your process willingly yield control to the OS (which is inherently non-deterministic for non realtime OSes). No memory allocation, no sockets, no mutexes, nada. Use the RDTSC to spin in a while loop waiting for your target time to arrive. It'll consume 100% CPU but it's the most accurate way to go.
  3. If number 2 is a bit too draconic, you can 'sleep short' and then burn the CPU up to your target time. Here, you take advantage of the fact that the OS schedules the CPU at set intervals. Usually 100 times per second or 1000 times per second depending on your OS and configuration (On windows you can change the default scheduling period of 100/s to 1000/s using the multimedia API). This can be a little hard to get right but essentially you need determine when the OS scheduling periods occur and calculate the one prior to your target wake time. Sleep for this duration and then, upon waking, spin on RDTSC (if you're on a single CPU... use QueryPerformanceCounter or the Linux equivalent if not) until your target time arrives. Occasionally, OS scheduling will cause you to miss but, generally speaking, this mechanism works pretty good.

这似乎是一个简单的问题,但是您的时间限制越严格,获得良好"时间的难度就会成倍增加.祝你好运!

It seems like a simple question, but attaining 'good' timing get's exponentially more difficult the tighter your timing constraints are. Good luck!

相关文章