Wie beschleunigt man eine einfache Methode (vorzugsweise ohne Schnittstellen oder Datenstrukturen zu ändern)?

8

Ich habe einige Datenstrukturen:

  • all_unordered_m ist ein großer Vektor, der alle benötigten Strings enthält (alle unterschiedlich)
  • ordered_m ist ein kleiner Vektor, der die Indizes einer Teilmenge der Strings (alle unterschiedlich) im vorherigen Vektor
  • enthält
  • position_m bildet die Indizes der Objekte vom ersten Vektor auf ihre Position in der zweiten ab.

Die Methode string_after(index, reverse) gibt die Zeichenfolge zurück, auf die request_m nach all_unordered_m[index] .

verweist

ordered_m wird als zirkulär betrachtet und abhängig vom zweiten Parameter in natürlicher oder umgekehrter Reihenfolge untersucht.

Der Code ist ungefähr wie folgt:

%Vor%

Angesichts dessen:

  • Ich brauche alle Datenstrukturen für andere Zwecke;
  • Ich kann sie nicht ändern, weil ich auf die Strings zugreifen muss:
    • nach ihrer ID im all_unordered_m;
    • nach ihrem Index innerhalb der verschiedenen ordered_m;
  • Ich muss die Position eines Strings (identifiziert durch seine Position im ersten Vektor) innerhalb des Vektors ordered_m kennen;
  • Ich kann die string_after-Schnittstelle nicht ändern, ohne den größten Teil des Programms zu ändern.

Wie kann ich die string_after -Methode beschleunigen, die milliardenfach aufgerufen wird und etwa 10% der Ausführungszeit in Anspruch nimmt?

BEARBEITEN: Ich habe versucht, position_m a vector anstelle von unordered_map zu machen und die folgende Methode zu verwenden, um Sprünge zu vermeiden:

%Vor%

Die Änderung von position_m scheint am effektivsten zu sein (ich bin mir nicht sicher, ob die Eliminierung der Verzweigungen einen Unterschied macht, ich bin versucht zu sagen, dass der Code kompakter ist, aber genauso effizient in dieser Hinsicht).

>     
baol 04.04.2010, 15:25
quelle

2 Antworten

3

vector lookups sind blitzschnell. size() Aufrufe und einfache Arithmetik sind blitzschnell. map lookups sind im Vergleich dazu so langsam wie eine tote Schildkröte mit einem Betonblock auf dem Rücken. Ich habe oft gesehen, dass diese bei ansonsten einfachem Code wie diesem zu einem Flaschenhals werden.

Sie könnten stattdessen unordered_map aus TR1 oder C ++ 0x (eine Drop-in-Hashtabelle-Ersetzung von map ) versuchen und sehen, ob das einen Unterschied macht.

    
Thomas 04.04.2010, 15:33
quelle
3

Nun, in solchen Fällen (eine kleine Funktion, die oft aufgerufen wird) kann jede Verzweigung sehr teuer sein. Da fallen mir zwei Dinge ein.

  1. Könnten Sie den Parameter reverse weglassen und zwei separate Methoden erstellen? Dies macht nur dann Sinn, wenn die if -Anweisung nicht einfach an den aufrufenden Code übergeben wird.
  2. Probieren Sie Folgendes aus, um pos : pos = (pos + 1) % ordered_m.size() zu berechnen (dies gilt für den Vorwärtsfall). Dies funktioniert nur, wenn Sie sicher sind, dass pos beim Inkrementieren niemals überläuft.

Im Allgemeinen versuchen Sie, in solchen Fällen Zweige durch arithmetische Operationen zu ersetzen, dies kann zu einer erheblichen Beschleunigung führen.

    
Björn Pollex 04.04.2010 15:45
quelle

Tags und Links