循环不消耗太多CPU周期而没有睡眠()?

时间:2011-01-10 16:11:38

标签: c++ multithreading winapi synchronization cpu-usage

我正在做一个VoIP程序,它不断检查录音缓冲区中是否有任何内容(FMOD库,只要函数getRecordPosition> 0,然后缓冲区中就有数据)。

所以这将是:

while (true) {
    if(getRecordPosition>0) {
     process data....
    }
}

然而,这会导致非常高的CPU使用率。一个版本是使用sleep()但是如果可能的话我宁愿不使用它。 例如,win32消息处理及其事件驱动的循环不会消耗很多cpu周期,这是我试图模仿的东西。同时我理解必须经常调用函数getRecordPosition()以查看返回值是否高于0.

为了保持低CPU使用率,我是否坚持做一段时间(真实)循环和睡眠()一段时间?

我用谷歌搜索并完成了一些查找,但大多数使用sleep()或某些POSIX与mutex同步返回。 (我正在做一个c ++ win32应用程序)

干杯

---编辑:忘记提及我无法访问fmod source corde:/ ---

6 个答案:

答案 0 :(得分:5)

如果可以的话,最好的办法就是不要像你说的那样模仿事件驱动的架构,而是实际使用事件驱动的架构。我对你的代码一无所知,特别是你是否能够控制录音缓冲区的代码。但是如果你确实控制了写入缓冲区的代码,那么你可以在写入缓冲区时触发事件:

(psudocude如下)

主线程:

HANDLE buf_event = CreateEvent(...);
// ...
CreateThread(BufferControl, ...);

缓冲区写入线程:

OnWriteToBuffer()
{
  buffer.Write(...);
  SetEvent(buf_event);
}

然后在线程中,当缓冲区中的数据等待时,您想要执行某些操作,等待事件发出信号:

缓冲区读取线程

rc = WaitForSingleObject(buf_event, INFINITE);
if( rc == WAIT_OBJECT_0 )
{
  // there's somethign in the buffer
}

答案 1 :(得分:1)

您可以使用'SwitchToThread'将处理器转换为另一个线程,并检查返回值。如果是,那么你就屈服了,如果没有,就没有其他线程需要运行。如果我没记错的话,FMOD会运行一个线程,所以你可能会屈服于那个线程。

如果它无法产生或者它继续消耗大量的CPU时间,你可以使用屈服和睡眠的某种组合。

答案 2 :(得分:1)

我不熟悉FMOD库,但它是否提供了数据放入缓冲区时的通知回调?如果没有,你几乎停留在使用某种形式的睡眠(你可以把这些代码放在一个线程中并使用类似nanosleep的东西来保持良好的响应时间)。

答案 3 :(得分:0)

我们遇到了类似的问题 我们有许多进程试图共享资源。在其中一个持有该资源之后,另一个应该等待该资源可用。这意味着,等待一段时间,而不是试图锁定资源,如果不可用,再次休眠 由于我们必须在Windows和Linux上开发该代码,我们面临着不同的解决方案,即使使用boost(但没有有效的结果)。 无论如何,Windows中的最佳解决方案是在资源上使用WaitForSingleObject(),但在linux上我们只需要睡眠1毫秒。该解决方案似乎消耗了非常低的CPU - 而不是一段时间(真实) - 授予资源尽快获取。

一开始,我们在资源可用性测试和以下之间休息了很多时间,因为我们睡了很多毫秒。现在我们实际上非常快。 HTH

答案 4 :(得分:0)

考虑Win32必须提供的其他同步原语。自动重置事件听起来就像您需要的那样。他们也在进行交叉处理。

答案 5 :(得分:0)

为了避免消耗CPU并避免Sleep()函数的低效率,您需要避免轮询,而是使用事件驱动机制。有一些现成的框架。例如,在GBL中,您将定义一个信号,比如getRecordPosition,并将其绑定到处理程序:

Handler([](){ do_something(); }) << getRecordPosition;

或者如果你需要一个单独的线程,你会等待信号:

CreateThread([](){ Wait(getRecordPosition); do_something(); });