直接用C或汇编语言编写DSP算法?[关闭]


18

我正在使用带有交叉编译器套件CrossCore Studio的Analog Devices数字信号处理器(BF706)进行DSP项目(IIR滤波)。它具有一些简单的DSP实例,例如FIR和IIR滤波器以及其库函数。处理器手册描述了汇编指令集,没有对C进行注释。

我的问题来自于此特定应用程序,但我认为DSP开发人员应遵循最佳实践。因此,我将以一般的方式对其进行构架:

通过此DSP附带的示例,我已经意识到,如果我想使用为DSP应用设计的电路,则需要进行汇编编程以直接运行这些指令(例如乘法和加法等)。我的问题是我只是用C编程,编译器(也来自DSP芯片公司)不会为该DSP优化它并使用其功能吗?还是真的需要直接在汇编中编写DSP例程?


17
我花了很多年时间为ADSP-21xx编写汇编程序(以后为Blackfin编写汇编程序,并为C编写程序。)您不会透露所使用的内容,因此任何答案都比其他任何事物都更能引起您的猜测和见解。但是,AD的DSP处理器实在是太棒了,可以这么说,对于C编译器编写者来说,很难适当地填补这些空白。我在该领域有二十年的经验(包括一些非常小的C编译器经验),直到我停止编写代码(几年前)为止,C编译器还不能接近手工编码。但是您的工作取决于您的目标。
jonk

1
@jonk希望您能为这个问题写一个答案-我只做过一个硬核DSP Blackfin项目,但我对它需要的一些性能
改进怀念不已

6
@pericynthion不,除非OP对有关特定DSP和项目目标的讨论多多,否则我无法想象为其写答案。否则,这将是含糊的,无指导性的意见,根据OP随后撰写的内容,它们可能是对还是错。所以我就等。
jonk

1
如果您希望它以最快的速度运行,请在组装时手动对其进行优化。那是时间/金钱的折衷。如果您知道如何编写好的C语言,那么您可以找到大部分的方法。
电压峰值

2
我不确定DSP,但是对于大多数微处理器,您可以使用 在编写汇编程序和C代码之间居中的内在函数
Maciej Piechotka'8

Answers:


20

即使您打算最终在汇编中实现所有内容,最好还是用高级语言(将C与汇编语言进行比较)来实现算法。

  • 机会是,您甚至不需要组装。如果编译器生成的代码满足您的设计目标,那么您的工作就完成了。

  • 如果没有,您将不会从头开始汇编代码。让编译器为您生成初始代码,并将其用作优化程序集版本的基础。

  • 稍后,当您需要测试优化的汇编代码时,您将很高兴拥有C版本。您无需手动为测试输入数据计算正确的输出,而只需将输入数据提供给未优化的C实现,然后在进行优化后检查程序集产生的输出是否完全相同。

如果几年后新的开发人员需要对您的算法进行修改,而他们手中仅有的是高度优化的汇编代码,那么他们很有可能必须从头开始。


23

如果编译器作者努力为该目标优化它,则它将至少使用一些特殊的DSP指令/体系结构。但是对于最终性能,它永远不会像手工调整的装配那样好。不过,它可能足够好-取决于您的应用程序。

其他替代方案包括:

  1. 用C语言编写程序的大部分内容,而仅用汇编语言编写最关键的数字部分。
  2. 用C编写程序,并使用制造商或第三方提供的库-如果您正在执行常见的DSP任务,例如FFT,FIR / IIR滤波器等,可能有人已经编写了手动调整的机器代码来执行此操作,所以您可以使用它(您可能需要付费)并将其链接到您的应用程序。

通常,DSP供应商将提供通用功能的源代码。如果他们的代码“足够好”,则可以将其放入。如果不太正确,则必须对其进行调整。几年前,我不得不做一个FFT层,以获得纯频率的真实FFT。有一个技巧可以让您将2N点实数FFT做为N点复数FFT,但是随后您必须对复数输出进行最后的传递才能恢复实数频率数据。ADI公司的示例代码中没有这种特殊情况。
约翰·斯特罗姆

21

过早的优化是万恶之源。-唐纳德​​·努斯

当发现您的代码无法获得足够的性能时,请首先对程序进行概要分析,找出瓶颈,分析性能要求,然后再开始进行优化。编写汇编代码是不得已的方法。

我的问题是,如果我只是用C编程,那么编译器(也来自DSP芯片公司)是否不会针对该DSP优化它并使用其功能?

是的,C编译器可以进行很多优化。但这取决于编译器的质量。通常,人类可以编写比汇编C代码更快的汇编代码。也就是说,这要付出巨大的人类痛苦和苦难。

还是真的需要直接在汇编中编写DSP例程?

首先用C语言编写,然后进行概要分析,然后确定是否需要用汇编语言编写。希望您不需要装配。


20
在一般编程中,这当然是个不错的建议,但是DSP稍有不同-如果OP确实想有效利用DSP,则可能需要在生产线上的某些地方编写一些手写代码。实际上,在DSP项目中,有时您甚至想开始编写该核心数字内核,以验证处理器将适合手头的任务。
pericynthion

11
您的结论是好的一般建议。但是,考虑到AD DSP ALU的具体细节时,它有些苍白。我想你没有检查过它们。
jonk

18

假设所有管道都已满,将以最大的持续MAC来通告您的DSP。这显然是可以达到的上限。通过分析,您知道过滤器和其他处理将使用多少个MAC。力争使第一个至少达到第二个的两倍,因为您将无法保持DSP内核的最大运行。正如您不会尝试将FPGA填充到70%以上的资源(PAR高于该资源会非常缓慢)一样,尝试将最后几个理论MAC挤出DSP也会使开发变得非常缓慢。

您将使用C对整个应用程序进行编码。用汇编器,测试注入和可见性,内务处理等内容来编写所有其他必要的东西是不切实际的。编写C版本的测试过滤器。编写同一过滤器的汇编程序版本,以验证您实际上可以为此野兽编写汇编程序。

现在做一些计时。使用供应商认可的RTOS。将您的测试汇编模块的运行时间与C版本进行比较。如果它们在百分之几以内,请继续前进。如果是三层,请阅读文档,向供应商提问,并找出编译器为何不对其进行调整。您可能需要学习编写C语言的方式,以及设置正确的编译器标志的程度,与查找汇编程序中的所有内容相比,更快地找到如何正确驱动编译器的方法。

在提交给DSP和工具链之前,您已经完成了所有这些工作。

一旦有了可以使用的工具链,就可以对其进行调整以使其接近合理地达到最大值,而DSP则还具有一定的时间余量,那么您就可以有把握地确信很少需要将代码套件的一部分放入其中。组装工来完成这项工作。


7

即使我已经回答了这个问题,我也会添加另一个答案来说明不同的观点:

用C写,用汇编读!

因此,您将不用C编写逻辑,而是用C编写逻辑,而要小心地确保C代码的汇编输出是最佳的。您通常可以对C代码做一些技巧来影响汇编程序的输出。在合理的情况下使用静态内联函数。如果您需要使用DSP支持的某些特殊指令,请对该特殊指令进行静态内联函数抽象,然后使用该抽象调用特殊指令。

尽管不得不说我从未编程过DSP,但是这种在仔细观察已编译程序集的同时编写C代码的方法对x86机​​器非常有效。实际上,是如此之好,以至于我不必为了获得最佳性能而在汇编中编写任何东西。我将不优化汇编代码,而是以最佳汇编的方式修改C代码。

当然,这取决于可用的优秀C编译器。对于x86,此类编译器可用(您通常必须指定比默认优化级别更高的优化级别)。对于DSP,坦率地说,我不知道编译器是否还不错。

这种方法的好处是您拥有一个可移植的代码库,该代码库经过优化以实现给定DSP的最佳组装,但是如果将DSP更改为其他代码,它也可以工作。当然,您可能必须稍微调整C代码才能在新DSP上获得最佳性能。


我对此有一个疑问:我在STM32F4 Cortex-M4处理器上工作,并且使用CMSIS / Cube库。我还使用了编译器的-O3标志,因为事实证明它比我能产生的任何东西效率更高。问题在于编译后的程序集总是太混乱,无法进行正确的分析。您是否总是在没有编译器优化的情况下进行编译?或者,如果到处都是组装前夕,您是否设法降低了组装前夕的时间?
佛罗伦萨(Florent)

2
@FlorentEcochard:如果程序员无法理解编译器的汇编器,则可能比该程序员可以编写的汇编器更好。作为您问题的直接答案:对组装程序进行最大程度的优化和手动分析,困难的零件可能很有启发性。
pasaba por aqui

4

通常,如果满足以下条件,则无需编写汇编程序源:

  • 您可以在以下关键部分中优化C:充分利用“ register”关键字,内联函数,...
  • 可能是使用asm块的C程序的某些功能

这意味着手动检查由C编译器生成的汇编器(用于关键部分),并修改源代码,直到进行足够的优化为止。


几乎所有现代编译器都忽略“ register”关键字,而与平台无关。使用它不太可能导致更好的代码。
Kef Schecter

@KefSchecter:他们不仅考虑到寄存器暗示,如今他们甚至允许选择寄存器使用:gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/...
pasaba POR褐

1
@KefSchecter:为嵌入式设备编写的编译器除外,在裸机上编程时,这是一个非常重要的关键字。
vsz

@pasabaporaqui:我忘记了一点语法。但是,如果您未指定寄存器名称(换句话说,如果您以ISO标准方式使用它),我敢打赌,GCC会忽略它。
Kef Schecter

3

在这里我要说的是,如果您使用FIR / IIR滤波器,则使用哪种算法(琐碎算法与快速傅里叶变换(FFT))比使用哪种语言(C与汇编语言)要重要得多。

我要在汇编中编写FFT吗?可能不会。

我自己写FFT吗?因为FFT已经实施了很多次,所以答案也可能不是。因此,您很可能会发现一些已经实现FFT的库。考虑到C是一种可移植的语言,而汇编语言不是,那么您将更有可能找到已经用C实现的现有库。

如果您想要最大的性能,显然可以手动调整FFT算法,使其以汇编语言尽快运行。但是我真的不相信这样做,除非在非常特殊的情况下。


2

我个人认为FWIW是,只要您精通,无论何时您想要最大的速度/效率/吞吐量/什么,汇编程序都是您的朋友。编译器很笨;它仅“知道”其作者想编程的内容,而它的作者根本不了解您的应用程序。

我必须承认,自80年代初以来我就很喜欢汇编器8位微控制器(在许多方面与现代MCU完全不同),在这种情况下,学习“机器代码”是获得有用性能的先决条件,但我认为它的作用仍然存在作为最大效率编程方式。另外,由于您可以抛出编译器根本不会想到的各种优化快捷键,这是非常有益的,因为编译器根本无法考虑。

我猜C还可以。但是,如果您真的知道您希望计算机在硬件级别上做什么,那就去组装。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.