Sva*_*Lop 8 c++ audio multithreading
在编写音频软件时,互联网上的许多人都说不要使用内存分配或阻塞代码,即没有锁定是至关重要的.由于这些是非确定性的,因此可能导致输出缓冲器下溢并且音频将出现故障.
当我编写视频软件时,我通常使用两者,即在堆上分配视频帧并使用锁和条件变量(有界缓冲区)在线程之间传递.我喜欢它提供的功能,因为每个操作都可以使用单独的线程,允许软件最大化每个内核,从而提供最佳性能.
对于音频,我想做类似的事情,在线程之间传递可能100个样本的帧,但是,有两个问题.
如何在不使用内存分配的情况下生成帧?我想我可以使用已预先分配的帧池,但这看起来很混乱.
我知道你可以使用无锁队列,并且boost有一个很好的库来做到这一点.这将是在线程之间共享的一种很好的方式,但是不断轮询队列以查看数据是否可用似乎是CPU时间的巨大腰部.
根据我的经验,使用互斥锁实际上并不需要花费太多时间,前提是互斥锁被锁定的部分很短.
实现线程之间传递音频帧的最佳方法是什么,同时将延迟保持在最小,不浪费资源并使用相对较少的非确定性行为?
好像你做了你的研究!您已经确定了可能导致音频故障的两个主要问题.问题是:10年前这有多少是重要的,现在只是民间传说和货物崇拜节目.
我的两分钱:
1.渲染循环中的堆分配:
根据处理块的小小,这些开销可能会有很大的开销.主要的罪魁祸首是,很少有运行时具有每个线程的堆,所以每次你搞乱堆时,你的性能取决于你的进程中的其他线程.例如,如果GUI线程当前正在删除数千个对象,并且您 - 同时 - 从音频呈现线程访问堆,则可能会遇到严重延迟.
使用预先分配的缓冲区编写自己的内存管理可能听起来很混乱,但最后它只是两个可以隐藏在实用程序源中的函数.由于您通常事先知道您的分配大小,因此有很多机会可以微调和优化您的内存管理.例如,您可以将段存储为简单的链接列表.如果完成,这有利于您再次分配最后使用的缓冲区.此缓冲区在缓存中具有非常高的概率.
如果固定大小的分配器不起作用,请查看ring-buffers.它们非常适合流式音频的使用案例.
2.锁定或不锁定:
我会说,这些天使用互斥锁和信号量锁是很好的,如果你可以估计你每秒少于1000到5000(在PC上,就像Raspberry Pi之类的东西不同).如果您保持在该范围之下,则不太可能在性能配置文件中显示开销.
转换为您的用例:如果您使用48kHz音频和100个样本块,则可以在简单的双线消费者/生产者模式中生成大约960次锁定/解锁操作.这是在范围内.如果您完全最大化渲染线程,则锁定将不会显示在分析中.另一方面,如果你只使用5%的可用处理能力锁可能会出现,但你也不会遇到性能问题:-)
无锁也是一种选择,但混合解决方案也是如此,它首先进行一些无锁尝试然后再回到硬锁定.你将通过这种方式获得两全其美.在网上有很多关于这个主题的好东西.
在任何情况下:
您应该轻轻提高非GUI线程的线程优先级,以确保如果它们遇到锁定,它们会快速退出.阅读优先级倒置是什么,以及您可以采取哪些措施来避免它,这也是一个好主意:
https://en.wikipedia.org/wiki/Priority_inversion
| 归档时间: |
|
| 查看次数: |
2685 次 |
| 最近记录: |