Prinzipiel: Fressen befehle wie z.B. glEnable, glRotate, glScale viel ressourcen, wenn sie 100 mal pro Frame aufgerufen werden? Beeinflusst es die performance wenn man diese befehle, wenn sie z.B. leer sind/keinen sichtbaren effekt habemn, in einem if-konstrukt auslagert und ausschliesst?
Beispiel: Die rotation ist 0,0,0; ebenso wie das offset. sämtliche dieser eigenschaften sind in variablen ausgelagert. Ich frage ab ob alles != 0 ist und nur falls eine der eigenschaften !=0 ist rufe ich auch die befehle Rotate,translate auf.
Je ein if vor einem Funktionsaufruf ist einer der Klassiker der Premature Optimization. Will heißen: Völliger Blödsinn
Funktionsaufrufe sind nicht teuer. Überhaupt nicht. In JIT-Sprachen merkt man sie quasi gar nicht, in nativen Sprachen sind sie in 99% der Fälle vernachlässigbar. Heißt bei deinen 100 Aufrufen also: Lass es bleiben (100 ist sowieso ne Zahl, da lacht jeder Computer drüber). Gute Compiler optimieren sowas sowieso weg, im Zweifelsfall solltest du Performance Bottlenecks sowieso mit einem Profiler aufspüren und dann beheben und nicht im Vorfeld a la "Oh... hm das kostet vielleicht ganz furchtbar viel. Machen wir mal ein if drum". Das macht den Code nur verdammt unlesbar und erhöht die Komplexität.
Außerdem, wer garantiert dir, dass der Treiber nicht bei glRotate3f(0, 0, 0) selbst ein if (x == 0, y == 0, z == 0) ... drin hat?
_________________ "Für kein Tier wird so viel gearbeitet wie für die Katz'."
Man kann viele glRotate, glScale-Aufrufe einsparen, wenn man eine eigene Mathelib (etwa CoolMath, siehe Projekteforum) benutzt. Das macht es einfacher Matrizen im voraus zu berechnen und zu speichern etc.
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Frase hat geschrieben:
Funktionsaufrufe sind nicht teuer. Überhaupt nicht. In JIT-Sprachen merkt man sie quasi gar nicht, in nativen Sprachen sind sie in 99% der Fälle vernachlässigbar. Heißt bei deinen 100 Aufrufen also: Lass es bleiben (100 ist sowieso ne Zahl, da lacht jeder Computer drüber). Gute Compiler optimieren sowas sowieso weg, ...
Die Aussage ist mit der heißen Nadel gestrickt und stimmt nicht ganz. Ja einfache call sind nicht gerade die teuersten ops, ja einige calls können von einer JIT optimiert werden und nun das ABER. Ein Funktionsaufruf besteht aus 0 bis n stack operationen, um alle parameter rein zu hämmern, je größe und modifiers sind diese von ziemlich billig bis die kostenintensivsten operationen die es gibt. Erst danach kommt der call, stack abbau, stack aufbau und dann noch der ret call, was nochmal teuer werden kann, wenn man nen ungünstiges return dabei hat. Was also Frase meint ist, ein bool GetValue()const; ist sehr günstig und im vergleich zu dingen wie string operationen, schlechten codepassagen die häufig durchlaufen werden zu vernachlässigen. Was man aber nicht mit z.B. MyClass DoSomething(MyOtherCLass val); verwechseln sollte, das würde in jeden Fall verdammt teuer werden und sollte man auch nicht 1mal aufrufen, denn hier werden Objekte erzeugt(OS API Calls und ein paar internal calls), durch Parameter werden diese auf den stack kopiert, dieser kann zu klein werden, dann kommen weitere OS API calls mit ins spiel um diesen zu vergrößern, bzw. die app schmiert aber oder hat nen bufferoverflow, dann kommen einige copies von der klasse, das sind wieder ne menge teuerer calls nur weil man ein paar modifier vergessen hat. MyClass* DoSomething(const MyOtherClass& val); wäre dann z.B. was ganz anderes, hier werden keine objekte onthefly erstellt, nur pointer wandern auf dem callstack rum, tonnenweise new, copy, delete calls werden gespart, const ist hier ein modifier der dem compiler weitere optimierungen erlaubt und dann gibt es noch so bei c++ inline welches wie bei jits einfach den code direkt an die stellen verfrachtet und die stack und call operationen weg optimiert. Was ich mal damit abschließe, es ist nicht die Anzahl der Funktionscalls sondern die Anzahl an cycle die die CPU für eine einzige braucht und die CPU's haben ne menge cycles pro sekunde zur verfügung.
Wie Frase anmerkte solltest du nicht an irgendwelchen stellen rum optimieren, sondern wirklich ein Profiler drüber laufen lassen und gucken was in deiner App ein Bottleneck ist und diese stellen optimieren. Bei OpenGL App's ist das etwas schwer, hier gibt es oft syncs zwischen cpu und gpu, die einfach zeit kosten und blocking sind, wie bei synchron IO und sockets. Braucht dein SwapBuffer die meiste Zeit, dann ist deine RenderPipeline zu voll gestopft mit calls und du solltest gucken ob du OpenGL calls zu batches verpacken kannst, alternative OpenGL Features nutzen um calls zu reduzieren. Sollte dies kein Effekt haben, dann ist die Füllrate oder der Vertice durchsatz dein Boottleneck und du musst gucken wie du die Komplexität vom Shading rezudiert bekommst, Overdraw vermeiden kannst und die zu verarbeitenden Triangle frühzeitig aus der Pipeline bekommst bzw. garnicht erst rein lässt.
Im Fall von Matrizen solltest du mal nach ner Mathe lib suchen oder eine selber schreiben, diese sind in 99% der fälle schneller, da die veralteten Matrix Funktionen nicht gut optimiert werden und sowieso auf cpu Seite laufen. Bei den Statebefehlen bist du leider recht Hilflos, wenn du nicht auf neuere Versionen von OpenGL gehst, einige kann man noch im alten Versionen optimieren wie z.B. die glBegin/glEnd durch VBO aber spätestens bei Texturen und lightning hast du ein Problem. Hier helfen nur noch Shader.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Ja, die Funktionsaufrufe kann man hier vernachlässigen, aber ich glaube nicht, dass die gemeint waren. Eher die Ausführung der Funktion (weil jedes Rotate Translate etc intern glUniform aufruft, soweit ich weiß jedenfalls). Aber in jedem Fall sollte hier die beste Lösung eine Mathelib sein.
bezüglich glEnable: also gerade da glaub ich schon, dass der bereits prüft, ob was gemacht werden muss. Immerhin ist´s in (naiv betrachtet) 50% der Fälle überflüssig.
Aus gar keiner. Aber irgendwie muss die neue Matrix ja an die Graphikkarte kommen hab ich mir mal gedacht. Und ob das jetzt intern glUniform aufruft oder das gleiche nochmal implementiert ist soweit ich weiß auch schon wurst. (Aber ja, es wird wahrscheinlich wenigstens geinlined sein, also wird wohl nicht wirklich was aufgerufen)
Im endeffekt ists aber nur eine Vermutung.
@ursprüngliche Frage: Außerdem wird wahrscheinlich diese geringe Datenmenge sowieso keine Auswirkungen auf die performance haben.
Warum? Es ist ja wohl klar das der Treiber die Matritzen irgendwie an die Grafikkarte geben muß.. ob das jetzt via glUniform oder auf irgendeinem anderen weg passiert ist doch völlig nebensächlich. Es wird auf irgendeine Art und weise übertragen, und diese Übertragung dauert eben gegebenenfalls auch länger als ein simpler funktionsaufruf.
Auch bei dingen wie glEnable/glDisable.. wenn man ständig z.B. GL_TEXTURE_2D enabled und wieder disabled wird auch dort jedesmal was an die Grafikkarte geschickt, so das es mehr ist als ein simpler funktionsaufruf.
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Wie intern die Matrix übergeben wird ist ne gute Frage und wird es auch bleiben, denn es ist Herstellerabhängig. Es geht auch nicht drum ob es glUniform oder ähnliches aufruft. glRotate nutzt die cpu und aufgrund von kompatibilität nutzt es reine fpu calls und keine extensions wie mmx,sse oder gar sse4.2 . Das ist der erste Performance Vorteil, der 2 ist dass der Treiber nie weiß, was effizient ist, du kannst immer effizienter die Matrizen übertragen, weil du weißt wann welche Objekte gleiche Matrizen haben, wann mehere matrizen operationen laufen oder draw calls mit der gleichen Matrix. Daher ist glLoadMatrix immer besser als glRotate, glLoadIdentity und co. Wenn du OpenGL3 und neuer verwendest hast du eh diese funktionen nicht mehr und musst auf Uniform um satteln. Spätestens hier wird es wirklich interessant, weil du mehrere Matrizen hoch laden kannst, instancing betreiben und somit die calls die teuren sync. calls reduzieren.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Also ich verstehe unter gefährlichem Halbwissen dinge die weit aus "gefährlicher" sind als sowas.
Wenn man hier bei dingen nichtmehr mit "Ich denke" oder "Meiner Meinung nach" antworten dürfte, würde es vermutlich kaum Antworten mehr geben. Für viele dinge gibt es eben keine "Es ist 100%ig so" Antwort.
Deiner Meinung nach wäre hier also die Antwort "Das weiß leider keiner, deswegen kann man nicht antworten auch wenn es Erfahrungswerte gibt, bzw es sehr wahrscheinlich ist das es so gelöst wird" besser gewesen??
Gut, sharkman hat sich eventuell unglücklich ausgedrückt und mit dem "soweit ich weiß jedenfalls" nicht klar genug zum ausdruck gebracht das es eine Vermutung ist, aber er hat auch nicht gesagt das es definitiv so ist.
Gefährliches Halbwissen ist für mich definitiv was anderes.
Registriert: So Sep 26, 2010 12:54 Beiträge: 238 Wohnort: wieder in Berlin
Programmiersprache: Englisch
Aya hat geschrieben:
Deiner Meinung nach wäre hier also die Antwort "Das weiß leider keiner, deswegen kann man nicht antworten auch wenn es Erfahrungswerte gibt, bzw es sehr wahrscheinlich ist das es so gelöst wird" besser gewesen??
Ein "Ich weiß nicht wie es funktioniert" wäre jedenfalls mehr Wert als sinnloses rumgestammel. Es sei denn man belegt seine Aussagen, durch tech paper oder Fachartikel. Ansonsten trägt es eher zur Verunsicherung bei.
Das verstehst Du hoffentlich. Mehr nicht.
Zuletzt geändert von phlegmatiker am Do Jun 09, 2011 16:21, insgesamt 1-mal geändert.
Registriert: Mo Sep 23, 2002 19:27 Beiträge: 5812
Programmiersprache: C++
Bitte bleibt beim Thema, sonst muss ich hier aufräumen
Fest steht aber dass "moderne" GPUs allesamt keine festverdrahtete TnL-Einheiten mehr haben wie sie z.b mit der ersten Geforce eingeführt wurden. Schon seit einigen Generationen werden die immediate Befehle (die es in GL 3.x mit passendem Kontext ja eh nicht mehr gibt) via Shader "emuliert". Wie genau das aussieht ist wie Tak schon sagte je nach Treiber/GPU/Hersteller unterschiedlich. Von 3DLabs gabs mal ein nettes Tool dass einen Shader erzeugen lies die die feste Funktionspipeline emulieren. Allerdings wird das intern sicher keine GPU so machen.
Was aber auch fest steht ist die Tatsache dass (wurde ja auch bereits gesagt) solche Befehle immer nen CPU-Overhead erzeugen. Also 1000x glRotate mit null Grad Rotationswinkel aufrufen erzeugt 1000x einen CPU-Overhead und (nicht zu vergessen) Traffic aufm Bus, und die Speicherbandbreite von CPU zu GPU ist ja relativ zur Speicherbandbreite GPU zu VRAM relativ langsam. Jetzt aber jedesmal zu prüfen ob der Winkel 0 ist verlagert die Limitierung hin zur GPU, auch nicht gut.
Also am besten direkt ne eigene Matrix erstellen und dann halt nur aktualisieren wenn nötig. Oder wenns der Fall erlaubt direkt im Shader rotieren. Was dort bleibt ist die Speicherbandbreite die durch die Übertragung der Daten verbraten wird. Das ist aber bei ner Matrix recht wenig, und die müsste man ja wenn sie z.b. in nem Shader genutzt wird eh jeden Frame übergeben.
Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.