Ich arbeite an einem DSP-Projekt (IIR-Filterung) auf einem digitalen Signalprozessor (BF706) von Analog Devices mit der mitgelieferten Compiler-Suite CrossCore Studio. Es enthält einige Beispiele für einfache DSP-Sachen wie FIR- und IIR-Filter und Bibliotheksfunktionen dafür. Das Prozessorhandbuch beschreibt den Bauanleitungssatz und kommentiert C nicht.
MEINE Frage ergibt sich aus dieser speziellen Anwendung, aber ich dachte, es gibt eine bewährte Methode, der DSP-Entwickler folgen. Also werde ich es allgemein formulieren:
Was ich durch die mit diesem DSP gelieferten Beispiele erkannt habe, ist, dass ich, wenn ich die für DSP-Anwendungen entwickelten Schaltungen verwenden möchte, in Assembly programmieren muss, um diese Anweisungen direkt auszuführen (wie Multiplizieren und Addieren usw.). Meine Frage ist ob Ich programmiere nur in C, würde der Compiler (der auch von der DSP-Chip-Firma stammt) ihn nicht für diesen DSP optimieren und seine Fähigkeiten nutzen? Oder muss ich DSP-Routinen wirklich direkt in Assembly schreiben?
Es ist immer besser, Ihren Algorithmus in einer höheren Sprache (die C mit Assembler vergleicht) zu implementieren, auch wenn Sie vorhaben, am Ende alles in Assembler zu implementieren.
Die Chancen stehen gut, dass Sie nicht einmal eine Montage benötigen . Wenn der von Ihrem Compiler generierte Code Ihren Designzielen entspricht, ist Ihre Arbeit erledigt.
Wenn nicht, werden Sie Ihre Assembly-Codierung nicht von Grund auf neu beginnen . Lassen Sie den Compiler den anfänglichen Code für Sie generieren und verwenden Sie diesen als Basis für Ihre optimierte Assembly-Version.
später, wenn Sie Ihren optimierten Assembler-Code testen müssen , werden Sie froh sein, die C-Version zu haben. Anstatt die korrekte Ausgabe für Ihre Testeingabedaten manuell zu berechnen, können Sie diese Eingabedaten einfach in Ihre nicht optimierte C-Implementierung einspeisen und dann überprüfen, ob die Assembly nach den von Ihnen vorgenommenen Optimierungen genau die gleiche Ausgabe erzeugt.
Wenn ein neuer Entwickler nach ein paar Jahren Änderungen an Ihrem Algorithmus vornehmen muss und nur einen hochoptimierten Assembler-Code zur Hand hat, besteht eine hohe Wahrscheinlichkeit, dass er bei Null anfangen muss.
Wenn die Compiler-Autoren sich Mühe geben, ihn für dieses Ziel zu optimieren, wird er zumindest die speziellen DSP-Anweisungen / -Architekturen nutzen. Aber für die ultimative Leistung wird es nie so gut sein wie eine von Hand abgestimmte Montage. Es könnte jedoch gut genug sein - hängt von Ihrer Anwendung ab.
Andere Alternativen sind:
Vorzeitige Optimierung ist die Wurzel allen Übels. -Donald Knuth
Wenn Sie feststellen, dass Ihr Code nicht genügend Leistung bringt, erstellen Sie zuerst ein Profil Ihres Programms, finden Sie die Engpässe, analysieren Sie Ihre Leistungsanforderungen und beginnen Sie erst dann mit der Optimierung. Das Schreiben von Assemblercode ist der letzte Ausweg.
Meine Frage ist, wenn ich nur in C programmiere, würde der Compiler (der auch von der DSP-Chip-Firma stammt) ihn nicht für diesen DSP optimieren und seine Fähigkeiten nutzen?
Ja, der C-Compiler kann ziemlich viel optimieren. Dies hängt jedoch von der Qualität des Compilers ab. Häufig kann ein Mensch schnelleren Assemblercode schreiben als den kompilierten C-Code. Das heißt, auf Kosten menschlichen Schmerzes und Leidens.
Oder muss ich DSP-Routinen wirklich direkt in Assembly schreiben?
Schreiben Sie zuerst in C, dann im Profil und entscheiden Sie dann, ob Sie in Assembly schreiben müssen. Hoffentlich würden Sie die Versammlung nicht brauchen.
Ihr DSP wird mit maximal anhaltenden MACs beworben, vorausgesetzt, alle Pipes sind gefüllt. Das ist natürlich eine Obergrenze dessen, was erreicht werden kann. Aus Ihrer Analyse wissen Sie, wie viele MACs Ihre Filter und andere Verarbeitungen benötigen. Versuchen Sie, den ersten mindestens doppelt so hoch wie den zweiten zu haben, da Sie den DSP-Kern nicht auf Maximum laufen lassen können. Genauso wie Sie nicht versuchen würden, ein FPGA mit mehr als 70 % Ressourcen zu füllen (PAR wird darüber sehr langsam), könnte die Entwicklung sehr langsam werden, wenn Sie versuchen, die letzten paar theoretischen MACs aus einem DSP herauszuquetschen.
Sie werden Ihre gesamte Anwendung in C codieren. Es ist unpraktisch, all die zusätzlichen, notwendigen Dinge in Assembler zu schreiben, Testinjektion und Sichtbarkeit, Haushalt usw. Schreiben Sie eine C-Version des Testfilters. Schreiben Sie eine Assembler-Version desselben Filters, um zu überprüfen, ob Sie tatsächlich Assembler für dieses Biest schreiben können.
Machen Sie jetzt einige Zeitmessungen. Verwenden Sie ein vom Lieferanten genehmigtes RTOS. Vergleichen Sie die Laufzeit Ihres Test-Assembler-Moduls mit einer C-Version. Wenn sie innerhalb weniger Prozent liegen, fahren Sie fort. Wenn es dreifach ist, lesen Sie die Dokumentation, fragen Sie den Anbieter ab und finden Sie heraus, warum der Compiler es nicht optimiert. Möglicherweise müssen Sie lernen, seine Variante von C zu schreiben und die richtigen Compiler-Flags zu setzen. Es wird schneller sein, herauszufinden, wie der Compiler richtig gesteuert wird, als alles in Assembler neu zu schreiben.
Sie haben all dies getan, bevor Sie sich auf einen DSP, auf eine Werkzeugkette festgelegt haben.
Sobald Sie eine Toolchain haben, mit der Sie arbeiten können, einen Compiler, den Sie so einstellen können, dass er einigermaßen nahe an das Maximum herankommt, einen DSP mit etwas verbleibendem Timing-Spielraum, dann können Sie einigermaßen sicher sein, dass nur sehr wenige Teile Ihrer Code-Suite eingefügt werden müssen Monteur, um die Arbeit zu beenden.
Obwohl ich diese Frage bereits beantwortet habe, werde ich eine weitere Antwort hinzufügen, um einen anderen Standpunkt zu veranschaulichen:
In C schreiben, in Assembler lesen!
Anstatt also in Assembler zu schreiben, schreiben Sie die Logik in C und stellen sorgfältig sicher, dass die Assembler-Ausgabe des C-Codes optimal ist. Sie können oft bestimmte Tricks im C-Code anwenden, um die Assembler-Ausgabe zu beeinflussen. Verwenden Sie statische Inline-Funktionen, wenn es sinnvoll ist. Wenn Sie einige spezielle Anweisungen verwenden müssen, die der DSP unterstützt, erstellen Sie eine statische Inline-Funktionsabstraktion der speziellen Anweisung und rufen Sie die spezielle Anweisung unter Verwendung der Abstraktion auf.
Obwohl ich sagen muss, dass ich noch nie DSPs programmiert habe, hat dieser Ansatz, den C-Code zu schreiben und dabei die kompilierte Assembly genau zu beobachten, für mich auf x86-Rechnern sehr gut funktioniert. So gut, dass ich nie etwas in Assembler schreiben musste, um die bestmögliche Leistung zu erzielen. Anstatt den Assemblercode zu optimieren, werde ich den C-Code so modifizieren, dass die Assemblierung optimal ist.
Dies hängt natürlich davon ab, ob gute C-Compiler verfügbar sind. Für x86 sind solche Compiler verfügbar (man muss oft eine höhere Optimierungsstufe als die Standardeinstellung angeben). Für DSPs weiß ich ehrlich gesagt nicht, ob die Compiler so gut sind.
Der Vorteil dieses Ansatzes besteht darin, dass Sie eine einzige tragbare Codebasis haben, die optimiert ist, um zu einer optimalen Zusammenstellung für einen bestimmten DSP zu führen, aber es funktioniert auch, wenn der DSP auf etwas anderes geändert wird. Natürlich müssen Sie den C-Code möglicherweise leicht anpassen, um die bestmögliche Leistung auf dem neuen DSP zu erzielen.
Im Allgemeinen ist es nicht notwendig, Assemblerquellen zu schreiben, wenn:
Das bedeutet , den vom C-Compiler generierten Assembler (auf die kritischen Teile) manuell zu überprüfen und den Quellcode zu ändern, bis ein ausreichendes Optimierungsniveau erreicht ist.
Ich würde hier sagen, dass es bei FIR / IIR-Filtern weitaus wichtiger ist, welchen Algorithmus Sie verwenden (den trivialen Algorithmus oder die schnelle Fourier-Transformation (FFT)) als welche Sprache Sie verwenden (C oder Assembly).
Würde ich FFT in Assembler schreiben? Wahrscheinlich nicht.
Würde ich selbst FFT schreiben? Die Antwort darauf ist wahrscheinlich auch nicht, da FFT bereits viele Male implementiert wurde. Die Chancen stehen gut, dass Sie eine Bibliothek finden, die FFT bereits implementiert hat. Wenn man bedenkt, dass C eine portable Sprache ist, Assembler jedoch nicht, werden Sie viel wahrscheinlicher vorhandene Bibliotheken finden, die bereits in C implementiert sind.
Wenn Sie die höchstmögliche Leistung wünschen, können Sie natürlich einen FFT-Algorithmus manuell so einstellen, dass er so schnell wie möglich in Assemblersprache arbeitet. Aber ich glaube nicht wirklich, dass es Sinn macht, das zu tun, außer in sehr außergewöhnlichen Umständen.
Meine eigene Ansicht FWIW ist, dass Assembler immer dann Ihr Freund ist, wenn Sie maximale Geschwindigkeit / Effizienz / Durchsatz / was auch immer wollen, solange Sie sich auskennen. Ein Compiler ist dumm; es "weiß" nur, was sein Autor zu programmieren gedacht hat, und sein Autor kannte Ihre Anwendung überhaupt nicht.
Ich muss zugeben, dass ich seit Anfang der 80er Jahre 8-Bit-Mikros in Assembler liebe (in vielerlei Hinsicht nicht unähnlich zu modernen MCUs), bei denen das Erlernen von "Maschinencode" eine Voraussetzung war, um eine nützliche Leistung aus ihnen herauszuholen, aber ich denke, seine Rolle bleibt bestehen als Weg zur Programmierung für maximale Effizienz. Außerdem ist es sehr lohnend, da Sie alle Arten von Optimierungskürzeln einwerfen können, an die ein Compiler nicht denken wird, weil ein Compiler überhaupt nicht denken kann.
C ist okay denke ich. Aber wenn Sie wirklich wissen, was Ihre Maschine auf Hardwareebene tun soll, gehen Sie zum Assembler.
Ale..chenski
jonk
Pericynthion
jonk
Spannungsspitze
doppeltE
Peter Schmidt
Maciej Piechotka
dmckee --- Ex-Moderator-Kätzchen