使用 "rude big hammer" 方法并行化 MacOS/CoreAudio 实时音频回调是否可行?
Is it practical to use the "rude big hammer" approach to parallelize a MacOS/CoreAudio real-time audio callback?
首先,一些相关的背景信息:我有一个基于 CoreAudio 的低延迟音频处理应用程序,它可以对来自输入设备的音频进行各种混音和特效 Mac(运行使用最新版本的MacOS)并将结果传送回Mac的本地音频设备之一。
为了获得 best/most 可靠的低延迟性能,此应用旨在挂接到 CoreAudio 的低级音频渲染回调(通过 AudioDeviceCreateIOProcID()、AudioDeviceStart() 等) ) 并且每次调用回调函数时(从 CoreAudio 的实时上下文),它读取传入的音频帧(例如 128 帧,每帧 64 个样本),进行必要的数学运算,并写出传出样本。
这一切工作得很好,但从我读过的所有内容来看,Apple 的 CoreAudio 实现有一个不成文的事实上的要求,即所有实时音频操作都在单个线程中发生。我承认这是有充分理由的(主要是在我已经使用的 SIMD/SSE/AVX 指令之外,几乎所有你可能用来协调并行化行为的机制都不是实时安全的,因此尝试使用它们会导致间歇性的音频故障。
然而,我和我的同事都很贪婪,尽管如此,我们还是希望每个样本缓冲区执行更多的数学运算,即使是最快的单核也能在短时间内可靠地执行 -window,这是避免音频不足运行和故障所必需的。
我的同事(在 embedded/purpose-built Linux 硬件的实时音频处理方面相当有经验)告诉我,在 Linux 下,一个程序可以请求独占访问一个或多个 CPU 核心,这样 OS 将永远不会尝试将它们用于其他任何事情。完成此操作后,他可以 运行 在那个 CPU 上简单地 busy-waits/polls 原子变量上的“裸机”样式代码,直到“真实”音频线程更新它以让专用核心知道是时候做它的事了;届时,专用核心将 运行 其对输入样本的数学例程,并在(希望)有限的时间内生成其输出,此时“真实”音频线程可以收集结果(更多 busy-waiting/polling 此处)并将它们合并回传出音频缓冲区。
我的问题是,这种方法值得在 MacOS/X 下尝试吗? (即 MacOS/X 程序,即使是具有 root 访问权限的程序,也可以说服 MacOS 授予它对某些核心的独占访问权,如果是这样,那么丑陋的 busy-waiting/polling 循环在这些核心上(包括同步 CoreAudio 回调线程所必需的轮询循环,相对于它们的 input/output 要求)产生足够可靠的实时结果,以至于有一天您可能想在付费观众面前使用它们?)
这似乎在原则上是可能的,但在我花太多时间去撞墙之前,我想了解一下这是否是一个值得在这个平台上追求的途径.
can a MacOS/X program, even one with root access, convince MacOS to give it exclusive access to some cores
我不知道,但你可以使用尽可能多的内核/real-time threads as you want for your calculations, using whatever synchronisation methods you need to make it work, then pass the audio to your IOProc
using a lock free ring buffer, like TPCircularBuffer。
但你的问题让我想起了新的 macOS 11/iOS 14 API 我一直想尝试,the Audio Workgroups API (2020 WWDC Video)。
我的理解是,这个 API 让你“祝福”你的非 IOProc real-time threads 具有音频实时线程属性,或者至少与音频线程更好地合作。
文档区分线程working in parallel (this sounds like your case) and working asynchronously(这听起来像我的建议),我不知道哪种情况更适合你。
我仍然不知道当你使用 Audio Workgroups
时实际上会发生什么,他们是选择你加入好东西还是选择你退出坏东西,但如果他们不是锤子你'重新寻找,它们可能具有一些有用的类似锤子的特性。
首先,一些相关的背景信息:我有一个基于 CoreAudio 的低延迟音频处理应用程序,它可以对来自输入设备的音频进行各种混音和特效 Mac(运行使用最新版本的MacOS)并将结果传送回Mac的本地音频设备之一。
为了获得 best/most 可靠的低延迟性能,此应用旨在挂接到 CoreAudio 的低级音频渲染回调(通过 AudioDeviceCreateIOProcID()、AudioDeviceStart() 等) ) 并且每次调用回调函数时(从 CoreAudio 的实时上下文),它读取传入的音频帧(例如 128 帧,每帧 64 个样本),进行必要的数学运算,并写出传出样本。
这一切工作得很好,但从我读过的所有内容来看,Apple 的 CoreAudio 实现有一个不成文的事实上的要求,即所有实时音频操作都在单个线程中发生。我承认这是有充分理由的(主要是在我已经使用的 SIMD/SSE/AVX 指令之外,几乎所有你可能用来协调并行化行为的机制都不是实时安全的,因此尝试使用它们会导致间歇性的音频故障。
然而,我和我的同事都很贪婪,尽管如此,我们还是希望每个样本缓冲区执行更多的数学运算,即使是最快的单核也能在短时间内可靠地执行 -window,这是避免音频不足运行和故障所必需的。
我的同事(在 embedded/purpose-built Linux 硬件的实时音频处理方面相当有经验)告诉我,在 Linux 下,一个程序可以请求独占访问一个或多个 CPU 核心,这样 OS 将永远不会尝试将它们用于其他任何事情。完成此操作后,他可以 运行 在那个 CPU 上简单地 busy-waits/polls 原子变量上的“裸机”样式代码,直到“真实”音频线程更新它以让专用核心知道是时候做它的事了;届时,专用核心将 运行 其对输入样本的数学例程,并在(希望)有限的时间内生成其输出,此时“真实”音频线程可以收集结果(更多 busy-waiting/polling 此处)并将它们合并回传出音频缓冲区。
我的问题是,这种方法值得在 MacOS/X 下尝试吗? (即 MacOS/X 程序,即使是具有 root 访问权限的程序,也可以说服 MacOS 授予它对某些核心的独占访问权,如果是这样,那么丑陋的 busy-waiting/polling 循环在这些核心上(包括同步 CoreAudio 回调线程所必需的轮询循环,相对于它们的 input/output 要求)产生足够可靠的实时结果,以至于有一天您可能想在付费观众面前使用它们?)
这似乎在原则上是可能的,但在我花太多时间去撞墙之前,我想了解一下这是否是一个值得在这个平台上追求的途径.
can a MacOS/X program, even one with root access, convince MacOS to give it exclusive access to some cores
我不知道,但你可以使用尽可能多的内核/real-time threads as you want for your calculations, using whatever synchronisation methods you need to make it work, then pass the audio to your IOProc
using a lock free ring buffer, like TPCircularBuffer。
但你的问题让我想起了新的 macOS 11/iOS 14 API 我一直想尝试,the Audio Workgroups API (2020 WWDC Video)。
我的理解是,这个 API 让你“祝福”你的非 IOProc real-time threads 具有音频实时线程属性,或者至少与音频线程更好地合作。
文档区分线程working in parallel (this sounds like your case) and working asynchronously(这听起来像我的建议),我不知道哪种情况更适合你。
我仍然不知道当你使用 Audio Workgroups
时实际上会发生什么,他们是选择你加入好东西还是选择你退出坏东西,但如果他们不是锤子你'重新寻找,它们可能具有一些有用的类似锤子的特性。