Vorheriger Beitrag: Parallel Talk: Warum Ct und Rapidmind gut zusammenpassen
Apps unter Mac OS X multicore-tauglich machen
Disclaimer: Dieser Beitrag ist ein Extrakt des Artikels “Mehrkern-Beschleuniger”, der in der mac-developer 1/2010 erschienen ist. Autor dieses Beitrags ist Maximilian Götzfried.
Ende August war ich bei Apple, um ein wenig mehr über deren Multicore-Beschleuniger Grand Central Dispatch zu erfahren. Diese in Snow Leopard implementierte Technik erlaubt es Anwendungsentwicklern, mit relativ wenig Aufwand, ihre Anwendungen multicore-tauglich zu machen. Und das ohne größeren Programmieraufwand, sondern lediglich mithilfe der C-API und den NSOperation-Klassen.
Das Tolle an GCD ist deren einfache Verwendung: Anstatt selbst Threads auf Basis von Tasks oder anderen Objekten zu erzeugen, kümmert sich GCD selbst darum. Das bedeutet aber für den Software-Entwickler, dass er sich für eine optimale Ausnutzung der vorhandenen Prozessorressourcen grundsätzlich Gedanken machen muss über die Programmlogik. Das Resultat seines überarbeiteten Programms sind einzelne Tasks, die je nach Programmablauf an die vorhandenen Multithreading-Queues übergeben werden können, wo sie von GCD bestmöglich verarbeitet werden.
Wie bereits angedeutet, stellt GCD zwei Möglichkeiten zur Verfügung, Programmcode zu multithreaden: Mithilfe der NSOperation-Klasse und der C-API. Beides soll kurz beleuchtet werden.
NSOperation: Warteschlangentechnik für asynchrone Tasks
Für das asynchrone, also zeitversetzte Ausführen von Anwendungen ist lediglich das Erstellen von NSOperation-konformen Objekten erforderlich, die dann an die zugehörige Warteschlange übergeben werden, die die Queue nach dem FIFO-Prinzip verarbeitet. Hierfür werden Tasks im Hintergrund ausgeführt, pausiert und zu Ende geführt. Es ist sogar möglich, die Anzahl der maximalen Threads festzulegen, was in Extremfällen ein einziger sein kann. Natürlich erlaubt GCD die ständige Rückkehr zum Main Thread.
Sehr hilfreich ist auch das “Verketten” mehrerer Threads, um so bestimmte Abhängigkeiten zu definieren. Hierzu gehört auch die Möglichkeit, Thread zu priorisieren. Darüber hinaus lassen sich NSOperation-Threads mit Rückgabewerten definieren, die während des Programmablaufs dann weiter verwendet werden können.
Grand-Central-Dispatch-API
Neben den NSOperation-Klassen erlaubt die GCD-API das direkte Verwenden der vorhandenen Funktionen. Hierfür kann man entweder eigene Queues erzeugen oder auf die globale Warteschlange zugreifen. Es existieren drei globale Queues, die sich lediglich in ihrer Priorität unterscheiden. Daneben gibt es natürlich auch eine Main Queue, die die Steuerung des Main Threads übernimmt.
Im Gegensatz zu den globalen Queues funktionieren eigene Warteschlange rein seriell, womit sie beispielsweise in Bereichen eingesetzt werden können, die bis dato mit Hilfe von Locks überwacht wurden. Queues werden blockweise gefüllt, der zugehörige Code wird asynchron im Hintergrund ausgeführt. Für eine problemlos Rückkehr zur Main Queue sollte jeder Block eine Callback-Funktion aufweisen, die auf das “Hauptprogramm” verweist. Natürlich lassen sich Queues auch pausieren (suspend) und weiter ausführen (resume).
Weitere wichtige GCD-Techniken
Neben den Klassen und APIs stehen weitere Techniken in GCD zur Verfügung, die man als Entwickler kennen sollte. So ermöglichen beispielsweise Semaphore die bessere Kontrolle bgrenzter Ressourcen. Aber auch Deadlocks lassen sich dank GCD besser vermeiden, Blöcke können zeitlich gesteuert genutzt werden, Systemereignisse lassen sich effizient und einfach überwachen und vieles mehr.



Trackbacks & Pingbacks