Logische Operationen bei mehreren Modulus-Operationen optimiert?

8

Es ist leicht zu sehen, dass:

%Vor%

Kann vereinfacht werden zu:

%Vor%

Aber wenn man sich die Ergebnisse von GCC anschaut, scheint es, dass dies selbst bei hohen Optimierungsstufen nicht geschieht.

Machen irgendwelche Compiler diese Art von Optimierungen oder gibt es einen guten Grund, warum diese beiden Tests nicht semantisch äquivalent sind?

Bearbeiten: Als Reaktion auf diejenigen, die sagen, dass dies ein Randfall ist, ist der folgende Fall ähnlich:

%Vor%

Eine Zahl unter 3 muss immer kleiner als 5 sein. Der zweite Test ist redundant.

Ich möchte auch Folgendes als Antwort auf die Antwort hinzufügen, dass der Compiler nicht wissen kann, ob die Umgebung betroffen ist ... Schau dir diesen Code an:

%Vor%

Die gesamte Funktion wird durch GCC mit -O2 auf "repz ret" reduziert. Das ist viel komplexer als alles, worüber ich spreche.

    
Matt 18.04.2012, 18:58
quelle

3 Antworten

5

Ignoriere all die dummen Antworten, die behaupten, dass dies für einen Compiler sehr schwierig / unmöglich ist. Ich sehe keinen Grund, warum es schwierig sein würde, aber vermutlich dachte niemand daran, es zu tun oder dachte, es wäre wichtig genug, um es zu optimieren. Wenn Sie eine bessere Antwort als diese benötigen, müssen Sie es auf dem GCC-Bug-Tracker als eine Aufforderung zur Verbesserung melden und sehen, was die Entwickler sagen.

    
R.. 18.04.2012, 19:43
quelle
3
___ qstnhdr ___ Logische Operationen bei mehreren Modulus-Operationen optimiert? ___ qstntxt ___

Es ist leicht zu sehen, dass:

%Vor%

Kann vereinfacht werden zu:

%Vor%

Aber wenn man sich die Ergebnisse von GCC anschaut, scheint es, dass dies selbst bei hohen Optimierungsstufen nicht geschieht.

Machen irgendwelche Compiler diese Art von Optimierungen oder gibt es einen guten Grund, warum diese beiden Tests nicht semantisch äquivalent sind?

Bearbeiten: Als Reaktion auf diejenigen, die sagen, dass dies ein Randfall ist, ist der folgende Fall ähnlich:

%Vor%

Eine Zahl unter 3 muss immer kleiner als 5 sein. Der zweite Test ist redundant.

Ich möchte auch Folgendes als Antwort auf die Antwort hinzufügen, dass der Compiler nicht wissen kann, ob die Umgebung betroffen ist ... Schau dir diesen Code an:

%Vor%

Die gesamte Funktion wird durch GCC mit %code% auf "repz ret" reduziert. Das ist viel komplexer als alles, worüber ich spreche.

    
___ tag123c ___ C ist eine universelle Computerprogrammiersprache, die für Betriebssysteme, Bibliotheken, Spiele und andere Hochleistungsanwendungen verwendet wird. Dieses Tag sollte bei allgemeinen Fragen zur C-Sprache verwendet werden, wie in der Norm ISO 9899: 2011 definiert. Fügen Sie ggf. ein versionsspezifisches Tag wie c99 oder c90 für Fragen zu älteren Sprachstandards hinzu. C unterscheidet sich von C ++ und es sollte nicht mit dem C ++ - Tag kombiniert werden, wenn ein rationaler Grund fehlt. ___ tag123gcc ___ GCC ist die GNU Compiler-Sammlung. Es ist der De-facto-Standard-C-Compiler unter Linux und unterstützt auch viele andere Sprachen und Plattformen. ___ answer10216795 ___

Ignoriere all die dummen Antworten, die behaupten, dass dies für einen Compiler sehr schwierig / unmöglich ist. Ich sehe keinen Grund, warum es schwierig sein würde, aber vermutlich dachte niemand daran, es zu tun oder dachte, es wäre wichtig genug, um es zu optimieren. Wenn Sie eine bessere Antwort als diese benötigen, müssen Sie es auf dem GCC-Bug-Tracker als eine Aufforderung zur Verbesserung melden und sehen, was die Entwickler sagen.

    
___ tag123optimierung ___ Optimierung ist der Akt der Verbesserung einer Methode oder eines Designs. In der Programmierung nimmt die Optimierung normalerweise die Form an, die Geschwindigkeit eines Algorithmus zu erhöhen oder die benötigten Ressourcen zu reduzieren. Eine weitere Bedeutung der Optimierung sind numerische Optimierungsalgorithmen. ___ answer10216386 ___

Ehrlich gesagt, das ist ein sehr spezifischer Fall. Wenn ein Teil der Gleichung geändert wird, würde die Optimierung nicht länger gelten. Ich denke, es ist eine Frage von Kosten gegen Gewinne und die Kosten für die Implementierung dieser Optimierung (erhöhte Kompilierungszeit, erhöhte Wartungsschwierigkeiten) überwiegen die Vorteile (ein paar weniger schnelle Operationen in seltenen Fällen).

Im Allgemeinen kann mathematisches Refactoring aufgrund der Genauigkeitsbeschränkung und der Möglichkeit eines Überlaufs nicht angewendet werden. Obwohl ich denke, dass es kein Problem ist.

    
___ antwort10216344 ___

Ihr Beispiel ist ziemlich einfach und lässt sich leicht zu einer einzigen Operation zusammenfassen. Der allgemeine Fall einer solchen Aussage ist jedoch nicht so einfach. Nehmen Sie zum Beispiel Folgendes:

%Vor%

Diese Variante kann nicht so einfach auf eine einzelne Modulusoperation vereinfacht werden (ich weiß, dass diese Aussage alle möglichen anderen Probleme damit hat), aber der Punkt ist, dass das Problem nicht so einfach ist, wenn Sie etwas anderes als verwenden eine einfache Variablenreferenz). Compiler werden im Allgemeinen nicht darauf achten, dass Ihr Fall nur einfache Variablen enthält und diese anders als im allgemeinen Fall optimiert. Sie versuchen, Optimierungen möglichst konsistent und vorhersehbar zu halten.

Aktualisierung: Die zusätzlichen Fälle, die Sie zu Ihrer Frage hinzugefügt haben, fallen in eine völlig andere Klasse der Optimierung als Ihr ursprüngliches Code-Snippet. Sie sind beide wegoptimiert, da sie unerreichbarer Code sind, und können zur Kompilierungszeit als solche nachgewiesen werden. Ihre ursprüngliche Frage bestand darin, zwei Operationen in eine einzige, vom Original abweichende Operation umzuschreiben. Die zwei Snippets, die Sie hinzugefügt haben, schreiben den vorhandenen Code nicht neu, sondern entfernen nur Code, der nie ausgeführt werden kann. Compiler sind in der Regel sehr gut darin, toten Code zu erkennen und zu entfernen.

Die Optimierung, die Sie suchen, ist eine Form der mathematischen Reduktion der Stärke . Die meisten Compiler bieten ein gewisses Maß an MSR-Optimierungen, auch wenn sie je nach Compiler und den Fähigkeiten der Zielplattform unterschiedlich detailliert sind. Zum Beispiel kann ein Compiler, der auf eine CPU-Architektur abzielt, die keine Modulus-Anweisung hat (was bedeutet, dass eine möglicherweise lange Bibliotheksfunktion stattdessen verwendet werden muss), solche Anweisungen aggressiver optimieren. Wenn die Ziel-CPU eine Hardware-Modul-Unterstützung hat, könnte der Compiler-Schreiber die zwei oder drei gespeicherten Anweisungen als zu gering für einen Nutzen ansehen, um die Zeit und Mühe zu wert, die zum Implementieren und Testen der Optimierungsverbesserungen benötigt würde. Ich habe dies in der Vergangenheit mit bestimmten Operationen gesehen, die in einer einzigen Anweisung auf einer x86-CPU (zum Beispiel) durchgeführt werden können, aber Dutzende von Anweisungen auf einer RISC-CPU erfordern würden.

    
___
bta 18.04.2012 19:15
quelle
1

Ehrlich gesagt, das ist ein sehr spezifischer Fall. Wenn ein Teil der Gleichung geändert wird, würde die Optimierung nicht länger gelten. Ich denke, es ist eine Frage von Kosten gegen Gewinne und die Kosten für die Implementierung dieser Optimierung (erhöhte Kompilierungszeit, erhöhte Wartungsschwierigkeiten) überwiegen die Vorteile (ein paar weniger schnelle Operationen in seltenen Fällen).

Im Allgemeinen kann mathematisches Refactoring aufgrund der Genauigkeitsbeschränkung und der Möglichkeit eines Überlaufs nicht angewendet werden. Obwohl ich denke, dass es kein Problem ist.

    
ikegami 18.04.2012 19:17
quelle

Tags und Links