我正在研究GPU合成音频的可行性,其中每个线程都会呈现一个样本。这对可以使用的算法提出了一些有趣的限制 - 任何引用前一组样本的算法都不能以这种方式实现。
过滤是其中一种算法。带通,低通或高通 - 所有这些都需要查看生成的最后几个样本以计算结果。这样做是不可能的,因为尚未生成这些样本。
这使得合成带限波形变得困难。一种方法是使用傅里叶级数对部分进行加法合成。但是,这在O(n)时间运行,并且在GPU上特别慢,以至于并行性增益丢失。如果有一个算法在O(1)时运行,这将消除分支,并且在处理可听范围时可以快1000倍。
我特意为锯齿寻找像DSF这样的东西。我一直试图手工完成傅里叶系列的简化,但这真的很难。主要是因为它涉及谐波数,AKA是Riemann-Zeta函数的唯一奇点。
是否可以实现恒定时间算法?如果没有,可以证明它不是吗?
答案 0 :(得分:8)
过滤是其中一种算法。带通,低通或高通 - 所有这些都需要查看生成的最后几个样本以计算结果。这样做是不可能的,因为尚未生成这些样本。
那不对。 IIR滤波器确实需要先前的结果,但FIR滤波器只需要先前的输入;对于GPU设计用来做的事情来说这是非常典型的,所以让每个处理核心访问让64个输入样本产生一个输出样本并不是一个问题 - 事实上, Nvidia和AMD使用的缓存架构适用于此。
是否可以实现恒定时间算法?如果没有,可以证明它不是吗?
是的!在两个方面:
评论您的方法:
我正在研究GPU合成音频的可行性,其中每个线程都会呈现样本。
从更高的角度来看,这听起来太精细了。我的意思是,让我们说你有3000个流处理器(高端消费者GPU)。假设你的采样率为44.1kHz,假设每个处理器只有一个样本,让它们全部运行一次只能得到1/14.7秒的音频(单声道)。然后你必须转到音频的下一部分。
换句话说:必然会有更多的样本而不是处理器。在这些情况下,让一个处理器处理一系列样本通常会更有效率;例如,如果你想生成30秒的音频,那就是1.323MS(amples)。简单地将问题分成3000个块,每个处理器一个,并为每个处理器提供44100 * 30/3000 = 441个样本,他们应该处理这些样本以及64个"历史记录"在他们的第一个"拥有"之前样本仍然可以很容易地融入本地记忆。
又一个想法:
我来自软件定义的无线电背景,其中通常每秒有数百万个样本,而不是几kHz的采样率,实时(即处理速度>采样率) 。尽管如此,在GPU上进行计算只需要支付更多CPU密集型任务,因为与GPU交换数据会带来很大的开销,而现在的CPU速度非常快。因此,对于相对简单的问题,与在CPU上优化它们相比,在GPU上执行操作可能永远不会更快;如果您必须立即处理批次样本或大量流,那么事情当然会有所不同。对于更细粒度的任务,填充缓冲区,将其移动到GPU以及将结果缓冲区恢复到软件中的问题通常会占据优势。
因此,我想向您提出挑战:下载GNU Radio live DVD,将其刻录到DVD或将其写入USB记忆棒(您也可以在VM中运行它,但当然如果您不知道如何优化虚拟器,则会降低性能;实际上 - 从实时媒体中尝试,运行
volk_profile
让VOLK library测试哪种算法在您的特定计算机上运行最佳,然后启动
gnuradio-companion
然后,打开以下两个信号处理流程图:
当然,借助我的GPU上的FFT,我可以更快,但这里的事情是:即使使用"简单" FIR滤波器,我可以用一个CPU内核从我的机器中获取50 Megasamples - 这意味着,对于每秒钟44.1kHz的音频采样率,我可以处理大约19分钟的音频。无需复制进出主机RAM。没有GPU冷却器旋转。它可能真的不值得进一步优化。如果您优化并采用FFT滤波器方法:160MS / s意味着每秒处理大约一小时的音频,包括锯齿生成。