使用“粗鲁的大锤”方法并行化 MacOS/CoreAudio 实时音频回调是否可行?

Jer*_*ner 3 audio multithreading multicore real-time core-audio

首先,一些相关的背景信息:我有一个基于 CoreAudio 的低延迟音频处理应用程序,它对来自专用 Mac(运行最新版本的 MacOS)上的输入设备的音频进行各种混合和特殊效果) 并将结果传送回 Mac 的其中一台本地音频设备。

为了获得最佳/最可靠的低延迟性能,此应用程序旨在挂钩 CoreAudio 的低级音频渲染回调(通过AudioDeviceCreateIOProcID()、 AudioDeviceStart() 等),并且每次回调函数为调用(来自 CoreAudio 的实时上下文),它读取传入的音频帧(例如 128 帧,每帧 64 个样本),进行必要的数学运算,并写出传出的样本。

这一切都运行良好,但从我读过的所有内容来看,Apple 的 CoreAudio 实现有一个不成文的事实上的要求,即所有实时音频操作都发生在单个线程中。我承认有充分的理由(主要是在我已经使用的 SIMD/SSE/AVX 指令之外,几乎所有您可能用来协调并行化行为的机制都不是实时安全的,因此尝试使用它们会导致间歇性故障音频)。

然而,我和我的同事很贪心,尽管如此,我们还是希望每个样本缓冲区执行更多的数学运算,即使速度最快的单核也能在避免音频的必要时间窗口内可靠地执行更多的数学运算-欠载和故障。

我的同事(在嵌入式/专用 Linux 硬件上的实时音频处理方面颇有经验)告诉我,在 Linux 下,程序可能会要求一个或多个 CPU 内核的独占访问权限,例如操作系统永远不会尝试将它们用于其他任何事情。一旦他这样做了,他就可以在那个 CPU 上运行“裸机”风格的代码,简单地忙着等待/轮询原子变量,直到“真正的”音频线程更新它,让专用核心知道是时候做它的事情了; 届时,专用内核将对输入样本运行其数学例程并在(希望如此)有限时间内生成其输出,此时“真实”音频线程可以收集结果(此处更忙等待/轮询) ) 并将它们合并回传出的音频缓冲区。

我的问题是,这种方法是否值得在 MacOS/X 下尝试?(即,MacOS/X 程序,即使是具有 root 访问权限的程序,是否可以说服 MacOS 授予它对某些内核的独占访问权限,如果是这样,则会在这些内核上出现丑陋的忙等待/轮询循环(包括必要的轮询循环)同步 CoreAudio 回调线程相对于它们的输入/输出要求)产生足够可靠的实时结果,您可能有一天想在付费观众面前使用它们?)

这似乎是原则上可能的事情,但在我花太多时间将头撞到那里可能存在的任何墙壁之前,我想了解一些关于这是否值得在这个平台上追求的途径的意见。

Rhy*_*man 5

MacOS/X 程序,即使是具有 root 访问权限的程序,能否说服 MacOS 授予它对某些内核的独占访问权限

我不知道这一点,但是您可以根据需要使用任意数量的内核/实时线程进行计算,使用您需要的任何同步方法使其工作,然后IOProc使用无锁环形缓冲区将音频传递给您,像TPCircularBuffer

但是您的问题让我想起了我一直想尝试的新 macOS 11/iOS 14 API,即音频工作组 API2020 WWDC 视频)。

我的理解是,这个 API 可以让你用音频实时线程属性“祝福”你的非 IOProc实时线程,或者至少与音频线程更好地合作。

文档区分了并行工作的线程(这听起来像您的情况)和异步工作的线程(这听起来像我的建议),我不知道哪种情况更适合您。

我仍然不知道当你使用 时在实践中会发生什么Audio Workgroups,他们是选择你加入好东西还是选择你退出坏东西,但如果他们不是你正在寻找的锤子,他们可能有一些有用的锤子 -像属性。