Sollte man Optimierung für bestimmte seltene Fälle einbauen?



  • volkard schrieb:

    zzzzzzz schrieb:

    bla

    die überlegung dauert hier keine zehn sekunden. da muß man sich nicht mit solcher gewalt dagegen wehren.

    Nein volkard. premature optimization is the root of all evil. Immer, ausnahmslos. Merk dir das endlich!!! 😡 😡 😡 👎 👎



  • Also bei uhsuhz hats deutlich länger gebraucht. Und in größeren Projekten hast du tausende Funktionen und viele mit komplexeren Problemen als diesen. Da kommen dann schnell ein ein paar Tage "über Befehle optimieren" nachdenken raus. Die steckst du besser in "über Design und Algorithmen" nachdenken rein.



  • Tim schrieb:

    volkard schrieb:

    zzzzzzz schrieb:

    bla

    die überlegung dauert hier keine zehn sekunden. da muß man sich nicht mit solcher gewalt dagegen wehren.

    Nein volkard. premature optimization is the root of all evil. Immer, ausnahmslos. Merk dir das endlich!!! 😡 😡 😡 👎 👎

    premature mikrooptimization würd ich sagen.



  • Tim schrieb:

    Immer, ausnahmslos. Merk dir das endlich!!! 😡 😡 😡 👎 👎

    zu späte optimierung hat aber auch schon so manches projekt zerstört. 😃



  • volkard schrieb:

    Tim schrieb:

    Immer, ausnahmslos. Merk dir das endlich!!! 😡 😡 😡 👎 👎

    zu späte optimierung hat aber auch schon so manches projekt zerstört. 😃

    sicher nicht so oft wie zu fruehe 🙄



  • nun ja meine Funktionen sind ja eigentlich bereits alle fertig, algorithmen implementiert und fehler rausgenommen 🙂
    damit müsste ich ja jetzt ans optimieren kommen oder?



  • raps schrieb:

    zu späte optimierung hat aber auch schon so manches projekt zerstört. 😃

    sicher nicht so oft wie zu fruehe 🙄[/quote]
    stimmt. deswegen soll man ja auch einerseits (vor allem sehr frühe) optimierung meiden, andererseits aber die effizienz insgesamt nie aus dem auge verlieren.



  • uhsuhz schrieb:

    nun ja meine Funktionen sind ja eigentlich bereits alle fertig, algorithmen implementiert und fehler rausgenommen 🙂
    damit müsste ich ja jetzt ans optimieren kommen oder?

    keine ahnung. ist denn an der klasse irgendwas, was danach riecht, optimiert werden zu wollen. ich rieche nichts. 😋



  • volkard schrieb:

    raps schrieb:

    zu späte optimierung hat aber auch schon so manches projekt zerstört. 😃

    sicher nicht so oft wie zu fruehe 🙄

    stimmt. deswegen soll man ja auch einerseits (vor allem sehr frühe) optimierung meiden, andererseits aber die effizienz insgesamt nie aus dem auge verlieren.

    ich muss bei der planung fuer die optimierungen genau wie fuer cleanup eine zeiteinschaetzung abgeben.
    von daher sehe ich das problem von 'zu spaet' nicht wirklich. von 'zu frueh' seh ich aber fast immer, denn optimierungen sind am effektivsten, wenn man den fall kennt fuer den man optimiert und der ist am ende erst bekannt (also verifizierbar).

    uhsuhz schrieb:

    nun ja meine Funktionen sind ja eigentlich bereits alle fertig, algorithmen implementiert und fehler rausgenommen 🙂
    damit müsste ich ja jetzt ans optimieren kommen oder?

    fast, hast du einen guten test case? profile ihn, je besser deine profiling daten sind, desto besser wird dein optimierungsergebnis.
    und wie du vielleicht an meinem beispiel von seite 1 siehst, kostet ein if das nie anschlaegt in einer mathematisch aufwendigen situation auf phenom/intel core2 cpus garnichts. es sind ganz andere einheiten die das abarbeiten.... aber auch hier solltest du das mit einem profiler pruefen.

    ich weiss nicht, ob das hier nicht zuviel des guten ist, aber ich hatte das vor ein paar tagen gelesen und fand es ziemlich unterhaltend

    http://www.ddj.com/hpc-high-performance-computing/217200602?pgno=3 schrieb:

    Many years ago, I got a call from a guy I had once worked for. He wanted me to do some consulting work to help speed up his new company's software. I asked him what kind of software it was, and he told me it was image processing software, and that the problem lay in the convolution filter, running on a Sparc processor. I told him I didn't know anything about either convolution filters or Sparcs, so I didn't think I could be of much help. But he was persistent, so I finally agreed to take a shot at it.

    He put me in touch with the engineer who was working on the software, who immediately informed me that the problem was that the convolution filter involved a great many integer multiplies, which the Sparc did very slowly because, at the time, it didn't have a hardware integer multiply instruction. Instead, it had a partial product instruction, which had to be executed for each significant bit in the multiplier. In compiled code, this was implemented by calling a library routine that looped through the multiplier bits, and that routine was where all the time was going.

    I suggested unrolling that loop into a series of partial product instructions, and jumping into the unrolled loop at the right point to do as many partial products as there were significant bits, thereby eliminating all the loop overhead. However, there was still the question of whether to make the pixel value or the convolution kernel value the multiplier. The smaller the multiplier, the fewer partial products would be needed, so we wanted to pick whichever of the two was smaller on average.

    When I asked which was smaller, though, the engineer said there was no difference. When I persisted, he said they were random. When I said that I doubted they were random (since randomness is actually hard to come by), he grumbled. I don't know why he was reluctant to get me that information -- I guess he thought it was a waste of time -- but he finally agreed to gather the data and call me back.

    He didn't call me back that day, though. And he didn't call me back the next day. When he hadn't called me back the third day, I figured I might as well get it over with and called him. He answered the phone and, when I identified myself, he said, "Oh, Hi. I'm just standing here with my managers, watching. We're all really happy."

    When I asked what exactly he was happy about, he replied, "Well, when I looked at the data, it turned out 90% of the values in the convolution kernel were zero, so I just put an if-not-zero around the multiply, and now the whole program runs three times faster!"



  • raps schrieb:

    von daher sehe ich das problem von 'zu spaet' nicht wirklich.

    aber du kannst dir schon vorstellen, daß man software so baut, daß man von anfang an überhaupt keinen wert auf performance legt und man am ende sehr unzufrieden ist und daß man dann doch optimiert und beim optimieren das tolle design total zerstört und das gibt dann häßliche unwartbare frickelsoftware.



  • Was lässt sich mit 1 und -1 denn verkürzen?



  • volkard schrieb:

    raps schrieb:

    von daher sehe ich das problem von 'zu spaet' nicht wirklich.

    aber du kannst dir schon vorstellen, daß man software so baut, daß man von anfang an überhaupt keinen wert auf performance legt und man am ende sehr unzufrieden ist und daß man dann doch optimiert und beim optimieren das tolle design total zerstört und das gibt dann häßliche unwartbare frickelsoftware.

    Ebenso sollte er sich vorstellen können, dass man software bauen muss wo (zumindest teilweise) schon zu Beginn offensichtlich ist wo viel Rechenzeit liegenbleiben wird. Und wenn man sich den anderen verallgemeindernden Spruch "make it work, make it right, make it fast" anschaut: Oft steht man vor dem Problem, dass man "make it fast" braucht um "make it work" zu bekommen.

    Der Dumme schrieb:

    Was lässt sich mit 1 und -1 denn verkürzen?

    x mul (a, b)
        if a=1
            x = b
        elif a=-1
            x = b.togglesign()
        elif a=0
            x = 0
        else (allgemeiner Fall)
            x = a*b
    


  • Warum nicht einfach ein Template und das für diese drei Fälle spezialisieren. Da kann man nichts im Projekt zerstören und hat maximale Performance?!

    MfG SideWinder



  • SideWinder schrieb:

    Warum nicht einfach ein Template und das für diese drei Fälle spezialisieren. Da kann man nichts im Projekt zerstören und hat maximale Performance?!

    MfG SideWinder

    weil templates fuer statische dinge sind, wenn der template parameter bekannt ist, kannst du auch einfach eine konstante zuweisen. ich glaube es geht darum zur laufzeit anhand von variablen parametern zu entscheiden wie vorzugehen ist.



  • volkard schrieb:

    raps schrieb:

    von daher sehe ich das problem von 'zu spaet' nicht wirklich.

    aber du kannst dir schon vorstellen, daß man software so baut, daß man von anfang an überhaupt keinen wert auf performance legt und man am ende sehr unzufrieden ist und daß man dann doch optimiert und beim optimieren das tolle design total zerstört und das gibt dann häßliche unwartbare frickelsoftware.

    klar, wenn man etwas optimiert, wird der code meistens 'weniger schoen', deswegen sollte man das auch am ende machen. dann wird naemlich 99% vom code generisch und einfach lesbar bleiben, waehrend der kritische vermutlich uglyfied wird fuer die performance.
    das problem ist, wenn man ueberall optimierungen blind einbaut (blind weil man garnicht gemessen hat, ob und was es bringt), dann weiss man nicht, ob man nicht sogar kontraproduktiv war, weil selbst die logischte theoretische annahme in der praxis das gegenteil bewirken kann. dafuer hat man aber ueberall schlechter zu lesenen code.
    damit sage ich nicht, dass diese eine abfrage in diesem fall hier dramatisch ist, aber man sollte den leuten die sich soeine frage stellen muessen beibringen keine premature optimizations zu machen.

    gestern beim optimieren hab ich folgenden lustigen code geschrieben

    //#define	V_OrOdd(X,Y) si_or(X,Y)
    #define	V_OrOdd(X,Y) si_shufb(Y,Y,*reinterpret_cast<qword*>(&reinterpret_cast<uint8*>(qOrSelect)[si_to_int(si_rotqbii(si_gb(X),4))]))
    

    damit hab ich auf einer SPU ein OR auf der odd pipe simuliert, der standartbefehl laeuft auf der even pipeline. dadurch dass ich die even pipeline 100% ausnutze und nur 10% der odd, konnte ich laut statischem code analyser den load besser verteilen. hab 16 OR gespart und nun eine 100:70 auslastung (effektiv also 16cycles im inner loop schneller).
    feierabend, oder? 🙂
    beim profilen war dann dieser schnellere code langsammer, der simulator hat dann ergeben, dass die 1kb mehr code und das lesen von qOrSelect zwar wirklich schneller sind, aber dadurch den DMA-transfer mehr blockieren der parallel ablaeuft und deswegen die gesammtperformance weniger ist.

    den grossteil meiner arbeit optimiere ich, und ich weiss dass ich einem profiler mehr vertraue als mir



  • rapso schrieb:

    #define V_OrOdd(X,Y) si_shufb(Y,Y,*reinterpret_cast<qword*>(&reinterpret_cast<uint8*>(qOrSelect)[si_to_int(si_rotqbii(si_gb(X),4))]))

    damit hättest du 'ne gute chance bei einem obfuscated C contest. allein schon die benamung ist grossartig, si_rotqbii und so.
    🙂



  • +fricky schrieb:

    rapso schrieb:

    #define V_OrOdd(X,Y) si_shufb(Y,Y,*reinterpret_cast<qword*>(&reinterpret_cast<uint8*>(qOrSelect)[si_to_int(si_rotqbii(si_gb(X),4))]))

    damit hättest du 'ne gute chance bei einem obfuscated C contest. allein schon die benamung ist grossartig, si_rotqbii und so.
    🙂

    hat mich auch ne zeit gekostet rauszufinden weshalb er bei si_rotqbi den immediate nicht will, bis ich rausfand dass es si_rotqbi und si_rotqbii gibt *hehe*.

    ist aber standard spu assemlber (bzw die instrinsics die lediglich si_ davor haben), siehe http://www.scribd.com/doc/2978344/SPU-Instruction-Cheat-Sheet-Insomniac-Games 😉



  • rapso schrieb:

    klar, wenn man etwas optimiert, wird der code meistens 'weniger schoen', deswegen sollte man das auch am ende machen. dann wird naemlich 99% vom code generisch und einfach lesbar bleiben, waehrend der kritische vermutlich uglyfied wird fuer die performance.

    nicht nur das. wenn du's zu weit treibst, handelste dir abhängigkeiten ein, so dass deine optimierungen mit der nächsten prozessorgeneration, irgeneiner unscheinbaren hardwareänderung oder mit 'nem compiler-update, alle nicht mehr da sind.

    rapso schrieb:

    hat mich auch ne zeit gekostet rauszufinden weshalb er bei si_rotqbi den immediate nicht will, bis ich rausfand dass es si_rotqbi und si_rotqbii gibt *hehe*.
    ist aber standard spu assemlber (bzw die instrinsics die lediglich si_ davor haben)

    ja, ich finds ja auch doof dass prozessorenhersteller den befehlen keine sprechenden namen geben, sondern auf bis zur unkenntlichkeit verstümmelte kürzel stehen.
    🙂



  • +fricky schrieb:

    ja, ich finds ja auch doof dass prozessorenhersteller den befehlen keine sprechenden namen geben, sondern auf bis zur unkenntlichkeit verstümmelte kürzel stehen.
    🙂

    ah, naja, sobald man sich dran gewoehnt hat, ist es schoen. der spu assembler folgt wenigstens einer konsistenten namenskonvention, sodass man sich viele befehle denken kann.
    an sich ist spu assembler der schoenste den ich bisher sah, alles ist grundsaetzlich vektorisiert und viele dinge gibt es entweder in einen befehl (z.b. static_cast<int>(clamp(v,0.f,1.f)*INT_RANGE) was sonst 4 bis 8 instruktionen waere, ist si_cfltu) oder es gibt befehle die auf die beiden pipelines verteilt werden koennen, z.b. fuer reciproc hast du einen estimate auf der odd pipeline und interpolate (naehrung) auf der even pipeline, womit du effektiv nur 7cycles auskommst fuer 4gleichzeitig.



  • volkard schrieb:

    aber du kannst dir schon vorstellen, daß man software so baut, daß man von anfang an überhaupt keinen wert auf performance legt und man am ende sehr unzufrieden ist und daß man dann doch optimiert und beim optimieren das tolle design total zerstört und das gibt dann häßliche unwartbare frickelsoftware.

    Es gibt etliche Punkte, an denen man sich von vorneherein bessere oder schlechtere Karten verschafft und die zu selten ins Bewußtsein der Programmierer gerückt zu sein scheinen, weil die normalerweise an einem schnellen PC sitzen, da fällt's lange nicht auf, wenn Rechenzeit sinnlos verbrunzt wird. Natürlich gibt es weitere Aspekte, aber ich möchte das nur exemplarisch anreißen.

    1. Systemdesign nach Umgebung
    In Anbetracht der Targetplattform(en) muß eine grundlegende Strategie unter Berücksichtigung auch der Performance gefunden werden. Also, wenn ich eine API bedienen muß, die Hyperthreading anbietet, suche ich nach parallelisierbaren oder gänzlich unabhängigen Jobs, was sich als Ansatz eher verbietet, wenn einem ein nackter 8-Bit µC als Target ohne OS und Framework unterkommt. Wahrscheinlich werde ich auf dem PC nicht die optimale Strategie für den Ansatz finden, da ich eher auf den kleinen Kisten unterwegs bin; umgedreht bekomme ich immer wieder "gestückeltes" Polling zu sehen, das nur dann funktioniert, wenn die Plattform schnell im Vergleich zur Aufgabe ist. Haarsträubendes Zeug, das auch nur jemand einfallen kann, der glaubt, daß unter 16 Bit getrommelt werden muß.

    2. Summe der kleinen Sünden
    Immer wieder nervend sind die Sachen, bei denen Mehrfachberechnungen immer des Gleichen angestoßen werden, weil Leute statt Zwischenergebnisse zu verwenden zweimal das Gleiche hinpinseln, frei nach dem Motto "soll sich der Compiler doch drum kümmern". Also z.B. e1 = a/b*c mit e2 = a/b*d. In der Tat, ein paar erkennen das und führen a/b nur einmal aus, aber bei einem for (i = 0; i <= strlen(searchstring); i++) kann auch der beste Optimierer nichts mehr machen. Auf dem PC fällt das erst ins Gewicht, wenn man wirklich große Datenmengen zu bearbeiten hat, ein Controller, der von 'ner Solarzelle, einem Goldcap und einem Uhrenquarz leben muß, kann sich so einen hirnlosen Luxus nicht leisten - Profiler gibt's dort auch eher selten. Derlei Beispiele gibt es übrigens noch viele mehr, wie mit ein bisserl Hirn viel Rechnerei zu sparen ist.

    Beides muß im Vorfeld und bei der Erstellung präsent sein, um nicht in eine Performance- Falle zu tappen, hat aber eigentlich nichts mit Optimierung zu tun.

    An Tims 0/1/-1 Beispiel sieht man deutlich, daß es was bringen kann, wenn z.B. ein Hardwaremultiplizierer fehlt. Die nötige Gegenfrage lautet, wie sehr die Vergleiche weh tun und führt uns zu der Antwort, daß wir keine Antwort darauf haben, solange wir die typische Betriebssituation nicht kennen. Und wenn man Denke auf etwas verschwendet, von dem man nicht weiß, ob es überhaupt was bringt, dann ist das der klassische Fall von "premature optimization".

    Ein sauberes Systemdesign und das "Performancekeeper- Bing" im Hinterkopf sind wichtiger, als sich im Vorfeld über sowas einen Kopf zu machen.


Anmelden zum Antworten