c++ - 为什么条件变量会固定我们的功耗?

标签 c++ thread-sleep condition-variable energy

我们在 Mac 上开发音频播放器项目,发现耗电量非常高(大约是 google chrome 执行相同工作负载的 7 倍。)

我使用了 xcode 的能量分析工具,其中一个问题是我们有太多的 cpu-wake 开销。

根据xcode:

Each time the CPU wakes from idle, there is an incurred energy penalty. If the wakes are high, and the CPU utilization per wake is low, then you should consider batching work.

我们已将问题缩小到一个 usleep 函数调用。

在我们的代码中,音频解码器是一个生产者,它产生音频数据并将其插入消费者——音频播放器。我们的音频播放器基于 OpenAL,它有一个音频数据缓冲区。

因为音频播放器可能比生产者慢,所以我们总是在向音频播放器提供新的音频数据之前检查缓冲区的可用性。如果没有可用的缓冲区,我们会睡一会儿,然后再试一次。所以代码看起来像:

void playAudioBuffer(Data *data)
{
    while(no buffer is available)
    {
         usleep()
    }
    process data.
}

知道usleep 是个问题,我们做的第一件事就是简单地删除usleep()。 (因为 OpenAL 似乎没有提供回调或任何其他方式,所以轮询似乎是唯一的选择。)在这样做之后,我们成功地将功耗减少了一半。

然后,昨天,我们尝试了

for(int i =0; i<attempts; ++i)
{
    std::unique_lock<std::mutex> lk(m);
    cv.wait_for(lk, 3, []{
                            available = checkBufferAvailable(); 
                            return available;
                         })

    if (available)
    {
         process buf;
    }
 }

这是我们偶然尝试的实验。这对我们来说真的没有意义,因为从逻辑上讲它执行相同的等待。而且条件变量的使用是不正确的,因为变量“available”只能被一个线程访问。但它实际上将我们的能耗降低了 90%,线程的 cpu 使用率下降了很多。现在我们比 Chrome 更好。但是条件变量的实现方式与以下代码有何不同?为什么它可以为我们省电?

mutex lock;
while(condition is false)
{
    mutex unlock;
    usleep();
    mutex lock;
}
...
mutex unlock
...

(我们使用mac的activity monitor(能量数)和cpu usage profiling工具来测量能耗。)

最佳答案

我可能是错的,但据我了解,当你使用条件变量来实现等待缓冲区数据收入时。它所做的主要工作是将渲染此条件变量的线程置于休眠状态,直到与之关联的信号唤醒该线程。这就是您减少唤醒开销并更有效地使用资源的原因。

这里是在 Linux 中使用线程的链接,我在其中读到了它:

也许这会让您了解它为什么以及如何发生。

再一次,我不完全确定我是否完全正确,但在我看来这是一个正确的方向。

对不起,我的纯英语。

关于c++ - 为什么条件变量会固定我们的功耗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29310100/

相关文章:

c++ - 就地去交错阵列?

java - 如何使用 Thread.sleep()?

c++ - 如何在 Visual C++ 2012 中 sleep 不受系统时钟调整影响的固定时间

c# - 使用 Thread.Sleep 等待的替代方法

c++ - 这个函数定义是如何工作的?

c++ - `XSetWMNormalHints` 和 `XSetWMSizeHints`

Java 互斥体与条件变量的关联

c++ - std::condition_variable::wait with predicate

C++11 线程安全队列

c++ - 正确放置 "toCSV"函数 : In each object, 还是放在通用类中?