Performance Frage
Übersicht

![]() |
FirstdeathmakerBetreff: Performance Frage |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi,
Es geht hauptsächlich um die Zeile 88 und 107ff. Wenn man bei Zeile 88 ein sqr vor den Ausdruck auf der rechten Seite setzt, dann wird meine Quicksort-Funktion extrem langsamer (Wenn man es startet, sieht man jeweils die Zeit für einen Aufruf der Funktion TQuicksort_sort()). Das seltsame ist jetzt aber, das die Berechnung aus Zeile 88 garnicht im Aufruf von TQuicksort_sort() geschieht, sondern vorher. Eigentlich dürfte sich das also garnicht auf die Geschwindigkeit der Funktion auswirken. Hat jmd eine Idee weshalb es das trotzdem tut? Test.bb Code: [AUSKLAPPEN] Include "Includes\Spannbaum.bb"
Include "Includes\QuicksortQueue.bb" TNode_InitAll() For i=0 To 100 TConnection_InitAll() For c.TConnection = Each TConnection Delete c Next Next ;TConnection_CreateSpanningTree(First TNode) WaitKey() End Includes\Spannbaum.bb Code: [AUSKLAPPEN] Const NODES%=100 Global NODES_XDIST# = 100 / 2 Global NODES_YDIST# = 100 / 2 Global NODES_ZDIST# = 100 / 2 Global CurrentConnections_counter% = 0 Dim CurrentConnectionsArray.TConnection(NODES-1) Dim NODE_ARRAY.TNode(NODES) Type TNode Field id% Field entity% Field pos#[3] Field connected% End Type Function TNode_getDistanceBetween(n1.TNode,n2.TNode) Return Sqr(n1\pos[0]-n2\pos[0])*(n1\pos[0]-n2\pos[0])+(n1\pos[1]-n2\pos[1])*(n1\pos[1]-n2\pos[1])+(n1\pos[2]-n2\pos[2])*(n1\pos[2]-n2\pos[2]) End Function Type TConnection Field node.TNode[2] Field dist# Field valid% Field entity% End Type Global CONNECTIONS% = TConnection_calcConnCount%() Dim CONNECTION_ARRAY.TConnection(CONNECTIONS) Function TConnection_calcConnCount%() Return (NODES*(NODES+1)/2) - NODES; See http://de.wikipedia.org/wiki/Der_kleine_Gau%C3%9F End Function Function minInt(c1%,c2%) If c1<=c2 Return c1 Return c2 End Function Function maxInt(c1%,c2%) If c1>=c2 Return c1 Return c2 End Function Function TConnection_getConnection.TConnection(n1%,n2%) If n1=n2 Return Null Return CONNECTION_ARRAY(TConnection_getArrayPos(n1,n2)) End Function Function TConnection_getArrayPos%(n1%,n2%) Local na% = minInt(n1,n2) Local nb% = maxInt(n1,n2) Local pos% = 0 For i% = 1 To na pos = pos + Sgn((na-i)) * (NODES - i) Next pos = pos + (nb-na) - 1 Return pos End Function Function TConnection_getConnectionTest() For i% = 5000 To 5005 Local c2.TConnection = TConnection_getConnection((i/1000)+1,(i Mod 1000)+1) If c2<>Null Print ((i/1000)+1)+"/"+((i Mod 1000)+1) + " = "+c2\node[0]\id + "/"+c2\node[1]\id EndIf Next End Function Function TNode_InitAll() DebugLog "Init Nodes" For i% = 1 To NODES Local n.TNode = New TNode n\id = i n\pos[0] = Rnd(-NODES_XDIST,NODES_XDIST) n\pos[1] = Rnd(-NODES_YDIST,NODES_YDIST) n\pos[2] = Rnd(-NODES_ZDIST,NODES_ZDIST) NODE_ARRAY(i-1) = n Next End Function Function TConnection_Create.TConnection(n1.TNode,n2.TNode) Local c.TConnection = New TConnection c\node[0] = n1 c\node[1] = n2 ;c\dist = TNode_getDistanceBetween(n1,n2) c\dist = (n1\pos[0]-n2\pos[0])*(n1\pos[0]-n2\pos[0])+(n1\pos[1]-n2\pos[1])*(n1\pos[1]-n2\pos[1])+(n1\pos[2]-n2\pos[2])*(n1\pos[2]-n2\pos[2]) Return c End Function Function TConnection_InitAll() DebugLog "Init Connections" Local stmp% = NODES-1 Local c% = 0 TQuicksort_Clear() For i1% = 0 To stmp For i2% = i1 To stmp If i1<>i2 CONNECTION_ARRAY(c) = TConnection_Create(NODE_ARRAY(i1),NODE_ARRAY(i2)) TQuicksortLink_create.TQuicksortLink(CONNECTION_ARRAY(c)\dist,Handle(CONNECTION_ARRAY(c))) c = c + 1 EndIf Next Next DebugLog "sorting connections: ..." Local time% = MilliSecs() TQuicksort_sort() DebugLog "sorting connections: finished within "+(MilliSecs()-time)+" ms" End Function Function TConnection_CreateSpanningTree(startNode.TNode) DebugLog "Reset" CurrentConnections_counter = 0 For n.TNode = Each TNode n\connected = False Next For c.TConnection = Each TConnection c\valid = False Next DebugLog "calculating min spanning tree" startNode\connected = True For i% = 1 To NODES TConnection_CreateSpanningTree_Sub() Next DebugLog "cleaning up" ;For qsl.TQuicksortLink = Each TQuicksortLink ; Local c.TConnection = Object.TConnection(qsl\objHandle) ; If c\node[0]\connected And c\node[1]\connected ; Local pos% = TConnection_getArrayPos%(c\node[0]\id,c\node[1]\id) ; If CONNECTION_ARRAY(pos)<>Null Delete CONNECTION_ARRAY(pos) ; CONNECTION_ARRAY(pos) = Null ; EndIf ;Next TQuickSort_clear() DebugLog "finished calc spanning tree" For i% = 0 To NODES-1 c.TConnection = CurrentConnectionsArray(i) If c<>Null DebugLog "c "+c\node[0]\id+" <--> "+c\node[1]\id+" dist:"+c\dist Next End Function Function TConnection_CreateSpanningTree_Sub() ;Kleinste Kante wählen die Graph mit noch nicht verb. Knoten verbindet. For qsl.TQuicksortLink = Each TQuicksortLink Local c.TConnection = Object.TConnection(qsl\objHandle) If c\node[0]\connected Xor c\node[1]\connected c\node[0]\connected = True c\node[1]\connected = True c\valid = True CurrentConnectionsArray(CurrentConnections_counter) = c CurrentConnections_counter = CurrentConnections_counter + 1 Delete qsl Return EndIf Next End Function Includes\QuickSortQueue.bb Code: [AUSKLAPPEN] ;QuickSortQueue.bb
;version 1.0 ;by Christian Geißler ;24.1.2009 Type TQuicksortLink Field value# Field objHandle% End Type Function TQuicksortLink_create.TQuicksortLink(value#,objectHandle%) Local pl.TQuicksortLink = New TQuicksortLink pl\value = value pl\objHandle = objectHandle Return pl End Function Function TQuicksortLink_removeFirst%() Local l.TQuicksortLink = First TQuicksortLink If l<>Null Local h% = l\objHandle Delete l Return h EndIf End Function Function TQuicksortLink_removeLast%() Local l.TQuicksortLink = Last TQuicksortLink If l<>Null Local h% = l\objHandle Delete l Return h EndIf End Function Function TQuicksort_clear() For ql.TQuicksortLink = Each TQuicksortLink Delete ql Next End Function Function TQuicksort_sort() TQuicksort_sortPart(First TQuicksortLink,Last TQuicksortLink) End Function Function TQuicksort_sortPart(f.TQuicksortLink,l.TQuicksortLink) If f = l Return If l = Null Return If f = Null Return p.TQuicksortLink = f e.TQuicksortLink = l ;p = pivot element this.TQuicksortLink = f enum.TQuicksortLink = After this While this<>e And enum<>Null this = enum enum = After enum If this\value < p\value Insert this Before f f = this Else Insert this After l l = this EndIf Wend TQuicksort_sortPart(f,p) TQuicksort_sortPart(After p,l) End Function |
||
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon Gewinner des BCC #57 User posted image |
![]() |
Who |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi!
Es ist mir unerklärlich, wie fehlende Klammern so viel Extrazeit beanspruchen ![]() auskommentiert (Zeile 88): Code: [AUSKLAPPEN] Abstand = x1^2 + x2^2 + x3^2
Zeit: 35 ms pro Dings mit Formel (Zeile 87): Code: [AUSKLAPPEN] Abstand = Sqrx1^2 + x2^2 + x3^2
Zeit: 1000 ms richtig: Code: [AUSKLAPPEN] Abstand = Sqr(x1^2 + x2^2 + x3^2)
Zeit: 80 ms trotzdem kommt mir das sehr lahm vor, nur die eine Wurzel will doppelt so viel Zeit haben... MFG Who |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wenn man in der Schule gelernt hat wie man Wurzeln zieht ohne Hilfe eines Taschenrechners und weiß, dass der Rechner kaum andere Möglichkeiten anwendet. Dann leuchtet einem auch ein, dass bestimmte Rechenweisen eben viel mehr Rechenzeit benötigen.
Beispiele: Addition kann der Rechner fast direkt mit AND-Operatoren durchführen. Daher kann der Rechner mit nur wenigen Taktzyklen eine Addition ausrechnen. Soweit ich informatiert bin, nach etwa 3 Takten ist das Ergebnis berechnet. Multiplikation muß dagegen internt bereits mehrfach aufgeteilt werden. Das ganze benötigt dann etwa 15 bis 30 Taktzyklen. Wurzel muß komplett aufgelöst und jede Ziffer einzelnd berechnet werden. Dabei müßen verschiedene Regeln eingehalten werden. Das ganze benötigt dann im Schnitt 90 bis etwa 130 Taktzyklen eines Prozessors. - Meine Angaben können mitlerweile überholt sein. Meine Angaben stützen sich auf Rechern die etwa 10 jahre alt sind. Neuere Rechner können sicherlich das eine oder andere schon schneller ausrechnen. Das Verhältnis aller sollte aber denoch nahezu gleich sein. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
Firstdeathmaker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ähm, um das nochmal klar zu stellen:
Mir geht es nicht darum, dass Sqr so viel Zeit verbraucht (das ist schließlich klar) oder dass x1*x1 nunmal schneller als x1^2 ist, sondern darum, dass ich in meinem code ungefähr folgendes mache (Pseudocode): (Da der gepostete Quicksort auch nur eine absolute Ordnung braucht, kann ich mir das berechnen der Quadratwurzel sogar sparen). Code: [AUSKLAPPEN] COUNT = 1000
dim arr#[COUNT] for i=0 to COUNT-1 arr[i] = ;komplexe Berechnung next time = millisecs() for i=0 to COUNT-1 ;verarbeite arr[i] next debuglog (time - millisecs()) Sprich, die komplexe Berechnung dürfte überhaupt keine Zeitliche Auswirkung auf die gestoppte Zeit haben, weil sie vor dem starten der Stoppuhr stattfindet. Leider hat sie dass aber in meinem im vorherigen geposteten Code. |
||
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon Gewinner des BCC #57 User posted image |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nach jeden Programmstart eines Blitzprogrammes wird nach etwa 0.5 bis 1.0 Sekunden noch einmal eine Optimierung durchgeführt. Diese Optimierung lässt das Programm stocken. Ob diese Optimierung von Blitz oder Windows durchgeführt wird, kann ich nicht sagen. Aber ich habe dieses Verhalten schon immer beobachten können. Daher sind auch Geschwindigkeitstest ohne mindestens 2 Sekunden Pause vor dem eigendlichem Test fast nicht zu gebrauchen, was viele hier im Forum immer wieder gerne vernachlässigen. die Optimierungen könnten auch zusätzliche Speicherplatzreservierungen oder sonstiges sein, die für ein Programm benötigt werden. Wer es weiß, kann es ja gerne mal erläutern. Mich würde es schon interessieren.
Edit1: Worauf ich hinaus will. Vielleicht misst du einfach nur genau dieses stocken, und nicht irgendwelche Berechnungen die bereits durchgeführt wurden. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
Firstdeathmaker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hmm, das klingt schon logisch, allerdings sprechen die Zeiten total dagegen:
Wenn ich die langsamere Vorberechnung wähle, bekomme ich beim Quicksort Zeiten von 38 Sekunden raus, im Gegensatz zu vllt. 2 Sekunden die man anders bekommt. Es liegt also definitiv nicht an einem 2-Sekunden Ruckler. |
||
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon Gewinner des BCC #57 User posted image |
![]() |
Who |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das ist wirklich mysteriös, hoffentlich kann das noch jemand klären.
Ein ausgiebiges Delay bevor die Uhr läuft ändert nichts. Nebenbei: Deine Felder sind alle 1 zu groß ![]() MFG |
||
![]() |
Meoqan |
![]() Antworten mit Zitat ![]() |
---|---|---|
hi!
nach einigen tests und dem herausfinden das bei deiner "alten" rechenart ein bug von blitz zugrundeliegt, kann ich dir sagen das manche floats nur "NaN"(not a number) zurückgeben. das kommt davon: Code: [AUSKLAPPEN] If Sqr(-1) = 0 And Sqr(-1) = 12345 Then Print "unmoeglich" WaitKey() End und hier aus einem forum ein paar funktionen die dem problem vorbeugen: Code: [AUSKLAPPEN] Function isNaN(n#) Return n = 0 And n = 12345 End Function Function isInf(n#) Return n / 1000 = n And (Not isNaN(n)) End Function Function isPosInf(n#) Return isInf(n) And Sgn(n) = 1 End Function Function isNegInf(n#) Return isInf(n) And Sgn(n) = -1 End Function have phun, Meoqan |
||
meine codes sind die essenz des bössen. nicht du veränderst meine codes sondern meine codes verändern dich! |
![]() |
Jan_Ehemaliger Admin |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nimm, die Zeit, mal bevor du loslegst, und dann nochmal, beim richtigen loslegen.
Ich bin der Meinung, das verschiedene Befehle bei der Erstnutzung erst initialisiert werden. Hatte da auch schon einmal was. |
||
between angels and insects |
![]() |
Firstdeathmaker |
![]() Antworten mit Zitat ![]() |
---|---|---|
@ Meoqan:
Die Werte die ich bekomme sind aber niemals negativ wenn ich sie in sqr reinstopfe. Schließlich ist x*x >= 0 Ich hab trotzdem mal mit deinen Funktionen überprüft ob die Werte vielleicht NaN ergeben, dies ist aber nicht der Fall. @ Jan_: Ich lasse in meinem Test die Berechnung 100x durchführen und nehme immer wieder die Zeit. Es hat also nichts mit Erstnutzung und Initialisierung oder 2 Sekunden Lag zu tun. Die Zeiten bleiben konstant schlecht oder gut. |
||
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon Gewinner des BCC #57 User posted image |
![]() |
Meoqan |
![]() Antworten mit Zitat ![]() |
---|---|---|
hi
deine alte schreibweisse: c\dist = (n1\pos[0]-n2\pos[0])*(n1\pos[0]-n2\pos[0])+(n1\pos[1]-n2\pos[1])*(n1\pos[1]-n2\pos[1])+(n1\pos[2]-n2\pos[2])*(n1\pos[2]-n2\pos[2]) plus deinem satz: "Wenn man bei Zeile 88 ein sqr vor den Ausdruck auf der rechten Seite setzt, dann wird meine Quicksort-Funktion extrem langsamer" c\dist = Sqr(n1\pos[0]-n2\pos[0])*(n1\pos[0]-n2\pos[0])+(n1\pos[1]-n2\pos[1])*(n1\pos[1]-n2\pos[1])+(n1\pos[2]-n2\pos[2])*(n1\pos[2]-n2\pos[2]) das ergibnis ist das nicht alles "NaN" ist sondern nur welche wo n1\pos[0] kleiner ist als n2\pos[0] wenn ich das ganze jetzt in klammernsetze dann ist wieder alles normal: c\dist = Sqr((n1\pos[0]-n2\pos[0])*(n1\pos[0]-n2\pos[0])+(n1\pos[1]-n2\pos[1])*(n1\pos[1]-n2\pos[1])+(n1\pos[2]-n2\pos[2])*(n1\pos[2]-n2\pos[2])) und zur überprüfung des ganzen: c\dist = Sqr(-1) oder c\dist = 0 mehr schreib ich jetzt mal nicht dazu ![]() |
||
meine codes sind die essenz des bössen. nicht du veränderst meine codes sondern meine codes verändern dich! |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group