Schnellster Weg, um einen Wert in jedem Strukturelement eines Vektors zurückzusetzen?

8

Sehr ähnlich wie diese Frage , außer dass stattdessen vector<int> Ich habe vector<struct myType> .

Wenn ich für jedes Element im Vektor myType.myVar zurücksetzen möchte (oder auf einen Wert setzen möchte), was ist die effizienteste Methode?

Im Moment durchlaufe ich:

%Vor%

Aber da Vektoren garantiert zusammenhängend gespeichert werden, gibt es sicher einen besseren Weg?

    
OJFord 27.03.2014, 19:25
quelle

6 Antworten

7

Das Zurücksetzen muss jedes Element des Vektors durchlaufen, so dass es mindestens O (n) -Komplexität braucht. Ihr aktueller Algorithmus benötigt O (n).

In diesem speziellen Fall können Sie operator[] anstelle von at verwenden (das könnte eine Ausnahme auslösen). Aber ich bezweifle, dass das der Flaschenhals Ihrer Anwendung ist.

In diesem Sinne sollten Sie wahrscheinlich std::fill verwenden:

%Vor%

Aber wenn Sie nicht auf Byte-Ebene gehen und einen Teil des Speichers auf 0 setzen wollen, was Ihnen nicht nur Kopfzerbrechen bereitet, sondern in den meisten Fällen auch die Portabilität verliert, gibt es hier nichts zu verbessern.

    
Shoe 27.03.2014, 19:28
quelle
6

Anstelle des untenstehenden Codes

%Vor%

mache es wie folgt:

%Vor%

Da die "at" -Methode intern prüft, ob der Index außerhalb des gültigen Bereichs liegt oder nicht. Da der Schleifenindex jedoch berücksichtigt wird (myVec.size ()), können Sie die zusätzliche Überprüfung vermeiden. Ansonsten ist dies der schnellste Weg, es zu tun.

BEARBEITEN

Zusätzlich können wir die Größe () des Vektors vor dem Ausführen der for-Schleife speichern. Dies würde sicherstellen, dass es keinen weiteren Aufruf der Methode size () innerhalb der for-Schleife gibt.

    
Mantosh Kumar 27.03.2014 19:29
quelle
2

Einer der schnellsten Wege wäre das loop unwinding und das Geschwindigkeitslimit konventioneller for -Schleifen, das zu großen Geldverschüttungen führt. In Ihrem Fall, da es sich um eine Laufzeit handelt, gibt es keine Möglichkeit, die Template-Metaprogrammierung anzuwenden, sodass eine Abwandlung des guten alten Duff-Geräts den Trick machen würde

%Vor%

Hier wähle ich einen 8-Block-Abwickelvorgang, um den Wert (sagen wir mal) b einer myStruct -Struktur zurückzusetzen. Die Blockgröße kann optimiert werden und Schleifen werden effektiv abgerollt. Denken Sie daran, dies ist die zugrunde liegende Technik in memcpy und eine der Optimierungen (Schleifen-Abrollung im Allgemeinen) wird ein Compiler versuchen (eigentlich sind sie ziemlich gut darin, also können wir sie genauso gut ihre Arbeit machen lassen).

    
Nikos Athanasiou 27.03.2014 20:00
quelle
1

Zusätzlich zu dem, was vorher gesagt wurde, sollten Sie bedenken, dass der Compiler beim Aktivieren von Optimierungen wahrscheinlich ein Loop-entrolling durchführt, wodurch die Schleife selbst schneller wird.

    
edmz 27.03.2014 19:32
quelle
1

Auch das Vorinkrement ++i benötigt einige Instruktionen weniger als post increment i++ . Erklärung hier

    
AdUki 27.03.2014 19:54
quelle
1

Hüten Sie sich davor, viel Zeit damit zu verbringen, über Optimierungsdetails nachzudenken, die der Compiler nur für Sie erledigen wird.

Hier sind vier Implementierungen dessen, was ich unter dem OP verstehe, zusammen mit dem Code, der mit gcc 4.8 mit --std=c++11 -O3 -S

generiert wurde

Erklärungen:

%Vor%

Explizite Schleifenimplementierungen, grob aus Antworten und Kommentaren, die dem OP zur Verfügung gestellt wurden. Beide produzierten neben Etiketten einen identischen Maschinencode.

%Vor%

Zwei andere Versionen, eine mit std::for_each und die andere mit dem Bereich for Syntax. Hier gibt es einen subtilen Unterschied im Code für die beiden Versionen (außer den Labels):

%Vor%     
rici 27.03.2014 20:13
quelle

Tags und Links