循环而不消耗太多CPU周期并且不使用sleep()?
我正在做一个 VoIP 程序,它不断检查音频记录缓冲区中是否有任何内容(FMOD 库,每当函数 getRecordPosition > 0 时,缓冲区中就有数据)。
所以它会是这样的:
while (true) {
if(getRecordPosition>0) {
process data....
}
}
然而这会导致非常高的 CPU 使用率。一种版本是使用 sleep() 但如果可能的话我宁愿不使用它。 例如,win32 消息处理及其事件驱动循环不会消耗很多 cpu 周期,这是我试图模拟的。同时,我知道必须经常调用函数 getRecordPosition() 来查看返回值是否高于 0。
我是否坚持执行 while(true) 循环和 sleep() 一小段时间,以便按顺序保持低CPU使用率?
我已经用谷歌搜索并做了一些查找,但大多数返回要么使用 sleep() 要么使用互斥锁进行一些 POSIX 同步。 (我正在做一个 c++ win32 应用程序)
干杯
---编辑:忘记提及我无权访问 fmod 源代码 :/ ---
I am doing a VoIP program which continously checks whether the audio-recording buffer has anything in it (FMOD library, whenever the function getRecordPosition > 0, then the buffer has data in it).
So it would be something along the lines of:
while (true) {
if(getRecordPosition>0) {
process data....
}
}
However this would cause a very high CPU usage. One version would be to use sleep() but I'd rather not use it if possible.
For example the win32 messagehandling with its event-driven loop dosn't consume many cpu cycles and it's something I'm trying to emulate. At the same time I understand the function getRecordPosition() would have to be called frequently to see if the return value gets above 0.
Am I stuck with doing a while(true) loop and sleep() for some small amount of time in order to keep low-CPU usage?
I've googled and done some lookup but most returns either using sleep() or some POSIX synchronization with mutex. (I am doing a c++ win32 app)
Cheers
---EDIT: Forgot to mention I dont have access to fmod source corde :/ ---
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果可以的话,最好的做法是不要像您所说的那样模拟事件驱动架构,而是实际使用事件驱动架构。我对您的代码一无所知,特别是您是否控制音频录制缓冲区的代码。但是,如果您确实控制写入缓冲区的代码,那么您可以在写入缓冲区时触发一个事件:
(psudocude如下)
主线程:
缓冲区写入线程:
然后在您想要做某事的线程中当缓冲区中有数据等待时,等待事件发出信号:
Buffer-Read Thread
The best thing to do, if you can, is to not emulate an event-driven architecture as you say, but to actually use an event-driven architecture. I don't know anything about your code, in particular whether you're in control of the audio-recording buffer's code or not. But if you do control the code that writes to the buffer, then you can trigger an event when you have written to the buffer:
(psudocude follows)
Main Thread:
Buffer-Write Thread:
And then in the thread where you want to do something when there's data in the buffer waiting, wait for the event to be signaled:
Buffer-Read Thread
您可以使用“SwitchToThread”将处理器交给另一个线程,并检查返回值。如果这是真的,那么你就屈服了,如果不是,则没有其他线程需要运行。如果我没记错的话,FMOD 运行一个线程,因此您可能会屈服于该线程。
如果它无法让出或者继续占用大量 CPU 时间,您可以使用让出和睡眠的某种组合。
You could use 'SwitchToThread' to yield the processor to another thread, and check the return value. If it is true, you yielded, and if not, there are no other threads that need running. If I remember correctly, FMOD runs a thread, so you would likely be yielding to that thread.
If it fails to yield or if it continues to use up a lot of CPU time, you could use some combination of yielding and sleeping.
我不熟悉 FMOD 库,但它是否提供数据放入缓冲区时的通知回调?如果没有,您几乎会陷入使用某种形式的睡眠的困境(您可以将该代码放入线程中并使用诸如 nanosleep 之类的东西来仍然具有良好的响应时间)。
I'm not familiar with the FMOD library, but does it provide a notification callback for when data is placed in the buffer? If not, you're pretty much stuck using some form of sleep (you could put that code in a thread and use something like nanosleep to still have good response times though).
我们遇到了类似的问题。
我们有许多进程试图共享资源。其中一个拥有该资源后,另一个应该等待该资源可用。这意味着,等待一段时间,然后尝试锁定资源,如果不可用,则再次休眠。
由于我们必须在 Windows 和 Linux 上开发该代码,因此我们面临不同的解决方案,甚至使用 boost(但没有有效的结果)。
不管怎样,Windows 中最好的解决方案是对资源使用 WaitForSingleObject(),但在 Linux 上我们只能休眠 1 毫秒。该解决方案似乎消耗非常低的 CPU - 而不是 while(true) - 授予资源尽快可用。
一开始,我们在资源可用性测试和接下来的测试之间浪费了很多时间,因为我们睡眠了很多毫秒。现在我们实际上更快了。
华泰
We faced a similar problem.
We have many processes trying to share a resource. After one of those held that resource, the other should wait for that resource to be available. That means, wait a while, than try to lock the resource and, if not available, sleep again.
Since we have to develop that code both on Windows and Linux we faced different solutions, even using boost (but wit no valid results).
Anyway, best solution in Windows was to use a WaitForSingleObject() on the resource, but on linux we had to sleep for just 1 millisecond. That solution seems to consume very low CPU - instead of a while(true) - granting the resource to be taken as soon as available.
In the beginning we were loosing much time sleeping between a test of resource availability and the following since we sleep for to many milliseconds. Now we're actually very faster.
HTH
考虑 Win32 必须提供的其他同步原语。自动重置事件听起来正是您所需要的。它们也跨进程工作。
Consider other sync primitives that Win32 has to offer. An auto-reset event sounds like what you need. They work cross-process, too.
为了避免消耗CPU并避免Sleep()函数效率低下,您需要避免轮询,而是使用事件驱动机制。有现成的框架。例如,在 GBL 中,您可以定义一个信号,例如 getRecordPosition,并将其绑定到处理程序:
或者如果您需要一个单独的线程,您将等待该信号:
In order to avoid consuming CPU and avoid inefficiency of Sleep() function, you need to avoid polling, instead use event driven mechanism. There are ready frameworks for that. For example, in GBL, you would define a signal, say getRecordPosition, and bind it to handler:
or if you need a separate thread, you would wait for the signal: