Da es mit dem iPhone und Assemblercode zusammenhängt, gebe ich ein Beispiel, das in der iPhone Welt relevant wäre (und nicht irgendeines sse oder x86 asm). Wenn jemand beschließt, Assembler-Code für eine echte Welt-App zu schreiben, dann wird dies höchstwahrscheinlich eine Art digitale Signalverarbeitung oder Bildmanipulation sein. Beispiele: Umwandeln des Farbraums von RGB-Pixeln, Kodieren von Bildern in das JPEG/PNG-Format oder Kodieren von Tönen in mp3, amr oder g729 für voip-Anwendungen. Im Fall von Sound-Encoding gibt es viele Routinen, die vom Compiler nicht in effizienten Asm-Code übersetzt werden können, sie haben einfach kein Äquivalent in C. Beispiele für die gebräuchlichsten Dinge in der Soundverarbeitung: gesättigte Mathematik, Multiply-Accumulate-Routinen, Matrixmultiplikation .
Beispiel für gesättigte hinzufügen: 32-Bit vorzeichenbehaftete Int hat Bereich: 0x8000 0000 < = int32 < = 0x7fff ffff. Wenn Sie zwei Ints hinzufügen, könnte das Ergebnis überlaufen, aber dies könnte in bestimmten Fällen in der digitalen Signalverarbeitung inakzeptabel sein. Grundsätzlich, wenn Ergebnis Überlauf oder Unterlauf gesättigt add sollte 0x8000 0000 oder 0x7fff ffff zurückgeben. Das wäre eine vollständige c-Funktion, um das zu überprüfen. eine optimierte Version von gesättigten Add könnte sein:
int saturated_add(int a, int b)
{
int result = a + b;
if (((a^b) & 0x80000000) == 0)
{
if ((result^a) & 0x80000000)
{
result = (a < 0) ? 0x80000000 : 0x7fffffff;
}
}
return result;
}
Sie auch mehrere haben kann, wenn/sonst für Überlauf oder auf x86 zu überprüfen, können Sie Überlauf-Flag überprüfen (die auch Sie asm zu verwenden, erfordert). iPhone benutzt Armv6 oder v7 CPU, die dsp asm haben. Die Funktion saturated_add
mit mehreren Brunchs (if/else-Anweisungen) und zwei 32-Bit-Konstanten könnte also eine einfache asm-Anweisung sein, die nur einen CPU-Zyklus verwendet. So einfach saturated_add asm Anweisung verwenden könnte gesamten Algorithmus zwei-dreimal schneller machen (und kleiner in der Größe). Hier ist die Qadd Handbuch: QADD
andere Beispiele von Code, der oft in langen Schleifen ausgeführt sind
res1 = a + b1*c1;
res2 = a + b2*c2;
res3 = a + b3*c3;
wie nichts scheint hier nicht optimiert werden, sondern auf ARM-CPU können Sie bestimmte dsp Anweisungen verwenden, die nimm weniger Zyklen als einfache Multiplikation! Das stimmt, a + b * c mit bestimmten Anweisungen könnte schneller ausgeführt werden als einfach a * b. Für diese Art von Fällen können Compiler die Logik Ihres Codes einfach nicht verstehen und diese dsp-Anweisungen nicht direkt verwenden. Deshalb müssen Sie asm manuell schreiben, um den Code zu optimieren, ABER Sie sollten nur einige Teile des Codes manuell schreiben, die es sein müssen optimiert. Wenn Sie anfangen, einfache Loops manuell zu schreiben, werden Sie mit Sicherheit den Compiler nicht schlagen! Es gibt mehrere gute Papiere im Internet für die Inline-Assemblierung, um Tannenfilter, amr Codierung/Decodierung etc.
Nicht auf Sie zu picken, aber es gibt eine Menge Leute auf SO Fragen Optimierung und Geschwindigkeit Fragen und sehr wenige sagen, dass sie es brauchen, weil sie die Anforderungen nicht erfüllen. Anscheinend haben wir nicht in das "vorzeitige Optimierung ist die Wurzel allen Übels" Mantra genug geschlagen –
Was meine Fragen ausgelöst hat, war, dass ich mit Inline-Assembly auf dem iPhone herumfummelte und wollte einen Blog-Post darüber schreiben . Aber ich konnte nicht für das Leben von mir meinen Compiler übertreffen. So wurde ich neugierig, ob es bekannte Fälle gibt, in denen Compiler ineffizienten Code produzieren. –
ARM-Assembly ist einer der "saubereren" Befehlssätze. Ein Teil der Philosophie von RISC-Prozessoren besteht darin, keine Befehle hinzuzufügen, die nicht einfach vom Compiler verwendet werden können. Sie müssten sich den Befehlssatz einer bestimmten ARM-Variante ansehen und Opcodes finden, die keine eindeutige C-Übersetzung haben. – NoMoreZealots