Schnellere Sortierung?

Übersicht BlitzBasic Allgemein

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

Xaymar

ehemals "Cgamer"

Betreff: Schnellere Sortierung?

BeitragDi, Jun 15, 2010 10:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Meine aktuelle Sortierung der Type ist extrem langsam(Ich gehe alle Partikel 3mal durch, was schon bei ~1000 Partikeln ruckelt). Kennt jemand eine schnellere, aber trotzdem genaue Sortierungsmethode?
(http://www.sorting-algorithms.com/ kenne ich, nur sind die codes so irre mini)

BlitzBasic: [AUSKLAPPEN]
Function eg_Particle_Emitter_Sort()
Local eg_P.eg_Particle, ceg_P.eg_Particle, eg_PS.eg_ParticleSort

;Partikel sortieren
Local MinD#=0, MinDP.eg_Particle
Repeat
MinD#=0:MinDP.eg_Particle = Null

ceg_P = First eg_Particle
If ceg_P = Null Then Exit

For eg_P = Each eg_Particle
Local CurDist# = Math_Distance3(eg_P\fPos[0],eg_P\fPos[1],eg_P\fPos[2],EntityX(eg_Engine_Camera),EntityY(eg_Engine_Camera),EntityZ(eg_Engine_Camera))
If CurDist > MinD#
MinD = CurDist
MinDP = eg_P
EndIf
Next
If MinDP <> Null
eg_PS = New eg_ParticleSort
For I = 0 To 7
eg_PS\fColor[I] = MinDP\fColor[I]
If I <= 5 Then eg_PS\fDir[I] = MinDP\fDir[I]
If I <= 3 Then eg_PS\fSize[I] = MinDP\fSize[I]
If I <= 2 Then eg_PS\fPos[I] = MinDP\fPos[I]
If I <= 1 Then eg_PS\fSpeed[I] = MinDP\fSpeed[I]
Next
eg_PS\eg_PE = MinDP\eg_PE
eg_PS\iLifeTimeCur = MinDP\iLifeTimeCur
eg_PS\iSpawnTime = MinDP\iSpawnTime
Delete MinDP
EndIf
Forever
Delete Each eg_Particle

;Partikel sortiert wieder zurückgeben
For eg_PS.eg_ParticleSort = Each eg_ParticleSort
eg_P = New eg_Particle
For I = 0 To 7
eg_P\fColor[I] = eg_PS\fColor[I]
If I <= 5 Then eg_P\fDir[I] = eg_PS\fDir[I]
If I <= 3 Then eg_P\fSize[I] = eg_PS\fSize[I]
If I <= 2 Then eg_P\fPos[I] = eg_PS\fPos[I]
If I <= 1 Then eg_P\fSpeed[I] = eg_PS\fSpeed[I]
Next
eg_P\eg_PE = eg_PS\eg_PE
eg_P\iLifeTimeCur = eg_PS\iLifeTimeCur
eg_P\iSpawnTime = eg_PS\iSpawnTime
Next
Delete Each eg_ParticleSort
End Function
 

Matthias

BeitragDi, Jun 15, 2010 10:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Hay.
Erstmal würde ich vorschlagen die Camerakoordinaten in einer Variable Zwichenzuspeichern.

EntityX(eg_Engine_Camera)

Vieleicht kannst du dann auch noch dein Sortieren auf mehrere Mainloops verteilen.

Was hat das für einen sinn die Partikel zu sortieren.
 

flashmaxel

BeitragDi, Jun 15, 2010 11:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Distanz auf jedenfall zwischenspeichern und einen effizienteren Sortieralgorithmus verwenden.
Du suchst immer den Partikel mit dem kleinsten Abstand zur Kamera raus und fügst diesen dann in eine neue Liste ein, das ist Selectionsort.
Selectionsort ist, wie du auch auf der Seite http://www.sorting-algorithms.com/ sehen kannst nicht besonders schnell. Ich würde entweder Mergesort, Heapsort oder Quicksort verwenden. Die gibts zum Teil auch schon im Codearchiv z.B. hier https://www.blitzforum.de/foru...=quicksort - auch für Types- kannst du also direkt verwenden!
Berechne also zunächst in einer Schleife die Distanz eines jeden Partikels zur Kamera und speicher das Ergebnis in dem Typeeintrag in einer Variable. Anschließen sortierts du den Type nach dieser Variable mit Quicksort!

Midimaster

BeitragDi, Jun 15, 2010 11:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Na klar gibt es da Möglichkeiten....

Du scheinst die Partikel nach der Nähe zur Camera zu sortieren. Daher müßten Sie eigentlich nach dem ersten Aufruf der Sortierfunktion auch beim 2.Aufruf noch ziemlich sortiert sein.

Deine Sortierfunktion fasst immer alles an und schichtet es neu um. Bei vorsortieren Felder ist das fast nicht nötig.

Daher kommt ein Verfahren in Frage, dass mit vorsortiertem Feld besonders schnellzurechtkommt. In einem Beitrag vor einigen Tagen habe ich eine tolle Vergleichstabelle gefunden, wo man auch die Performance verschiedener Verfahren vergleichen kann. http://www.sorting-algorithms.com/

Dort gewinnt Insertion und Bubble-Sort für dein Problem. Und Bubblesort wird in diesem Beitrag bereits auf deutsch erklärt: https://www.blitzforum.de/foru...p?t=35032.

Im Prizip ist Bubblesort schnell erklärt:

Du fasst nur dann etwas an, wenn der folgende Eintrag (n+1) größer ist als der vorherige Eintrag n . In deinem Fall, wenn die Distanz größer ist.

In diesem Fall vertauscht du dann die beiden Elemente sofort und weiter geht es bis nach unten. Dann beginnt der Spaß von vorne. Solange du in der vorherigen Runde noch mind. eine Vetauschung gemacht hast, musst immer noch ein weiteres Mal suchen. Findest du in einer Runde keine Vertauschung mehr, ist alles sortiert.

Xaymar

ehemals "Cgamer"

BeitragDi, Jun 15, 2010 11:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für den Link nach quicksort... suche nach "quick sort" hatte hier nichts ergeben.

Grandios wie man das überliest...
Zitat:
(http://www.sorting-algorithms.com/ kenne ich, nur sind die codes so irre mini)


@Matthias: SingleSurface Z-Sorting?
@Midimaster: Sie sind nicht vorsortiert. Wenn nu jemand die Kamera nur eine Blitzenheit bewegt ist die "vorsortierung" komplett zu "random" geworden.

darth

BeitragDi, Jun 15, 2010 12:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

BubbleSort ist schlecht. Selbst für beinahe vorsortierte Listen ist es ziemlich uneffizient, weil es einfach Werte hin und her schiebt.
MergeSort ist in diesem Falle auch nicht zu empfehlen, weil der nicht von bereits geleisteter Sortierung profitiert, er läuft immer ganz durch, ist allerdings viel effizienter als Bubble.
Die beste Wahl hier wäre wohl tatsächlich QuickSort, Erklärungen, oder sogar SourceCodes (du warst doch der, der auf c++ wechseln wollte? Alternativ gibts die auch in Java oder Pseudocode). Oder du guckst hier nach.

Code:

BlitzBasic: [AUSKLAPPEN]
;Quick Sort
Function quickSort(list[100], anz)
quick(list, 0, anz-1)
End Function

Function quick(list[100], lo, hi)
Local i=lo, j=hi
Local q=list[(lo+hi)/2]

While i<=j
While list[i]<q ;COMPARE(List[i], Q)
i=i+1
Wend

While q<list[j] ;COMPARE(Q, List[i])
j=j-1
Wend

If i<=j
tmp=list[i] ;EXCHANGE(List[i], List[j])
list[i]=list[j]
list[j]=tmp

i=i+1
j=j-1
EndIf
Wend

If lo<j
quick(list, lo, j)
EndIf

If i<hi
quick(list, i, hi)
EndIf
End Function


Viel Erfolg mit deiner Engine,
MfG,
Darth
Diese Signatur ist leer.

Midimaster

BeitragDi, Jun 15, 2010 13:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Als sehr effizient erweisen sich auch Test, ob denn überhaupt alle Partikel sortiert werden müssen. Das kommt natürlich darauf an, zu welchem Zweck du die Sortierung durchführst.

Ideen, die Performance bringen:

1. Partikel, die hinter der Camera() liegen...

2. Partikel, die weit entfernt liegen...

...müssen vielleicht gar nicht sortiert werden, sondern wandern als Block ans Ende der sortierten Partikel.

3. Des weiteren könntest Du Partikel schon beim Entstehen an die richtige Stelle in die Liste aufnehmen.

4. Muss die Liste jeden FLIP sortiert werden? Vielleicht genügt es nach jedem 3. Flip, etc...

@Darth
"BubbleSort ist schlecht". Ah! Warum gibt es dann das Verfahren noch? Es ist wie im richtigen Leben: "kommt drauf an!". Bubble-Sort hängt Quicksort bei vorsortieren Listen auf jeden Fall ab! Und bei 60 FLIPs pro Sekunde wäre ich mir echt nicht sicher, wie oft eine solche Liste dann doch "vorsortiert" wäre.

@Xaymar
beschreib doch mal um welche Partikel es sich handelt und wozu das Sortieren nötig sein wird.

Xaymar

ehemals "Cgamer"

BeitragDi, Jun 15, 2010 13:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Particle-Z-Sorting, Da ich ja mit SingleSurface arbeite. Und QuickSort ist wirklich gut dafür aktuell.

1. Sollte machbar sein
2. Die werden nicht eingezeichnet, allerdings noch berechnet(Wieso eigentlich...)
3. Lässt sich umsetzen
4. Sie wird alle eg_Particle_Sort_TweenMS sortiert(aktuell 2500ms)

darth

BeitragDi, Jun 15, 2010 15:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Midimaster,

"BubbleSort ist schlecht", weil es ein (veralteter) Algorithmus ist, der ein Laufzeitverhalten von O(n^2) aufweist. Das heisst, bei doppelter Listengrösse, die vierfache (maximale) Arbeit, bei vierfacher Grösse die sechzehnfache Arbeit usw. (Siehe hier).

Man hat gezeigt, dass gewisse Listen nicht schneller als in O(n*ld(n)) sortiert werden können (ld = Logarithmus Dualis (oder lb, binärer Logarithmus), sprich Logarithmus zur Basis 2). Der wächst, für grosse Listen, beinahe linear, d.h doppelte Listengrösse -> doppelte Arbeit usw. (Siehe hier).

Warum gibt es das Verfahren noch? Weil der Algorithmus dazu so kinderleicht ist, dass er sich eignet um Anfängern die Sortierung zu erklären. Ganz einfach deshalb.

BubbleSort hängt Quicksort vielleicht bei ganz kleinen Listen ab, die praktisch schon vollständig vorsortiert sind, das kann sein - das liegt daran, dass Quicksort rekursiv läuft und gewisse Dinge auf den Stack legt, was zu einem (minimalen) Geschwindigkeitsverlust führen kann.

Allerdings ist Quicksort in jedem Falle BubbleSort vorzuziehen, ganz einfach weil der Algorithmus in (beinahe) jedem Falle effizienter ist.

MfG,
Darth
Diese Signatur ist leer.

Midimaster

BeitragDi, Jun 15, 2010 17:48
Antworten mit Zitat
Benutzer-Profile anzeigen
@darth
danke für die infos. Ich hab es jetzt mal ausprobiert und muss zugeben: Quicksort ist besser!

Xaymar

ehemals "Cgamer"

BeitragDo, Jun 17, 2010 0:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Die vorschläge ließen sich nur mäßig umsetzen. das meiste davon hat derbe die rechenzeit erhöht.

Kurze nebenfrage, würde es sinnmachen die Partikel in zwei listen aufzuteilen, einmal Near einmal Far? (Nur Near wird sortiert, Far bleibt unsortiert)

Midimaster

BeitragDo, Jun 17, 2010 7:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Wieviele Partikel sind es denn? Und wie lange ist denn aktuell die Rechenzeit?

So wie ich das jetzt getestet habe, scheint das QuickSort ja unter 2 msec bei 10.000 Werten zu sortieren. Allerdings Integer-Feld und unter BMax.

Ich denke mal, du verlierst die meiste Zeit dabei, die Fields der Typen "von Hand" zu kopieren.

Xaymar

ehemals "Cgamer"

BeitragDo, Jun 17, 2010 13:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Partikelanzahl variiert zwischen 0 und 2^16(Durchschnitt: 2^13)
von Hand kopiere ich ja nichts, das macht alles Blitz

Normale Rechenzeit: 0-2ms
Mit Vorsortierung: 15-45ms(Bei erstellung)
Mit Prüfen ob hinter der Kamera: 190-364ms
Mit Prüfen auf entfernung: 66-153ms

Alles ohne Debugger an
 

GERMAX

BeitragDo, Jun 17, 2010 20:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Schau mal da:

http://www.informatiktreff.de/...m/baum.htm

vllt hilft das was und berichte von deinen Erfahrungen!
Erfolglos begonnene BB-Projekte:TRON/CONVOY/MYSTIC

Rallimen

Sieger des 30-EUR-Wettbewerbs

BeitragDo, Jun 17, 2010 21:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,
ich habe mal einen Quicksort für Typelisten erstellt
https://www.blitzforum.de/foru...p?p=126111

dieser sortiert innerhalb der Liste und kopiert nichts in ein Array!
Und der Code ist schnell erstellt, Typename und Fieldname angeben fertig!
Probiere das doch mal aus und sag mal was zu der Geschwindigkeit.
[BB2D | BB3D | BB+]
 

BIG BUG

BeitragDo, Jun 17, 2010 23:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe mal kurz Deinen Code oben überflogen und es dünkt mir als würdest Du für jeden Vergleich die Entfernung der Partikel neu berechnen. Wenn Du die anderen Sortierungen auch so implementiert hast, dann ist es jedenfalls kein Wunder wenn das nicht flutscht.

Habe mal ein bisser gegoogled aber nicht wirklich einen tollen Vorschlag gefunden, wie man Partikel im 3D-Raum möglichst effizient nach Tiefe sortiert.
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final)

Xaymar

ehemals "Cgamer"

BeitragFr, Jun 18, 2010 14:02
Antworten mit Zitat
Benutzer-Profile anzeigen
Ihr seit zu spät... Ich zitiere:
flashmaxel hat Folgendes geschrieben:
Die Distanz auf jedenfall zwischenspeichern und einen effizienteren Sortieralgorithmus verwenden.
Du suchst immer den Partikel mit dem kleinsten Abstand zur Kamera raus und fügst diesen dann in eine neue Liste ein, das ist Selectionsort.
Selectionsort ist, wie du auch auf der Seite http://www.sorting-algorithms.com/ sehen kannst nicht besonders schnell. Ich würde entweder Mergesort, Heapsort oder Quicksort verwenden. Die gibts zum Teil auch schon im Codearchiv z.B. hier https://www.blitzforum.de/forum...=quicksort - auch für Types- kannst du also direkt verwenden!
Berechne also zunächst in einer Schleife die Distanz eines jeden Partikels zur Kamera und speicher das Ergebnis in dem Typeeintrag in einer Variable. Anschließen sortierts du den Type nach dieser Variable mit Quicksort!


Der Binäre Baum wird mir relativ wenig bringen. Ich müsste den sozusagen bei jeder Z-Sortierung dann neu anpflanzen. Genauso wenig bringen mir leute die nur den ersten post lesen und bei allen anderen denken: "TL,DR!". Trotzdem danke für den versuch...

@BIG BUG: Das Hauptproblem ist ja, das ich keine GeometryShader oder VertexShader in BB habe.(Beides würde das Z-Sorting auf die Grafikkarte verlagern)
 

GERMAX

BeitragFr, Jun 18, 2010 23:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Xaymar hat Folgendes geschrieben:
Partikelanzahl variiert zwischen 0 und 2^16(Durchschnitt: 2^13)
von Hand kopiere ich ja nichts, das macht alles Blitz

Normale Rechenzeit: 0-2ms
Mit Vorsortierung: 15-45ms(Bei erstellung)
Mit Prüfen ob hinter der Kamera: 190-364ms
Mit Prüfen auf entfernung: 66-153ms

Alles ohne Debugger an


Welche Zeiten kriegst du denn wenn du das sortieren 10* 100* machst? Ähnliche oder deutlich verschiedene?
Erfolglos begonnene BB-Projekte:TRON/CONVOY/MYSTIC

Xaymar

ehemals "Cgamer"

BeitragFr, Jun 18, 2010 23:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Sortieren brauch ich doch nur einmal? Wo ist nu der unterschied zwischen einmal und 10/100 mal in einer schleife?(Außer dem deutlich höherem aufwand). Und btw immernoch an meiner letzten frage vorbei.

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSa, Jun 19, 2010 1:12
Antworten mit Zitat
Benutzer-Profile anzeigen
1.) Mir ist bis jetzt unklar, wozu eine bis zu 2^16 Partikel in Z zu sortieren sind. Darstellungsfehler treten nur innerhalb mehrerer transparenter Partikel hintereinander auf, die im übrigen kaum auffallen (tritt eher selten auf). Probleme von transparenten Partikeln die sich vor nicht transparenten Polygonen befinden, treten auch keine Fehler auf.

2.) Wer sich mit 1.) ''den wenigen Fehlern'' nicht abfinden kann, nimmt maskierte Texturen für die Partikel. Sind nicht nur etwas schneller in der Darstellung, haben zudem auch keine Fehler mehr. Lediglich so viele Anstallten kann man damit dann nicht mehr machen.

3.) Wer sich weder mit 1.) noch 2.) abfinden kann, sollte auf unnötige Funktionsaufrufe wie Math_Distance3 verzichten, und in diesem Teil der Funktion als direkten Code einfügen. Dabei - wie schon genannt - die Cameraposition nicht immer wieder auslesen, sondern in Variablen zwischen speichern.

4.) Innerhalb Math_Distance3 dann auf keinen Fall sqr verwenden, sondern direkt mit den Werten rechnen. Denn hier ist die tatsächliche Entfernung völlig irrelevant, lediglich die ''>/< als'', sind wichtig.
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group