C++ 为什么条件变量会固定我们的功耗?
我们在mac上进行音频播放器项目时,注意到它的耗电量非常高(大约是谷歌chrome的7倍) 我使用了xcode的能量分析工具,其中一个问题是我们有太多的cpu唤醒开销 根据xcode: 每次CPU从空闲状态唤醒时,都会产生能量损失。如果唤醒很高,并且每个唤醒的CPU利用率低,那么您应该考虑批处理工作。 我们已将问题缩小到usleep函数调用 在我们的代码中,音频解码器是产生音频数据并将其插入消费者(音频播放器)的生产者。我们的音频播放器基于OpenAL,它有一个音频数据缓冲区 因为音频播放器可能比制作者慢,所以我们总是在向音频播放器提供新的音频数据之前检查缓冲区的可用性。如果没有可用的缓冲区,我们将休眠一段时间,然后重试。因此,代码如下所示:C++ 为什么条件变量会固定我们的功耗?,c++,thread-sleep,condition-variable,energy,C++,Thread Sleep,Condition Variable,Energy,我们在mac上进行音频播放器项目时,注意到它的耗电量非常高(大约是谷歌chrome的7倍) 我使用了xcode的能量分析工具,其中一个问题是我们有太多的cpu唤醒开销 根据xcode: 每次CPU从空闲状态唤醒时,都会产生能量损失。如果唤醒很高,并且每个唤醒的CPU利用率低,那么您应该考虑批处理工作。 我们已将问题缩小到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;
}
}
(我们使用mac的活动监视器(能量数)和cpu使用情况分析工具来测量能量消耗。)我可能错了,但据我所知,当您使用条件变量来实现等待缓冲区数据收入时。它所做的主要工作是,将呈现此条件变量的线程置于睡眠状态,直到与之相关的信号唤醒此线程。这就是为什么唤醒开销更少,资源使用效率更高的原因 以下是在Linux中使用线程的链接,我从中了解到:
对不起,我说的是纯英语。如果你想在Mac或iOS上尽可能地降低能耗,至少你可以使用调度信号灯精确地等待缓冲区已满,或者将一些块传递给缓冲区填充代码 也许在某些情况下cv会旋转而不是睡觉?也许它会做一个“慢”或“低功率”旋转锁定。。。以某种方式(顺便问一下,3是什么时间单位?我们在这里谈论的是
std::condition\u variable
?3在那里是如何工作的?)哦,你不是在发布实际代码,你是在手动转录,并且引入了未知数量的错误和遗漏。请不要这样做:请张贴代码,实际上复制你感兴趣的东西。这可能涉及到简化您现有的代码:如果您了解是什么引起了您感兴趣的事情,您就不会在这里提问了!或者您可能只是在与usleep比较的情况下等待更长的时间?在这两种情况下,我们都会等待3毫秒,然后重试。例如,我们尝试了4毫秒,注意到hiccupsI不认为实现是开源的吗?(例如,微软的CRT源代码随VisualStudio一起提供,对于追踪像这样的特定于实现的异常情况非常有帮助。)@BillYan还有一个提示,3-4毫秒还是微秒?用4微秒usleep(4)
处理器可以加载到100%。在OP的情况下,没有任何东西会唤醒线程-它总是休眠到超时。
mutex lock;
while(condition is false)
{
mutex unlock;
usleep();
mutex lock;
}
...
mutex unlock
...