Ich suche nach einem Beispiel, bei dem ein Algorithmus anscheinend seine Komplexitätsklasse aufgrund von Compiler- und / oder Prozessoroptimierungsstrategien ändert.
c++
algorithms
optimization
big-o
Lorenz Lo Sauer
quelle
quelle
int main(void) { exit(0); };
Antworten:
Nehmen wir ein einfaches Programm, das das Quadrat einer in der Befehlszeile eingegebenen Zahl druckt.
Wie Sie sehen können, handelt es sich um eine O (n) -Berechnung, die immer wieder wiederholt wird.
Wenn Sie dies mit
gcc -S
einem kompilieren, erhalten Sie ein Segment, das ist:Hier sehen Sie, wie das Hinzufügen durchgeführt wird, ein Vergleich und ein Rücksprung für die Schleife.
Durchführen der Kompilierung mit
gcc -S -O3
, um Optimierungen des Segments zwischen den Aufrufen von printf zu erhalten:Man kann jetzt sehen, stattdessen hat es keine Schleife und außerdem keine Adds. Stattdessen gibt es einen Anruf, bei
imull
dem die Zahl mit sich selbst multipliziert wird.Der Compiler hat die Schleife und den darin enthaltenen mathematischen Operator erkannt und durch die richtige Berechnung ersetzt.
Beachten Sie, dass dies einen Anruf
atoi
zum Abrufen der Nummer beinhaltete. Wenn die Nummer bereits im Code vorhanden ist, berechnet der Complier den Wert vor, anstatt tatsächliche Anrufe zu tätigen, wie in einem Vergleich zwischen der Leistung von sqrt in C # und C gezeigt, bei dersqrt(2)
(eine Konstante) 1.000.000 Mal über eine Schleife summiert wurde.quelle
Die Tail Call-Optimierung kann die Speicherplatzkomplexität verringern. Ohne TCO weist diese rekursive Implementierung einer
while
Schleife beispielsweise eine Raumkomplexität im ungünstigsten Fall aufΟ(#iterations)
, während sie mit TCO eine Raumkomplexität im ungünstigsten Fall aufweistΟ(1)
:Dies erfordert nicht einmal allgemeine Gesamtbetriebskosten, sondern nur einen sehr engen Sonderfall, nämlich die Beseitigung der direkten Schwanzrekursion.
Sehr interessant wäre jedoch, wenn eine Compileroptimierung nicht nur die Komplexitätsklasse ändert, sondern den Algorithmus tatsächlich vollständig ändert.
Der Glorious Glasgow Haskell Compiler macht das manchmal, aber das ist nicht wirklich das, worüber ich spreche, das ist eher wie Betrug. GHC verfügt über eine einfache Pattern Matching Language, mit der der Entwickler der Bibliothek einige einfache Codemuster erkennen und durch anderen Code ersetzen kann. Und die GHC Umsetzung der Haskell - Standardbibliothek hat einige dieser Anmerkungen zu enthalten, so dass bestimmte Verwendungen von spezifischen Funktionen , die ineffizient sind dafür bekannt, neu geschrieben in effizientere Versionen.
Diese Übersetzungen werden jedoch von Menschen geschrieben und sind für bestimmte Fälle geschrieben. Deshalb halte ich das für Betrug.
Ein Supercompiler kann den Algorithmus möglicherweise ohne menschliche Eingabe ändern, aber AFAIK hat noch nie einen Supercompiler auf Produktionsebene erstellt.
quelle
Ein Compiler, der sich bewusst ist, dass die Sprache eine Reduzierung der Stärke durch große Zahlen verwendet (Multiplikationen durch den Index einer Schleife durch eine Addition ersetzen), würde die Komplexität dieser Multiplikation von O (n log n) bestenfalls auf O (n) ändern. .
quelle