In diesem Modul befinden sich alle Funktionen, welche das Setup der Rechenknoten im Fall der parallen EGO-Version und die Kommunikation zwischen den Rechenknoten (Slaves) untereinander und die Kommunikation des Kontrollknotens (Master) mit den Rechenknoten erledigen. Die Namen aller Funktionen in egmach.c beginnen mit dem PCI, das für "Parallel Computer Interface" steht. In jeder PCI-Funktion wird in der Regel zwischen den Parallelbibliotheken MPI, PARIX und PVM unterschieden. Alle anderen EGO-Module rufen nur PCI-Funktionen von egmach.c auf und nicht direkt selbst MPI, PARIX oder PVM Befehle. Dadurch entfällt in allen anderen Module in der Regel eine entsprechende Fallunterscheidung. Das fördert die Modularität und die Lesbarkeit der anderen Module. Zugegeben, ... die Lesbargkeit der PCI-Funktionen ist nicht gerade überragend gut, aber von der Struktur her ist jede PCI-Funktion einfach aufgebaut und leicht versändlich.
main(...) -->
PCI_start(...)
Die Aufgabe dieser Funktion besteht darin die Grösse des zur Verfügung stehenden Parallelrechner zu untersuchen. Dabei wird in nProcs die Anzahl der zur Verfügung stehenden Rechenknoten (Slaves) zurückgeliefert. Dabei ist zu beachten, dass der Masterknoten von EGO einen physikalischen Rechenknoten belegt, der dann natürlich später nicht als Slaveknoten verwendet werden kann. Die entsprechenden Funktionen der Parallellibraries liefern in der Regel die Anzahl der physikalisch vorhandenen Rechenknoten zurück; deshalb müssen wir von der Anzahl der physikalisch vorhandenen Rechenknoten den Masterknoten abziehen, um auf die Anzahl der verwendbaren Slaveknoten zu kommen.
Jeder physikalische Rechenknoten eines Parallelrechners hat eine ID-Nummer, die in der Regel die Rechenknoten einfach durchnummerieren. Diese ID-Nummer wird in MyProcID zurückgegeben. In EGO wird der Knoten mit der ID-Nummer 0 der Masterknoten und als Returnwert MasterID zurückgegeben. Bei MPI und PARIX wird jeder Rechenknoten mit dem selben executable (in unserem Fall EGO) gestartet und jeder Rechenknoten gelangt in die Funktion PCI_start(...). Anhand des Vergleichs der ID-Nummer des Masterknotens mit MyProcID verzweigt dann der Programmcode später und führt dann entweder die Aufgaben des Masterknotens aus oder die Aufgaben eines Slaveknotens (siehe main(...)) aus. Bei PVM läuft das etwas anders als bei MPI und PARIX. Bei PVM startet nur zuerst der Masterknoten und nur dieser ruft PCI_start(...) auf. Deshalb wird dort MasterID = *MyProcID gesetzt. Später erst werden die Slaveknoten mit einem eigenen Programm node gestartet (siehe PCI_master_setup(...).
Also merke:
Bei MPI und PARIX gibt es nur ein executable, bei PVM gibt es zwei ("ego"
für den Master und "node" für den Slave).
PCI_set_no_nodes(...)
PCI_master_setup(...)
main(...) -->
pex(...) -->
node(...) -->
PCI_exit(...)
Die Wichtigkeit dieser Funktion sollte nicht unterschätzt werden! In dieser Funktion werden je nach verwendeter Parallelisierungsbibliotheken "Aufräumfunktion" aufgerufen. Dies ist für ein geregeltes Programmende von Parallelprogrammen oft wirklich wichtig. Beispielsweise können auf einer SP2 unter Umständen die Slave-Knoten noch "laufen" und Rechenzeit verbrauchen, obwohl EGO schon fertig ist, wenn nicht eben solche "Aufräumfunktion" am Programmende aufgerufen werden.