Jump to content
Unity Insider Forum

Identischer Code deutlich langsamer in Unity


Life Is Good

Recommended Posts

Hey

Ich bin gerade ein bisschen ratlos.
Ich hab bei mir in Unity die Fast Marching methode implementiert - und musste feststellen, dass sie wahnsinnig langsam ist (Etwa 15 Sekunden). Eigentlich so langsam das etwas nicht stimmen kann.
Ich hab dann testweise einfach mal den Code gepackt und den in eine leere C# Konsolenanwendung geschmissen. (heißt natürlich auch .Net 4.5.2) und der selbe Code braucht da bloß etwa 3 Sekunden (VS im Debug Mode, Release nochmal etwas schneller)

Meine Frage ist also, ob jemand eine Idee haben könnte warum das in Unity so langsam läuft.
Hier der Code:

    // Der Einfachheit halber ist die Methode statisch und nimmt Group direkt als Parameter an.
    // Eigentlich würde die Methode über eine Anzahl an Gruppen in der 1. for schleife iterieren.
    private static void FastMarching(Group group)
    {
        // for each group
        for (int i = 0; i < 1; i++)
        {
            group.unknown = new List<GroupCell>();
            group.known = new List<GroupCell>();
            group.candidate = new List<GroupCell>();
			
            // GridCells enthält 10.000 Elemente.
            for (int j = 0; j < group.gridCells.Length; j++)
            {
                var cell = group.gridCells[j];
              
              	// Zu Beginn sind alle Zellen in der unknown liste.
                group.unknown.Add(cell);
                cell.isCandidate = false;
				
              	// 100 Elemente in gridCells sind hier mit isGoal = true markiert.
                if (cell.isGoal)
                {
                    cell.isKnown = true;
                    cell.isUnknown = false;

                    group.known.Add(cell);
                    group.unknown.Remove(cell);
                }
              	// 9.900 demnach nicht.
                else
                {
                    cell.isKnown = false;
                    cell.isUnknown = true;
                }
            }

	    // Ziel erreicht, wenn keine Zellen mehr in der unbekannten Liste liegen.
            while (group.unknown.Count > 0)
            {
                // Diese For schleife ist auch zugleich die lastigste (logischerweise)
                for (int j = 0; j < group.known.Count; j++)
                {
                    var cell = group.known[j];
                    // Holt sich einfach die 4 direkt angrenzenden Zellen einer gegebenen Zelle (cell)
		    // Das Grid ist also 2 dimensional.
                    var neighbours = Grid.GetNeighbourCells(width, length, group.gridCells, cell);
					
                    for (int k = 0; k < 4; k++)
                    {
                        var neighbour = neighbours[k];
                        if (neighbour != null && neighbour.isUnknown)
                        {
                            neighbour.isCandidate = true;
                            neighbour.isUnknown = false;

                            group.candidate.Add(neighbour);
                            group.unknown.Remove(neighbour);
                        }
                    }
                }

                for (int j = 0; j < group.candidate.Count; j++)
                {
                    // Nichts wichtiges hier.
                }

                GroupCell bestCell = null;
                for (int j = 0; j < group.candidate.Count; j++)
                {
                  // Nichts wichtiges hier, liefert einfach die beste Zelle zurück.
                }

                bestCell.isCandidate = false;
                bestCell.isKnown = true;

                group.known.Add(bestCell);
                group.candidate.Remove(bestCell);
            }
        }
    }

 

Edit:
Ich hab die Konsolenanwendung mal auf .Net 2.0 geändert und der Code läuft auch bloß minimal langsamer, also weit von den Werten in Unity entfernt.

Edit 2:
Unwichtige Codestellen entfernt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich vermute mal, dass Unity selber eben parallel auch was macht. Vorallem wenn du im Editor bist.

Haste mal ein ganz einfaches Build gemacht, wo nur dieser Code ausgeführt wird?
Ich könnte wetten, dass der Code dann viel schneller abläuft.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich denke dieser Algorithmus eignet sich hervorragend, um die Berechnung auf mehrere Prozessorkerne zu verteilen, Unity läuft ja nur auf einem Kern und auf diesem Kern laufen eben auch noch die Kernelfunktionen von Unity, soll heißen, wenn du den Code z.b. auf dem 2. Kern einer CPU (parallel) ausführst, könnte ich wetten du bist wieder bei 4 Sekunden. Noch mehr Performance kann man denke ich herausholen, wenn du den Algorithmus auf die PUs der GPU verteilst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Jo, ich hab auch schon daran gedacht das zu parallelisieren.
Im Paper das ich lese wird aber leider nicht klar ausgedrückt, ob der Algorithmus tatsächlich parallelisiert wurde. Deswegen bin ich mir gerade verdammt unsicher, ob ich nicht einfach blödsinn gemacht habe :D

Ich übersetz den Code gerade noch in C++, einfach um mal zuschauen was das nochmal für einen Unterschied ausmachen würde.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich denke auch je höher die Auflösung bei der Berechnung sein soll, desto mehr Zeit wird der Algorithmus vermutlich auch benötigen (und je grösser die 3d Raw files sind). Aber laut dem Artikel den ich kurz überflogen habe lässt er sich sehr gut parallelisieren.
Hier ist sogar der Quellcode für eine GPU Implementierung bei:
https://www.eriksmistad.no/marching-cubes-implementation-using-opencl-and-opengl/

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 59 Minuten schrieb Torigas:

Arbeitest du gerade an Continuum Crowds?

Ja, besser gesagt ich versuch's zumindest :)

Ich bin vor ein paar Tagen auf die Info gestoßen, dass die original Implementation mit OpenCL war, also doch auf der GPU lief.

Danke für den Link ! Ich denke ich werd sowohl GPU durch Compute Shader als auch Multithreading auf der CPU unterstützen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hab ich letztens auch implementiert. Läuft halt so semi-gut auf der CPU und auch nur bis zu einer gewissen Griddichte.

Spannend, dass ich nicht der einzige hier bin. 

https://yearlyboar.wordpress.com/2015/03/30/implementation-of-continuum-crowds-physically-based-crowd-simulation/ Das ist eine ganz gut Basis. Siehe der Code auf Github.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zitat

Spannend, dass ich nicht der einzige hier bin. 

Ja ! Ich hab wirklich nicht erwartet so schnell jemand anderen zu finden. Es gibt ja auch kaum Material dazu.
Die Seite kenn ich, ist glaub ich auch das einzige praktische was man zu Continuum Crowds findet. Ist eigentlich ein bisschen komisch, da CC ja anscheinend in größeren Spielen schon relativ oft Anwendung gefunden hat (bzw. eine abgeänderte Version)

Wie zufrieden bist du denn mit deinen Ergebnissen ?
Discomfort und Höhen werden bei mir auch passend behandelt, aber irgendwie passt das mit der gegenseitigen Erkennung bei mir noch nicht, die Personen laufen einfach ineinander, sogar in der selben Gruppe.
Ich glaube ich hab bei der Berechnung der Dichte Werte noch irgendwo einen Fehler drin...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Joa also die vermeiden sich schon. Da musst du mal in der Gewichtung gucken. Ganz zufrieden bin ich aber auch nicht.

https://howtorts.github.io/2014/01/09/continuum-crowds.html

http://www.derivativesinvesting.net/article/482547368/implementing-continuum-crowds-part-1-writing-an-eikonal-equation-solver/

Gibt so ein paar Resourcen ja.

Ich hab bei mir viel mit OnDrawGizmos gearbeitet und jede Grid Cell je nach Dichte eingefärbt und so. Hilft ziemlich beim Debuggen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 1 month later...

Leider noch nicht dazu gekommen meine CC Implementation zu multithreaden.

Bin allerdings sowieso noch mit Problemen am kämpfen.


@Torigas
Bist du auch auf solch ein komisches "Gestotter" gestoßen ? Das mit dem Teleportieren ist auch irgendwie merkwürdig, löst sich aber vielleicht auch einfach auf wenn ich den Vektor auf eine bestimmte Größe beschränke...
Ansonsten tendieren die halt aus irgendeinem Grund dazu seeehr nah aneinander zu laufen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...