Ich arbeite an einem DSP-Projekt (IIR-Filterung) auf einem digitalen Signalprozessor von Analog Devices (BF706) mit der mitgelieferten Compiler-Suite CrossCore Studio. Es enthält einige Beispiele für einfache DSP-Funktionen wie FIR- und IIR-Filter und Bibliotheksfunktionen. Das Prozessorhandbuch beschreibt die Montageanleitung und kommentiert C nicht.
Meine Frage ergibt sich aus dieser bestimmten Anwendung, aber ich dachte, es gibt eine bewährte Methode, die DSP-Entwickler befolgen. Also werde ich es allgemein einrahmen:
Anhand der mit diesem DSP gelieferten Beispiele habe ich festgestellt, dass ich, wenn ich die für DSP-Anwendungen konzipierten Schaltungen verwenden möchte, Assembler 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 ebenfalls von der DSP-Chip-Firma stammt) es nicht für diesen DSP optimieren und seine Fähigkeiten nutzen? Oder muss ich wirklich DSP-Routinen direkt in Assembler schreiben?
quelle
Antworten:
Es ist immer besser, Ihren Algorithmus in einer höheren Sprache zu implementieren (wobei C mit Assembly verglichen wird), auch wenn Sie am Ende alles in Assembly implementieren möchten.
Möglicherweise müssen Sie nicht einmal zusammengebaut werden . Wenn der von Ihrem Compiler generierte Code Ihre Entwurfsziele erfüllt, ist Ihre Aufgabe erledigt.
Andernfalls werden Sie Ihre Assembly-Codierung nicht von Grund auf neu starten . Lassen Sie den Compiler den ersten Code für Sie generieren und verwenden Sie diesen als Basis für Ihre optimierte Assembly-Version.
Wenn Sie später Ihren optimierten Assembly-Code testen müssen, ist die C-Version für Sie von Vorteil. 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 dieselbe Ausgabe erzeugt.
Wenn ein neuer Entwickler nach einigen Jahren Änderungen an Ihrem Algorithmus vornehmen muss und nur ein hochoptimierter Assembler-Code zur Verfügung steht, besteht eine hohe Wahrscheinlichkeit, dass er von vorne anfangen muss.
quelle
Wenn die Compiler-Autoren einige Anstrengungen unternehmen, um es für dieses Ziel zu optimieren, wird zumindest ein Teil der speziellen DSP-Anweisungen / -Architektur verwendet. Aber für ultimative Leistung wird es nie so gut sein wie eine handgestimmte Montage. Es könnte jedoch gut genug sein - hängt von Ihrer Anwendung ab.
Andere Alternativen umfassen:
quelle
Vorzeitige Optimierung ist die Wurzel allen Übels. - Donald Knuth
Wenn Sie feststellen, dass Sie nicht genügend Leistung aus Ihrem Code herausholen, profilieren Sie zuerst Ihr Programm, finden Sie die Engpässe, analysieren Sie Ihre Leistungsanforderungen und führen Sie erst dann Optimierungen durch. Das Schreiben von Assembly-Code ist das letzte Mittel.
Ja, C-Compiler kann einiges an Optimierung leisten. Dies hängt jedoch von der Qualität des Compilers ab. Häufig kann ein Mensch schneller Assembler-Code schreiben als der kompilierte C-Code. Das ist mit großen Kosten menschlichen Schmerzes und Leidens verbunden.
Schreiben Sie zuerst in C, dann in profile, und entscheiden Sie dann, ob Sie in assembly schreiben müssen. Hoffentlich brauchen Sie die Montage nicht.
quelle
Ihr DSP wird mit einem Maximum an dauerhaften MACs beworben, vorausgesetzt, alle Pipes sind gefüllt. Dies ist offensichtlich eine Obergrenze für das, was erreicht werden kann. Sie wissen aus Ihrer Analyse, wie viele MACs Ihre Filter und andere Verarbeitungen benötigen. Streben Sie an, dass der erste mindestens zweimal der zweite ist, da Sie sonst den DSP-Core nicht maximal laufen lassen können. So wie Sie nicht versuchen würden, ein FPGA mit mehr als 70% Ressourcen zu füllen (PAR wird darüber hinaus sehr langsam), könnte die Entwicklung sehr langsam werden, wenn Sie versuchen, die letzten theoretischen MACs aus einem DSP herauszupressen.
Sie werden Ihre gesamte Anwendung in C codieren. Es ist unpraktisch, alle zusätzlichen erforderlichen Informationen in Assembler, Testinjektion und -sichtbarkeit, Haushaltsführung usw. zu schreiben. Schreiben Sie eine C-Version des Testfilters. Schreiben Sie eine Assembler-Version desselben Filters, um sicherzustellen, dass Sie tatsächlich Assembler für dieses Biest schreiben können.
Jetzt mach ein paar Timings. Verwenden Sie ein vom Lieferanten zugelassenes RTOS. Vergleichen Sie die Laufzeit Ihres Test Assembler-Moduls mit einer C-Version. Wenn sie innerhalb einiger Prozent liegen, fahren Sie fort. Wenn es dreifach ist, lesen Sie die Dokumentation, befragen Sie den Anbieter und finden Sie heraus, warum der Compiler es nicht optimiert. Möglicherweise müssen Sie lernen, die C-Variante zu schreiben, um die richtigen Compiler-Flags zu setzen, und Sie können schneller herausfinden, wie der Compiler ordnungsgemäß betrieben wird, als alles in Assembler neu zu schreiben.
Sie haben dies alles getan, bevor Sie sich auf einen DSP, eine Toolkette festgelegt haben.
Sobald Sie eine Toolchain haben, mit der Sie arbeiten können, einen Compiler, der sich dem Maximum annähert, einen DSP mit einigem zeitlichen Spielraum, können Sie sich darauf verlassen, dass nur noch wenige Teile Ihrer Codesuite eingefügt werden müssen Assembler, um den Job zu beenden.
quelle
Obwohl ich diese Frage bereits beantwortet habe, werde ich eine weitere Antwort hinzufügen, um einen anderen Standpunkt zu veranschaulichen:
Schreiben Sie in C, lesen Sie in der Montage!
Anstatt also in Assembler zu schreiben, schreiben Sie die Logik in C und achten dabei darauf, dass die Assembler-Ausgabe des C-Codes optimal ist. Sie können häufig bestimmte Tricks im C-Code ausführen, um die Assembler-Ausgabe zu beeinflussen. Verwenden Sie statische Inline-Funktionen, wenn dies sinnvoll ist. Wenn Sie 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 mithilfe der Abstraktion auf.
Obwohl ich sagen muss, dass ich noch nie DSPs programmiert habe, hat dieser Ansatz, den C-Code unter sorgfältiger Beobachtung der kompilierten Assembly zu schreiben, bei x86-Computern sehr gut funktioniert. So gut, dass ich noch nie etwas in der Montage schreiben musste, um die bestmögliche Leistung zu erzielen. Anstatt den Assembly-Code zu optimieren, werde ich den C-Code so ändern, dass die Assembly optimal ist.
Dies hängt natürlich davon ab, ob gute C-Compiler verfügbar sind. Für x86 sind solche Compiler verfügbar (häufig müssen Sie eine höhere Optimierungsstufe als die Standardeinstellung angeben). Bei DSPs weiß ich ehrlich gesagt nicht, ob die Compiler so gut sind.
Der Vorteil dieses Ansatzes besteht darin, dass Sie über eine einzige tragbare Codebasis verfügen, die für eine optimale Zusammenstellung für einen bestimmten DSP optimiert ist. Dies funktioniert jedoch auch, wenn der DSP in einen anderen geändert wird. Natürlich müssen Sie möglicherweise den C-Code leicht anpassen, um die bestmögliche Leistung auf dem neuen DSP zu erzielen.
quelle
Im Allgemeinen ist es nicht erforderlich, Assembler-Quellen zu schreiben, wenn:
Das bedeutet, dass Sie den vom C-Compiler generierten Assembler (für die kritischen Teile) manuell überprüfen und die Quelle ändern, bis ein ausreichender Grad an Optimierung erreicht ist.
quelle
Ich würde hier sagen, dass es bei FIR / IIR-Filtern viel wichtiger ist, welchen Algorithmus Sie verwenden (den Trivialalgorithmus gegenüber der schnellen Fouriertransformation (FFT)) als welche Sprache Sie verwenden (C gegenüber der Assemblierung).
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. Möglicherweise finden Sie eine Bibliothek, in der FFT bereits implementiert ist. In Anbetracht dessen, dass C eine portable Sprache ist, während dies bei Assemblern nicht der Fall ist, werden Sie mit größerer Wahrscheinlichkeit 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 von Hand so einstellen, dass er in Assemblersprache so schnell wie möglich funktioniert. Aber ich glaube nicht wirklich, dass es Sinn macht, dies zu tun, außer unter sehr außergewöhnlichen Umständen.
quelle
Meiner Ansicht nach ist FWIW, dass der Assembler immer Ihr Freund ist, wenn Sie maximale Geschwindigkeit / Effizienz / Durchsatz / was auch immer wollen, solange Sie kompetent sind. Ein Compiler ist dumm; es "weiß" nur, was der Autor gedacht hat, um es zu programmieren, und der Autor kannte Ihre Anwendung überhaupt nicht.
Ich muss zugeben, ich habe Assembler seit Anfang der 80er Jahre geliebt. 8-Bit-Mikros (die modernen MCUs in vielerlei Hinsicht überhaupt nicht unähnlich sind), bei denen das Erlernen von "Maschinencode" eine Grundvoraussetzung war, um eine nützliche Leistung daraus zu ziehen, aber ich denke, ihre Rolle bleibt wie die Art und Weise zu Programm für maximale Effizienz. Außerdem ist es sehr lohnenswert, da Sie alle Arten von Optimierungsverknüpfungen verwenden können, an die ein Compiler nicht denken kann, weil ein Compiler überhaupt nicht denken kann.
C ist okay, denke ich. Wenn Sie jedoch genau wissen, was Ihre Maschine auf Hardwareebene tun soll, gehen Sie zu Assembler.
quelle