Optimieren, need help



  • Optimizer schrieb:

    ch habe assert neu definiert und assert erwartet nun einen bool!

    Dann schreib doch

    assert(m_buffer != 0)
    

    Das ist gar nicht mal noetig. Ein einfaches

    assert(m_buffer);
    

    reicht voellig aus, da der Zeiger automatisch in eine boolischen Wert konvertiert
    wird.

    mfg
    v R



  • neben den ganzen hässlich- und merkwürdigkeiten, die dein Programmierstil beinhält, ist das Hauptproblem für die Ineffizient die Verwendung von Schleifen und von byte (bzw. 2byte) weise Kopier vorgängen. Verwende memcpy oder so was, wenn es geht, da diese Funktion deutlich effizienter sein sollte, als jeder Schleife.

    Das wars, was ich auf den ersten Blick gesehen habe



  • virtuell Realisticer schrieb:

    Das ist gar nicht mal noetig. Ein einfaches

    assert(m_buffer);
    

    reicht voellig aus, da der Zeiger automatisch in eine boolischen Wert konvertiert
    wird.

    Jo, dachte ich eigentlich auch, das war auch mein erster Vorschlag. Irgendwie hat -------- dann gemeint, er hat es redefiniert und es frisst jetzt ein bool 😮 aha!?). Naja ich wollte des gar nicht so genau wissen, wieso und wie das assert redefiniert ist 🙄 .



  • Au weia, au weia, au weia. Ohne dir zu nahe treten zu wollen, aber der Code ist wirklich dreckig. Zur Performance komm ich nachher noch, aber erst mal Programmierstil allgemein - kapsel deinen verdammten Code. Du hast allein in dieser kleinen Funktion zig Stellen, an denen du den selben Code immer und immer wieder stehen hast. Du könntest die Code-Größe deutlich verringen (und auch ein bisschen speed rausholen), wenn du zum Beispiel erst auf clipping und danach auf transparente Pixel prüfst, denn so wie der Code im Moment aussieht, ist es dir, wenn clipping an ist, eh egal, ob du transparente Pixel hast. Jedenfalls ist der Code haargenau gleich. Und wenn ich das richtig sehe, ist der Code für nicht clipping und keine transparenten Pixel eigentlich auch genau der gleiche, nur dass du m_height und m_width fest gecodet hast, obwohl in diesem Fall srcBottom, srcTop usw. genau die entsprechenden Werte haben.

    Dann hast du einige völlig unnötige Zuweisungen - srcLeft und srcTop sind schon 0, das musst du ihnen nicht mehr zuweisen. Eigentlich kannst du srcRight und srcBottom auch gleich entsprechend initialisieren.

    Ansonsten - memcpy benutzen.

    Ohne das jetzt groß getestet zu haben (Ich hab im Moment keinen Compiler zur Hand, und den Rest deines Codes kenn ich ja auch nicht...), ich denke, das hier sollte das selbe tun wie deine Methode, und wenn nicht, sollte zumindest die Idee klar werden, so dass du was damit anfangen kannst.

    void CBitmap::drawNormal (int x, int y, unsigned short *dest)
    {
        assert (m_buffer);
    
        unsigned short *source = m_hasTransparentPixels ? m_rleBuffer : (m_buffer + srcLeft + srcTop * m_width);
    
        int srcLeft   = x < 0 ? -x : 0;
        int srcTop    = y < 0 ? -y : 0;
    
        dest += x + srcLeft + (y + srcTop) * g_screenWidth;
    
        if (m_hasTransparentPixels)
        {
            int realCount = 0;
            int index     = 0;
    
            for(int i = 0; i < m_height;) {
                if (!source [index]) {
                    ++index;
                    dest      += source[index];
                    realCount += source[index];
                    ++index;
                } else {
                    memcpy(dest, &source[index + 1], source[index] * sizeof(unsigned short));
    
                    realCount += source[index];
                    dest      += source[index];
                    index     += source[index] + 1;
                }
    
                if(realCount == m_width) {
                    realCount = 0;
                    dest += g_screenWidth - m_width;
                    ++i;
                }
            }
        } else {
            int srcRight  = x + m_width  > g_screenWidth  ? g_screenWidth  - x : m_width ;
            int srcBottom = y + m_height > g_screenHeight ? g_screenHeight - y : m_height;
    
            for (int i=srcTop; i<srcBottom; ++i) {
                memcpy(dest, src, (srcRight - srcLeft) * sizeof(unsigned short));
    
                source += m_width;
                dest   += g_screenWidth;
            }
        }
    }
    


  • Whoopsie, kleiner Fehler unterlaufen. also so:

    void CBitmap::drawNormal (int x, int y, unsigned short *dest)
    {
        assert (m_buffer);
    
        unsigned short *source = m_hasTransparentPixels ? m_rleBuffer : (m_buffer + srcLeft + srcTop * m_width);
    
        int srcLeft   = x < 0 ? -x : 0;
        int srcTop    = y < 0 ? -y : 0;
        int srcRight  = x + m_width  > g_screenWidth  ? g_screenWidth  - x : m_width ;
        int srcBottom = y + m_height > g_screenHeight ? g_screenHeight - y : m_height;
    
        int no_clipping = srcLeft | srcTop | srcRight | srcBottom;
    
        dest += x + srcLeft + (y + srcTop) * g_screenWidth;
    
        if (m_hasTransparentPixels && no_clipping)
        {
            int realCount = 0;
            int index     = 0;
    
            for(int i = 0; i < m_height;) {
                if (!source [index]) {
                    ++index;
                    dest      += source[index];
                    realCount += source[index];
                    ++index;
                } else {
                    memcpy(dest, &source[index + 1], source[index] * sizeof(unsigned short));
    
                    realCount += source[index];
                    dest      += source[index];
                    index     += source[index] + 1;
                }
    
                if(realCount == m_width) {
                    realCount = 0;
                    dest += g_screenWidth - m_width;
                    ++i;
                }
            }
        } else {
            for (int i=srcTop; i<srcBottom; ++i) {
                memcpy(dest, src, (srcRight - srcLeft) * sizeof(unsigned short));
    
                source += m_width;
                dest   += g_screenWidth;
            }
        }
    }
    


  • Wieso ich keinen namespace benutze und assert neu definiere und kein memcpy benutzen kann ist einfach: ich kann keine Standardlib benutzen? Wie denn auch wenn ich sie für meine Zwecke nicht mitlinken darf?

    @0xdeadbeef
    danke.

    @otze
    nur weil ich m_ und g_ benutze heißt das das ich die ganze Ungarische Notation benutze? Nö. nur 2 sachen die sich für mich persönlich durchgesetzt haben! Merk dir: es gibt nicht immer nur schwarz und weis sondern auch graustufen.



  • achja zum assert:
    CBitmap.cpp(244) : warning C4800: 'unsigned short *' : forcing value to bool 'true' or 'false' (performance warning)



  • ------------ schrieb:

    achja zum assert:
    CBitmap.cpp(244) : warning C4800: 'unsigned short *' : forcing value to bool 'true' or 'false' (performance warning)

    ja, die warnung stört. ich hab mir für den msvc ein eigenes idiom ausgedacht, was nur diese warnung auszumachen hat.

    assert(!!m_buffer);
    

    bei m_buffer?true:false muss ich erst genau lesen, was passert. das !! ist als ein symbol erkennbar. und assert(bool(m_buffer)) macht die warnung nicht aus.



  • Man könnte natürlich auch die Zeiger einfach auf 0 testen... dürfte den selben Code generieren wie assert(pointer), IMHO. Bedeutet also das selbe und ist auch noch klarer, wie ich finde.



  • Optimizer schrieb:

    Man könnte natürlich auch die Zeiger einfach auf 0 testen... dürfte den selben Code generieren wie assert(pointer), IMHO. Bedeutet also das selbe und ist auch noch klarer, wie ich finde.

    nee.
    ich frage mit assert(pdata), ob der zeiger gültig ist. mit assert(pdata!=0) frage ich bloß, ob er gleich 0 ist (und nach sekundenlanger überlegung komme ich bestimmt drauf, daß das aussagt, ob er gültig ist). das ist für mich ein großer unterschied, auch wenn hume gleich andeuten wird, daß ich immer aus ner mücke nen elefanten mache.



  • Ich bin von Java verdorben und bevorzuge daher, explizit den Vergleich mit 0 hinzuschreiben. Naja auch net wild, solang mans lesen kann...
    Mach nicht immer aus ner Mücke nen Elefanten. 😉 🤡

    Willkommen Newbie

    Auf diese Seite zu kommen ist wahrscheinlich die erste kluge Entscheidung von dir. Hier lernst
    du alles was du brauchst um dir selbstständig Information mit Google zu besorgen. In diesem
    Tutorial wird beschrieben, wie du einen C++ Kurs mit Google finden kannst.

    Ich krieg mich nicht mehr. 😃



  • ------------- schrieb:

    Wieso ich keinen namespace benutze und assert neu definiere und kein memcpy benutzen kann ist einfach: ich kann keine Standardlib benutzen? Wie denn auch wenn ich sie für meine Zwecke nicht mitlinken darf?

    also ich musste noch nie etwas mitlinken, um namespaces benutzen zu können...hmmm liegts vielleicht daran, dass "namespace" ein normales c++ schlüsselwort wie "int" oder "class" ist? :p

    und wieso zum geier willst du die stl nicht benutzen? die ist doch eigentlich das, was c++ ausmacht

    @otze
    nur weil ich m_ und g_ benutze heißt das das ich die ganze Ungarische Notation benutze? Nö. nur 2 sachen die sich für mich persönlich durchgesetzt haben! Merk dir: es gibt nicht immer nur schwarz und weis sondern auch graustufen.

    und alle diese graustufen sind absolut häßlich 🙄. schon allein die unterstriche sind ne sünde und urhäßlich, aber sie dann auch noch als präfix trenner zu mißbrauchen....tzz 👎



  • otze schrieb:

    und wieso zum geier willst du die stl nicht benutzen? die ist doch eigentlich das, was c++ ausmacht

    falsch.

    und assert muß man umdefinieren, weil das alte assert keine destruktoren aufruft.



  • hmm gehört die stl nicht mehr zum standard?
    und beschreibt der standard nicht mehr, was für inhalte die sprache haben muss?



  • Die STL gehört zum Standard, aber was die Sprache ausmacht, sind eher ihre Paradigmen - im Fall von C++ vor allem das generische und das objektorientierte Paradigma.



  • dann formuliere ich es um "ohne die STL verliert man den großteil der funktionalität von C++"

    🙄



  • ------------- schrieb:

    nur weil ich m_ und g_ benutze heißt das das ich die ganze Ungarische Notation benutze? Nö. nur 2 sachen die sich für mich persönlich durchgesetzt haben! Merk dir: es gibt nicht immer nur schwarz und weis sondern auch graustufen.

    g für globale variablen? erklärt uns bitte noch mehr über guten stil. das müssen alle lernen.



  • otze schrieb:

    dann formuliere ich es um "ohne die STL verliert man den großteil der funktionalität von C++"

    ohne die sl verliert man den großteil der funktionalität der stl.
    ich schreibe oft saenstrukturen selber.
    wie lange braucht es, ne string-klasse zu schreiben? bloß minuten doch.
    und nen doppelt vberketteten ring kaum läner.
    die verketten datenstrukturen werden gerne intrusiv, naja, man will ja top speed.
    wie lange dauert's nen heap zu bauen? steht ja beim sedgewck deutlich genug da.
    und dann noch nen stack und ne queue.
    ein array und einm vector.
    das war's doch auch schon in sachen datenstrukturen.
    bei den algos ist nch sort manchmal nett. rest ist trivial.
    also wirklich absolut nix, auf das man ganz dringend angewiesen wäre.
    also wenn man keinen bock hat, sich was selber zu schreiben und vor allem, wenn man zu doff dazu ist, lebt c++ von der stl. wenn einem so einfache sachen aber endlich auch einfach von der hand gehen, empfindet man große teile der stl eher als ballast, der alle nubes von der echten welt abschneidet. den spaß, eine genau angemessene datenstruktur zu haben, werden sie nie erleben. und bei diesem hype um die stl scheint es, als sei ich der letze, der das je erlebt hat.



  • Ich für meinen Teil möchte möglichst schnell möglichst sauberen Code bauen, und wenn ich mich jedesmal hinsetze und eine neue Listenklasse hinschlure, wird das nichts. Wenn die einfache Liste für meine Zwecke mal wirklich nicht ausreichen sollte, kann ich immer noch davon ableiten und ein paar Methoden drancoden, was den riesigen Vorteil hat, dass das Ding nachher noch kompatibel zu den Standard-Algorithmen ist - und zur Hälfte meines sonstigen Codes,

    Mal ganz ehrlich - wenn du selbst eben mal ne String-Klasse hinschlurst, wird die weder bugfreier noch stabiler noch schneller als die gängigen STL-Implementierungen sein, und wenn du das in ein paar Minuten schaffst, kümmerst du dich höchstvermutlich nicht um die Konzepte kümmern, die für eine generische Sprache wie C++ so unglaublich wichtig und praktisch sind.

    Ganz abgesehen davon vergisst du einige der komplizierteren Dinge der STL - set, map, bit_vector - ich möchte sehen, wie du nen RB-Baum in 5 Minuten zusammenschraubst. Dazu kommen Iteratoren, Streams und so weiter und so weiter. Zugegeben, die STL stellt nur recht grundsätzliche Funktionalität zur Verfügung, aber dafür ist sie auch da. Wenn du gerne irgendwelche Anfängerübungen wieder und wieder neu machst, meinetwegen, aber ich für meinen Teil will in der Zeit was gebacken kriegen.



  • ich möchte sehen, wie du nen RB-Baum in 5 Minuten zusammenschraubst

    Das traue ich volkard durchaus zu ;).

    mfg
    v R


Anmelden zum Antworten