PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Performance - sonderbar


Che
2003-01-20, 21:58:13
Mein PC macht komische Sachen: Ich habe einen Quadtree den ich rekursiv durchlaufe, das Programm macht ca. 6 FPS. Das wunderte mich weil ich bei demselben Programm OHNE den Quadtree auf 40 FPS kam. Hinzu kommt das der Quadtree jede Menge Vertices spart, ohne wird alles gezeichnet. Ich spiele also herum, und entferne den Zeichenteil aus dem Quadtree (d.h. er wird durchlaufen aber nichts wird gezeichnet) -> 40 FPS. Also füge ich in den Zeichenteil folgende Zeilen ein:

glBegin(GL_TRIANGLES);
glEnd();

-> 6 FPS.
Also schalte ich den Quadtree ganz ab und lasse eine testschleife laufen, in der 5000 mal glBegin()/glEnd() aufgerufen wird -> macht ihm gar nix. (Erst ab 50000 glBegin()/glEnd() macht sich ein Performanceunterschied bemerkbar)

Hier stimmt etwas nicht, ich vermute die Rekursion hat damit zu tun, weiß aber üverhaupt nicht wieso und warum. ???

Demirug
2003-01-20, 22:07:17
Schwer zu sagen was da schief läuft. Wobei glBegin und glEnd ja sowieso nicht gerade für Top-Performances bekannt sind.

Auf wie viele glBegin glEnd Paare kommst du den mit dem Quadtree?

Che
2003-01-20, 22:17:58
Originally posted by Demirug

Auf wie viele glBegin glEnd Paare kommst du den mit dem Quadtree?

Das ist ja das komische: Ich würde schätzen zwischen 500 und 2000. Bei der Schleife in der ich glBegin()end() durchlaufen gibts bei 5000 (!) noch keine (!) Performanceänderung. Mal testen ab wanns langsamer wird.

ethrandil
2003-01-20, 22:18:34
also, ich weiß es ja nicht, aber bei einer Rekursion werden doch im Speicher (stack ...) jedesmal eine kopie der Funktion angelegt ... was das Performancemäßig bedeutet, dass weiß ich nicht. ich denke das ist zu vernachlässigen ;)

Eth

Che
2003-01-20, 22:21:02
Nachtrag: ab 12000 Paaren wirds merkbar (ca. 10 FPS) langsamer.

Che
2003-01-20, 22:23:26
Originally posted by ethrandil
also, ich weiß es ja nicht, aber bei einer Rekursion werden doch im Speicher (stack ...) jedesmal eine kopie der Funktion angelegt ... was das Performancemäßig bedeutet, dass weiß ich nicht. ich denke das ist zu vernachlässigen ;)

Eth

Das komische ist ja dass wenn ich nur die Rekursion durchlaufen lasse aber nichts zeichne alles in Ordnung ist. Erst mit glBegin/end gibts Probleme.
Andere GL Befehle zb.

glActiveTextureARB(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, BaseTex.ID);

glActiveTextureARB(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, DetailTex.ID);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(32,32,32);
glMatrixMode(GL_MODELVIEW);

machen auch nichts.

Xmas
2003-01-20, 22:24:20
Originally posted by ethrandil
also, ich weiß es ja nicht, aber bei einer Rekursion werden doch im Speicher (stack ...) jedesmal eine kopie der Funktion angelegt ... was das Performancemäßig bedeutet, dass weiß ich nicht. ich denke das ist zu vernachlässigen ;)

Eth
Nicht die Funktion wird kopiert, sondern es wird bei jeden Funktionsaufruf auf dem Stack Speicherplatz für Funktionsparameter, lokale Variablen und die Rücksprungadresse benötigt.


Che, vielleicht wäre es sinnvoll wenn du etwas mehr Code von deinem Baum posten würdest.

Che
2003-01-20, 22:28:19
Zeichenfunktion:

int len = Tree[pos].len;
int len2 = len/2;

int UpLeft[2], LowLeft[2], UpRight[2], LowRight[2];

UpLeft[0] = Center[0] - len/4;
UpLeft[1] = Center[1] - len/4;

LowLeft[0] = Center[0] + len/4;
LowLeft[1] = Center[1] - len/4;

UpRight[0] = Center[0] - len/4;
UpRight[1] = Center[1] + len/4;

LowRight[0] = Center[0] + len/4;
LowRight[1] = Center[1] + len/4;


if(Tree[pos].refine)
{
RenderNode(UpLeft);
RenderNode(LowLeft);
RenderNode(UpRight);
RenderNode(LowRight);
}

//sonst node zeichnen, code spar ich mir hier

Demirug
2003-01-20, 22:31:57
Das erst die glBegin und glEnd zuschlagen ist nicht verwunderlich denn erst damit werden die vorhergehende Settings auch zu Karte geschickt.

Gerade der zeichencode für deinen node könnte aber das problem enthalten.

Che
2003-01-20, 22:44:33
if(Tree[pos].refine)
{
RenderNode(UpLeft);
RenderNode(LowLeft);
RenderNode(UpRight);
RenderNode(LowRight);
}
else
{
glActiveTextureARB(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, BaseTex.ID);

glActiveTextureARB(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, DetailTex.ID);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(32,32,32);
glMatrixMode(GL_MODELVIEW);

glBegin(GL_TRIANGLE_FAN);

glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos].TextureCoord);
glVertex3fv(Vertex[pos].VertexCoord);

//oben
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2*breite].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2*breite].TextureCoord);
glVertex3fv(Vertex[pos-len2*breite].VertexCoord);

//oben links
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2*breite-len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2*breite-len2].TextureCoord);
glVertex3fv(Vertex[pos-len2*breite-len2].VertexCoord);

//links
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2].TextureCoord);
glVertex3fv(Vertex[pos-len2].VertexCoord);

//unten links
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos+len2*breite-len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos+len2*breite-len2].TextureCoord);
glVertex3fv(Vertex[pos+len2*breite-len2].VertexCoord);

//unten
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos+len2*breite].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos+len2*breite].TextureCoord);
glVertex3fv(Vertex[pos+len2*breite].VertexCoord);

//unten rechts
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos+len2*breite+len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos+len2*breite+len2].TextureCoord);
glVertex3fv(Vertex[pos+len2*breite+len2].VertexCoord);

//rechts
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos+len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos+len2].TextureCoord);
glVertex3fv(Vertex[pos+len2].VertexCoord);

//oben rechts
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2*breite+len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2*breite+len2].TextureCoord);
glVertex3fv(Vertex[pos-len2*breite+len2].VertexCoord);

//Fan beenden (oben)
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2*breite].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2*breite].TextureCoord);
glVertex3fv(Vertex[pos-len2*breite].VertexCoord);

glEnd();

glActiveTextureARB(GL_TEXTURE0); //Umschalten auf 1. TMU
return;
}


pos ist der Mittelpunkt der Node
len ist die Länge/Breite der Node
len2 ist die Hälfte von len :)
breite ist die breite der gesamten karte

Che
2003-01-20, 22:54:28
Originally posted by Che

if(Tree[pos].refine)
{
RenderNode(UpLeft);
RenderNode(LowLeft);
RenderNode(UpRight);
RenderNode(LowRight);
}
else
{

glActiveTextureARB(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, BaseTex.ID);

glActiveTextureARB(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, DetailTex.ID);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(32,32,32);
glMatrixMode(GL_MODELVIEW);

glBegin(GL_TRIANGLE_FAN);

glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos].TextureCoord);
glVertex3fv(Vertex[pos].VertexCoord);

//oben
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2*breite].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2*breite].TextureCoord);
glVertex3fv(Vertex[pos-len2*breite].VertexCoord);

//oben links
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2*breite-len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2*breite-len2].TextureCoord);
glVertex3fv(Vertex[pos-len2*breite-len2].VertexCoord);

//links
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2].TextureCoord);
glVertex3fv(Vertex[pos-len2].VertexCoord);

//unten links
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos+len2*breite-len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos+len2*breite-len2].TextureCoord);
glVertex3fv(Vertex[pos+len2*breite-len2].VertexCoord);

//unten
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos+len2*breite].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos+len2*breite].TextureCoord);
glVertex3fv(Vertex[pos+len2*breite].VertexCoord);

//unten rechts
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos+len2*breite+len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos+len2*breite+len2].TextureCoord);
glVertex3fv(Vertex[pos+len2*breite+len2].VertexCoord);

//rechts
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos+len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos+len2].TextureCoord);
glVertex3fv(Vertex[pos+len2].VertexCoord);

//oben rechts
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2*breite+len2].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2*breite+len2].TextureCoord);
glVertex3fv(Vertex[pos-len2*breite+len2].VertexCoord);

//Fan beenden (oben)
glMultiTexCoord2fvARB(GL_TEXTURE0, Vertex[pos-len2*breite].TextureCoord);
glMultiTexCoord2fvARB(GL_TEXTURE1, Vertex[pos-len2*breite].TextureCoord);
glVertex3fv(Vertex[pos-len2*breite].VertexCoord);

glEnd();

glActiveTextureARB(GL_TEXTURE0); //Umschalten auf 1. TMU
return;
}


pos ist der Mittelpunkt der Node
len ist die Länge/Breite der Node
len2 ist die Hälfte von len :)
breite ist die breite der gesamten karte

Ich bin wirklich ein würstel! Wenn ich das bei jeder Node mach wunderts mich dass ich überhaupt noch 6 FPS krieg.

(Wie oft habe ich gelesen, dass glBindTexture() u.ä. teuer sind? WIE OFT?)

Wieder einmal einen großen Dank an alle die mir geholfen haben :)

Demirug
2003-01-20, 23:04:33
Wenn du jedesmal die gleiche Texturen benutzt sollte sich das gar nicht so heftig auswirken weil der Treiber so etwas erkennen und optimieren sollte.

Viel mehr Sorgen macht mir da dein Fan mit nur jeweils 10 Vertexdaten. Das ist Verschwendung von Leistung pur.

Schau dir doch mal bei NVIDIA die Dokumente zur OpenGL Performances an da gibt es viele gute Tips die sich auch auf andere Karten übertragen lassen.

Che
2003-01-20, 23:21:00
Originally posted by Demirug
Wenn du jedesmal die gleiche Texturen benutzt sollte sich das gar nicht so heftig auswirken weil der Treiber so etwas erkennen und optimieren sollte.



Meiner nicht :D Nein ernsthaft, später im Frame benutze ich noch andere. Anstatt die texturen für jedes Node zu laden, lade ich sie jetzt einmal bevor der Baum aufgerufen wird -> heißa, 90 FPS!
Originally posted by Demirug
Viel mehr Sorgen macht mir da dein Fan mit nur jeweils 10 Vertexdaten. Das ist Verschwendung von Leistung pur.


GL_TRIANGLE_FAN: 8 dreiecke -> 10 Vertices
GL_TRANGLE_STRIP: 8 dreiecke -> 12 Vertices
GL_TRANGLES: 8 dreiecke -> 24 Vertices

Ich weiß, ein Fan mit 10 Vertices ist nicht ideal, aber für meine Anforderungen die beste Lösung.

Originally posted by Demirug
Schau dir doch mal bei NVIDIA die Dokumente zur OpenGL Performances an da gibt es viele gute Tips die sich auch auf andere Karten übertragen lassen.


Danke, werd ich machen.

zeckensack
2003-01-21, 02:03:23
Mein Tip geht an die Sache mit der Texturmatrix.

Erstmal ist das Laden der Texturmatrix für jede Node überflüssig, weil du immer das gleiche machst (identity, scale(32,32,32)). Dann kann es sein, daß deine Grafikkarte Texturmatrizen nicht beschleunigt (->argh!).

Schritt 1:
Texturmatrix nur einmal laden, und dann den Baum durchrattern. Performance vergleichen.

Schritt 2:
Die Texturkoordinaten gleich beim Laden vorskalieren und die Texturmatrix überhaupt nicht anfassen. Performance vergleichen.

Che
2003-01-21, 11:06:01
Originally posted by zeckensack
Mein Tip geht an die Sache mit der Texturmatrix.

Schritt 1:
Texturmatrix nur einmal laden, und dann den Baum durchrattern. Performance vergleichen.



Alles was rot markiert ist (hier nochmal)

glActiveTextureARB(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, BaseTex.ID);

glActiveTextureARB(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, DetailTex.ID);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(32,32,32);
glMatrixMode(GL_MODELVIEW);

wird natürlich vor dem Baum aufgerufen (=1 mal pro Frame)
Originally posted by zeckensack
Schritt 2:
Die Texturkoordinaten gleich beim Laden vorskalieren und die Texturmatrix überhaupt nicht anfassen. Performance vergleichen.

Werd ich machen, danke

zeckensack
2003-01-23, 14:40:19
Originally posted by Che
Werd ich machen, danke Und? Besser? :flower:

Che
2003-01-23, 17:26:00
Originally posted by zeckensack
...überhaupt nicht anfassen.


Originally posted by zeckensack
Und? Besser? :flower:

Nö. 1 mal anfassen ist erlaubt... ;)