"Mikro"-Optimierung von Code. Wo greift man an?



  • Ich bin gerade damit beauftragt mir anzuschauen, wie viel ich aus einem bestimmten Stück C/C++-Code auf einer CPU rausholen kann (d.h. threadbasiert parallelisiert ist das ganze schon).

    Bei dem Code handelt es sich um einen Decoder von Bilddaten eines bestimmten Codecs.

    Was ich jetzt schon untersucht und dementsprechend auch implementieren werde:

    - Aufpassen, dass alles schön cachelokal bleibt. Laut Valgrinds cachegrind haben wir keine großartigen cache-misses an Stellen, an denen wir was dagegen unternehmen könnten. Die größten Kandidaten hierfür (verschachtelte for-Schleifen) passen hierfür schon.

    - Ein eigener Allokator ersetzt malloc() / new() bereits, und macht das ganze auch ein wenig schneller (aber nicht viel schneller, gibt nicht viel neu angelegten dynamischen Speicher während des Dekodiervorgangs). Es spart allerdings einen Haufen Speicher.

    - Unnötige Branches werden entfernt. Hier gibts im Code einige die praktisch komplett entfernt werden können. Laut cachegrind könnten dabei auch 5-10% Leistungsverbesserung rumspringen, aber ich bin vorsichtshalber mal nicht so optimistisch.

    Davon ausgehend, dass an der Algorithmik an sich ohne viel Zeitaufwand nichts mehr zu machen ist, gibt es da noch andere offensichtliche Stellen, wo man anpacken könnte?



  • Manche Binär"kombinationen" kann man durch schnellere ersetzen. Bei SHA-2 z.B.

    // return (x & y) ^ (x & z) ^ (y & z); So steht's im Standard
    return y ^ ((x ^ y) & (y ^ z)); // Scheint deutlich schneller zu sein
    

    Keine Ahnung ob's sowas bei dir gibt, nur so eine Idee.



  • Du könntest versuchen, verschachtelte Bedingungen umzustrukturieren, sodass die Branch Prediction besser arbeitet, d.h. die Bedingungen so umstellen, dass sie meistens true oder meistens false ergeben. Dadurch hab ich mal AFAIR ein Programm um 40% beschleunigen können.



  • Du kannst ja mal schaun, ob man mit handgeklöppeltem SIMD-Kram was machen könnte.



  • +1 für SIMD Befehle



  • Danke erstmal für die Beiträge. Ich hätte noch eine Frage:

    Bekommt man irgendwoher, bzw. kann mich sich irgendwie ausrechnen, wie lange typische Zeiten sind die bei L1 cache misses verloren gehen? Die Cache-misses, die ich erwähnte, gegen die wir nicht so viel machen können, sind nämlihc noch zahlreich vorhanden. Die zu beseitigen würde eben auch stärkeres Refactoring des Codes bedeuten.

    Laut Cachegrind haben wir insgesamt 16 Millionen davon.

    Ansonsten: Ich werde die Vorschläge nutzen und dementsprechend im Code rumsuchen. Was SIMD-Operationen angeht, sieht's wohl zunaechst schlecht aus. Es wäre zwar prinzipiell mit Sicherheit möglich, allerdings nicht ohne aufwändigeres refactoring des Codes. Da das ganze jetzt hauptsächlich eine Zeitsache ist, werde ich das erstmal zur Seite stellen müssen.


Anmelden zum Antworten