C ++ Vektor bei / [] Bedienergeschwindigkeit

7

Um Funktionen die Möglichkeit zu geben, den Vektor zu ändern, kann ich nicht

%Vor%

Aber ich muss tun:

%Vor%

(wie die Antworten meiner anderen Frage gezeigt haben)

  • Ich werde dann eine Menge Aufrufe an myvec.at() machen. Wie schnell ist es, verglichen mit dem ersten Beispiel, das eine Variable verwendet, um das Ergebnis zu speichern?

  • Gibt es eine andere Möglichkeit für mich? Kann ich irgendwie Zeiger verwenden?

Wenn es ernst wird, wird es Tausende von Anrufen zu myvec.at() pro Sekunde geben. Also ist jeder kleine Performance-Esser wichtig.

    
sub 05.04.2010, 13:39
quelle

9 Antworten

17

Sie können eine Referenz verwenden:

%Vor%

Die Funktion at member prüft die Grenzen, um sicherzustellen, dass das Argument innerhalb der Größe von vector liegt. Profiling ist nur eine Möglichkeit genau zu wissen, um wie viel langsamer es im Vergleich zu operator[] ist. Wenn Sie hier eine Referenz verwenden, können Sie die Suche einmal durchführen und dann das Ergebnis an anderen Stellen verwenden. Und Sie können es zu einem Verweis-zu- const machen, wenn Sie sich davor schützen wollen, den Wert versehentlich zu ändern.

    
Michael Kristofik 05.04.2010, 13:44
quelle
4

Aus meinen eigenen Tests mit ähnlichem Code (kompiliert unter gcc und Linux) kann operator[] merklich schneller sein als at , nicht wegen der Überprüfung der Grenzen, sondern wegen des Overheads der Ausnahmebehandlung. Ersetzen von at (was eine Ausnahme auf Out-of-Bounds wirft) mit meinen eigenen Grenzen, die das Überprüfen einer Assertion auslösen auf Out-of-Bounds hat eine messbare Verbesserung gebracht.

Unter Verwendung einer Referenz, wie sagte Kristo , können Sie nur Überschreiten Sie die Grenzen Überprüfung einmal Overhead.

Beim Ignorieren der Überprüfung der Grenzen und des Overheads für die Ausnahmebehandlung sollten sowohl operator[] als auch at so optimiert werden, dass sie dem direkten Array-Zugriff oder dem direkten Zugriff über den Zeiger entsprechen.

Wie Chris Becke sagte, gibt es keinen Ersatz für Profiling.

    
Josh Kelley 05.04.2010 13:58
quelle
2

Wenn die Leistung ein Problem darstellt, kann Profiling nicht ersetzt werden. Die Optimierungsmöglichkeiten von Compilern ändern sich von Version zu Version und winzige, unbedeutende Änderungen am Quellcode können die resultierende Leistung dramatisch verändern.

Niemand kann diese Frage beantworten, aber Sie selbst: Erstellen Sie eine Testumgebung und werfen Sie mehrere Algorithmen darauf und sehen Sie, was Sie bekommen.

ps. Wenn die Leistung wirklich ein Problem ist, dann habe ich einen Geschwindigkeitszuwachs von Faktor 10 aus einem PNG-Decoder bekommen, indem ich die Vektoren entfernt und durch rohe Arrays ersetzt habe. Auch dies war für Visual Studio 6. Ich behaupte nicht, dass eine rohe Array-Ersetzung Ihnen eine Verbesserung von Faktor 10 bringt, aber es ist etwas, das Sie ausprobieren sollten.

    
Chris Becke 05.04.2010 13:44
quelle
2

Der Grund, warum der erste nicht funktioniert, ist, dass Sie keinen Zeiger oder Iterator auf die Adresse der i-ten Variablen setzen. Stattdessen setzen Sie curr gleich dem Wert der i-ten Variablen und ändern dann curr. Ich nehme an, dass doThis und doThat Referenzen sind.

Mach das:

%Vor%     
wheaties 05.04.2010 13:44
quelle
2

Der Operator [] ist möglicherweise schneller als at , weil die Überprüfung der Grenzen nicht erforderlich ist.

Sie können curr zu einer Referenz machen, um das zu tun, was Sie wollen.

%Vor%

Sie können auch ein Benchmarking durchführen, bevor Sie sich Sorgen machen. Moderne Prozessoren können problemlos Tausende von Operationen pro Sekunde verarbeiten.

    
Mark Ransom 05.04.2010 13:43
quelle
1

Optionen, die ich in ungefähr umgekehrter Reihenfolge der Präferenz sehe:

  1. Speichern Sie Zeiger in Ihrem Container anstelle der tatsächlichen Objekte. Dies kann trotzdem sinnvoll sein, wenn die Objekte komplex genug sind, dass das Kopieren problematisch ist.
  2. Verwenden Sie den Indexierungsoperator [] anstelle von at() .
  3. Rufen Sie einfach at() einmal auf und speichern Sie sie in einer Referenz (siehe Kristos Antwort oben).
  4. Vergiss es, bis du tatsächlich ein Problem mit exzessiver Laufzeit hast. Wenn das passiert, profiliere deinen Code zuerst, um sicherzustellen, dass der Flaschenhals hier ist, und mach dir dann nur Sorgen darüber, die Dinge zu beschleunigen .

Ehrlich gesagt, was Sie tun sollten, ist, mit den vier verschiedenen Ansätzen zu spielen und einfach den zu verwenden, der den am einfachsten zu verstehenden Code erzeugt. In den meisten Fällen sind wir froh, ein paar Maschinenzyklen für Code zu opfern, der für den Menschen leichter zu warten ist.

    
T.E.D. 05.04.2010 13:57
quelle
0

Die Komplexität von at() ist konstant, d. h. in der Praxis bedeutet dies, dass sie so ausgelegt sein muss, dass sie keine relevante Leistungseinbuße aufweist.

Sie können [] verwenden, was ebenfalls eine konstante Komplexität ist, aber keine Grenzen überprüft. Dies wäre äquivalent zur Zeigerarithmetik und somit möglicherweise ein Bit schneller als das erste.

In jedem Fall ist der Vektor speziell für den konstanten Leistungszugriff auf jedes seiner Elemente ausgelegt. Das sollte also die geringste Sorge sein.

    
Daniel Daranas 05.04.2010 13:44
quelle
0

Vektoren sind am besten für die Zugriffsgeschwindigkeit geeignet. Der Zugriff auf ein zufälliges Element in einem Vektor hat die Komplexität O (1) verglichen mit O (n) für allgemeine verknüpfte Listen und O (log n) für Verbindungsbäume.

Diese Frage ist jedoch falsch gestellt, da die Antwort auf Ihre andere Frage Sie in die Irre geführt hat, indem Sie nicht erklärt haben, wie Sie Ihr ursprüngliches Problem mithilfe einer Referenz beheben können.

    
Richard Harrison 05.04.2010 13:59
quelle
0

Wenn Sie einen Vektor laden, dann verarbeiten Sie ihn, ohne weitere Elemente hinzuzufügen oder zu löschen. Ziehen Sie dann einen Zeiger auf das zugrunde liegende Array und verwenden Sie Array-Operationen, um den Vektor-Overhead zu vermeiden. .

Wenn Sie Elemente als Teil Ihrer Verarbeitung hinzufügen oder löschen, ist dies nicht sicher, da das zugrunde liegende Array an irgendeiner Stelle durch den Vektor selbst verschoben werden kann.

    
EvilTeach 05.04.2010 16:35
quelle

Tags und Links