Von Latenz, Cores, Multithreading und SMT (Hyperthreading)

Da ich krank bin, im Bett liege und ich mich gerne ablenken möchte, schreibe ich mal zusammen, was ich über diese Themen weiß.

Vorab meine Qualifikation: ich bin Softwarearchitekt und seit 2001 als Entwickler tätig, hab mich in meiner Jugend exzessiv mit x86 auseinandergesetzt (Sound- und Grafikdemoszene, falls das jemandem hier etwas sagt). Programmiere heute hauptberuflich in C#, privat auch noch in C++, Ruby und x86-Assembler.

Ich schreibe das hier deshalb, weil ich damit ausdrücken möchte, daß das nicht irgendwelche “Spinnereien” oder “Halbwissen” darstellt, sondern durchwegs auf Fakten und, wo angegeben, “educated guesses” basiert.

Threads, Cores und Scheduling

Grundsätzlich ist es so, daß Windows SELBST das Konzept des “Threads” kennt, das ist tief in der sogenannten “Win32” (heute halt “Win64”) API verankert. Windows macht das grundsätzlich so, daß neu gestartete Threads auf jene Cores verteilt werden, die gerade am wenigstens zu tun haben.

Die Messung dazu basiert, wie übrigens ÄHNLICH (nicht identisch - bei DAWs ist da eine Besonderheit dabei, auf die ich später eingehen werde) auch bei Cubase, auf der Zeit, die einem Kern zwischen “Kontextwechseln” (das ist, wenn ein Kern von einem zugewiesenen Thread zum nächsten Thread schaltet) übrig bleibt. Meines Wissens nach wird das bei Windows über einen bestimmten Zeitraum ermittelt.

Nehmen wir also z.B. einen Dualcore-Prozessor her, ohne HT (um es einfacher zu halten).

Core 0 hat 70% Last, Core 1 hat 10% Last.

Kommt nun ein Thread dazu, dann wird dieser neue Thread zuerst Core 1 zugewiesen, weil ja Core 0 ohnehin schon recht tüchtig am werken ist.

Cubase, so wie die meisten DAWs wohl, erzeugt nun für jede Spur sinnvollerweise (das hätte ich exakt auch so programmiert) einen eigenen Thread. Die Zuteilung zu Cores erfolgt standardmäßig von Windows her durch den Windows-Scheduler, es ist aber auch möglich, über die sogenannte “ThreadAffinityMask” (so heißt das Konzept in der Windows-API), Threads durch das Programm zu “schedulen”.

(Scheduling = Threads einerseits auf die Cores zu verteilen und andererseits, diese auch “reihum” mit Rechenzeit zu versorgen. Ein Thread kann auch, durch sogenanntes “Yielding”, selbst sagen: “herst, ich bin fertig für den Moment, ich gebe freiwillig den Rest meiner mir zustehenden Rechenzeit ab”. Lustigerweise hieß die Methode in der Windows-API früher auch so. Nämlich “Yield()”. Heute nimmt man eher “Sleep()” dafür.)

Wie bereits angedeutet erfolgt die Zuweisung von Rechenzeit an Threads “reihum”, das heißt, daß mehrmals pro Sekunde zwischen den Threads pro Core umgeschalten wird. Das geht so schnell, daß der Benutzer (und auch der Programmierer in vielen Fällen) den Eindruck hat, daß die Threads nicht nur über Cores hinweg (dort ist es ja der Fall), sondern auch pro Core (dort wird umgeschalten) tatsächlich parallel laufen.

Die ASIO-Auslastung, die Spursynchronisation, die Divergenz zur CPU-Auslastung - und warum niedrige Latenzen übermäßig Rechenzeit fressen

Das ist ein happigeres Thema, weil hier viele Mißverständnisse vorliegen und viel Viertel- und (im Optimalfall oft) Halbwissen herangezogen werden, um ein Urteil zu bilden - und mir als Entwickler stellts dann manchmal die Haare auf, wenn ich die vielen Vermutungen lese (ist nicht böse gemeint, aber manchmal ist es wirklich schauderhaft).

Grundsätzlich zeigt die ASIO-Auslastung an, wieviel Zeit von der Zeit, die zur Berechnung eines gesamten Playbackbuffers zur Verfügung steht, tatsächlich gebraucht wird.

Rechenbeispiel:

Latenz = 10ms

Berechnungen für alle VSTis, etc… benötigen pro 10ms-Buffer 5ms ergibt eine ASIO-Auslastung von 50%.

Das wäre ja einfach. :slight_smile:

Aber:

Es gibt Abhängigkeiten. Sends, Gruppen, Sidechains. Hier muß synchronisiert werden.

Ein Beispiel:

Zwei Spuren + 1 Send.

Spur 1 braucht 1 ms, Spur 2 braucht 2 ms, beide senden auch zum Send.

Das bedeutet aber, daß der Send erst nach 2 ms überhaupt mit der Berechnung des, z.B., Halls beginnen kann. Vorher ists da zappenduster, weil der ja auf die Datenpakete der anderen beiden Threads warten muß (das nennen wir Entwickler übrigens “Threadsynchronisation”, bzw. ist das das Teilgebiet “Threadkommunikation”, das damit untrennbar verbunden ist).

Ist jetzt der Core, der mit dem Send beschäftigt ist, ansonsten unterbeschäftigt, dann kann es sein, daß hier sogar die ASIO-Auslastung gar nicht steigt, wenn auf diesem Core ein anderer Thread hinzukäme, weil der nur den freien Zeitslot der ersten 2 ms vor Einsetzen der Hallberechnung nutzen könnte.

Somit aber kann es sein, daß der Taskmanager unter Windows nur, hm, 10% CPU-Last anzeigt, die ASIO-Auslastung aber bereits bei 50% liegt, weil da eben, durch die Synchronisation bedingt, Rechenzeit brach liegt.

Warum aber brauchen nun niedrigere Latenzen mehr Rechenleistung?

Das hat folgende Gründe (ich HOFFE, die Liste ist erschöpfend, bin mir da aber nicht zu 100% sicher):

  1. Kontextwechsel (umschalten zwischen Threads) kosten Zeit durch Umladen der CPU-Register, Cache-Thrashing, etc… (früher sprach man auch noch vom hierzu nötigen Interrupt, aber heute lacht man über die paar Clockcycles, nebenbei bemerkt - die Pipeline des Cores muß auch neu befüllt werden, das ist aber nicht so schlimm, weil das eigentlich nur einem Branch Prediction-Miss entspricht, der zwar auch ungünstig, aber “zu überleben” ist)
  2. Manche (nicht alle) DSP-Algorithmen sind effizienter, wenn sie “durchgehalten” werden über größere Datenblöcke (wegen der Rechenzeit, die für die Initialisierung der Berechnung eines neuen Datenblocks benötigt wird)
  3. Der Sychronisationsaufwand steigt, wenn häufiger sychronisiert werden muß
  4. Unter bestimmten Umständen kann (muß aber nicht) auch die Kommunikationsinitialisierung mit der Audiohardware Rechenzeit fressen (da sind RME ziemlich vorn, die haben einfach ASIO direkt in die Hardware implementiert, was ich ziemlich leiwand finde, ich werde auch nie wieder was anderes kaufen)

SMT (Hyperthreading)

Was macht jetzt also Hyperthreading?

Nun, es ist so, daß der limitierende Faktor bei heutigen CPUs (pipelined, “superskalar”, RISCish, etc…), was die Ausführungseffizienz betrifft, eher auf der Seite des “architectural state” als bei den tatsächlich befehlsausführenden Einheiten zu suchen ist.

Soll heißen:

So eine CPU kann ur schnell z.B. multiplizieren - auch mehrere Multiplikationen auf einmal (das nannte man früher “superskalare Architektur”), aber die “Anlieferung” der CPU-Befehle und der innere Zustand der CPU (Register, Pipeline) sind hier limitierend.

Um jetzt die Ausführungseinheiten (z.B. eben so eine Multiplikatorschaltung) besser auszulasten, tut die CPU so, als wäre da nicht 1 Core, sondern gleich 2 Cores, wo in der Realität aber nur 1 Core vorhanden ist (der “architectural state” ist also 2x vorhanden, die Ausführungseinheiten bleiben aber gleich von der Zahl her).

Somit schaut eine 2-Core-CPU wie eine 4-Core-CPU aus.

Natürlich kann man damit nicht die volle Leistung einer mit doppelt sovielen echten Cores ausgestatteten CPU erreichen, aber man kann die Ausführungseinheiten besser auslasten (die stehen dann nicht einfach nur mit Zigarette und Bierflasche herum, sondern hackeln wirklich was) und so einiges an Leistung rausholen.

FRÜHER (!) war das ineffizient umgesetzt, sowohl im Betriebssystem (die frühen Scheduler kannten den Unterschied zwischen “echten” und “simulierten” Cores nicht und haben nicht darauf Rücksicht genommen, heutige Scheduler tun das aber), als auch in der CPU - darum war, in der PC-Bronzezeit (Mitte der Nullerjahre), Cubase OHNE HT besser dran.

Aber mit den heutigen Sandy Bridges, etc… ist das alles kein Thema mehr. Da würde ich eher mal ausprobieren, wie sich die eigenen Projekte mit HT verhalten. Bei MIR ists MIT HT wesentlich besser, aber das liegt wohl definitiv an der Projektstruktur.

Gute Besserung!!!
boa, Super Danke!!!

Hab angenommen das Cubase die “Pluginrechenzeit” verwaltet, darum dachte ich mir, dass eine Bitbridge sehr schlecht ist, weil da “Windows mit ins Spiel” kommt, was aber vl. anscheinend Blödsinn ist (kann man diese Cubase Threads auch im Taskmanager sehen?).

Bedeutet dass jetzt vl., so gut wie kein Leistungsunterschied wenn ein Plugin z.b. jBridge läuft als wenn man es in der x64 Version verwendet?

LG

Sollte kaum Unterschied machen. Ein paar Clockcycles kostet die Durchreichung via “marshalling”, das wars auch schon.

jBridge nervt eigentlich viel mehr, finde ich, weil man dazu Cubase mit Administratorrechten starten muß.

Inzwischen hab ichs aber auch gar nicht mehr im Einsatz, weil es jetzt auch den Largo in 64 Bit gibt.

Die Cubase-Threads kannst, wie alle anderen Threads, auch sehen. Sind ja normale Threads, die mit dem hier: CreateThread function (processthreadsapi.h) - Win32 apps | Microsoft Learn erzeugt werden.

Wegen dem Marshalling noch was - das ist ein sogenannter “RPC” (remote procedure call), der funktioniert “synchron”, das bedeutet, daß, aus Sicht der aufrufenden Applikation (Cubase) die Rechenzeit “auf eigene Kosten” geht, was natürlich das Handling einfacher macht.

Super Danke!!! muss ich mir mal genauer anschaun wenn ich wieder am Musikrechner sitz.

Was bedeutet eigentlich ASIO in Hardware gegossen? (meine alte Delta 1010lt konnte von der Perfomance mit dem HDSPe MultifaceII locker mithalten, Stabilität e.t.c. aber nicht…)

Hier im Forum hat TabSel einen extrem geilen “VST2 Plugin Manager” gemacht: Bei 32bit Plugins, soll man zuerst Automappen > jbridgen > und dann macht der “VST2 Plugin Manager” mit einer (glaub das heist VSTloader.dll oder so) quasi fake plugins (mit jeweiliger Plugin ID, und Namen) welche nur die richtigen Plugins (b.z.w. jbridge>automap>plugin) in den Adressraum holen (hoffe das sagt man so) und man dann wieder schöne pluginnamen, nicht doppelte “Automap versionen” (was beim Preset speicher laden blöd sein soll) und, einmal eingerichtet, alles so sortiert wie man will hat (für mehrer hosts wie man will). Hab nur positive Erfahrungen mit diesen “VST2 Plugin Manager” gemacht, aber ist eine “VSTloader.dll” (falls die so heißt) wirklich absolut unbedenklich?
http://www.familiekraft.de/PluginManager/

RME hat offenbar viele Funktionen der ASIO-Schnittstelle, die andere Hersteller halt in den Treibern abbilden, direkt in die Chips eingebaut. :slight_smile:

Solche Pluginmanager sollten, von der Theorie her, problemlos sein, weil sie ja im Prinzip nur eine Art “Schale” um das Plugin, das sie “managen”, herum legen.

Diese Durchreichung von Aufrufen ist dann halt ein weiterer “call” oder “jump” für die CPU, das kostet nicht allzuviel, vor allem, weil (meines Wissens nach, ich bin da jetzt aber NICHT zu 100% sicher) sogar die Pipeline korrekt mit den Befehlen in der richtigen Reihenfolge befüllt wird (ist ja keine sogenannte “Bedingung”, “condition”, dabei).

In der Praxis hängts halt von der Umsetzung ab.

ok. Super Danke!!! konnte keinen Unterschied feststellen bis auf die Verbesserungen die der “VST2 Plugin Manager” bringt. Bin leider “gezwungen” noch länger jBridge einzusetzen…

PS: Leiwande Musik was ihr da macht!!!


Cheers :smiley:

Danke! :slight_smile:

Hallo.

Ich wünsch dir schnell ne gute Besserung… auch wenn dadurch vielleicht kein so interessanter Artikel mehr ensteht.
Ich kann nicht behaupten, dass ich viel davon verstanden habe, aber ich finds toll, dass du dir die Zeit genommen hast, das so ausführlich zu erklären… bin beeindruckt.
Vor allem hab ich das über RME gerne gelesen, da ich mir erst neulich, unter finanziellen Schmerzen, ein UCX zugelegt hab. Aber ich denke nun, das wars dann wohl wert.
Als nächstes steht eine neue CPU aufm Plan, auch hier hat mich der Artikel übers HT etwas weitergebracht…

Als Hobby-Studioist solls jedoch die 500,-Euro-Grenze nicht so wahnsinnig übersteigen…
Deswegen bitte ich um nen Tip - i7 4790 (hört man nur Gutes) oder lieber 4930 oder noch was anderes?
Overclocken trau ich mich nicht, brauch dann auch keinen “K”, richtig?
Und… spielt das Mainboard so ne große Rolle? Hab bei einem Hersteller (ich glaub Asus) bereits 10 verschiedene Modelle mit Z97 gesehn.

Danke im Vorraus und Gruß, Vacsy

Ach ja, da wär noch ne Frage, die mir bisher NIEMAND beantworten konnte… darf ich?
Ich bin z.Zt. auf nem Phenom X4 840 mit MSI 880g-55e Mainboard, Win7 Home 64bit.
Habe mir 4x4GB RAM Corsair XMS3 1333 gegönnt.
Hier das Problem: bei 2 Riegeln, also 8 GB läuft der PC einigermaßen rund, bis auf einige Freezes pro Abend, die ich aber nicht zuordnen kann, jedoch nur im Cubase-Betrieb vorkommen.
Bei allen 4 Riegeln freezt der Rechner so ca. nach Benutzeranmeldung, also gleich beim Desktop.
Hab alle Riegel in allen Steckplätzen ausprobiert und das Mainboard ist auch für 16 GB ausgelegt…
Auch Bios passt und erkennt auch 16 Gb, aber Windows freezt. (War auch bei neu aufgesetztem System so…)
Hab mich zwar seither mit 8 GB “abgefunden” aber mein Halion4 ist schon am meckern.

Jetzt aber tschüß :smiley:
Wo in aller Welt muss ich suchen?

Bevor ich antworte: wovor genau hast beim Overclocken Angst?

Hi,
ich rühr ja sebst das Bios kaum an… :smiley:
Nee, im ernst, ich hab grade geschrieben, das mir mein PC mehrere Male am Tag einfriert, abstürzt oder Cubase lahmlegt.
Ein Overclocken geht meines Wissens, oder eher Halbwissens, zu Lasten der Stabilität…
noch mehr unstabil packen meine Nerven nicht :wink:
Ausserdem weiß ich nicht, was man da noch an Frequenzen, Bus Takt MHz, Voltage und Zeugs einstellen muss,
also lass ich da eher die Finger von…

Nimm trotzdem den 6-Kerner. Gerade eine DAW skaliert sehr schön mit den Cores. :slight_smile:

Das wäre dann der 4930… richtig? Mal schauen ob das mein HeimMusiker Budget zulässt :slight_smile:

By the way, fällt dir irgendwas zu dieser RAM-Geschichte ein? selbst sog. Fachleute konnten mir noch nichts dazu sagen…

Naja, bei Speicherübertaktung passiert das manchmal - oder bei hohen CPU-Übertaktungen kann es sein, daß bei Nutzung von mehr Bänken Instabilitäten auftauchen (z.B. habe ich deshalb nur 32 GB und nicht 64 GB in der Kiste, zur Sicherheit).

Aber unter normalen Bedingungen finde ich das strange.

Meine Vermutung: Motherboard.

ok, ist eh ein neues in Planung nebst CPU…
ich danke dir nochmals und wünsche gute Besserung.
Toller Artikel, wirklich…

Waren übrigens kürzlich in Wien, nettes Städtchen.

Hab jetzt mal im taskmanager reingeschaut: unter details konnte ich keine anderen prozesse außer cubas selbst die bridge und videoshice e.t.c. finden. Hab ich falsch geschaut?

Lg

Ja, Du musst die Anzahl der Threads betrachten, nicht die Prozesse.

1 Prozess = 1…n Threads

Super Danke!!!