Sind messbare Leistungssteigerungen durch die Verwendung von VC ++ __assume möglich?

9

Sind messbare Leistungssteigerungen durch die Verwendung von VC ++ 's __assume möglich? Wenn ja, bitte einen Beweis mit Code und Benchmarks in Ihrer Antwort.

Der spärliche MSDN-Artikel zu __assume: Ссылка

In diesem Artikel wird die Verwendung von __assume (0) erwähnt, um switch-Anweisungen schneller zu machen, indem (__) der Standardfall angenommen wird. Ich habe keine Leistungssteigerung gemessen, indem ich __assume (0) auf diese Weise verwendet habe:

%Vor%

Abgerundete Konsolenausgabe, 1000000 Iterationen:

NoAssumeSwitchStatement: 46ms
AssumeSwitchStatement: 46ms

    
Neil Justice 29.02.2012, 17:56
quelle

2 Antworten

7

Scheint, es macht einen kleinen Unterschied, wenn Sie die richtigen Compiler-Schalter setzen ...

Drei Läufe folgen. Keine Optimierungen, entscheiden Sie sich für Geschwindigkeit und wählen Sie Größe.

Dieser Lauf hat keine Optimierungen

%Vor%

Dies ist mit maximalen Optimierungen (/ Ox). Beachten Sie, dass / O2 im Grunde genommen identisch schnell war.

%Vor%

Dieser Durchlauf sollte den Coderaum minimieren

%Vor%

Beachten Sie, dass der Ausgabe-Assembly-Code mit dem übereinstimmt, was Matthiu M. zu sagen hatte, wenn die Geschwindigkeitsoptionen verwendet werden. Die Schalterfunktionen wurden in anderen Fällen aufgerufen.

    
JimR 29.02.2012, 20:06
quelle
9

Benchmark liegt. Sie messen selten, was Sie wollen. In diesem speziellen Fall waren die Methoden wahrscheinlich inline, und so war die __assume einfach überflüssig.

Was die eigentliche Frage angeht, ja, kann es helfen. Ein Switch wird im Allgemeinen durch eine Sprungtabelle implementiert. Durch das Reduzieren der Größe dieser Tabelle oder das Entfernen einiger Einträge kann der Compiler möglicherweise bessere CPU-Anweisungen zum Implementieren von switch auswählen.

In Ihrem Extremfall kann die switch in eine if (i == 0) { } else { } Struktur umgewandelt werden, was normalerweise effizient ist.

Darüber hinaus hilft das Trimmen von toten Zweigen dabei, den Code sauber zu halten, und weniger Code bedeutet eine bessere Nutzung des CPU-Befehlscache.

Aber das sind Mikro-Optimierungen, und sie zahlen sich selten aus: Sie brauchen einen Profiler, um sie auf Sie aufmerksam zu machen, und selbst diese können die genaue Umwandlung schwierig machen (ist __assume die beste?) . Das ist die Arbeit eines Experten.

BEARBEITEN : In Aktion mit LLVM

%Vor%

Beachten Sie, dass der einzige Unterschied das Vorhandensein oder Fehlen von __builtin_unreachable() ist, das MSVC __assume(0) ähnlich ist.

%Vor%

Beachten Sie hier, wie die switch -Anweisung in regular zu einem einfachen Vergleich in optimized optimiert werden kann.

Dies wird der folgenden x86-Assembly zugeordnet:

%Vor%

Beachten Sie, wie im zweiten Fall:

  • Der Code ist enger (weniger Anweisungen)
  • es gibt einen einzigen Vergleich / Sprung (cmpl / je) auf allen Pfaden (und nicht einen Pfad mit einem einzelnen Sprung und einen Pfad mit zwei)

Beachten Sie auch, dass dies so nahe ist, dass ich keine Ahnung habe, wie man etwas anderes als Rauschen misst ...

Auf der anderen Seite zeigt es semantisch eine Absicht an, obwohl vielleicht ein assert besser nur für die Semantik geeignet wäre.

    
Matthieu M. 29.02.2012 18:19
quelle