Unix für speichergekoppelte Multiprozessoren:

Synchronisation unterstützt Anwenderprozesse

05.12.1986

Die große Verbreitung des Unix-Betriebssystems legt nahe, es auch bei speichergekoppelten Multiprozessorsystemen einzusetzen. Für spezielle rechenintensive Applikationen ist es sinnvoll, unter der Kontrolle des Benutzers auf die einzelnen Prozessoren spezielle Anwenderprozesse zu laden, die über geeignete Synchronisationsmechanismen auch zusammen an einer Aufgabe arbeiten können.

Der Betriebssystemkern läuft auf einem dedizierten Prozessor und übernimmt die Verteilung der Prozesse sowie die Bearbeitung deren Systemaufrufe. In einer typischen Unix-Umgebung ist es wegen der hohen Rate der Systemaufrufe notwendig, alle Prozesse gleichberechtigt Anwender- und Systemroutinen ausführen zu lassen. Dies erfordert eine zusätzliche Synchronisation der einzelnen Prozessoren innerhalb des Betriebssystemkerns. Für den Benutzer bleibt dies transparent, er arbeitet wie an einem Einzelprozessorsystem. Dadurch wird eine schrittweise Erhöhung der Rechenleistung durch zusätzliche Prozessoren ermöglicht.

Mehrprozessorsysteme unter Unix

Bei Mehrprozessorsystemen ist die Art der physikalischen Kopplung der Prozessoren entscheidend für die Sicht, die ein Benutzer von dem Gesamtsystem hat. Bei einer losen Kopplung über ein Netzwerk besitzt jeder Prozessor sein eigenes Betriebssystem. Es existieren lediglich Kommunikationsmechanismen zwischen den einzelnen Rechnern, die für den Benutzer mehr oder weniger transparent sind. Eine enge Kopplung über gemeinsame Speicher ermöglicht jedoch die Kontrolle aller Prozessoren durch ein Betriebssystem.

In diesem Zusammenhang ist nur die Kopplung über lokale Netzwerke (LAN) interessant. Hier haben sich am Markt Ethernet und Token-Ring-Systeme durchgesetzt. Viele Hersteller von Rechnersystemen unterstützen in ihren Unix-Systemen eine Kopplung über lokale Netze. Die Zielsetzung liegt dabei im Datenaustausch zwischen den einzelnen Rechnern; ein Benutzer arbeitet vorwiegend auf dem eigenen Prozessor. Ihm stehen mehr oder weniger transparent die folgenden Möglichkeiten zur Verfügung:

Remote File Access

Es wird der Zugriff auf Dateien, die auf einem anderen Rechner liegen, ermöglicht.

Resource Sharing

Spezielle E/A-Geräte wie Magnetband oder besondere Drucker können von allen Rechnern aus benutzt werden.

Remote Execution

Ein Benutzer kann explizit einen Prozeß auf einem anderen Rechner starten.

Remote Login

Der Benutzer kann sich über den eigenen Rechner bei einem anderen Rechner des Systems anmelden und dort rechnen.

Obwohl alle Hersteller großen Wert auf Effizienz legen, ist der Zugriff auf Daten über ein Netz immer langsamer als lokal, was sich besonders bei extremen Anforderungen bemerkbar macht. Derartige Systeme gehen daher immer davon aus daß ein Großteil der Zugriffe lokal sind.

Im Gegensatz zu Systemen, die über ein lokales Netzwerk verbunden sind, ist der Betrieb von speichergekoppelten Prozessoren unter einem Unix-System selten. Das liegt zu einem Großteil daran, daß Unix für Einprozessorsysteme konzipiert wurde.

Bisher werden lediglich intelligente E/A-Prozessoren eingesetzt, die in einem gemeinsamen Speicher vom Hauptprozessor Auftrage erhalten und diese selbständig abarbeiten. Dadurch wird die Belastung des Zentralsystems durch E/A-Treiber reduziert.

Es sind auch Systeme realisiert worden, die auf jedem Prozessor einen eigenen Unix-Kern laufen lassen. Durch zusätzliche Mechanismen, die nicht dem Unix-Standard entsprechen, ist über das Shared-Memory eine Interprozessorkommunikation möglich. Funktional ist dabei kein großer Unterschied zur Kopplung über ein Netzwerk. Eine Verlagerung von Prozessen von einem Prozessor auf einem anderen ist nicht möglich.

Manche Hersteller haben auf einen bestehenden Multiprozessor-Betriebssystemkern eine Unix-Oberfläche gesetzt. Dies bringt Probleme bei der Einhaltung der vollen Unix-Semantik mit sich. Unter der zusätzlichen Schnittstelle kann auch die Effizienz leiden.

Die Zielvorstellung für ein echtes Multiprozessor-Unix liegt jedoch in einer Implementierung, die nur auf den Hardwaremechanismen aufbaut. Das Erscheinungsbild eines Unix-Systems für speichergekoppelte Prozessoren sollte sich von dem für Einzelprozessoren nicht unterscheiden. Ebenso sollte die Semantik der Schnittstelle zum Unix-Kern unverändert bleiben. Der Vorteil gegenüber einem Netz von Rechnern besteht darin, daß die Leistung des Systems durch zusätzliche Prozessoren auch für einzelne Benutzer oder eine Applikation gesteigert werden kann. Alle Prozesse können je nach Anwendung dynamisch oder statisch auf die einzelnen Prozessoren verteilt werden um die vorhandene Prozessorleistung von auszunutzen.

Die Steigerung der Rechenleistung kann durch die parallele Abarbeitung von Unix-Prozessen erreicht werden. Zur Erhöhung der Ein-/Ausgabeleistung müssen ebenfalls Lösungen gefunden werden.

Hardwarestrukturen für ein Mehrprozessor-Unix

Der Aufbau eines Unix-Systems für mehrere Prozessoren und die Sicht, die der Benutzer davon hat, ist stark von der vorhandenen Hardwarestruktur abhängig. Dies gilt insbesondere, wenn man großen Wert auf Effizienz legt.

Es ist entscheidend, ob der gesamte Speicher von allen Prozessoren aus erreichbar ist oder jeder auch lokalen Speicher besitzt. Der gemeinsame Speicherbereich sollte auf jeden Fall so groß sein, um alle Datenstrukturen des Unix-Kerns und das Speicherabbild der Unix-Prozesse darin ablegen zu können. Letzteres ist Voraussetzung für eine einfache Verlagerung von Prozessen.

Für ein Multiprozessor Unix wäre es von Vorteil, wenn das System aus gleichartigen Prozessoren bestünde. Sie sollten zumindest auf Objektcodeebene kompatibel sein und äquivalente Trap- beziehungsweise Interruptmechanismen besitzen.

Für manche Applikationen ist auch eine inhomogene Prozessorstruktur denkbar. In diesem Fall kennt der Benutzer die Systemstruktur und legt selber fest, welche Prozesse auf welchem Prozessor laufen. Dies kann so auf eine bestimmte Applikation abgestimmt werden, daß die größtmögliche Leistung erzielt wird.

Da ein System aus mehreren Prozessoren über wesentlich mehr Rechenleistung verfügt, sollte auch die Ein-/Ausgabeleistung gegenüber einem Einzelprozessorsystem gesteigert werden. Dies muß schon beim Entwurf der Hardwarestruktur beachtet werden, noch wichtiger ist es aber, die vorhandenen Hardwarekomponenten durch das Betriebssystem auch effizient zu nutzen. Hier sind folgende Kriterien von besonderer Bedeutung:

- bestmögliche Ausnutzung aller vorhandenen Übertragungswege zwischen E/A-Geräten und Speicher

- möglichst verzögerungslose Reaktion auf Unterbrechungen durch E/A-Geräte

- große Parallelität der E/A-Vorgänge

Diese Überlegungen können zu einer Konfiguration führen, bei der an jedem Prozessor einige der peripheren Geräte angeschlossen sind, die somit auch parallel bedient werden können. Eine andere, durchaus realistische Alternative bestellt darin, alle Geräte an bestimmte Prozessoren anzuschließen, die ausschließlich E/A-Aufgaben haben. Als dritte Alternative wäre denkbar, daß jedes Gerät von allen Prozessoren aus erreichbar ist und durch geeignete Hard- und Softwaremechanismen an einzelne Prozessoren dynamisch zugeteilt werden.

Zusatzbelastung so klein wie möglich halten

Da aus Benutzersicht die Ein-/Ausgabe auf jedes Gerät von jedem Prozessor aus möglich sein muß, sollte das Betriebssystem Mechanismen beinhalten, die E/A-Aufträge von einem Prozessor zum anderen weiterleiten. Die dadurch im Vergleich zu einem Einzelprozessorsystem entstehende zusätzliche Belastung muß so klein wie möglich gehalten werden. Dies stellt an das E/A-System eines Mehrprozessor-Unix große Anforderungen.

Die erste reale Mehrprozessoranlage, die den Überlegungen für ein Multiprozessor-Unix zugrunde lag, war der 3260MPS von Concurrent-Computer. Er kann aus bis zu 10 Prozessoren bestehen, die alle zusammen auf einen globalen Speicher zugreifen. Einer der Prozessoren (CPU) ist der Master des Systems und kontrolliert die restlichen Prozessoren, die entweder als Rechen- (Application-Processing-Unit) oder E/A-Prozessoren (Input/Output Processor) konfiguriert werden können. Die beiden Prozessortypen sind objektcodekompatibel, besitzen aber jeweils besondere Fähigkeiten.

APU:

- Task-Scheduling im Microcode

- Mechanismen zum Task-Passback an die CPU

- nur primitive E/A-Mechanismen IOP:

- leistungsfähige E/A-Mechanismen

- kein Task-Konzept

Es existieren leistungsfähige Mechanismen zur Kommunikation zwischen den Prozessoren. Über spezielle E/A-Befehle kann die CPU folgende Aktionen auslösen:

- Link-check

- Start APU task excution

- Passback task to CPU

- Reschedule APU

- Stop APU and checkpoint task

- Report status

Die Zahl der Prozessoren sowie die Aufteilung in APUs und IOPs ist wählbar und den Anforderungen der Applikation anpaßbar. Die E/A-Geräte können entweder lokal an den einzelnen Prozessoren angeschlossen oder über einen Bus-Switch von allen Prozessoren aus zugänglich sein. Die Datenübertragung zwischen Gerät und Speicher erfolgt über spezielle DMA-Interfaces, an die wiederum mehrere Selektorkanäle angeschlossen werden können.

Der neue Rechner von Concurrent-Computer (3280MPS) ist ebenfalls ein Mehrprozessorrechner mit gemeinsamen Speicher. Von der internen Struktur ist bisher nur bekannt, daß es sich im Gegensalz zum 3260MPS um gleichartige Prozessoren handelt, die wesentlich leistungsfähiger als die des 3260MPS sind. Die E/A-Geräte sollen von allen Prozessoren aus erreichbar sein. Welche Mechanismen zur Interprozessorkommunikation zur Verfügung stehen, ist noch nicht bekannt.

Der Einsatz von Multiprozessorsystemen wird besonders dann in Erwägung gezogen, wenn extreme Anforderungen an die Rechenleistungen gestellt werden. Auch der Aspekt nachträglich die Leistung durch zusätzliche Prozessoren erhöhen zu können, ist oft ausschlaggebend. Ein Betriebssystem für Multiprozessoren sollte auch diesen Anforderungen gerecht werden.

Die Idealvorstellung für ein Mehrprozessor-Unix für jede Art von Applikationen besteht in der vollkommenen Transparenz der Hardwarekonfiguration gegenüber dem Benutzer. Er benötigt keinerlei Kenntnis über die Zahl der vorhandenen Prozessoren und wo die peripheren Geräte angeschlossen sind. Das Unix-System hat gegenüber einem Einzelprozessorsystem folgende zusätzliche Aufgaben:

- Automatische Verteilung der lauffähigen Prozesse auf die vorhandenen Prozessoren;

- Weiterleiten von E/A-Aufträgen an den Prozessor, der auf das externe Gerät zugreifen kann und dafür zuständig ist;

- Fehlertoleranz gegenüber dem Ausfall von einzelnen Prozessoren.

Dies sollte sich aber nicht an der Schnittstelle zum Kern des Betriebsystems (SVC-Schnittstelle) bemerkbar machen. Programme, die auf einem Einzelprozessor laufen, sollten unverändert auch auf einem Mehrprozessorsystem ausgeführt werden können.

Prozeßwechsel nur an natürlichen Wartestellen

Bei der Erweiterung eines Einzelprozessor-Unix-Systems zur Unterstützung mehrerer Prozessoren wird man mit einigen Problemen konfrontiert. Das größte besteht darin, daß ein Unix-Prozeß, während er Routinen des Systemkerns ausführt, nicht vom Prozessor verdrängt wird. Ein Prozeßwechsel im Kern ist nur an natürlichen Wartestellen möglich. Demzufolge sind im Unix-Kern keinerlei Vorkehrungen zur Synchronisation von lauffähigen Prozessoren, die Systemroutinen ausfahren, getroffen. Es wird immer zuerst der höherpriore aufgegriffen und auf jeden Fall bis zur nächsten natürlichen Wartestelle oder dem Verlassen des Kerns kein Prozeßwechsel vorgenommen. Bei einem Mehrprozessorsystem ist daher eine zusätzliche Synchronisation innerhalb der Routinen des Kerns nötig. Es bieten sich zwei Lösungsmöglichkeiten an:

- Es wird die Bedingung, daß zu jedem Zeitpunkt immer nur ein Prozessor Routinen des Unix-Kerns ausführt, beibehalten.

Vorteile

- Es muß nur an wenigen Stellen zusätzlich synchronisiert werden; der Implementierungsaufwand ist gering.

- Bei einer neuen Release eines Unix-Systems können Änderungen einfach nachgezogen werden.

Nachteile

- Die Ausführung von Systemroutinen kann leicht zum Engpaß werden. In einer typischen Programmentwicklungsumgebung unter Unix wird im Mittel zirka 30 bis 40 Prozent der Prozessorzeit durch Systemroutinen verbraucht. Der Engpaß tritt somit schon bei 3 bis 4 Prozessoren auf. Das Verhältnis der Prozessorzeit für Routinen im User- und System-Mode ist jedoch stark von der Applikation abhängig.

- In Unix-Systemen ist eine Rate von 50 bis 1 00 SVC-Aufrufen pro Sekunde bei einer Prozessorleistung von zirka 1 Mips keine Seltenheit. Es müssen daher schnelle Synchronisationsmechanismen verwendet werden, um den zusätzlichen Overhead so klein wie möglich zu halten.

- Es werden alle kritischen Abschnitte innerhalb des Unix-Kerns gesucht und dort zusätzlich synchronisiert.

Vorteile

- Es wird die größtmögliche Parallelität von Prozessen erreicht und ein Engpaß beim Bearbeiten von Systemroutinen vermieden.

Nachteile

- Es ist äußerst aufwendig, alle kritischen Abschnitte zu finden und dort geeignete Synchronisationsmechanismen einzubauen.

- Bei einem neuen Unix-Release können sich die kritischen Abschnitte ändern.

- Da es für die Routinen des Unix-Kerns noch nicht gelungen ist Verifikationstechniken einzusetzen, ist es leicht möglich, daß manche kritischen Abschnitte übersehen werden. Darunter kann die Stabilität des Systems leiden.

- Pro SVC-Aufruf können sehr viele Synchronisationen erforderlich sein. Der dadurch erzeugte Overhead kann sehr hoch werden.

Die Entscheidung, welche der beiden Alternativen die bessere ist, kann nur nach einer genauen Studie über die Aufrufhäufigkeiten und der mittleren Bearbeitungszeit der einzelnen Systemroutinen getroffen werden. Der Aufwand des Suchens der kritischen Abschnitte scheint nur für häufig aufgerufene Routinen (zum Beispiel read, write) sinnvoll.

Schon bei Einprozessorsystemen tritt wegen der Asynchronität der E/A-Vorgänge Parallelität zwischen Kern- und Gerätetreiberroutinen auf. Es ist daher auch schon für die entsprechende Synchronisation gesorgt. Die dabei verwendeten Mechanismen müssen Multiprozessorsystemen angepaßt werden. Die gleichzeitige Bearbeitung von Treiberroutinen durch verschiedene Prozessoren sollte ohne Probleme möglich sein.

Es ist jedoch nur sinnvoll, ein E/A-Gerät von einem Prozessor aus zu bedienen, um eine Synchronisation bei Zugriffen zu vermeiden. Über den gemeinsamen Speicher ist es einfach, E/A-Aufträge von einem Prozessor zum anderen zu verschieben. Aus einer erweiterten Konfigurationsbeschreibung muß nur erkennbar sein, welcher Prozessor welches Gerät bedient. Damit ist ebenfalls realisierbar, spezielle Prozessoren als E/A-Prozessoren einzusetzen. Bei einem Ausfall eines einzelnen Prozessors kann gegebenenfalls die Zuordnung der Geräte geändert werden.

Zusätzliche Fähigkeiten eines Multiprozessor-Unix

Die Existenz mehrerer Prozessoren ermöglicht die echte Parallelarbeit mehrerer Unix-Prozesse. Dies legt nahe, eine Aufgabe auf verschiedene Teilprozesse zu verteilen. Durch die parallele Abarbeitung der Prozesse durch die Prozessoren ist eine Beschleunigung für diese Aufgabe im Vergleich zu einem Einzelprozessorsystem erzielbar. Da bei einem Multiprozessor-Unix alle Systemdienste unverändert zur Verfügung stehen, ist eine Kommunikation dieser Prozesse zum Beispiel über die System-V Interprozesskommunikationsmechanismen (Message-Queue, Shared-Memory, Semaphore) möglich. Über Shared-Memory Segmente, die sich auch Prozesse auf verschiedenen Prozessoren einrichten können, ist die Implementierung von effizienten Kommunikationsmechanismen auf Benutzerebene möglich.

Um bei einem derartigen Prozeßsystem auch eine Beschleunigung zu erreichen, ist es vorteilhaft, die einzelnen Prozesse fest einem Prozessor zuzuordnen. Demzufolge sollte der Benutzer auch die Möglichkeit besitzen, die Prozessorvergabe zu beeinflussen.

Für den Concurrent-Computer Rechner 3260MPS ist das Xelos-Betriebssystem, eine Portierung des AT&T System V, verfügbar. Es ist auf der CPU des Rechners ablauffähig, unterstützt aber keine APUs und IOPs. In dieses System wurden Mechanismen eingebaut, die eine Verlagerung von Benutzerprozessen auf APUs ermöglichen. Zunächst ist vorgesehen, Prozesse bei jeden SVC beziehungsweise Trap auf die CPU zu verlagern und dort so wiederaufzusetzen, als ob der SVC beziehungsweise Trap von der CPU selber ausgelöst worden wäre. Diese Realisierung löst eine Reihe von Problemen:

- Da alle Systemroutinen nur von der CPU bearbeitet werden, sind keinerlei zusätzliche Synchronisationen innerhalb Unix Kerns nötig.

- Da alle E/A-Geräte an der CPU angeschlossen sind, erübrigt sich ebenfalls die Weiterleitung von E/A-Aufträgen.

Der dazu nötige Implementierungsaufwand war relativ gering, es sind lediglich Änderungen beziehungsweise Erweiterungen bei folgenden Punkten erforderlich gewesen.

- Überwachung und Kontrolle der APUs

- Mechanismen zur Verlagerung von Prozessen zwischen CPU und APU

- Rechenzeitaccounting und Berechnung der dynamischen Prioritäten

- Scheduling für mehrere Prozessoren gemäß der dynamischen Prioritäten

- Ein-/Auslagerung von Prozessoren

Ziel dieses Systems ist es, wenn der Aufwand für die Prozeßverlagerung im Rahmen bleibt, alle Benutzerprozesse auf APUs zu verlagern, und die CPU nur Systemroutinen ausführen zu lassen. Ansonsten ist daran gedacht, nur rechenintensive Prozesse zu verlagern. Dazu müßte das System die mittlere SVC-Rate von Prozessen messen und diesen Wert als Kriterium für eine Verlagerung heranziehen. Anhand dieses Systems soll untersucht werden, inwieweit die CPU als SVC-Server zum Engpaß wird. Als Anwendung dient eine Programmentwicklungsumgebung wie sie im universitäten Bereich auftritt.

Wenn die Architektur des 3280MPS Rechners genauer bekannt ist und er zur Verfügung steht, ist geplant, das System auf ihn zu übertragen. Es wird dann auch schrittweise versucht werden, Kernroutinen parallel von mehreren Prozessoren ausführen zu lassen. Da zur Zeit insbesondere die E/A-Struktur des 3280MPS im dunkeln liegt, wurden bis jetzt auch keine Überlegungen bezüglich des Betriebs peripheren Geräte angestellt.