我需要实时绘制音频的峰值表。每秒最少44100个样本,最少40个流。每个缓冲区介于64到1024个样本之间。我需要从每个缓冲区中获取最大值。 (然后通过一种低通滤波器馈送它们,并以约20ms的间隔绘制。)
for(int i = 0; i < numSamples; i++)
{
absMaxOfBuffer = MAX( fabs( buffer[i] ), absMaxOfBuffer);
}
这就是我现在的表现。我想更快地做到这一点。缓冲区的浮点数在-1到1范围内,因此是晶圆厂。
问题,是否有一些棘手的comp-sci quicksort-esque方式更快地做到这一点?
如果失败,无分支ABS和MAX函数用于浮点数,它们是否存在?
编辑: 主要平台是Linux / gcc,但计划使用Windows端口(可能是mingw)。
编辑,第二个:
由于关于实际算法结构的一点点问题,我接受了一个人的接受
我会尝试将循环展开到四个,将符号位置零,然后使用SSE(maxps指令)获取最大值,看看是否不会剥离香蕉。感谢您的建议,我已经投票给了你们中的一些人,作为参赛者。 :)
答案 0 :(得分:5)
如果编译器没有内联这两个操作,那么要么直接进行操作,要么找到您的体系结构的实现并自行内联。
你可以从正 IEEE浮点数与具有相同位模式的整数的顺序相同的事实中获得一些东西。也就是说,
f > g iff *(int*)&f > *(int*)&g
所以,一旦你有了fabs'ed,我认为int的无分支max也适用于float(假设它们的大小当然相同)。这里解释了为什么会这样:http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm。但是你的编译器已经知道了这一切,你的CPU也是如此,所以它可能没有任何区别。
没有复杂性 - 更快的方式。你的算法已经是O(n),你无法击败它并仍然看着每个样本。
我猜你的处理器的SIMD(即英特尔的SSE2)可能会有一些东西,它可以通过在每个时钟周期处理比代码更多的数据来提供帮助。但我不知道是什么。如果有,那么很可能会快几倍。
你可能可以在多核CPU上并行化,特别是因为你无论如何都在处理40个独立的流。这将充其量只是一些因素。 “只是”启动适当数量的额外线程,在它们之间拆分工作,并使用最轻量级的原语来指示它们何时完成(可能是线程障碍)。我不太清楚你是否正在绘制所有40个流的最大值,或者每个流的最大值,所以也许你实际上并不需要同步工作线程,除了确保结果传递到下一个阶段没有数据损坏。
可能值得看一下反汇编,看看编译器已经展开了多少循环。尝试将它展开一点,看看是否有任何区别。
要考虑的另一件事是你得到了多少缓存未命中,以及是否可以通过给缓存提供一些线索来减少数量,以便它可以提前加载正确的页面。但我没有这方面的经验,我也不会抱太大希望。 __builtin_prefetch是gcc的神奇咒语,我想第一个实验就像是“在进入这个块的循环之前预取下一个块的开头”。
您目前所需速度的百分比是多少?或者是“尽可能快”的情况?
答案 1 :(得分:2)
要尝试的事情:
答案 2 :(得分:2)
在http://www.scribd.com/doc/2348628/The-Aggregate-Magic-Algorithms
上记录了一个无网点工厂请注意,最新版本的GCC将使用MMX指令为您内联无分支fabs
。还有fmin
和fmax
,但GCC不会内联这些内容(您将获得call fmin
)。
答案 3 :(得分:1)
您可能需要查看Eigen。
它是一个C ++模板库,它使用 SSE(2及更高版本)和AltiVec指令集,优雅地回退到非向量化代码。
快速。 (见基准) 表达式模板允许智能地移除临时值并启用延迟评估,在适当的时候 - 在大多数情况下,Eigen会自动处理这种情况并处理混叠。
对SSE(2和更高版本)和AltiVec指令集执行显式矢量化,优雅地回退到非矢量化代码。表达式模板允许对整个表达式全局执行这些优化 对于固定大小的对象,可以避免动态内存分配,并在有意义时展开循环 对于大型矩阵,特别注意缓存友好性。
答案 4 :(得分:0)
由于你是用C ++开发的,而且你正在使用dsp,你不能连接到matlab,或八度(这是开源)你的数学,只是得到结果?
在这些软件中已经实现了函数(如conv,fft,ifft,fir和plotting util函数,如freqz,stem,graph,plot,mesh等)。我在Photoshop中看了一下,有一个名为MATLAB的大文件夹......有一些.m文件可以从应用程序中调用,将它发送到动态的matlab,然后将结果返回给应用程序。
希望它有所帮助。
答案 5 :(得分:0)
我看到的简单优化:
答案 6 :(得分:0)
为了您的目的,您可以将其平方而不是取绝对值;以数学方式| a | &LT; | B |如果a ^ 2&lt; b ^ 2,反之亦然。在某些机器上,乘法可能比fabs()更快(?),我不知道。