yip: verschiedene Retrografik-Funktionen mit und ohne Optimizer



  • @lemon03 sagte in yip: verschiedene Retrografik-Funktionen mit und ohne Optimizer:

    img ist doch ein 2Dvector?

    Ja, das nächste Performance-*lach* lol



  • vector<vector<pixel>> ist aber die schlechteste Datenstruktur für 2D-Bild (weil speichertechnisch anders aufgebaut und auch unperformant).
    Entweder array<pixel, N>benutzen (falls die Größe schon zur Kompilierungszeit feststeht) oder aber nur vector<pixel>(und dabei das 2D-Bild als Rows*Columns auffassen und die Indizes selber berechnen bzw. eine passende Klasse bzw. Funktionen dafür schreiben).

    Und den Code selbst kann man sicherlich auch noch weiter optimieren. Ich würde z.B. die Floatingpointberechnungen (bzw. casten) eliminieren und nur mit Integern arbeiten, also z.B. newred = triple.red + (112*dist.red) / 256.



  • Wenn doch bloß letztens hier jemand ausführlich, inklusive Beispiel Implementierung, erklärt hätte, wie man ein 2 dimensionales Array in C++ implementiert.





  • Oder eine struct mit je pos_x, pos_y und einem Farbwert/einen Index aus einem bestimmten Farbbereich.



  • @swordfish sagte in yip: verschiedene Retrografik-Funktionen mit und ohne Optimizer:

    @Mechanics Klar, der ganze unnütze objektorientierungs-Schmarrn und Templates machen doch alles nur unnötig überkompliziert und lahm. Mit der Meinung bin ich auch nicht alleine:

    Es geht nicht um Meinungen. Nenn mir objektive Gründe, warum das so sein sollte. Es gibt keine.
    Und ja, in der Praxis wirst du oft Recht haben. Und man kann mit Objektorientierung ganz leicht etwas überkompliziertes bauen, was nicht mehr optimierbar ist. Das ist aber kein Grund pauschal zu sagen, C wär grundsätzlich schneller. Wenn du identischen Code wie in C schreibst, wird der C++ Compiler auch (mindestens) genauso schnellen Code erzeugen. Und mit Templates kann man leicht schnelleren Code erzeugen, als man das in C (mit vernünftigem Aufwand) machen könnte.



  • Ich bin mir sicher, dass Swordfish mitunter zu Sarkasmus neigt.



  • Yeah 🙂 Aber ich frage mich, ob Mechanics gerade dies bewusst war und extra "unschuldig" darauf reagiert hat. Sozusagen diesen Sarkasmus absichtlich ignoriert hat.



  • Mir ist schon klar, dass Swordfish zu Sarkasmus neigt. In dem Fall ist mir aber nicht klar, ob das so beabsichtigt war. Es gibt viele sehr gute Entwickler, die C bevorzugen, warum sollte das nicht seine ehrliche Meinung sein?



  • @mechanics sagte in yip: verschiedene Retrografik-Funktionen mit und ohne Optimizer:

    Es gibt viele sehr gute Entwickler, die C bevorzugen, warum sollte das nicht seine ehrliche Meinung sein?

    Vielleicht lehne ich mich zu weit aus dem Fenster, aber weil Swordfish den Thread [WinAPI und C: Zukunftschancen und mehr] als Beispiel seiner Argumentation genannt hat und sich schon dort sehr sarkastisch gegenüber dem C-Verfechter geäußert hat.



  • @yadgar sagte in yip: verschiedene Retrografik-Funktionen mit und ohne Optimizer:

    profitiert sichtlich am meisten von der Optimierung - aber wieso? Liegt es am häufigen Zugriff auf Klassenobjekte?

    Auch wenn schon einiges dazu geschrieben wurde, hier auch meine 2 Cent:

    Das .at() ist natürlich wegen der Range-Prüfung nicht besonders effizient, selbst wenn man sog. "Zero Overhead"-Exceptions nutzt. Möglicherweise kann der Compiler bei besserer Optimierung aber beweisen, dass die Range immer eingehalten wird, und daher die Prüfungen herausoptimieren. Das ist durchaus ein möglicher Grund.

    Allgemein ist der häufige "Zugriff auf Klassenobjekte" nicht langsamer. Diese Abstraktionen sind in C++ eigentlich recht leichtgewichtig und es kann gut sein, dass deine ganzen img[r].at(c+1).get_red() etc. am Ende in einzelne CPU-Instuktionen zerfallen, die man auch so "von Hand" in Assembler geschrieben hätte. Sowas habe ich schon oft am erzeugten Maschinencode beobachtet, wenn man die Abstraktion möglichst schlank hält und es ist auch einer der Gründe, weshalb ich C++ besonders mag 😉

    "Klassen" werden eigentlich nur "langsam" wenn man den Blick auf das Wesentliche verliert und unnötige Arbeit macht (z.B. bereits geprüfte notwendige Vorbedingungen irgendwo in einem tieferen Funktionsaufruf nochmals prüft, ohne es zu merken) - wie in jeder Sprache. Virtuelle Funktionen haben auch einen geringen Overhead - wenn man sie nicht benötigt, sollte man sie auch nicht verwenden - genauso wie man in C nicht für alles eine Funktionspointer-Tabelle benötigt.

    Ansonsten ist die Funktion auf den ersten Blick auch gut "manuell optimierbar", es würde mich also nicht wundern wenn der Compiler da auch einiges reißen kann: Z.B. lassen sich die Berechnungen gut vektorisieren (als SIMD-Operationen formulieren - SSE2, AVX, etc) und einige If-Blöcke aus den Schleifen herausziehen, so dass nur einmal, und nicht für jedes Pixel geprüft werden muss:

    z.B. ließe sich

    unsigned short w = img[0].size();
    ...
    for (r=0; r<h; r++)
    {
        for (c=0; c<w; c++)
        {
            t0.red = img[r].at(c).get_red();
            ...
            if (c < w-1)
            {
                t1.red = img[r].at(c+1).get_red();
                ...
    

    auch in ein

    unsigned short w = img[0].size();
    ...
    for (r=0; r<h; r++)
    {
        for (c=0; c<w-1; c++)
        {
            t0.red = img[r].at(c).get_red();
            ...
            t1.red = img[r].at(c+1).get_red();
            ...
        }
        t0.red = img[r].at(c).get_red();
        ...
    

    transformieren. Dafür müsste man zwar in diesem Fall zunächst zwar den Schleifenkörper in großen Teilen duplizieren, würde aber ein Prüfung pro Pixel einsparen . Ob das wirklich Sinn macht weiß der Compiler oft ganz gut, macht man es "manuell" sollte man natürlich immer messen. Das nur um eine Idee zu bekommen, was da alles möglich ist.

    Finnegan



  • @mechanics sagte in yip: verschiedene Retrografik-Funktionen mit und ohne Optimizer:

    Mir ist schon klar, dass Swordfish zu Sarkasmus neigt.

    Das ist doch nebenbei auch völlig wurscht.
    Wenn ich in einem (fremden) Forum nach einer Antwort suche, dann hab ich bestimmt keine Lust, mir 100te von alten Antworten durchzulesen, um einschätzen zu können, ob der Beantworter wohl zu Sarkasmus neigt.

    Danke fürs richtig stellen.



  • Doppelte Geschwindigkeit mit -O2 vs -O0 ist bei Schleifen die zum Grossteil aus eigenem Code bzw. Aufruf von Template-Gedöns aus der Standardlibrary bestehen nicht weiter verwunderlich. Da muss man IMO nicht anfangen nachzuforschen wieso.



  • @hustbaer sagte in yip: verschiedene Retrografik-Funktionen mit und ohne Optimizer:

    Doppelte Geschwindigkeit mit -O2 vs -O0 ist bei Schleifen die zum Grossteil aus eigenem Code bzw. Aufruf von Template-Gedöns aus der Standardlibrary bestehen nicht weiter verwunderlich. Da muss man IMO nicht anfangen nachzuforschen wieso.

    Schaden tut es aber auch nicht. Solche Nachforschungen fördern sicher das Verständnis und Vertrauen in die Arbeit des Compilers. Erst wenn man sowas schon mal ergründet hat, "wundert" man sich beim zweiten mal nicht mehr. Dann ist man vielleicht auch eher in der Lage intuitiv effizienten Code zu schreiben, den der Compiler gut verdauen kann.

    Kommt drauf an, wo man sich gerade auf der Lernkurve befindet 😉


Anmelden zum Antworten