Konzepte und Beispiele paralleler Rechnerarchitekturen (IX):Im Polyp arbeiten beliebig viele Datenpfade

15.11.1985

Computer mit mehreren Prozessoren, Speichereinheiten und Datenpfaden verhalten sich unter günstigen Umständen ähnlich wie ein Polyp: Selbst wenn mal einer der Arme, einer der Datenpfade, versagen sollte - die restliche Konfiguration ist immer noch aktionsfähig genug. An einem derartigen System arbeitet beispielsweise die Universität Heidelberg.

Diesen Polypen wollen die Heidelberger Hard- und Softwarespezialisten für Aufgaben wie die automatische Erkennung krebsverdächtiger Zellen einsetzen, berichtet in einer Diskussion dieses Systems Diplomphysiker Dr. Reinhard Männer vom Physikalischen Institut der altehrwürdigen Heidelberger Universität. Denn heute sei zwar immer noch das Gehirn des Menschen das "zweifellos wirksamste Werkzeug" für die Verarbeitung einzelner, komplizierter Bilder, doch beim laufenden Durchmustern großer Serien von Zell-Photos ermüde es bald und arbeite dann unzuverlässig.

Nun ist es zwar kein grundlegend neuer Gedanke, zur Bildanalyse Computer einzusetzen - doch leider gibt es da immer noch ein paar Probleme. So zum Beispiel das schiere Volumen an einlaufender Information: Mikroskope mit Laser-Abtastvorrichtung zum Beispiel liefern dem Rechner pro Sekunde 64 MB und mehr an Daten ins Haus; Daten die in Echtzeit verarbeitet werden sollten. Das aber stellt herkömmliche Minicomputer mit ihren wenigen Mips (Millionen Instruktionen pro Sekunde) Rechenleistung vor eine unlösbare Aufgabe.

Unterscheidung zwischen zwei Bearbeitungsebenen

Mustererkennungs- und Bildanalyse-Algorithmen sind etwas sehr Komplexes, und man unterscheidet dabei gern zwischen zwei Bearbeitungsebenen. Auf einer unteren werden einfachere Bildverarbeitungsaufgaben wie etwa Filterungen und die Verstärkung von Linien durchgeführt, auf einer höheren wird dann genauer untersucht, was da denn wohl konkret für ein Objekt vorliegen mag; hierzu bedient man sich multivarianter Datenanalyseverfahren. Doch um die Sache noch weiter zu komplizieren, beeinflussen Zwischenergebnisse, die auf Stufe Zwei gewonnen werden, vielfach wiederum die Arbeit auf Stufe Eins. Jedenfalls verspricht so ein hierarchischiteratives Vorgehen laut Männer "größere Vorteile als einfache Techniken" - aber der Rechenaufwand steigt damit eben auch.

Dieses zweistufig-iterativ-hierarchische Arbeiten bedingt erstens ein "wohlausgewogenes" Rechnersystem mit ausreichend Leistung für beide Bearbeitungsebenen und nicht nur, wie man es heute schon vorfinden kann, nur die untere, bei der ja spezielle Bildprozessoren eingesetzt werden können. Doch da die entsprechenden Verfahrensweisen heute alle noch Gegenstand intensiver Forschung sind, kann niemand schon jetzt sagen, wieviel Leistung (Mips), Speicherkapazität und Kommunikationsbandbreite so ein System wohl letztlich haben sollte; man benötigt also Rechner, die sich für die Forschung sehr freizügig immer wieder neu konfigurieren und ausbauen lassen.

So ein Rechnersystem nun ist, sagt Männer, der Heidelberger "Polyp"; ein Parallel-Rechner mit, wenn man will, Hunderten einzelner Prozessoren und auch beliebig vielen einzelnen Bussen zur Verbindung aller Elemente des Gesamtsystems sowie mit Hard- und Software-Managementfunktionen zur leichten Implementierung von Multi-Processing-Systemen. Der Polyp sei ein System, das, wie die in Heidelberg aktive Hardware belegt, als "kleine" Maschine implementiert, aber auch als ausgesprochener Großrechner genutzt werden kann.

Laut Männer ist der Polyp eine "MIMD"-Maschine, die zur gleichen Zeit "multiple instructions" auf "multiple data" ausführen kann; damit sei sie besonders für solche Problemstellungen geeignet, die nicht nur auf der Befehls-, sondern auf der Task(Prozeß-)Ebene eine inhärente Parallelität aufweisen.

Verfügt man über mehrere, unabhängig voneinander einsetzbare Prozessor-Module, so kann man die Arbeitslast auf zweierlei Art zwischen ihnen verteilen. Denn erstens kann man spezialisierte Prozessoren vorsehen, die unter der Steuerung einer zentralen Einheit arbeiten, beziehungsweise einen "Fließband"-Computer nach dem bekannten "Pipeline"-Prinzip bauen. Dann erhält man, zu günstigen Kosten, zwar einen sehr leistungsstarken Rechner, doch dessen Maximal-Durchsatz kann nicht mehr stufenweise variiert werden. Und schon ein einziger Hardwarefehler kann das ganze System unter Umständen lahmlegen.

Der zweite Weg führt zu Multiprozessor-Architekturen, die auf identischen Modulen aufbauen; aber auch hier stören bestimmte Nachteile. So kann man die Hardware nicht mehr dem Typus der vorherrschenden Problemstellung anpassen und muß beispielsweise in Kauf nehmen, daß sämtliche Module über extra Gleitkomma-Hardware verfügen müssen - auch wenn die entsprechenden Rechnungen selten sind. Aber man kann diese Rechner durch Wahl der gerade benötigten Zahl von Modulen wenigstens gut an die aktuellen Einsatzgegebenheiten anpassen - und man kann fehlertolerante Rechner konfigurieren, bei denen ruhig mal ein Modul ausfallen darf: Die anderen arbeiten einfach weiter.

Die Heidelberger wollen mit ihrem Polyp nun beide Welten verbinden. Alle Funktionen eines solchen Systems werden auf "Pools" von unter sich identischen Prozessoreinheiten verteilt, und dadurch kann man ein System durch Hinzufügen oder Weglassen einzelner Pools und Pool-Elemente genau auf die jeweiligen Anforderungen zuschneiden; und durch Wahl der Größe einzelner Pools kann man die Rechengeschwindigkeit modifizieren. Denn jeder weitere Prozessor bringt mehr Tempo. Beim System Polyp läßt sich nun zwar die Größe des einzelner Pools nahezu beliebig wählen, doch gibt es nur eine kleine Zahl unterschiedlicher Modultypen: nämlich Allzweckprozessoren (GPP), Ein-Ausgabe-Prozessoren (IOP), globale Speicher (GM) und einen Host-Rechner für das ganze System. Dabei können die GPP teilweise auch noch mit Erweiterungen wie Gleitkomma-Zusatzhardware oder auch einem schnellen Cache ausgestattet werden. Ein lokaler Speicher, der die Programmbefehle aufnimmt, erlaubt es den GPPs, auf "lokalen Daten" autonom zu operieren.

Verbindung zu Laborexperimenten

Der Hostrechner dient zur Softwareentwicklung und zur Steuerung des Systems durch den Benutzer, die Ein-Ausgabe-Prozessoren stellen die Verbindung etwa zu Laborexperimenten und so weiter her und die GMs schließlich nehmen Daten auf, auf die mehrere GPPs Zugriff haben sollen. Insgesamt umfaßt ein Polyp - entsprechend der Auslegung der Adressierlogik - bis zu 64 K Module; in Planung sind schon Rechner mit immerhin bis zu 100 Modulen.

Wo viele Module sich auf engem Raume drängen, wird rasch die Frage aktuell: Auf welche Weise mögen die miteinander verbunden sein? - Denn da stehen doch beispielsweise die bekannten "inhomogenen" Stern-, Baum- oder auch Pyramiden-Topologien zur Wahl, die übrigens meist, so Männer, "die Anforderungen besonderer Anwendungen widerspiegeln". Aber auch "homogene" Topologien sind darstellbar - und so eine liegt nun auch dem Polyp aus Heidelberg zugrunde.

Beim Polyp verbindet, neben einem optionalen weiteren Bus, ein sogenannter "Polybus" alle Module miteinander, und dieser Polybus wiederum besteht aus mehreren Datenbussen. Jedes Modul eines Polypen kann jedes andere über jeden beliebigen dieser Datenbusse erreichen,

zumal alle Module topologisch gleich sind; diese Erreichbarkeit ist auch der Grund, weshalb man jeweils alle Module des gleichen Typs abstrakt als "Pool" identischer Module betrachten kann.

Funktionell identische Module können wegen der homogenen Konfiguration eines Polyp-Systems also jede Task übernehmen, die sonst ein anderes Modul bearbeitet hätte; es gibt ja keine von der Topologie her festgelegte "Hierarchie". Und der Polyp verfügt auch über Vorkehrungen, die es erlauben, jedes Modul eines Pools "anonym" einzusetzen, die konkrete Wahl also einer zufallsgesteuerten "Entscheidung" der Hardware zu überlassen. Erst dadurch wird es ja möglich, die Größe des einzelnen Pools beliebig zu variieren, ohne deshalb stets gleich wieder besondere Modifikationen der Hard- oder auch der Software vornehmen zu müssen.

Mehr Rechenleistung durch mehr Module

Man hat infolge dieser bemerkenswerten Eigenschaften nun also ein System zur Hand, das auf denkbar einfache Weise den anstehenden Aufgaben angepaßt werden kann: Braucht man mehr Rechenleistung, so vergrößert man einfach durch Hinzufügen von Modulen den Pool der GPPs oder auch den, der aus mehreren (identischen) Spezialprozessor-Modulen bestehen mag; braucht man mehr Ein-Ausgabe-Leistung oder mehr Bandbreite zur Kommunikation der Module untereinander, so fügt man eben mehr lOPs oder mehr Datenbusse zum Polybus hinzu.

Das Heidelberger System kann auf diese Weise wahlweise zu einem "lose gekoppelten" Rechnersystem, aber auch zu einem "eng gekoppelten" ausgebaut werden; im ersteren Fall ist der Kommunikationsanfall zwischen den Modulen (über den entsprechend sparsam ausgebauten Polybus) bescheiden, im anderen Fall hingegen sehr ausgeprägt. Wobei es übrigens, dank der parallelen Struktur des "Polybusses", auch möglich ist, Module simultan miteinander kommunizieren zu lassen.

Wie steht's nun um die Fehlertoleranz? Da man ja erreichen kann, daß die einzelnen Module der Pools zufallsgesteuert aktiviert werden, erreicht man natürlich auch eine automatische, dynamische Last-Verteilung über jeweils alle verfügbaren Mitglieder eines Pools. Und das bedeutet, defekte Module oder auch Datenbusse des Polybus können einfach abgeschaltet und umgangen werden; die Leistung des Gesamtsystems wird dabei nur graduell reduziert. Darauf wiederum, so Männer, komme es ja besonders bei Systemen mit sehr vielen Modulen und Datenwegen an, denn mehr Hardware fällt ja auch häufiger aus.

Nicht allein die Gesamtstruktur des Polypen läßt ein interessantes

Konzept erkennen, auch ein Blick in die tieferen Details der Maschinerie fördert Bemerkenswertes zutage. Man sieht dann, daß die Prozessor- und Speichermodule intern nochmals modular strukturiert sind; sie bestehen aus einzelnen "Einheiten", die über einen modulinternen, eigenen Bus miteinander kommunizieren.

Unterschiedliche Module aus diversen Einheiten

Bei diesen Einheiten kann es sich um eine CPU-Einheit, einen Cache-Speicher, um eine lokale Speichereinheit, eine Buszugriffseinheit zum Erreichen der anderen Module via Polybus oder auch um eine Fehlererkennungs- und Korrektureinheit (ECC) handeln. Aus ihnen kann man unterschiedliche Module zusammenbauen; seien es einfache mit nur einer CPU, einem Speicher und einer Buszugriffseinheit, oder auch komplizierte und vielleicht noch einem Cache, einer ECC, mehr Speicher und mehr Bus-Zugriffseinheiten.

Die Polyp-Architektur kann mit unterschiedlichen CPU-Chips implementiert werden, doch in Heidelberg hat man sich für die Serie "68000" entschieden. Neben diesem Prozessor gehören zu jedem Prozessormodul noch bis zu je 2 MB Speicher für Code, private und allgemeine Daten und Kontroll- und Statusregister; alles in allem also maximal 6 MB. Besondere Logikschaltungen, die zur CPU-Einheit des einzelnen Moduls gehören, passen das simple Bus-Protokoll des CPU-Chips dem komplizierteren Protokoll an, das für den modulinternen Bus gilt.

Zur effizienteren Nutzung der CPU-Leistung und auch der gegebenen Busbandbreite dient die Cache-Einheit, die vor allem die besonders häufig benutzten Befehle und Daten festhält. Jene gelangen über einen separaten, schnellen Datenweg automatisch direkt in die CPU, wobei dies übrigens auch wieder "softwaretransparent" geschieht, den Programmierer eines Polypen also kaum zu kümmern braucht.

Während der Datenzugriff über den normalen Modulbus rund 600 Nanosekunden dauert, geht es mit Hilfe des 16 KB großen Cache zehnmal schneller (60ns). Das sollte ausreichen, meint Männer, um selbst eine mit 16 MHz Taktfrequenz betriebene CPU voll auf Tempo zu halten.

Nach Männers Feststellungen führen die meisten CPUs viel mehr Befehlszugriffe als Datentransfers aus, und deshalb werde die Cache dann am effizientesten genutzt, wenn man ihn mit Programminstruktionen füllt; allerdings könne es auch sinnvoll sein, lokale Daten, wie etwa den Inhalt des Prozessorstacks, oder auch globale Daten wie Tabellen, die nur gelesen werden, hier abzulegen.

Für den Einsatz des Cache spricht auch die Überlegung, daß zum Beispiel ein 40-Modul-Polyp mit nur 256 KB Speicher pro Modul schon 10 MB umfaßt - und das bedeutet, man müsse allgemein zu preiswerten, aber eben langsamen dynamischen RAM-Chips greifen. Die flotten Caches aber erlaubten es, auf sie bei Lesezyklen dennoch schnell zuzugreifen; und Schreib-Zugriffe beschleunigen besondere Pufferregister auf jeder Speichereinheit.

Polybus mit Zugriffen nicht weiter belastet

Ein weiterer interessanter Aspekt der Speicherorganisation im Rahmen eines Polyp-Systems ist der, daß die beiden lokalen Speichereinheiten jedes Prozessormoduls eine Kopie des Betriebssystems, eine Kopie "aller existierenden Programme" und alle lokalen Daten wie etwa Stacks und so weiter aufnehmen: sie bieten ja bis zu sechs MB Platz. Und da nun aller Task-Code in jedem lokalen Speicherelement verfügbar ist, wird der Polybus mit Zugriffen auf Instruktionen nicht mehr weiter belastet; das vermeidet, so hört man, Interferenzen bei globalen Speichermodulen oder Busblockierungen. Auch muß beim Wechsel von einer Task zur anderen nicht erst der Taskcode zwischen Prozessor- und globalem Speichermodul ausgetauscht werden. Denn nun müssen nur noch dynamisch erzeugte lokale Daten übertragen werden, bemerkt Männer; und zwar nur bei Systemen mit dynamischer Taskverteilung. Von ihnen soll später die Rede sein.

Die schon erwähnte Fehlerkorrektureinheit (ECC) arbeitet mit

32-Bit-Worten plus sieben Bits redundantem, modifiziertem Hamming-Code. Sie erlaubt es, Ein-Bit-Fehler automatisch zu korrigieren und alle Doppelbit- sowie viele Mehrbitfehler wenigstens noch zu erkennen.

Diese ECC schützt in erster Linie den Inhalt der Speicher, aber auch alle Adressen und Daten, die bei einem Transfer von Modul zu Modul auftreten. Dabei sorgen die Busprotokolle dafür, daß alle an so einer Übertragung beteiligten Einheiten korrekt synchronisiert werden.

Interessant ist schließlich auch, doch soll dies hier nur kurz gestreift

werden, daß nicht nur die Module modular in Einheiten, sondern jene ihrerseits wieder modular in Untereinheiten gegliedert sind.

Hatten die bisherigen Beschreibungen noch mehr oder weniger konventionelle Einheiten zum Gegenstand, so ändert sich nun das Bild, betrachtet man den Polybus, also quasi das "Rückgrat" der Heidelberger Konzeption, sowie außerdem seine schon kurz erwähnte Ergänzung, den sogenannten Syncbus. Denn hier finden sich bemerkenswerte Ideen verwirklicht.

Bei der Diskussion der Überlegungen, die zur Entscheidung für gerade diese Bustopologie geführt haben, bemerkt Männer zunächst, es gebe für Multiprozessor-Systeme zwar vielerlei Verbindungstopologien, doch für Allzweck-Anwendungen seien doch wohl nur solche geeignet, die homogen sind und mithin keine "topologische Hierarchie von Modulen" kennen. Und er erinnert weiter daran, daß Verbindungsstrukturen stets einen Kompromiß zwischen Eigenschaften darstellen, die einander wechselseitig mehr oder weniger ausschlössen, so beispielsweise hohe Übertragungskapazität, schnelle Einzelübertragungen, Erweiterbarkeit, Fehlertoleranz und günstige Kosten.

Die Heidelberger Informatiker entschieden sich für ein, laut Männer, "völlig homogenes Bussystem" in Form eines zweistufigen Verbindungsnetzes. Mehrfach vorhandene Busse verbinden dabei alle Module und ermöglichen jenen den Datenaustausch; auch Unterbrechungsanforderungen von einem Prozessor zu anderen gehen über diese Polybusbusse. Die einzige Ausnahme sind "System-Interrupts", die kein bestimmtes Modul adressieren und die der Zuteilung eines Prozessors zu einer Task dienen; sie, und wirklich nur sie, gehen über den getrennt verlegten Syncbus.

Doch bleiben wir zunächst beim Polybus. Er besteht aus einer beliebigen Zahl einzelner Busse, die meistens völlig unabhängig voneinander arbeiten. Für die angeschlossenen Module allerdings ist diese Multiplizität des Polybus transparent, denn sie sind an ihn wie an einen gewöhnlichen Allein-Bus gekoppelt.

Im Polybus-System erfolgen die Übertragungen asynchron, was den Zusammenschluß von Modulen unterschiedlicher Arbeitsgeschwindigkeit ermöglicht, und die Bandbreite beträgt n mal 10 MB pro Sekunde; damit gibt n die Zahl der konkret vorhandenen Einzelbusse an.

Dezentralisierte Logistik verwaltet den Bus

Die Busverwaltung besorgt eine dezentralisiert arbeitende Zuteilungslogik, die sowohl prioritätsabhängige als auch gleichberechtigte

Zugriffe ermöglicht: Dabei ist es möglich, fehlerhafte Pfade durch eine erneute Zuteilungsanforderung zu umgehen. Außerdem bietet der Polybus mehrere Adressierungsmodi, die den Zugriff auf spezifische Module, auf ganze Pools von Modulen und auch auf ein beliebig auszuwählendes Mitglied so eines Pools erlauben. Der Nutzen: Man könne somit, meint Männer, "multiprozessor-transparent programmieren" und Datenflußanwendungen realisieren.

Wie ein Polybus konfiguriert sein kann, illustriert Bild 3 sehr plastisch. Es zeigt eine Reihe von Modulen sowie deren interne Busse und daneben mehrere identische Busse des Polybusses. Ferner ist eine wahlweise vorsehbare Verbindung eingezeichnet, der "Transfer Priority Bus"; er besorgt den prioritätsgesteuerten Zugriff auf den Polybus.

Das Bild läßt eine durchgeschaltete Verbindung zwischen zwei Modulen erkennen, die über Bus 0 lauft, und eine weitere über Bus n. Über Bus eins läuft beim dritten Modul von links gerade ein Zugriff ein, der aber

bei dessen Datenbus-Interface wegen Kollisionsgefahr gestoppt wird. Eines dieser Interfaces von Modul drei, nämlich jenes zu Bus n, ist gerade defekt und Modul zwei schließlich fordert gerade einen Bus an.

Jeder der Polybus-Datenbusse ist ein Multiplexbus für Adressen und Daten mit 32 plus sieben (Fehlerkorrektur-) Bits.

Besondere Erwähnung verdient, daß ein Daten sendendes Modul nicht nur ein bestimmtes anderes ansprechen kann, sondern auch gleichzeitig alle Module einer ganzen, vorher definierten Gruppe. In diesem Falle müssen diese Gruppenmitglieder nicht Module des gleichen Typs sein, sondern es können beliebige zusammengestellt worden sein; sie werden nämlich einfach, per Programm, als Gruppe im Sinne der Bus-Adressierung definiert. Und dann ist es schließlich noch möglich, alle Mitglieder eines Pools gleicher Module gemeinsam anzusprechen und dann der Hardware zu überlassen, mit welchem Modul - zufallsgesteuert - die Verbindung konkret zustande kommt. So kann man programmieren, ohne sich um die konkrete Größe jedes Pools von Prozessoren kümmern zu müssen. Nicht zuletzt aus Gründen der Fehlertoleranz ist die Busverwaltung völlig dezentralisiert; außerdem ist sie in zwei Richtungen kaskadierbar: sowohl die Zahl der Busse als auch die der Module ist praktisch beliebig wählbar.

Token kennzeichnet den freien Bus

Daß ein Bus frei ist, erkennen die Module an einem "Token" (Kennung), das den ganzen Bus "entlangläuft". Benötigt ein Modul einen Bus, so aktiviert er alle seine Busschalter, die jenen Bus, dessen Kennung als nächste bei ihnen vorbeikommt, mit Beschlag belegen. Dieses Verfahren ist laut Männer "sehr schnell" und sorgt dafür, daß die Buszuteilung, im Vergleich zur eigentlichen Übertragungsdauer, sehr rasch erfolgt; dies wiederum erlaube es, ein Polyp-System auch als "enggekoppeltes" Rechnersystem zu betreiben.

Und wie steht es nun um prioritätsgesteuerte Zugriffe? - Hier kommt der Transfer Priority Bus samt der speziellen Prioritäts-Interfaces jedes einzelnen Moduls zum Einsatz, wobei die letzteren Angaben einmal über die momentane Priorität der CPU und zweitens über die momentane Priorität eines zum Modul gehörenden Speicherdirektzugriffs-Steuerbausteins (DMA-Controller bereithalten. Benötigt das Modul nun den Bus, so legt es Signale, die diese Prioritäten (dekodiert) widerspiegeln, auf den Transfer Priority Bus und alle anderen Module, die ja das gleiche tun, können nun mit Hilfe ihrer eigenen Prioritäts-Interfaces feststellen, ob sie selber oder ein anderes Modul die momentan höchste Priorität aufweisen. Dadurch wird dafür gesorgt, daß am anschließenden "Abfangen" einer Bus-Frei-Kennung nur jene Module teilnehmen, die die höchste Prioritätsstufe aufweisen.

Diese Buszuteilungstechnik macht den Polybus im Zusammenwirken mit Modulen mit Fehlerkorrektureinheiten sehr zuverlässig, bemerkt Männer. Denn da ja neben den Einzelbit-Fehlern, die einfach korrigiert werden, auch alle Zweibit- und viele Mehrbitfehler erkannt werden, muß der zum Fehler führende Bus-Zyklus ja nun einfach bloß wiederholt werden. Das geschieht, indem erneut ein Buszuteilungsverfahren abläuft, und dadurch besteht eine hohe Sicherheit, daß spätestens nach einer gewissen Zeitspanne ein defektfreier Bus erwischt wird, sollte es so einen im System überhaupt noch geben.

Beim System Polyp kann man unterscheiden zwischen lokalen Datentransfers, bei denen nur Einheiten beteiligt sind, die zum gleichen Modul gehören, und globalen Transfers bei denen Modulgrenzen überschritten werden; letztere benötigen eine Adresse, die ein Modul, eine Einheit in jedem Modul und in dieser wiederum eine Adresse spezifizieren.

Mit seiner bisher beschriebenen Struktur stellt der Heidelberger Polyp eine so hohe Rechenleistung bereit, daß man ihn auch zur Bearbeitung von Echtzeitproblemen heranziehen könne, meint Männer. Doch dazu bedarf es noch einiger weiterer Vorkehrungen, soll das System wirklich einsetzbar sein.

Welche Überlegungen hier eine Rolle spielen, skizziert der Heidelberger Wissenschaftler kurz so: Könne man einfach dafür sorgen, daß jede Task jeweils einem bestimmten Prozessor zugeteilt wird, so hätte man eine sehr simple und sehr effiziente Lösung parat - bloß ist das leider oft nicht möglich. Man muß vielmehr den allgemeinsten Fall bedenken, also den, in dem eine große Zahl von Tasks mit unterschiedlichen Prioritäten ausgeführt werden muß, wobei deren Zahl überdies noch online variieren und mithin von der tatsächlichen Ausbaugröße des Polyp, auf dem die Anwendung läuft, unabhängig sein kann: Tasks werden dabei dynamisch geschaffen und wieder gelöscht.

In so einer allgemeinen Situation gilt es, zwei Hauptproblemen gerecht zu werden: Einmal muß festgelegt werden, in welcher Reihung die einzelnen Tasks ausgeführt werden, und zweitens muß für die jeweilige Task der sie bearbeitende Prozessor ausgewählt werden.

In Heidelberg wird nun die Reihenfolge der Ausführung allein durch die Prioritätsstufen der einzelnen Tasks festgelegt, und das Ziel besteht darin, den einzelnen Prozessor-Pools zu einem gegebenen Zeitpunkt jeweils nur die momentan wichtigsten Tasks zur Bearbeitung zu übergeben; gegebenenfalls müssen also weniger wichtige Tasks unterbrochen werden, meldet sich eine vorrangige an.

Nun ist so ein Prozessorzuteilungsmechanismus zwar nichts Neues mehr, doch im allgemeinen, so erinnert Männer, wird er in Form von Software-Algorithmen implementiert: eine allerdings selbst bei Einprozessorsystemen zeitraubende Lösung. Denn das Umschalten von einer Task auf eine andere dauert hierbei typisch etwa 100 Mikrosekunden - und das ist für Echtzeitmultiprozessor-Multitaskingsysteme einfach zu lange. Schon gar, wenn hier vielleicht einmal mehrere hundert Prozessoren zusammenarbeiten sollen.

Einen Ausweg bieten hardwareorientierte, parallele Verfahren an, die in Heidelberg unter dem Namen Syncbus entwickelt wurden. Es handelt sich dabei um jeweils einen speziellen Bus für jeden Pool von untereinander gleichartigen Prozessoren wie etwa Gleitkomma-, Festkomma- und andere Typen. Diese Busse sind über Interfaces an die internen Busse der einzelnen Prozessormodule gekoppelt, wobei jeweils der eine Teil des Interface für die Schaffung und der andere für die Akzeptierung von "Requests" (Anforderungen) zuständig ist. Dabei kann jeder Prozessor zwar auf jedem der einzelnen Busse des Syncbus Anforderungen schaffen, aber nur solche akzeptieren, die auf jenem speziellen Bus angetroffen werden, der zum Pool dieses Prozessors, also zu seinem speziellen Typ paßt.

Wie läßt sich nun die Arbeitsweise dieser Interfaces und des Syncbus knapp skizzieren? Jeder Prozessor legt seine momentane Priorität in seinem Interface ab, wo sie decodiert und auf eine besondere Gruppe von Leitungen gelegt wird. Nunmehr können an Hand dieser Informationen alle beteiligten Interfaces eines Pools von gleichartigen Prozessoren auf einfache Weise selbständig feststellen, ob sie zu einem Prozessor mit der niedrigsten momentanen Prioritätsstufe innerhalb des Pools gehören oder nicht. Und diese Information wiederum erlaubt es nun, trotz dynamisch immer wieder sich ändernder Prozessor-Prioritäten sicherzustellen, daß innerhalb einer Klasse von Prozessoren stets nur einer jener Prozessoren für die Bearbeitung einer Tasks von höherer Priorität herangezogen wird, die eine Task der untersten Prioritätsstufe bearbeiten.

Im einzelnen sieht das so aus, daß kontinuierlich fortlaufend festgestellt wird, welcher Prozessor eines Pools wohl die niedrigste Priorität hat. Gleichzeitig werden fortlaufend alle Anforderungen auf Ausführung weiterer Tasks über den ganzen Pool hinweg auf ihre Priorität abgeklopft und dann aus jenen der höchsten Prioritätsstufe zufallsgesteuert eine ausgewählt. Doch solange deren Priorität nicht höher ist als die des Prozessors mit der niedrigsten Priorität, geschieht weiter gar nichts.

Im anderen Fall wird dem nun zu unterbrechenden Prozessor, also dem mit der niedrigsten momentanen Priorität, die Nummer der auszuführenden Task übermittelt, während das anfordernde Interface die Nummer des ausgewählten Prozessors "erfährt". Dann werden beide Prozessoren unterbrochen und der anfordernde löscht seine Anforderung, während der akzeptierende Prozessor seine momentane Task unterbricht, für sie eine Aktivierungsanforderung mit der entsprechenden Priorität erzeugt und anschließend beginnt, die neue Task höherer Priorität zu bearbeiten.

Dieses Verfahren, das hier natürlich nicht in allen Details dargestellt werden konnte, ist verblüffend wirksam: Laut Männer arbeitet es um rund zwei Größenordnungen (!) schneller als die normalerweise üblichen Softwarealgorithmen. Und es ist in jener sehr häufig vorkommenden Situation effizient, in der die Zahl der Tasks die der verfügbaren Prozessoren bei weitem übersteigt.

Hervorzuheben ist des weiteren, daß die Arbeit des Syncbus in keiner Weise von der Zahl der Prozessoren in jedem Pool abhängt, wodurch ein transparentes Multiprozessing, bei dem die Zahl der Module beliebig wechseln kann, möglich wird. Mit der Taskverwaltung und Prozessorzuteilung werden übrigens die Prozessoren selber in keiner Weise belastet beziehungsweise aufgehalten, und Prozessorunterbrechungen erfolgen stets erst dann, wenn schon klar ist, daß ein Prozessor auf eine neue Task umschalten muß. Nicht aber auch in allen anderen Fällen, wo "hinterher" vielleicht "alles beim alten bleiben" kann, der Zeitverlust also unnötig gewesen sein mag.