see wald
web biz

  seewald webbiz  
 
  



   

  Parallelisierung, MultiCore, ManyCore, ...
 

   
Die Zeit des Geschwindigkeitsrausches ist vorbei, zumindest was die Prozessoren betrifft, die heutzutage in Workstations, Servern und Laptops verbaut werden. Höhere Taktraten sind aufgrund der geltenden physikalischen Gesetze nicht mehr DIE Lösung für eine bessere Performance (neben der Optimierung der Instruktionen und des Cash-Speichers). Dafür werben die Hersteller mit neuen Produkten wie Dual-Core, Quad-Core, etc.. In diesen Lösungen sind mehrere (Haupt)Prozessoren auf einem einzigen Chip untergebracht und das in einer symmetrischen Art und Weise. Das heisst, die Kerne sind identisch und können dieselben Aufgaben erfüllen. Die einzelnen Kerne erhalten dabei einen eigenen Cash, der weitere Möglichkeiten der Performanceoptimierung bietet. Okay, das war die Hardware. Leider kann die Software diese neuen Möglichkeiten nicht in jedem Fall per se nutzen; sie muss darauf vorbereitet sein. Der Weg dahin ist steinig und kompliziert und wird leider durch die existierenden Compiler, Entwicklungsumgebungen und Frameworks nicht genügend unterstützt. Hier muss man zwischen den existierenden Programmiersprachen und Laufzeitumgebungen (Java, .NET) unterscheiden, die verschiedene Ansätze bieten. Dazu kommen Frameworks wie OpenMP und MPI, die in der Welt des Hochleistungsrechnens schon länger existieren. Neuerdings denkt man in dem Kontext der Parallelisierung auch wieder über funktionale Programmiersprachen nach. Wie man leicht erkennen kann, ist die Lernkurve für Entwickler hoch und die Fehlerquellen sind zahlreich. Dazu kommt, dass es oft Unschärfen in den Begrifflichkeiten gibt, vor allem wenn es um Multi-Threading, Hyper-Threading und Multi/Many-Core sowie Multi-Tasking (im Rahmen von Betriebssystemen) geht. Oft wird die Parallelisierung in der Softwareentwicklung mit dem Meilenstein Objektorientierte Programmierung verglichen. Dieser Vergleich ist durchaus realistisch. Ich befasse mich auf meinem Blog mit dem Thema Parallelisierung und möchte dabei Lösungen und aktuelle Trends aufzeigen.   

Use-Cases und Problemstellungen im Bereich Nebenläufigkeit und Parallelisierung 

Ich habe die Thematik bereits mehrfach angerissen – „Wann ist welche Art von Parallelisierung sinnvoll und wann nicht?“. Diese Frage steht in engem Zusammenhang mit vielen Unschärfen in den Begrifflichkeiten. Ich möchte keinesfalls engagierte Entwickler davon abhalten, sich in dieser Herausforderung zu stellen. Aber ähnlich zum Lernkurven-Vergleich drängen sich auch hier Analogien mit dem Meilenstein Objektorientierung in der Softwareentwicklung auf. Es gibt Code der ist „dermaßen objektorientiert“ geschrieben, dass er unübersichtlich, kaum wartbar und nicht mehr weiterverwendbar ist. Ein typischer Fall, beim dem über das Ziel hinausgeschossen und damit die Objektorientierung konterkariert worden ist.

Was hat das mit Parallelisierung zu tun? Im Prinzip gilt auch hier der Ansatz: was ist die konkrete Anforderung und welche Use-Cases (Anwendungsfälle) lassen sich daraus ableiten? Wobei man die Zielplattform (Systemarchitektur) nicht vernachlässigen darf. Hier eine (nicht vollständige) Liste von Fragen, mit Hilfe derer man einer Lösung näher kommen kann:
 

  1. Wie sieht die HW-Architektur der Zielplattform aus (Schlüsselworte: Hyprerthreading, symmetrische oder asymmetrische MultiCore-CPU’s, Shared Memory, Distributed Memory)?
  2. Welches Betriebssystem mit welchen Laufzeitumgebungen und Programmiersprachen werden auf der Zielplattform eingesetzt? Dabei ist das Betriebssystem immer mehr zu vernachlässigen, da präemptives Multitasking heutzutage Allgemeingut ist und damit zumindest parallele Prozessausführung gegeben ist.
  3. Ist Performance die wichtigste nicht-funktionale Anforderung? Mit Performance sind in diesem Zusammenhang Datendurchsatz und Verarbeitungsgeschwindigkeit gemeint. Hier geht es auch um den Fakt, dass die Zeiten höherer Taktraten vorbei sind und der Cache leider nicht die Lösung aller Probleme darstellt.
  4. Haben die betreffenden Use-Cases einen synchronen oder asynchronen Charakter?
  5. Wie soll der Datenaustausch zwischen Ausführungsströmen (ich verwende diesen Begriff hier ganz bewusst) erfolgen und in welchem Umfang? Benötige ich Zugriff auf „shared“ Ressourcen und in welchem Umfang?

Ausgehend von der Beantwortung dieser Fragen kann eine Architektur entwickelt werden, die den Anforderungen genügt und die auf die richtigen Lösungen setzt. Richtig bedeutet in diesem Zusammenhang auch, dass die passenden Techniken verwendet werden um weitere nicht-funktionale Anforderungen wir Wartbarkeit, Erweiterbarkeit, Testbarkeit und Einfachheit (!) zu erfüllen. Ich möchte und kann an dieser Stelle keine Entscheidungsmatrix liefern; werde aber kurz ein paar Lösungsmöglichkeiten skizzieren.

  • Wenn Punkt 3 das entscheidende Kriterium ist, sollte eine gute Auslastung der zur Verfügung stehenden Rechenkerne das Ziel sein. Es gibt in diesem Fall immer noch die Möglichkeit, eine Lastverteilung der Prozesse als Lösung zu wählen. Sollte dies aufgrund der Problemstellung (Arithmetik, etc.) nicht möglich sein, muss der Weg über eine Verteilung der Threads gefunden werden. Hier bietet sich beispielsweise OpenMP an. Natürlich kann sich Punkt 3 auch mit Punkt 5 überlagern, wenn auf viele „shared“ Variablen zugegriffen werden muss.  Es ist anzumerken, dass OpenMP uns nicht vor Race-Conditions oder Dead-Locks bewahrt.
  • Bezüglich Punkt 4 gibt es sicherlich die am weitesten entwickelten Lösungsmöglichkeiten und gute Chancen, diese Problemstellung umfassend zu lösen. Eine gute Entkopplung sowie asynchrone Kommunikationsmechanismen sind hier die Erfolgkriterien. Konkrete Anwendungsfälle existieren vor allem im Umfeld von Benutzerschnittstellen (UI’s) auf Clientsystemen. Ausführungsströme (z.B. Threads) in der Präsentationslogik sollten von der Geschäftslogik mithilfe geeigneter asynchroner Kommunikationsmechanismen getrennt werden, um gezielt eine lose Kopplung zu erreichen.
    Ich möchte noch anmerken, dass die Aufgabenstellung in Punkt 5 (Asynchronität) für mich nicht originär zur Problemdomäne Parallelisierung / Nebenläufigkeit gehört, in der Diskussion aber dort oft eingeordnet wird.
  • Punkt 5 ist sicherlich die komplizierteste Aufgabenstellung, da bisher nur wenig Unterstützung durch Entwicklungsumgebungen, Compilern und Frameworks vorliegt. Bis es diese gibt (beispielsweise auf der Grundlage von Konzepten des „Transactional Memory“) muss man noch mit all den Schwierigkeiten des „Lock-Free Programming“ leben. Dazu gehört natürlich ein ausgefeiltes Testkonzept, um Dead-Locks und Race-Conditions auf die Spur zu kommen. Generell kann ich hinsichtlich Punkt 5 nur empfehlen, Architektur und Design hinsichtlich alternativer Lösungsmöglichkeiten des Datenaustausches genau zu prüfen.  

Natürlich ist anzumerken, dass es auch einen Mix an Lösungen geben kann. Als konkretes Beispiel im Hochleistungsrechnen sind Hybridanwendungen aus MPI (Message Passing Interface) und OpenMP zu nennen.

  

 
 
 home    seewald webbiz    top  

Dipl.-Ing. Maik G. Seewald, Computer Professional, Software Architect, Security Expert, CISSP
© 1996-2010 seewald webbiz •  Dresden, Nuremberg / Germany
 
 
see wald
web biz