Jump to content
Unity Insider Forum
  • Announcements

    • Lars

      Allgemeine Forenregeln   03/13/2017

      Forenregeln Nimm dir bitte einen Moment um die nachfolgenden Regeln durchzulesen. Wenn du diese Regeln akzeptierst und die Registration fortsetzen willst, klick einfach auf den "Mit der Registrierung fortfahren"-Button. Um diese Registration abzubrechen, klick bitte einfach auf den "Zurück" Button deines Browsers. Wir garantieren nicht für die Richtigkeit, Vollständigkeit und Brauchbarkeit der Nachrichten und sind auch nicht dafür verantwortlich. Die Beiträge drücken die Meinung des Autors des Beitrags aus, nicht zwangsläufig das, wofür die Forensoftware steht. Jeder Nutzer, der denkt, dass ein veröffentlichter Beitrag unzulässig bzw. störend ist, ist aufgefordert uns unverzüglich per E-Mail zu kontaktieren. Wir haben das Recht störende Beiträge zu löschen und bemühen uns, das in einem realistischem Zeitraum zu erledigen (sofern wir beschlossen haben, dass die Löschung notwendig ist). Du akzeptierst, durchgehend während der Nutzung dieses Services, dass du dieses Forum nicht dazu missbrauchen wirst, Inhalte zu veröffentlichen, welche bewusst falsch und/oder verleumderisch, ungenau, beleidigend, vulgär, hasserfüllt, belästigend, obszön, sexuell belästigend, bedrohlich, die Privatsphäre einer Person verletzend oder in irgend einer Art und Weise das Gesetz verletzen. Des Weiteren akzeptierst du, dass du keine urheberrechtlich geschützte Inhalte ohne Erlaubnis des Besitzers in diesem Forum veröffentlichst. Mit dem Klick auf den "Mit der Registrierung fortfahren"-Button, akzeptierst du zudem unsere Datenschutzerklärung und stimmst der Speicherung deiner IP-Adresse und personenbezogenen Daten zu, die dafür benötigt werden, um dich im Falle einer rechtswidrigen Tat zurückverfolgen zu können bzw. permanent oder temporär aus dem Forum ausschließen zu können. Es besteht keine Pflicht zur Abgabe der Einwilligung, dies erfolgt alles auf freiwilliger Basis.   Zusatzinformationen Der Forenbetreiber hat das Recht, Nutzer ohne Angabe von Gründen permanent aus dem Forum auszuschließen. Des Weiteren hat er das Recht, Beiträge, Dateianhänge, Umfrage, Blogeinträge, Galleriebilder oder Signaturen ohne Angabe von Gründen zu entfernen. Mit der Registrierung verzichtest du auf alle Rechte an den von dir erstellten Inhalten, bzw. treten diese an das Unity-Insider.de und Unity-Community.de ab. Dies bedeutet im Klartext, dass das Unity-Insider.de und Unity-Community.de frei über deine Texte verfügen kann, sofern diese nicht wiederum die Rechte anderer verletzen. Es besteht weiterhin kein Anspruch von registrierten Nutzern bzw. ehemaligen registrierten Nutzern darauf, dass erstellte Inhalte und/oder die Mitgliedschaft (User) wieder gelöscht werden (Erhaltung der Konsistenz dieses Forums).   Einwilligungserklärung Wenn du mit der Speicherung deiner personenbezogenen Daten sowie den vorstehenden Regeln und Bestimmungen einverstanden bist, kannst du mit einem Klick auf den Mit der Registrierung fortfahren-Button unten fortfahren. Ansonsten drücke bitte Zurück. Stand: 07.03.2011
runner78

Unity 2017 und .NET 4.6

Recommended Posts

vor 3 Stunden schrieb runner78:

Hauptziel von async/await war die UI Programmierung, um den UI-Thread nicht zu blockieren.

Hmpf. Ich versteh nicht ganz warum du das jetzt schreibst. Kann man das als

Zitat

Ja.

zusammenfassen und interpretieren ?
Wenn du einen Thread entlasten willst hast du bloß 2 Möglichkeiten (so funktionieren CPUs nunmal) entweder du verteilst die Arbeit über mehr Zeit (So wie Coroutinen) oder du lagerst sie auf seperate Threads aus. Da steckt keine dunkle Magie hinter asynchroner Programmierung. (Dass die Heinzelmännchen kommen, wenn du die Keywords async und await nutzt ist bloß ein Mythos :) )

 

vor 3 Stunden schrieb runner78:

Coroutinen an sich blockieren immer den Main Thread, nur eben aufgeteilt auf mehrere Frames.

Was du hier als "blockieren" bezeichnest ist halt die Art, wie unsere Prozessoren funktionieren. Await auf dem selben Thread macht da nichts anderes, siehe oben.

 

vor 3 Stunden schrieb runner78:

Das neue Entity System

Hier bin ich mal pingelig.
Unity Tech arbeitet gerade an einem Entity-Component System.
Entity System != Entity Component System; außerdem:
Entity Component Model (oft einfach Entity Component, EC) != Entity System und Entity Component != Entity Component System (ECS)

vor 3 Stunden schrieb runner78:

Das neue Entity System benutzt ein "Data oriented design" und wurde für eine gute Zusammenarbeit mit dem c# Jobsystem entwickelt, das Multithreading auf das äußerste ausreizen dürfte.

Jein. Dass Daten & Logik (Behaviour) voneinander getrennt werden ist schon DoD mäßig, das ist richtig.
Aber ein ECS schließt im Grunde DoD aus.
Siehe https://en.wikipedia.org/wiki/Data-oriented_design
Denn
1. ist DoD das genaue Gegenteil von sowas wie ECS, EC, MVC etc. Bei DoD folgst du keinen strengen Paradigmen, und keinem festen Design Plan.
2. ist vieles am ECS (variiert natürlich je nach Implementation) ziemlich anti DoD. Beispiel: Eine super Klasse wie Unity's Object Klasse.
Alle Objekte (ob GameObject oder Komponenten) erben von Object. In DoD hast du sowas nicht, weil es Datenmüll und Abhängigkeit produziert. (DoD ist vorallem auf high performance ausgerichtet, wie man dem Namen wohl entnehmen kann.) Manchmal allokiert man absichtlich überflüssigen Speicher, aber das ist ein anderes Thema.

Zu deinen anderen Texten: Ich verstehe Englisch recht gut, danke ;) Darauf wollte ich nicht hinaus.
Sondern, dass du 2, statt einem Objekt hast, was wieder ziemlich anti DoD ist.
Vorallem aber macht es den Code komplexer. Wie gesagt, ECS ist (zumindest aktuell) auch nicht wirklich verbreitet.

Ein guter link noch http://gamedevs.org/uploads/pitfalls-of-object-oriented-programming.pdf

Share this post


Link to post
Share on other sites
vor 12 Stunden schrieb Life Is Good:

Hmpf. Ich versteh nicht ganz warum du das jetzt schreibst. Kann man das als

 

vor 12 Stunden schrieb Life Is Good:

zusammenfassen und interpretieren ?
Wenn du einen Thread entlasten willst hast du bloß 2 Möglichkeiten (so funktionieren CPUs nunmal) entweder du verteilst die Arbeit über mehr Zeit (So wie Coroutinen) oder du lagerst sie auf seperate Threads aus. Da steckt keine dunkle Magie hinter asynchroner Programmierung. (Dass die Heinzelmännchen kommen, wenn du die Keywords async und await nutzt ist bloß ein Mythos :) )

Asynchron bedeutend nicht automatisch im Hintergrund.
Coroutinen sind abhängig von der Framerate, auch wenn der Prozessor noch Ressourcen frei hat, z.B. bei fixen Frameraten, wird die Ausführung unnötig in die länge gezogen. Ich werde mal heute Abend mal etwas experimentieren, mal sehen wie sich Coroutinen und async/await so in Sachen Performance so verhalten, wenn man im Mainthread bleibt.

vor 13 Stunden schrieb Life Is Good:

Hier bin ich mal pingelig.

Ich war hier einfach zu faul es auszuschreiben:D

vor 13 Stunden schrieb Life Is Good:

Jein. Dass Daten & Logik (Behaviour) voneinander getrennt werden ist schon DoD mäßig, das ist richtig.
Aber ein ECS schließt im Grunde DoD aus....

Ein so ganz festes Pattern scheint Unity hier aber nicht zu haben. du musst nicht 2 Klassen machen, du kannst ja auch eine ScriptBehaviour machen, die bestehende Daten benutzt, ohne eine eigene DataComponent an das Entity zu hängen.
Die Daten-Componenten sind alles structs, die werden nicht mehr von Unitys "Object" ableiten.

Eigentlich ist es noch zu früh für diese Diskussion, da man noch nicht selbst reinschnuppern kann.

Share this post


Link to post
Share on other sites
vor 14 Minuten schrieb runner78:

Coroutinen sind abhängig von der Framerate

Ahhh, jetzt versteh ich worauf du hinaus willst. Naja, dafür müsste man sich async / await mal genauer anschauen. Wie genau die das intern machen weiß ich gerade nicht. Aber das Prinzip bleibt ja das selbe :)

vor 15 Minuten schrieb runner78:

Eigentlich ist es noch zu früh für diese Diskussion, da man noch nicht selbst reinschnuppern kann.

Da stimme ich zu, also lass ich's mal so stehen.

Share this post


Link to post
Share on other sites
Zitat

Coroutinen sind abhängig von der Framerate,

Sind sie nicht, es ist genau anders herum. Coroutinen beeinflussen die Framerate, werden aber immer zu einem definierten Zeitpunkt durch den Prozessor (in Unity auf dem Mainthread) ausgeführt, dauert eine Coroutine zu lang, verschlechtert sich deine Framerate in Unity.

Unity main thread auf CPU Kernel 1:

Loop each Frame: {
  Unitykernelprozess
  Coroutine 1 (skip/wait or execute next coroutine instructions?)
  Coroutine 2 (skip/wait or execute next coroutine instructions?)
  Coroutine 3 (skip/wait or execute next coroutine instructions?)
}

Werden Instruktionen einer Coroutine ausgeführt, verlängert sich die Ausführungszeit pro Frame (Time.deltatime).

Kann man dagegen einen Thread auf den 2. CPU Kernel auslagern, so wird sich deine FPS verbessern (Vorrausetzung ist natürlich man hat eine CPU mit mehreren Kernels und man verwendet keine Unity-Kernelfunktionen innerhalb des Threads)
Womit ich mich allerdings noch nicht im Detail beschäftigt habe, wie ermittle ich, auf welchem Kernel der Unity-Mainthread aktuell läuft und wie starte ich einen Thread auf einem spezifischen Kernel.

Share this post


Link to post
Share on other sites

Ich glaube nicht, dass er das meinte, sondern, dass MoveNext() in Update statt findet. In diesem Sinne ist deine Coroutine schon ein wenig davon abhängig.
Ansonsten scheint await nicht sonderlich davon abzuweichen. Der Compiler generiert eine Statemachine, die von der Struktur ähnlich wie IEnumerator & yield aussieht.
Der Unterschied ist, das MoveNext() dort über Callbacks (sobald die Arbeit verichtet wurde) aufgerufen wird. Wie das aussieht, wenn auf dem selben Thread gewartet wird hab ich jetzt auf die Schnelle aber nicht herausgefunden.
https://weblogs.asp.net/dixin/understanding-c-sharp-async-await-1-compilation

Wenn du mit "Kernel" CPU Kerne meinst, das übernimmt für gewöhnlich das Betriebssystem. Vermutlich liegt der Unity Main Thread einfach auf dem 1. Kern.
Mit https://msdn.microsoft.com/en-us/library/system.diagnostics.process.processoraffinity.aspx könntest du allerdings Threads auf spezifischen Kernen starten.

Share this post


Link to post
Share on other sites

Mit Kernel meinte ich den jeweiligen Prozessorkern.

Wenn man Threads oder Tasks ohne Prozessorkernzuordnung startet, dann läuft man Gefahr, daß diese Threads oder Tasks ebenfalls auf dem 1 Core laufen und damit bremst man ja den Core aus, auf dem Unity ohnehin schon läuft.

Wenn ich google finde ich auch sowas in der Richtung wss du meintest:
https://stackoverflow.com/questions/6584397/how-to-start-a-thread-on-a-specific-core

Share this post


Link to post
Share on other sites
vor 3 Stunden schrieb Zer0Cool:

Sind sie nicht, es ist genau anders herum. Coroutinen beeinflussen die Framerate, werden aber immer zu einem definierten Zeitpunkt durch den Prozessor (in Unity auf dem Mainthread) ausgeführt, dauert eine Coroutine zu lang, verschlechtert sich deine Framerate in Unity.

Doch, Coroutinen sind von der Framerate abhängig, alles zwischen 2 yield returns wird in einem Frame ausgeführt. Bei einer fixen Framerate wäre die Ausführungsdauer unabhängig der Prozessorgeschwindigkeit immer gleich. Auch wenn die Anweßung zwischen zwei yields nur 2 Millisecunden dauert, wird bei 60 FPS erst 15 Millisekunden später wieder vorgesetzt. In solchen Fällen sollte man die Logik in einen seperaten Thred arbeiten lassen, und da ist async/await mit Task die nach  meinen bisherigen Erfahrung die Variante mit dem geringsten Overhead.

Auf welchen Prozessorkern was läuft, das entscheidet in der Regel das Betriebsystem.

vor 46 Minuten schrieb Life Is Good:

Der Compiler generiert eine Statemachine, die von der Struktur ähnlich wie IEnumerator & yield aussieht.
Der Unterschied ist, das MoveNext() dort über Callbacks (sobald die Arbeit verichtet wurde) aufgerufen wird. Wie das aussieht, wenn auf dem selben Thread gewartet wird hab ich jetzt auf die Schnelle aber nicht herausgefunden.

Ein unterschied ist noch, die Statemachine wird als Valuetype realiesiert, der Enumerator als Referenztype.

async/await ist nicht wirklich dafür ausgelegt, Logik asynchron innerhalb der Anwendung auf dem Mainthread auszuführen, so wie es die Coroutine macht.

Share this post


Link to post
Share on other sites
Zitat

Doch, Coroutinen sind von der Framerate abhängig, alles zwischen 2 yield returns wird in einem Frame ausgeführt

Da ist man aber selbst schuld wenn man sowas macht. Klar kann ich eine Coroutine jedes Frame ausführen lassen, muss ich aber nicht und sollte man auch nicht, insofern es nicht zwingend notwendig ist.

// suspend execution for 5 seconds
yield return new WaitForSeconds(5);

 

Share this post


Link to post
Share on other sites
vor 1 Minute schrieb Zer0Cool:

Da ist man aber selbst schuld wenn man sowas macht. Klar kann ich eine Coroutine jedes Frame ausführen lassen, muss ich aber nicht.

Ich habe auch schon Methoden gesehen, wo jemand erst ganz am ende den yield return gesetzt hatte.:D

Share this post


Link to post
Share on other sites
Gerade eben schrieb runner78:

Ich habe auch schon Methoden gesehen, wo jemand erst ganz am ende den yield return gesetzt hatte.:D

Bin ja eh der Meinung so jemand sollte die Finger komplett vom "IEnumerator" weglassen und Invoke() und InvokeRepeat() verwenden :D

Share this post


Link to post
Share on other sites

Hab mal nachgeforscht, man kann zwar den Core für einen Prozess setzen, aber für einen Thread gestaltet es sich schwierig. Die Threads werden wohl entweder durchs Betriebssystem über die Kerne verteilt oder hängen am Kern ihres Prozesses, wobei letzteres schlecht wäre.

Hier ist Code zum Setzen eines Cores für einen einzelnen Thread, aber zumindest unter Unity scheint er nicht zu funktionieren:
http://blog.rebuildall.net/2010/03/08/Running_NET_threads_on_selected_processor_cores

Der Thread lief bei mir nicht an, immer wenn ich die "CurrentThread.ProcessorAffinity" gesetzt habe.

Mhh wirft eine Exception:
"Operation is not valid due to the current state of the object"

Share this post


Link to post
Share on other sites

Ok, das Problem ist, Unity gibt die Threads von sich selbst nicht zurück und daher wurde der Thread nicht gefunden und daher konnte ich die Affinität nicht setzen .. Unity 2017.1.2
https://forum.unity.com/threads/process-getcurrentprocess-threads-count-returns-zero-all-the-time.292069/

Hier ein ganz einfaches Beispiel, um den Fehler zu verdeutlichen. Auch wenn man selber einen Thread erzeugt, wird dieser nicht gelistet.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;

public class MultiCoreTest : MonoBehaviour
{
    void Start()
    {
        // Make sure there is an instance of Unity running.
        Process[] unityProcesses = Process.GetProcessesByName("Unity");

        // Sollte 1 zurückgeben
        UnityEngine.Debug.Log("Number of Unity processes: " + unityProcesses.Length); 
        ProcessThreadCollection threads;

        unityProcesses[0].Refresh(); // Sicherheitshalber noch einmal refreshen
        
        threads = unityProcesses[0].Threads;
        // Sollte > 0 zurückgeben
        UnityEngine.Debug.Log("Number of Unity threads: " + threads.Count);

        // Der Rest funktioniert leider nicht mehr, da keine Threads zurückgeben werden
        // Set the properties on the first ProcessThread in the collection
        // threads[0].IdealProcessor = 0;
        // threads[0].ProcessorAffinity = (IntPtr)1;

    }

Siehe auch:
https://msdn.microsoft.com/de-de/library/system.diagnostics.processthread.processoraffinity(v=vs.110).aspx

Share this post


Link to post
Share on other sites

Im Ressourcenmonitor von Windows kannst du nachsehen, wie viele Threads Unity verwendet, der Editor benutzt bei mir zwischen 124 und 127 Threads im Editromodus, im Gamemodus  ca. 128 (Unity 2017.3.0f1)

Ich denke, es ist wohl besser die Hände davon zu lassen, am Ende macht man alles nur schlimmer. 

Share this post


Link to post
Share on other sites

 

vor 8 Stunden schrieb Zer0Cool:

Hier ein ganz einfaches Beispiel, um den Fehler zu verdeutlichen. Auch wenn man selber einen Thread erzeugt, wird dieser nicht gelistet.

Nachtrag: Wenn man das Codebeispiel in einer einfachen .net Konsoleanwendung ausprobiert, listet er die Thread korrekt. Entweder ein Bug von Unity, oder Unity verhindert hier bewusst das manipulieren der Threads.

Share this post


Link to post
Share on other sites
vor 1 Stunde schrieb runner78:

 

Nachtrag: Wenn man das Codebeispiel in einer einfachen .net Konsoleanwendung ausprobiert, listet er die Thread korrekt. Entweder ein Bug von Unity, oder Unity verhindert hier bewusst das manipulieren der Threads.

Ja, vermutlich ein Bug:
https://stackoverflow.com/questions/28014662/current-process-without-threads?noredirect=1#comment44416985_28014662
 

Zitat

Im Ressourcenmonitor von Windows kannst du nachsehen, wie viele Threads Unity verwendet, der Editor benutzt bei mir zwischen 124 und 127 Threads im Editromodus, im Gamemodus  ca. 128 (Unity 2017.3.0f1)

Die interessante Frage ist aber, wie viele von diesen Threads laufen auf dem gleichen Core. Ich habe hier 12 Cores und Windows ist nicht in der Lage anzuzeigen, welche Threads auf welchem Core laufen.
Ich vermute nämlich, daß sich eine große Anzahl der Unity Threads auf dem gleichen Core tummeln.

Share this post


Link to post
Share on other sites

Sie sind leider nicht optimal verteilt, die Last verteilt sich auf die ersten 7 Kerne von insgesamt 12 Kernen. Scheinbar bevorzugt Unity auch die geraden Prozessorkerne.
Am meisten sind der Kerne 2 und 4 "belagert".
Dies kann natürlich von Betriebsystem zu Betriebssytem und von Unityversion zu Unityversion verschieden sein. Aber ich vermute trotzdem, daß die hinteren Cores oft frei sind...

Die Kerne 3,5,7,9,11 sind beispielsweise fast komplett ohne Arbeit. Dies kann aber auch am Hyperthreading liegen, wobei das OS gerade Kerne bevorzugt.
Wäre aber auch ein Ansatzpunkt, der dafür spricht, nebenläufige Tasks in Unity in die ungeraden hinteren Kerne zu packen, damit vom Hyperthreading profitiert wird.

K6se9lY.png

Share this post


Link to post
Share on other sites

Ich glaube das könnte wirklich Hyperthreading liegen.

Wenn man jetzt aber anfängt manuell die Thread auf bestimmte Kerne zu beschränken, kann es aber auch dazukommen, dass man einen Kern erwischt, der vielleicht von einem anderen Prozess stärker Ausgelastet wird.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


×