【发布时间】:2017-07-06 13:50:48
【问题描述】:
我正在尝试在我的 CPP 项目中使用 Project NE10 执行 FFT->signal manipulation->Inverse FFT,并将复数输出转换为幅度和相位以用于 FFT,反之亦然以用于 IFFT。但是根据基准测试,我的 C++ 代码的性能不如启用 SIMD 的 NE10 代码。由于我没有手臂组装经验,我正在寻找一些帮助来为未优化的 C 模块编写霓虹灯代码。例如,在 IFFT 之前,我会这样做:
for (int bin = 0; bin < NUM_FREQUENCY_BINS; bin++) {
input[bin].real = amplitudes[bin] * cosf(phases[bin]);
input[bin].imag = amplitudes[bin] * sinf(phases[bin]);
}
其中input 是一个 C 结构数组(用于复数值),amplitudes 和 phases 是 float 数组。
上面的块(O(n) complexity) 需要大约 0.6ms 来处理 8192 个 bin 而 NE10 FFT (O(n*log(n)) complexity) 因为 SIMD 操作只需要 0.1ms。从我目前在 StackOverflow 和其他地方读到的内容来看,内在函数不值得付出努力,所以我只尝试使用 arm neon。
【问题讨论】:
-
内在函数绝对值得付出努力。特别是,您可以将寄存器分配等繁琐的工作留给编译器,与手写汇编相比,这将提高性能,除非您非常擅长编写汇编并且知道代码将在其上运行的微架构的详细信息。
-
我有a godbolt example,它在循环中显示对
cosf和sinf的调用。函数调用会产生大量内存开销。这是link here for you 和another link。cosf和sinf是相关的,所以计算两者。标准的“C”库具有非常严格的精度(或者至少这是重点)。 sin(x)^2+cos(x)^2=1. -
...同时在上面...也就是说,您的“信号操纵”可以在极坐标或实数/虚数上执行,因此您无需进行此转换。确实,您需要做一些数学运算以使事物保持在相同的坐标中(或者至少值得研究)。 '卷积'可能是你添加到你的工具包中的东西?或者至少问题的信号处理方面可能很重要;即,您为什么需要转换?
-
我正在通过将幅度转移到更高频率来更改来自麦克风的输入信号。对我来说,最简单的方法是使用振幅。