c++ - Neon/RPi 上的 64 位 DSP 滤波性能优化
问题描述
我在 Analog Devices Sharc DSP 处理器上有一个 32 位 C++ DSP 音频处理项目,需要将其转移到 64 位处理,现在已经有一段时间可用于 ARM AArch64 的嵌入式用例。
我正在考虑两种选择:
- 要么使用我自己的 FIR 和 IIR 过滤的自定义实现,要么
- 去寻找一些针对 AArch64 和 Neon 优化的库函数。
在 64 位精度之上,我有相当多的 CPU 密集型处理。我还需要获得更多的处理能力,因为目前 Sharc 的性能也是一个瓶颈。IIR 和 FIR 功能应提供 64 位实时、基于块的信号处理。
我的目标平台是 Raspberry Pi,3B+ 可能是 4。我需要的功能类型是在 CMSIS 库中提供的arm_biquad_cascade_df2T_f64()
(它实际上与一个补充 init 函数一起工作,该函数实现了以基于块的方式处理数据所需的状态数组)。库函数似乎适用于 64 位。但我怀疑它们是否适合 AArch64 并针对 AArch64 进行了优化,因为通常 CMSIS 标记为 32 位,Ne10 类似。
我正在探索自定义代码路径,我的问题是:
- 什么样的 Neon 和 AArch64 特定优化是可能的
- 与基于块的双二阶函数的普通 C 实现相比,可以预期的性能改进幅度是多少
还是留给编译器优化和使用 Neon 就足够了?
解决方案
如果您有选择,为了性能,您肯定会选择 AArch64 而不是 32 位 Neon 实现。AArch64 有更多/更宽的向量寄存器。而 CPU 从乱序执行中获益更多,因为 AArch64 放弃了无处不在的 32 位指令集的条件执行,这很容易通过条件标志导致指令之间的额外依赖。
我最近从一项具体的优化任务中得出的个人结论:
- clang 管理比 gcc 更好的自动向量化
- clang 10 比 clang 8 有更好的自动向量化
- clang 对特定 Cortex 内核的调优令人印象深刻
- 有用的clang标志:
-Rpass=loop-vectorize -Rpass-missed=loop-vectorize -Rpass-analysis=loop-vectorize
- 两个编译器都没有设法克服缺乏 AArch64 向量收集负载的问题
- 手动矢量化代码的性能仍然比自动矢量化高 2 倍
- 使用 ARM 向量内在函数的编程受到索引不足的文档的阻碍,并且 ARM 将所有向量指令从 ARMv7 重命名为 AArch64
- 使用 llvm-mca ( https://llvm.org/docs/CommandGuide/llvm-mca.html ),它非常有用
请注意,这些经验不应该被随意概括,这是一项具体的任务。
通过手动优化实现获得多少性能取决于使用特定纯 C 代码的自动矢量化器是否成功。
我从一个普通的 C 实现开始,让它自动矢量化,研究 llvm-mca 输出,发现自动矢量化代码的弱点,并从那里开始工作。
推荐阅读
- nativescript - 根据设备高度在 ScrollView 中动态调整 Nativescript ContentView 的大小
- python - 检查numpy数组的任何元素是否不在列表中?
- java - 在 NetBeans 的同一个 java 应用程序项目中具有多个具有 Main() 函数的 jar 文件
- swift - swift如何将日期组件转换为双精度以获得上传速度
- reactjs - 另一个组件中的状态更改
- python - 在终端中导入 Python 库
- html - 使用html从外部源更改按钮的颜色?
- anychart - Anychart 缩放非地图图表类型
- javascript - 使用 React JavaScript 的 Spring-Boot
- android - onActivityResult 返回空数据