Multi-Prozessor-Systeme: Was nützen die vielen Kerne wirklich?
|Dass auch die Rechenpower von Quad-Core-, Dual-Quad-Core- oder 12-Kerne-Maschinen nicht unbegrenzt ist, kann man als Binsenweisheit betrachten. Was bringen leistungsstarke Prozessorausrüstungen in der Praxis wirklich? Wie viel von der Kraft der multiplen Kerne kommt der Echtzeitberechnung von Audioprozessen wirklich zugute? Wer schon einmal die Leistungsanzeige innerhalb des Sequencers mit der des Betriebssystems verglichen hat, wird wahrscheinlich festgestellt haben, dass die Anzeigen erheblich voneinander abweichen: Während der Sequencer schon das Erreichen der Leistungsgrenze signalisiert oder es gar zu Audio-Aussetzern kommt, weist die Anzeige des Betriebssystems noch eine stattliche Reserve aus. Im Einzelfall kann die Diskrepanz ohne weiteres an die 80 % betragen. 80 % Rechenpower, die einfach brach liegt? Woran liegt das, was kann man dagegen tun? Diesen Fragen wollen wir in unserem Artikel nachgehen.
Da das Thema sehr komplex ist und letztlich nur Software-Entwicklern gänzlich transparent, haben wir zwei von Ihnen befragt: Stephan Bernsee, freier Software-Entwickler, und Georg Conrads von Steinberg. Die banale Antwort auf die oben gestellte Frage “woran liegt das”, nämlich die Erklärung, dass die Sequencer-Software es einfach nicht schafft, die Prozessoren auszulasten, ist sicher zu kurz gegriffen, erklärt nichts und ist letztlich sogar falsch. Am Audio-Prozess sind viele Mitstreiter beteiligt, auch der User selbst – es gibt also Einiges zu erörtern.
Inhalt
- Komponenten, die für die Rechenauslastung verantwortlich sind
- Testsystem 1, Jürgen Drogies
- Testsystem 2, Holger Obst
- Wie kommt es, dass die Prozessorpower nicht ausgeschöpft wird?
- Antworten vom Experten: Georg Conrads, Steinberg
- Antworten vom Experten: Stephan Bernsee, freier Software-Entwickler
- Was tun, wenn dem Rechner die Puste ausgeht?
- Was leistet das Audio Interface?
Komponenten, die für die Rechenauslastung verantwortlich sind
- Die Hardware des Rechners: Allem voran sind es die Prozessoren mit vorgeschaltetem Cache
- Das Audio-Interface
- Das Betriebssystem – und hier der für Audioprocessing zuständige Bereich (Beim Mac: Core Audio)
- Der Sequencer, der die zu errechnenden Aufgaben an die Prozessoren adressiert.
- Die Plug-ins und virtuellen Instrumente.
- Das User-Management: die Auswahl der Plug-ins, die Verteilung der Plug-ins auf unterschiedliche Kanäle.
Tipps für die Arbeitsweise und die Ausnutzung der zur Verfügung stehenden Rechenpower finden Sie im Kapitel 8 “Was tun, wenn dem Rechner die Puste ausgeht?”
Begleitend zur theoretischen Erörterung haben wir exemplarische Tests an verschiedenen Systemen durchgeführt, also verschiedene Projekte unter verschiedenen Hosts auf verschiedenen Rechnern laufen lassen und die beiden Leistungsanzeigen (Host und Betriebssystem) gegenübergestellt. Die Resultate sollen in erster Linie veranschaulichen, worum es geht. Sie sind untereinander nicht vergleichbar in dem Sinne, dass die Ergebnisse nicht als Aussage über die Prozessor-Auslastungsfähigkeit des betreffenden Sequencer-Programms reduziert werden kann. Sie sind auch nicht ausreichend standardisiert, um einen Vergleich zwischen den verschiedenen Systemen oder gar Sequencern zuzulassen.
Wir würden uns freuen, wenn Leser ihre persönlichen Testergebnisse als Kommentar zu diesem Artikel anhängen. In diesem Fall bitte eine Beschreibung des Systems (Rechner / Prozessorausstattung / Betriebssystem / Host-Sequencer Version / Audio-Interface mit verwendeter Buffer-Size (und, wenn möglich, Latenzangabe) hinzufügen. Auch eine Angabe über die Anzahl der Spuren und die verwendeten Plug-ins wäre hilfreich.
Testsystem 1 – Jürgen Drogies, 26. Januar 2011
Nachdem im Sommer 2010 neue Mac Pro Modelle mit 6 und 12 Prozessorkernen auf den Markt gekommen waren, konnte man im Logic Diskussionsforum (Apple Discussions, Forum Logic Pro) lesen, dass nicht alle Kerne von Logic ausgenutzt würden. Einige User waren sogar der Meinung, ein Mac der vorherigen Generation mit 4 Kernen sei leistungsfähiger als ein neuer mit 6, weil durch das Hyperthreading einschließlich der virtuellen Kerne 8 Prozessorkerne zur Verfügung stünden.
Das kurze Zeit danach erschienene Update auf Logic Pro 9.1.3 brachte die Sache wieder ins Gleichgewicht. Seitdem werden die physischen Kerne der neuen Geräte ausgelastet, wenn auch nicht gleichmäßig. Das ist genau genommen kein Bug, sondern ein Feature, denn Apple weist in einem Support-Dokument darauf hin, dass die Plug-ins eines Mixerkanals immer nur von einem Prozessorkern verarbeitet werden. Sollten Überlastungen auftreten, wird empfohlen mit Bussen zu arbeiten und die Plug-ins auf Bus-Kanäle zu verteilen.
Seit September 2010 besitze ich einen Mac Pro mit 12 Prozessorkernen und kann deshalb meine Erfahrungen mit der Prozessorauslastung zum vorliegenden Artikel beisteuern.
Zunächst die technischen Angaben
- Mac Pro 2 x 2,66 GHz 6-Core Intel Xeon, 8 GB RAM
- Mac OS X Snow Leopard 10.6.6
- Logic Pro 9.1.3
Alle Versuche wurden zweimal durchgeführt und zwar jeweils mit einer Puffergröße von 128 und einmal mit dem Wert 1024. Um es vorweg zu sagen: Ich konnte beim Abspielen der Songs hier keinen Unterschied in der Performance feststellen wie auch die Screenshots belegen. Meiner Meinung nach hat die Puffergröße nur eine Auswirkung auf die Latenz beim Einspielen, die wurde aber in diesem Test nicht bewertet.
Ich habe für meine Beispiele gleichzeitig die interne Systemauslastungs-Anzeige von Logic und die Aktivitätsanzeige des Systems eingeblendet.
Die verwendeten Songs enthalten Audiospuren, Instrumentenspuren (so heißen bei Logic die internen MIDI-Spuren, die Plug-in-Instrumente abspielen) aber keine MIDI-Spuren um externe Instrumente zu triggern, da ich solche nicht mehr besitze. Es gibt jede Menge Plug-ins zur Klang- und Dynamikbearbeitung sowie Hall. Nur wenige davon gehören zum Lieferumfang von Logic, die meisten sind von anderen Herstellern als Apple.
Beispiel A
Ein Song mit 13 Audiospuren und 12 Instrumentenspuren. Hier fällt die Diskrepanz zwischen den beiden Anzeigen auf, wie auch bei allen folgenden Beispielen. Die Logic-interne Anzeige, die gar keine Darstellungsmöglichkeit für virtuelle Kerne bietet, zeigt hinter dem achten Balken eine Lücke, erst bei Nummer zwölf ist wieder etwas Aktivität zu sehen. Die Aktivitätsanzeige des Systems zeigt eine recht gleichmäßige Auslastung an, in Slot 14 ist sogar etwas Aktivität für einen virtuellen Kern dargestellt, ich vermute von einem Systemprozess außerhalb von Logic. Die Screenshots zeigen zuerst das Ergebnis mit der Puffergröße 128 und an zweiter Stelle 1024.
Beispiel B
Eine reine Audioproduktion. 38 Audiospuren, zahlreiche Dynamik- und EQ-Plug-ins und Hall.
Beispiel C
Ein Screenshot mit dem Buchstaben c wie “crash”. Ich habe unter meinen Songs leider (nein, zum Glück!) keinen gefunden, der den Mac richtig zum Schwitzen bringt. Ich bin deshalb in Frankensteins Fußstapfen getreten und habe ein Monster erschaffen: 77 Spuren (etwa halb und halb Audio/Instrumente), 65 Plug-ins aller Sorten. Kurzzeitige Systemüberlastungen kann man schon mit weniger Aufwand bewerkstelligen, aber diese treten meistens nur auf, wenn ein bestimmtes Plug-in zum ersten Mal angesprochen wird. Spielt man den Song von vorn, ist alles OK. Ich wollte aber den totalen Crash-Kandidaten und habe dutzendweise Kontakt-Sampler und algorithmische Hall-Plug-ins eingebaut sowie Absynth, Reaktor und was es noch alles für eine DAW zu beißen gibt. Als Ausgangsmaterial diente der Song von Bespiel A, bei dem ich Spuren einschließlich Inhalt auf neue Spuren kopiert und zahlreiche Plug-ins hinzugefügt habe.
Der Screenshot zeigt den Stillstand und die Warnmeldung von Logic bei der Buffereinstellung 128. (Es gab keinen Unterschied bei der Puffergröße 1024.) Logic stürzte auch bei diesem Versuch nicht ab, ich konnte einige Plug-ins deaktivieren und damit den Song wieder zum Laufen bringen.
Interessanterweise sieht es so aus, als könnte das System noch wesentlich mehr verkraften, da die blauen Balken nur jeweils ein Drittel Auslastung aller 12 Kerne anzeigen. Logic verzichtet ganz darauf, Kern 11 zu benutzen und auf der 12 ist auch kaum etwas zu sehen.
Fazit
Sicher lässt sich in Bezug auf die gleichmäßige Auslastung der Prozessorkerne noch einiges optimieren. Bei meinen Anforderungen reicht es aber aus, wenn acht bis neun Kerne zuverlässig arbeiten. Ob es überhaupt sinnvoll oder möglich ist, virtuelle Kerne in Realtime-Anwendungen wie Audioprogramme einzubeziehen, kann ich nicht beurteilen. Der Trend, dass Software immer höhere Anforderungen an die Hardware stellt, geht sicher weiter. Ich hoffe, dass Apple gleichzeitig Logic und Mac OS X immer mehr an die Mehrkernprozessoren anpassen wird.
Testsystem 2 (Holger Obst)
Versuch 1 unter OSX 10.5.8, Cubase 5.5, Buffer-Size 128 Samples, Motu 828 mKII (weist eine Gesamtlatenz von ca. 7 ms aus bei 44,1 kHz Sampling Rate, 24 Bit):
Test A
Mit zwei Schwergewichten, 2C Aether (Reverb), auf 4-faches Oversampling eingestellt, und dem FXpansion-Synth Cypher aus dem DCAM Bundle, auf 8-faches Echtzeit-Oversampling eingestellt, war es kein Problem, die ASIO-Last-Anzeige mit den Spikes in den roten Bereich zu treiben. Laut Mac Aktivitätsanzeige kamen die 8 Kerne dabei nicht wirklich zum Schwitzen: 5 % Systemlast, etwa 20-22 % Benutzerlast.
Erhöhe ich die Puffergröße auf 1024 Samples (Gesamtlatenz 48 ms, für’s Einspielen untauglich und nur für den Mix zu gebrauchen), so zappelt die ASIO-Anzeige nicht mehr und kommt bei etwa 65-70 % zur Ruhe. Die Mac Aktivitätsanzeige meldet 2,39 % Systemlast und etwa 17,6 % Auslastung durch den Benutzer.
Geht man davon aus, das 2C Aether und Cypher nur von je einem Prozessor berechnet werden, verzerrt dies natürlich das Bild – die anderen Prozessoren kommen gar nicht mehr zum Zuge und daraus ergibt sich zwangsläufig eine geringe Auslastung der Prozessoren in ihrer Gesamtheit.
Test B
Daher starte ich einen zweiten Versuch mit verschiedenen Effekt- und Audio-Bearbeitungs-Plug-ins, verteilt auf 10 Spuren. Zum Einsatz kommen Waves-Plug-ins, der Amplitube 3 von IK Multimedia mit vollgepackten Effektracks (immer eine gute Methode, den Prozessor zu fordern), ein Softube TSAR-1. Im Gegenzug schalte ich das Oversampling bei 2C Ather und Cypher aus. Bei 128 Samples Buffer zappelt die ASIO-Anzeige wieder von 60 % an aufwärts, vereinzelt treten Überlastungen auf. Die Mac-Aktivitätsanzeige weist knapp 26 % durch den Benutzer und etwa 5,5 Prozent durch das System aus. Es sieht so aus, als ob es Cubase nicht gelingt, die Rechenaufgaben gleichmäßig auf alle Kerne zu verteilen: knapp 70 % des CPU-Leistungspotenzials bleibt unangetastet. Die Verteilung der Plug-ins auf Kanäle entspricht in etwa der üblichen Praxis, Effekte dort einzusetzen, wo man sie braucht, ohne Rücksicht auf deren Anforderungen an die CPUs und ohne Rücksicht auf die Funktionsweise des Algorithmus, der die Rechenlast auf die Prozessoren verteilt.
Bei einer Puffergröße von 1024 Samples liegt die ASIO-Last stabil bei etwa 55 %, die Systemlast bei 3 % und die Benutzerlast bei 17 %, etwa 80 % inaktiv – ein nach wie vor ernüchterndes Bild.
Auf dem selben Rechner unter 10.6.6 im 32-Bit-Modus sieht es folgendermaßen aus
Test A
128 Samples Puffergröße: ASIO 100 %mit Aussetzern, Systemlast 5,5 %, Benutzer ca. 24,5 % 1024 Samples Puffergröße: ASIO etwa 72 % stabil, Systemlast 3 %, Benutzer 25 %.
Test B
128 Samples Puffergröße: ASIO-Anzeige: zappelt zwischen 70 und 80 %, Systemlast 5,8 %, Benutzer ca. 29 %, inaktiv: 65 % 1024 Samples: ASIO Anzeige stabil bei etwa 50 %. Benutzer 20,5 %, System 2,7 %, inaktiv: 70 % Die Größe des Puffers hat auf die Verteilung der Rechenaufgaben auf die einzelnen Kerne offensichtlich keine oder nur eine untergeordnete Bedeutung.
Test C
Den dritten Test habe ich nicht zu Ende geführt, da Cubase (reproduzierbar) beim Versuch, eine vierzehnte Instanz des Hall-Plug-ins Reverence zu öffnen, den Dienst quittierte (Grafikfehler, anschließend Freeze). Trotzdem sind die Zwischenergebnisse interessant: Ich habe ein Projekt mit 36 Stereospuren angelegt, das Motu auf 128 Samples eingestellt und die Tracks 1-25 jeweils mit dem 4-Band parametischen EQ, dem Effekt “Mod-Machine” und dem Kompressor geladen (alles Cubase On-Board-Mittel). In Track 12-25 habe ich zudem Reverence eingebaut. Es ergab sich eine ASIO-Last von etwa 37 % mit Spikes bis ca. 43 % und eine Systemlast von 34 bis 35 %. Dieses Mal lagen die beiden Werteangaben also deutlich näher beieinander. Zwischendurch habe ich in den Master-Out den Brainworx bx_XL (Mittel-Seitensignal-Limiter mit diversen Sonderfunktionen) geladen. Dieses Plug-in ist eigentlich für das Mastering gedacht und sollte erst ganz am Schluß (bei großer Buffer-Size) eingesetzt werden, da es zu den Schwergewichten in punkto CPU-Last zählt. Die ASIO-Anzeige schnellte sofort um etwa 20 % in die Höhe, die CPU-Last der Mac Aktivitätsanzeige legte hingegen kaum merklich zu. Die Ursache ist naheliegend: Alle anderen Plug-ins, säuberlich auf die Einzelspuren verteilt, werden von allen Prozessoren berechnet. Die acht Kerne tun ihren Dienst und kommen zur Geltung. Der Brainworx bx_XL wird offenbar nur von einem Kern berechnet, sodass es bei der Gesamtkonstellation zu einem Ungleichgewicht kommt, mit der Folge, dass die Rechenlast über alle acht Kerne hinweg zwar kaum ansteigt (ca. 2-3 %), die “Langsamkeit” der Berechnung des Limitings durch einen Prozessor verkleinert jedoch das noch offene Zeitfenster in der ASIO-Anzeige.
Zum Schluß habe ich noch etwa zehn weitere Instanzen des bx_XL bevorzugt in die Kanäle, in denen nur Kompressor und Mod-Machine eingebunden waren, geladen. Die ASIO-Last stieg kaum an, während sich die CPU-Aktivitätsanzeige deutlicher nach oben bewegte und sich der ASIO-Last annäherte. Offensichtlich wurden die folgenden Limiter-Instanzen auf andere Kerne verteilt, die zuvor “pausiert” hatten, um die Berechnung des ersten vollgepackten Kanals abzuwarten.
Fazit
Bei gleichmäßiger Bestückung der einzelnen Tracks eines Projekts mit Plug-ins kommt das Potenzial der Prozessoren doch noch zum Zuge. Allerdings lassen sich künstlerische Bedürfnisse und mischtechnische Notwendigkeiten nicht immer so regeln, dass dieses Prinzip der gleichmäßigen Lastenverteilung gewährt bleibt.
Einen Test im 64-Bit Mode habe ich nicht durchgeführt, da sich herausstellte, dass einige der in den Tests 1 und 2 verwendeten Plug-ins derzeit auf dem Mac noch nicht als 64-Bit-Anwendung laufen.
Meine Ergebnisse im tabellarischen Überblick
- Cubase 5.5
- Cubase 6 (32 Bit)
- Test A, 128 Samples
- 100 % / 27 %
- 100 % /30 %
Test A, 1024 Samples
- 68 % / 20 %
- 72 % / 28 %
Test B, 128 Samples
- 60 % / 31,5 %
- 75 % / 35 %
Test B, 1024 Samples
- 55 % / 20 %
- 50 % / 25 %
Test C, 128 Samples
- 37 % / 35 %
Zwischen den beiden Konfigurationen A: Cubase 5.5 auf OSX 10.5.8 und B: Cubase 6.0 auf OSX 10.6.6 gibt es für meinen 8-Kerne-Mac keine signifikanten Unterschiede in dem Sinne, dass nach dem Update von OSX und Cubase ein deutliches Leistungsplus zu verzeichnen wäre.
Wie kommt es, dass die Prozessorpower nicht ausgeschöpft wird?
Zunächste eine kurze Einleitung zum Thema: Eingangs haben wir bereits erwähnt, dass mehrere Komponenten an dem Prozess beteiligt sind. Es gibt also nicht nur einen “Schuldigen”, das System schafft es insgesamt nicht, den Vorgaben durch den User optimal gerecht zu werden – und auch der User kann durch eine Anpassung seiner Vorgaben, sozusagen mit einer geschickten Dosierung der Plug-ins die gleichmäßige Verteilung der Rechenaufgaben und die bessere Auslastung des Systems unterstützen.
In Cubase beschreibt die ASIO-Last-Anzeige das Zeitfenster, das für die Berechnung zur Verfügung steht, bzw. wieviel davon noch offen ist. Die ASIO-Reserve entspricht der ungenutzten Zeit, und die Größe des Fensters hängt von der Einstellung der Buffer-Size im Audio-Interface ab. Verkürzt dargestellt beschriebt dieses Zeitfenster also die Latenz: Man gibt dem Rechner 5, 10, 20 oder mehr Millisekunden Zeit, alle Aufgaben zu erledigen, danach möchte man das Ergebnis hören. Dieses Zeitfenster muss statisch und kann nicht variabel sein, sonst würde es zu einer ungleichmässigen Wiedergabe mit Drop-Outs kommen. Die starre Definition von x Millisekunden Berechnungszeit hat zur Folge, dass die ASIO-Anzeige manchmal zappelt: Plötzliche aufwändige Rechenaufgaben benötigen mehr Zeit und verringern die Reserve, einfache Aufgaben laufen schneller ab. Der Anspruch der Rechenaufgaben innerhalb eines laufenden Songs hängt vom Einsatz der Plug-ins und der virtuellen Instrumente ab und ist nie absolut linear, sondern ungleichmäßig. Der Anspruch des Users ist, dass zu keinem Zeitpunkt Audioaussetzer auftreten dürfen. Das Zeitfenster muss also so gewählt werden, dass es in dem Moment ausreicht, in dem der Rechenanspruch an das System am höchsten ist und am meisten Zeit benötigt wird. Dies hat zur Folge, dass in den Passagen, in denen nur einfache Aufgaben zu bewältigen sind, die Prozessoren Pause machen bzw. nicht vollständig ausgelastet sind.
Sowohl ASIO- als auch Aktivitäts-CPU-Anzeige geben nur Durchschnittswerte wieder (unter Cubase signalisiert die ASIO-Anzeige durch eine rote Warn-LED zusätzlich Überlastungspeaks). Die eruierten Testwerte sind insofern mit einer gewissen Vorsicht zu genießen – Spitzenauslastungen werden hier unter Umständen nicht ausreichend abgebildet.
Antworten vom Experten: Georg Conrads, Steinberg
Wo liegen die ursächlichen Probleme dafür, dass die Auslastung der Prozessoren nicht gelingt und die Leistungsgrenze der Audio-Echtzeitberechnung schon weit vorher erreicht wird?
Da gibt es zahlreiche Ursachen, wie z. B. das Betriebssystem, die Rechnerarchitektur, die Prozess-Synchronisierung, die Speicherlatenz, der ASIO-Treiber und nicht zuletzt die Struktur des Projektes selbst (welche unabhängigen Signalpfade gibt es) etc. Das Zusammenspiel dieser ist immer Gegenstand aktueller Forschung hier bei Steinberg.
Wer ist eigentlich für die Verteilung der Aufgaben zuständig? Ein Scheduling-Algorithmus des Sequencer-Programms oder das Betriebssystem OSX oder beide? Wie bezieht der Algorithmus Informationen über den Umfang der Rechenaufgaben? Ist es Aufgabe der Plug-in-Anbieter, diese so zu programmieren, dass sie dem Compiler entsprechende Angaben liefern, sodass ein Grund der unzureichenden Prozessorauslastung vielleicht auch schlecht programmierte Plug-ins bzw. VIs sein können?
Das Echtzeitprocessing eines Plug-ins findet immer nur auf einem Kern statt. Der Host übernimmt bei einem Projekt die Abhängigkeitsanalyse der Signalpfade und verteilt die Plug-ins entsprechend auf die Prozessorkerne. Letztendlich hat dann allerdings der Scheduler des Betriebsystems das letzte Wort und da verhalten sich PC und Mac sehr unterschiedlich.
Kann man erwarten, dass mit 64-Bit-Berechnungen die Prozessoren endlich besser ausgelastet werden und wenn ja, wird dies ein deutlicher oder eher ein marginaler Unterschied sein?
32 oder 64 Bit haben keinen Einfluss auf das Multiprocessing, allerdings schon auf die Performance generell (da z. B. bei 64 Bit mehr Register zu Verfügung stehen). Unterscheiden muss man hier zwischen der Adressierbarkeit des Speichers im 64 Bit-Modus und tatsächlichen 64-Bit-Floating-Point-Berechnungen machen. Bei letzteren müssen dann im Vergleich zu 32 Bit auch doppelt so viele Daten bearbeitet werden. Übrigens ist es schon seit den x87-CPUs möglich, dass 32-Bit-Plugins jederzeit intern sogar mit 80-Bit Genauigkeit rechnen können.
Stephan Bernsee, Software Entwickler und Co-Autor mehrerer Plug-Ins und MacOS X Audio-Applikationen
Vom Standpunkt eines Plug-In Entwicklers gibt es vereinfacht gesagt beim Zusammenspiel von CPU-Auslastung, Puffergröße und Playback-Latenz (gemeint ist hiermit die Verzögerung, die zwischen der aktuell angezeigten Song-Position und dem Hörbarwerden des entsprechenden Klanges entsteht) drei grundsätzliche Größen, die zu beachten sind:
- die Zeit, die für die Bearbeitung eines Puffers durch den Algorithmus eines Plug-Ins benötigt wird
- die Anzahl der Puffer, die beim Lesen, der Bearbeitung und der Ausgabe verwendet werden
- die Größe des Puffers, der zur Bearbeitung verwendet wird
Da der Speicher im Computer nicht unendlich groß ist und man nicht alle Audio-Dateien auf einmal in den Speicher laden kann oder möchte, bearbeitet man sie in kleineren “mundgerechten“ Stücken, in einzelnen Puffern. Diese Puffer werden zum Beispiel mit Daten aus einer Audiodatei gefüllt, dann an das Plug-in weitergereicht und dort bearbeitet. Wenn nun ein Prozess in Echtzeit arbeiten und direkt auf Änderungen an der Benutzeroberfläche reagieren soll, beispielweise während gerade abgespielt oder aufgenommen wird, dann muss (a) immer kleiner sein als die Zeit, die man benötigt, um den Puffer abzuspielen. Sonst holt der Abspielvorgang den Berechnungsvorgang irgendwann ein und es entstehen Drop-Outs, also hörbare Knackser. Die momentane CPU-Auslastung alleine durch den DSP Prozess ergibt sich in diesem Falle durch die Formel 100 % * (Zeit die für die Berechnung des Puffers benötigt wird) / (Zeit die für das Abspielen des Puffers benötigt wird).
Einfaches Beispiel: Ausgehend von einem 1 Sekunden großen Puffer (bei 44.1 kHz Sample Rate sind das 44100 Sample Frames) wenden wir auf diesen Puffer einen Filter an. Angenommen dieser Filter ist in einer halben Sekunde fertig berechnet dann ergibt sich eine CPU-Auslastung für diese Berechnung von 100 % * 0.5 Sekunden / 1 Sekunde = 50 %. Anders gesagt, die andere Hälfte der Sekunde bleibt der Filter untätig, und die Leistung steht z. B. anderen Prozessen zur Verfügung.
Während der Berechnung des Puffers könnte das System nun bereits damit anfangen, ihn abzuspielen. Da der Berechnungsvorgang stets schneller abläuft als der Abspielvorgang läge der Berechnungsvorgang im Idealzustand zeitlich immer VOR dem Abspielvorgang. Nun ist es aber so, dass sich Berechnen und Abspielen eines Puffers üblicherweise gegenseitig ausschließen – in der Regel wird der fertig berechnete Puffer an das System zurückgereicht, das darauf noch weitere Bearbeitungen anwendet. Anpassen der Sampling-Frequenz und des Ausgabeformats an die Hardware der Soundkarte sind typische Beispiele. In einer Sequenzer-Umgebung kommen hier zusätzlich noch Mixer-, Effekt- und Masterwege und alle damit zusammenhängenden Berechnungen ins Spiel. Der fertig berechnete Puffer wird am Ende der Kette dann z. B. an CoreAudio zum Abspielen übergeben und erst dann tatsächlich hörbar. Das heißt aber, dass es hier eigentlich um (mindestens) zwei Puffer geht: einen zum Berechnen, einen zum Abspielen, während bereits der nächste berechnet wird. Hier kommt das erste Mal die oben erwähnte Latenz ins Spiel: der Abspielvorgang ist aus diesem Grund also immer mindestens einen Puffer später dran als die Berechnung. Bei großen Puffern ist das aus ebendiesem Grund eine lange Zeit, bei kleinen eine kurze. Die Größe des Puffers bestimmt damit die kleinstmögliche Verzögerung (= Latenz) die hier zwischen Berechnung und Hörbarkeit zum Tragen kommt.
Wie sieht das Ganze denn nun aus, wenn mehrere CPUs zur Verfügung stehen?
Grundsätzlich ändert sich nichts am Prinzip, nur dass die Verteilung der Aufgaben innerhalb eines Programmes anders aussieht. Dabei gibt es verschiedene Ebenen, auf welchen man als Software-Entwickler ansetzen kann um mehrere Prozessorkerne im eignen Programm bzw Plug-in zu nutzen. Man kann beispielsweise direkt am Algorithmus ansetzen. Das macht Sinn, wenn ein Algorithmus Berechnungen vornimmt, die für eine gewisse Zeit völlig unabhängig voneinander stattfinden können. Man sagt in einem solchen Fall, dass der Algorithmus “parallelisierbar“ ist, da innerhalb des Algorithmus einzelne Aufgaben unabhängig voneinander (“parallel“) ausgeführt werden können.
Als einfaches Beispiel: die Aufgabe A+B=C kann ich nicht parallelisieren, da A und B beide für die Bildung von C notwendig sind. Die Summenbildung A+B+C+D=E kann ich dagegen problemlos parallelisieren, indem ich z. B. den einen Prozessor A+B und den anderen (gleichzeitig dazu!) C+D berechnen lasse, und dann das Ergebnis (A+B) + (C+D) hinterher in einem getrennten Schritt zu E addiere. Die Operationen A+B sowie C+D finden dabei zur selben Zeit statt, der Vorgang ist also trotz derselben Anzahl an Additionen insgesamt schneller als die Bildung von A+B+C+D, bei welcher die Additionen nacheinander erfolgen. Dabei sind A, B, C und D nicht zwingend nur als reine Zahlenwerte zu sehen, sondern können auch größere Einheiten sein, wie z. B. unterschiedliche Signalpfade, Programmteile, oder nach bestimmten Kriterien ausgewählte Teilstücke des Audiosignals (z. B geradzahlige und ungeradzahlige Sample Frames).
Nicht jeder Algorithmus ist auf diese Weise parallelisierbar. Speziell bei Audioanwendungen ist eine derart großräumige Parallelisierung sogar häufig nicht möglich, da zeitlich später liegende Sample Frames meist in ihrer Berechnung direkt vom Ergebnis vorangehend berechneter Sample Frames abhängig sind. In den Fällen, in denen eine Parallelisierung zwischen Prozessoren möglich wäre, lohnt es sich nicht immer, diese auch innerhalb des Plug-ins auszunutzen, da hierfür Algorithmen oft aufwendig umgeschrieben werden müssen und der erzielte Geschwindigkeitsgewinn dann meist nur noch marginal ist. Zudem kann dieses Vorgehen auf Systemen, bei welchen nur ein Prozessor zur Verfügung steht (oder alle bis auf einen gerade ausgelastet sind) dann sogar die Leistung verschlechtern. Man nutzt daher bei der Audiobearbeitung – anders als bei der Videobearbeitung – in den meisten Fällen nur kleinräumige Parallelisierungen wie z. B. SIMD Befehle, die dann aber innerhalb desselben Prozessorkerns berechnet werden.
Auf modernen Betriebssystemen gibt es außer der Parallelisierung im Algorithmus aber noch eine ganze Reihe anderer Möglichkeiten, um als Entwickler Aufgaben innerhalb eines Programmes zum Beispiel auf mehrere Prozessoren zu verteilen. Dabei legt man zunächst die Aufgaben fest, schreibt also kleinere Programmabschnitte, die unabhängig voneinander ausgeführt werden sollen und stellt darüber hinaus durch entsprechende Maßnahmen sicher, dass die Ergebnisse in zeitlich vorhersehbarer Weise bereitgestellt und zusammengefügt werden können. Gelingt dies nicht, beispielsweise weil durch hohe Auslastung das Programm anders arbeitet, als der Entwicker das vorhergesehen hat, kommt es zu einer sogenannten “Race Condition“, ein Zustand bei welchem die verschiedenen Prozesse oder ihre Ergebnisse zeitlich durcheinander geraten und im schlimmsten Fall zu einem Absturz führen können.
Obwohl man diese Programmteile unabhängig voneinander erstellen und ausführen lassen kann, hat man in der Praxis nur sehr wenig Einfluß darauf, auf welchem Prozessor welche Aufgabe dann tatsächlich ausgeführt wird, da diese Entscheidung vom System nach bestimmten Kriterien gefällt wird. Darauf im Einzelnen einzugehen und die Vor- und Nachteile der verschiedenen Techniken darzustellen, wäre hier zu komplex. Im Falle von Audio Plug-Ins gibt es im Wesentlichen aber zwei Aufgaben, die sich gut trennen lassen: zum einen die Darstellung und Handhabung der Bedienung der Benutzeroberfläche (Regler, Animationen etc.) und zum anderen die eigentliche Bearbeitung der Audiodaten. Das sind zwei Aufgaben, die gut zu trennen sind, da sie nur über die Parameter des Algorithmus miteinander verbunden sind. Bei Apple AudioUnit Plug-ins wird dem Entwickler diese Aufteilung von der AudioUnit-Schnittstelle sogar schon abgenommen, man muss sich also nicht weiter darum kümmern, diese Aufgaben selbst zu verteilen. Wenn es nur einen Prozessor gibt, dann kümmert sich das System auch selbst darum, diese beiden Prozesse so miteinander zu verschachteln, dass der Eindruck entsteht, sie würden auch hier parallel ablaufen.
Ein anderes Beispiel für eine parallele Ausführung mehrerer Aufgaben ist die Bearbeitung eines Audiosignals durch einen Faltungshall. Eine Aufgabe könnte dabei die eigentliche Filterung übernehmen, während ein parallel dazu ausgeführter Programmteil zum Beispiel eine vorgegebene Bearbeitung der Impulsantwort vornimmt – beispielsweise um eine Änderung der Hüllkurve zu berechnen. Je nach Verfügbarkeit können dann unterschiedliche Prozessorkerne diese Aufgaben parallel zueinander übernehmen.
Bei all diesen parallel ausgeführten Aufgaben ist die systemweite Berechnung der CPU-Last nicht immer trivial. Zunächst einmal muss man sich darüber klar sein, was man da genau misst, auf welche Weise (wer ist der Zeitgeber und wie präzise ist er) und wie oft, sprich wie genau zeitlich aufgelöst diese Messung ist. Beim systemweiten Messen kann man zum Beispiel periodisch nachsehen, welcher Code gerade auf einem Prozessor ausgeführt wird. Rechenintensiver Code wird dabei in dieser Statistik häufiger auftauchen als Code, der nur alle paar Sekunden einmal ausgeführt wird. So kann man stichprobenartig ermitteln, mit welchen Aufgaben ein beobachteter Prozessorkern häufig beschäftigt ist. Auch die Häufigkeit der Messung ist eine wichtige Größe: Zu oft möchte man nicht messen, da dann die Messung, die ja ebenfalls ein kleines Programm ist das Rechenzeit benötigt, selbst zu einer sichtbaren Auslastung führen würde. Misst man zu selten, verpasst die Messung eventuell kurzzeitig auftretende Lastspitzen.
In vielen Programmen werden deshalb nur bestimmte interne Prozesse gemessen – zum Beispiel die oben erwähnte Zeit, die für die Berechnung eines Audio-Puffers benötigt wird. Diese kann bequem über die Messung der Zeitdifferenz zwischen vor und nach der Berechnung des Puffers ermittelt werden. Hierbei wird aber die Last außerhalb der Berechnung, z. B. die durch das Dekodieren von Audio-Dateien und die durch systemrelevante Aufgaben außerhalb des Programmes entstehende Belastung (z. B. für die Audio-Ausgabe) gar nicht gemessen – die angezeigte Last erscheint dann niedriger als sie tatsächlich ist und es kann trotz scheinbar geringer Auslastung zu Aussetzern kommen.
Anmerkung für den Selbstversuch
- Auf DSP Dimension steht ein kostenloses CPU-Last AudioUnit Plug-In namens “CPU Hog“ zum Download bereit
Auch innerhalb des Algorithmus ist eine Messung nicht immer unproblematisch: Bei vielen DSP-Algorithmen ist es so, dass innerhalb des berechneten Puffers nicht jedes Sample-Frame dieselbe Zeit für die Verarbeitung benötigt. Bei der Berechnung einer Fourier-Transformation werden z. B. zunächst eine ganze Weile nur Daten gesammelt (= geringe Auslastung), und dann wird auf einen Schlag die Umwandlung in die Fourier-Darstellung durchgeführt. Dieser Prozess ist natürlich aufwendiger als das Datensammeln, weswegen hier die CPU-Auslastung pro Sample Frame kurzzeitig in die Höhe schnellt. Von “außen“ ist über die Dauer des Puffers nur die durchschnittliche Auslastung sichtbar, obwohl man momentan innerhalb des Puffers für einen sehr kurzen Zeitraum sogar mehr als 100 % Auslastung erreichen kann. Die Auslastung erscheint dabei dann in der Messung unter Umständen niedriger, als sie eigentlich ist. Auch hier kann dann bei scheinbar niedriger Last das System an die Leistungsgrenze stoßen, ganz besonders dann, wenn sehr kleine Puffer verwendet werden.
Was tun, wenn dem Rechner die Puste ausgeht?
Wer bis hierhin gelesen hat, dem dürfte klar sein, wie komplex das Thema ist. Einen Vorteil kann man aus dieser Komplexität schon ziehen: Es gibt verschiedene Lösungsansätze, und die der beste heißt nicht “sofort den schnellsten Rechner kaufen, den es gibt”.
Lösungsvorschlag 1: Haushalten mit CPU-Leistung
Rechenintensive Plug-ins sind nicht zwingend auch die besten. Zwar ist es schon richtig, dass die Hersteller die steigende Leistung der Hardware nutzen und Programme schreiben, die diese auch zunehmend einfordert, beispielsweise indem internes Oversampling eingebaut wird, doch das Gesetz “Je mehr Leistungsverbrauch, desto besser der Sound” stimmt nicht. So gibt es beispielsweise den Wave Arts Tube Saturator, eine Röhrensimulation, die schnell mal die ASIO-Last auch eines aktuellen Rechners um 50 % und mehr in die Höhe treibt (bei mittlerer Buffer-Size) und daneben den Redline Preamp von 112dB, der wesentlich genügsamer ist und über ein viel breiteres Spektrum an Möglichkeiten verfügt. Die Kombination aus gutem Sound und geringem CPU-Verbrauch sollte ein Argument für eine Kaufentscheidung sein.
Lösungsvorschlag 2: CPU-schonende Arbeitsstrategie
Es macht zwar mehr Spaß, wenn schon die ersten Spuren eines Projekts hitverdächtig klingen und der Sound einen schier umhaut. Die Eqs, Kompressoren, Effekte und Hallinstanzen, die das möglich machen, versperren aber später den Einsatz eines weiteren leistungshungrigen virtuellen Instruments, zu einem Zeitpunkt, zu dem man noch mit niedrigen Latenzen arbeiten will. Besser ist es, von vorneherein Sounds auszuwählen, die von sich aus gut klingen und prima zusammenpassen. Dann werden Plug-ins für’s erste kaum benötigt.
Lösungsvorschlag 3
Jürgen hat das bereits geschrieben: Braucht man in einem Kanal tatsächlich mehrere CPU-fressende Plug-ins, so sollte man einen Teil davon auf einen Bus legen, der dann automatisch von einem anderen Prozessor berechnet wird. Das hilft dem Compiler bei der gelichmäßigen Arbeitsverteilung.
Lösungsvorschlag 4
Freezen, Bouncen, ASIO-Buffer-Size hochsetzen, wenn man das Einspielen von Tracks hinter sich hat.
Lösungsvorschlag 5, vor allem für weniger leistungsstarke Rechner
DSP-karte einbauen. Es empfiehlt sich eine Variante der UAD 2, eventuell auch gebraucht. Eine Kostenkalkulation und genaues informieren hilft bei dieser Option Geld zu sparen: Welche Plug-ins, welches Hardware/Software-Bundle brauche ich? Sind Effekte dabei, die ich in dieser Qualität noch nicht habe, sodass der Zugewinn nicht nur in der besseren Rechnerperformance besteht?
Lösungsvorschlag 6
Die Leistungsfähigkeit des Audio-Interfaces überprüfen und hier ggfls. investieren, siehe Kapitel 9.
Lösungsvorschlag 7
Ein schnellerer Rechner. Die Warnung: “Never change a running System!” sollte man ernst nehmen. Je nach Umfang des Software-Equipments ist mit erheblichem Arbeitsaufwand zu rechnen, Supportanfragen und evtl. kostenpflichtige Updates inklusive. Der Grad an Unzufriedenheit mit dem bestehenden System sollte hoch sein.
Was leistet das Audio Interface?
Kommt man mit den Lösungsvorschlägen 1-5 nicht weit genug, sollte man sich vor der Anschaffung eines neuen Rechners mit mehr Kernen die Werte des Audio-Interfaces ansehen. Je schneller das Interface, desto mehr Berechnungszeit steht bei einer akzeptablem Latenz zur Verfügung. Dem Interface kommt damit eine zentrale Bedeutung bei der Bereitstellung von Rechenpower im Echtzeitbetrieb zu.
Wieviel Latenz (hier: Eingangs- + Ausgangslatenz) ist noch OK?
Profis mit lupenreinem Timing fühlen sich schon bei einer Latenz oberhalb von 5 Millisekunden zunehmend unwohl. Gemeint sind timingsensible Menschen, die beim Ticken jeder Uhr das Eiern der Mechanik heraushören – oder die Synchronisationsschwankungen des Interfaces. Bedenkt man, dass der Schall etwa 5 ms benötigt, um eine Distanz von 1,7 Metern zurückzulegen, so müssten sich die Betroffenen auch Gedanken darum machen, ob sie die Boxen nicht näher an die Ohren rücken bzw. nur noch mit dem Kopfhörer einspielen sollten. Setzen wir einen normalen Abstand zu den Nahfeldmonitoren voraus und wollen ohne Kopfhörer als einigermaßen sensible Musiker das Echtheitsgefühl beim Einspielen nicht verlieren, so ist eine Latenz zwischen 7 und 12 Millisekunden sicher akzeptabel. Beim späteren Abmischen ist es hingegen völlig egal, ob das Signal 50 Millisekunden oder noch stärker verzögert wiedergegeben wird, und man kann die Latenz bequem hochsetzen.
Um eine Latenz dieser Größenordnung zu erreichen, benötigt man bei den meisten USB-Audiointerfaces eine Puffergröße von nur noch 64 Samples, bei einigen Kandidaten sogar 32 Samples. D.h.: Um groovig einzuspielen, muss man die Arbeitszeit des Rechners bei USB-Interfaces je nach Modell stark einschränken. Der Nachteil liegt auf der Hand: Solange noch live am Projekt gearbeitet wird, sind viele Plug-ins tabu. Der genialste Effekt bringt nichts, wenn der Groove daneben geht – und Quantisierungen sind immer die zweitbeste Wahl.
Bei Firewire-Interfaces sieht es schon besser aus. Wenn die Treiber sauber programmiert sind, kommt man mit 128 Samples deutlich unter 10 Millisekunden Gesamtlatenz. Noch schneller geht es mit guten PCI-Karten – Billigstprodukte aus dem Consumerbereich sind hingegen absolut ungeeignet.
Grundsätzlich gilt aber: Die Unterschiede innerhalb der jeweiligen Interface-Gattung sind enorm. Auch im “professionellen” Angebot für Musiker gibt vergleichsweise langsame PCI-Karten, die von guten Firewire-Interfaces übertroffen werden und angenehm schnelle USB-Interfaces, die kaum Wünsche offen lassen. Wenig erfreulich sind Kandidaten, bei denen die Treiber unsauber programmiert sind und dem Host falsche Werte anzeigen, um schneller auszusehen als sie in Wirklichkeit sind. Solche unehrliche Kosmetik kann zu frühzeitigen Audio-Aussetzern, zum ungenauen Aufnahmestart oder zu Synchronisationsproblemen zwischen Interface und Rechner führen, die die Klangqualität beeinträchtigen. Bei der Wahl des Audio-Interfaces ist also ein Check der Latenzwerte (soweit vom Hersteller angegeben) und ein genauer Test nach dem Eintreffen des Geräts empfehlenswert. Das Fernabnahmegesetz hilft bei Fehlgriffen.
Wir danken Stephan Bernsee und Georg Conrads für ihre Beiträge, ohne die dieser Artikel nicht möglich gewesen wäre.
Holger Obst