2010-03-03 9 views
6

Welche ist im Durchschnitt schneller - überprüfen Sie den Wert, dann, wenn erforderlich, zuweisen oder einfach zuweisen? Oder in C++ terms:Lesen dann bedingten schreiben vs. schreiben

bool b; 
if(b) 
    b = false; 

oder

b = false; 

Angenommen, der if() Zustand mit 50% Wahrscheinlichkeit, wahr ist. Die Antwort wird höchstwahrscheinlich sehr architekturabhängig sein - bitte äußern Sie sich zu Ihren Überlegungen auf niedriger Ebene. Schreiben verschmutzt immer die Cache-Zeile - richtig? Indem wir einen Schreibvorgang vermeiden, vermeiden wir einen Cache-Flush in 0,5 Fällen. Aber ein klug genug Cache kann einen trivialen Schreibvorgang erkennen und nicht selbst schmutzig. Aber das unbedingte Schreiben ist immer genau eine Speicheroperation, und Lesen-Schreiben ist im Durchschnitt 1,5 Operationen.

Haftungsausschluss: Dies ist eine Frage Neugier, kein Problem, das ich tatsächlich gegenüberstellen.

+0

ist es logisch wichtig, was b ist, wenn sie das Ergebnis sind, dass b sollte falsch sein? –

+0

@Fuzzy: Hier geht es um Optimierung, nicht um Logik. –

+0

ja, aber die zweite ist einfacher zu lesen und zu sagen, was ist meiner Meinung nach. – Earlz

Antwort

4

Verzweigungen sind auf modernen CPUs teuer, und der Speicherzugriff ist bei eingebetteten/älteren CPUs teuer. So ist die Wohnung nur-assign wird immer schneller sein, wenn Sie einige irgendwie komisch Speicher haben, der länger dauert, schreiben als lesen (Hinweis: Sie dies nicht tun)

Es ist schlimmer aus diesen Gründen speziell:

  • Eine Verzweigungsanweisung. Dies kann vom Prozessor vorhergesagt werden, aber es entsteht immer noch eine Overhead-Möglichkeit.
  • 2 Speicherzugriffe statt 1. Lesen und Schreiben auf den meisten Speicherformen ist die gleiche Geschwindigkeit, warum also zweimal, wenn Sie es einmal tun können?
  • Mehr Codeaufwand. Dies ist ein Mikro, aber mehr Anweisungen müssen ausgegeben werden, um die if Aussage zu tun.Dies bedeutet, dass ein zusätzlicher Paarspeicher gelesen wird und mehr Platz unnötig im Cache verbraucht wird.
  • Und für die pessimistischen, könnte es bedeuten, dass die C++ Compiler diese Variable in ein Register anstelle anderen notwendigen Variablen zu setzen entscheidet ..
  • Auch, wenn Sie davon ausgehen, dass b in ein Register gesetzt wird. Register liest/schreibt sind sehr billig, aber sie sind nicht frei ..
+0

Guter Punkt über Verzweigungs (mis) Vorhersage; gilt es immer noch für ARM-CPUs, wo if() 's ohne Verzweigung implementiert sind? –

+0

Es wäre immer noch kaum langsamer wegen der zusätzlichen Speicher gelesen .. Auch wenn Sie eine magische 'read-and-set-false-wenn-wahr'-Anweisung haben, muss der Prozessor immer noch den Wert aus dem Speicher lesen, um zu testen, ob es ist wahr. Und für die Verzweigung auf ARM, nein, Zweig Fehlschläge gelten nicht wirklich für bedingte Zuordnung. in x86 'ccmov' hat keinen Zweig Ich glaube nicht .. – Earlz

+0

So der große Wermutstropfen von R-W - Zweig Fehlvorhersage - gilt nicht für ARM. Der große Wermutstropfen von W - Cache Flush - tut es immer noch, oder? –

1

Es wäre definitiv wert, dies auf verschiedenen Architekturen zu erstellen, um tatsächliche Ergebnisse zu erhalten.

1

Es hängt von verschiedenen Dingen:

  • wie vorhersehbar die Niederlassung (im ersten Szenario) ist
  • ob b ist bereits in einem Register
  • welche Architektur Sie verwenden
1

Zusätzlich zu den Vorschlägen für das Profil hängt es auch davon ab, welcher Speicher diese Schreibanforderung sichert. Wenn es sich beispielsweise um ein flashfähiges Speichergerät handelt, kann der Schreibvorgang sehr kostspielig sein.

0

Wenn Sie die Zuweisung von Zeiger, Referenz oder Grundwerttyp machen, denke ich persönlich, dass die direkte Zuweisung schneller sein wird (scharf darauf, das Ergebnis auf Profiler zu sehen). In einer Umgebung mit einer Wahrscheinlichkeit von 50% werden Sie möglicherweise viel mehr Anweisungen ausführen, die den Wert in die Registrierung bringen. Das Zuweisen von Struktur- oder Klassenobjekten, die den Zuweisungsoperator auslösen, ist am teuersten. Bedingte Logik führt auch mehr Anweisungen und fügt es zu den Code Komplexität Metriken

1

Vor kurzem habe ich Papiere auf sehr schnelle Kompressionstechniken gelesen und Jungs betonte, dass die Notwendigkeit, if Verzweigung zu vermeiden, um die beste Leistung zu erzielen. Der Grund dafür ist das CPU-Pipelining. Die Verwendung von if s unterbricht viele Optimierungen, die eine CPU vornehmen kann, um Teile des Codes parallel auszuführen. Also, wenn Sie viele dieser Operationen hatten, könnte es schneller sein, b = false zu verwenden.

1

Auf einem modernen Pipeline-Prozessor Sie dies berücksichtigen müssen:

  • eine falsch vorhergesagte Verzweigung viele
  • kostet
  • Speicher und Ladevorgänge dauern lange
  • Caches können sowohl Lese- als auch Schreibvorgänge beschleunigen, aber wenn es sich um eine Multi-Cache-Architektur handelt und b in mehr als einem Cache geändert wird, können mehrere Schreibvorgänge mehrere Cache-Räumungen bedeuten und die Leistung beeinträchtigen des Caches.

Read mit bedingtem Schreib haben mindestens einen Speicherzugriff und einen Zweig, die Fehlvorhersage kann. Unter der Annahme, dass die Verzweigung in 50% der Zeit genommen wird, haben Sie im Durchschnitt 1,5 Speicherzugriffe plus die Möglichkeit einer Fehleinschätzung.

Unbedingtes Schreiben hat genau ein Speicherzugriff und keine Verzweigung überhaupt.

Jetzt müssen Sie die Kosten für Fehleinschätzungen mit den Kosten eines Geschäfts abwägen, die sich je nachdem, wie viele Cache-Agenten Sie haben, ändern.

+0

Schöne Berechnung! – pajton