Programmieren in CNAPS-C - Eine Einführung

Werbung
Referat: Programmieren in CNAPS-C
von
Peter Wendzioch
CNAPS-Projekt
Sommersemester 1998
Hochschule Bremen
13.05.2016
Anzahl der Seiten: 23
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
THEMENÜBERSICHT
1. EINLEITUNG
3
2. DIE PROGRAMMSTRUKTUR
4
3. DOMÄNEN UND PARALLELITÄT
5
3.1
3.2
3.3
3.4
3.5
3.6
3.7
ORGANISATION DER DATEN
DER DATENTYP DOMAIN
POLY- UND MONO-DATENTYPEN
PARALLELER CODE
ABLAUFSTEUERUNG IN PARALLELEM CODE
VERSCHACHTELTE DOMAIN EXECUTION STATEMENTS
NAMENSRÄUME (NAME SPACES)
6
7
8
9
10
11
12
4. DATENTYPEN, ZEIGER, OPERATOREN
13
4.1
4.2
4.3
4.4
4.5
4.6
13
14
15
16
17
18
GRÖßE VON DATENTYPEN
SCALED – SKALIERBARE FIXPUNKTDATENTYPEN
ZEIGER
DEKLARATION VON ZEIGERN
EINIGE NEUE OPERATOREN
NEUE BEDEUTUNG EINIGER OPERATOREN MIT POLY-VARIABLEN
5. FILE I/O
19
5.1
5.2
19
20
DIE BIBLIOTHEK CNIO.H
ZUSAMMENFASSUNG DER FILE I/O-OPERATIONEN
6. DIE ASM DEKLARATION
21
7. RESTRIKTIONEN CNAPS-C VS. ANSI-C
22
8. LISTING OF MATMUL.CN
23
Referat: Programmieren in CNAPS-C
Seite: 2
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
1. Einleitung
CNAPS-C ist die Hochsprache, mit der Algorithmen auf dem CNAPS-Board
implementiert werden. Sie werden mit dem CNAPS-Compiler cnc kompiliert
und durch CNapi-Aufrufe vom Hostrechner auf das CNAPS-Board übertragen
und dort ausgeführt.
Eine andere Möglichkeit, Programme für das CNAPS-Board zu entwickeln,
bietet die Assemblersprache CPL. CPL setzt jedoch wie alle maschinennahen
Sprachen sehr gute Kenntnisse der Hardware voraus und wird hier nicht näher
erläutert.
Weitere Informationen zu CNAPS-C und CPL findet man in den Manuals
CNAPS-C Programming Guide
CNAPS-C Language Reference
CPL Programming Guide
QuickLib Libraries Reference Manual
Einige Begriffsdefinitionen:
CNAPS
SIMD
domain
CSC
PN
CNapi
CPL
Connected Network of Adaptive ProzessorS
Single Instruction Multiple Data
Datentyp/-struktur für Parallelverarbeitung
CNAPS Sequencer Chip
Prozessor Node
CNAPS Application Programming Interface
CNAPS Programming Languange
Referat: Programmieren in CNAPS-C
Seite: 3
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
2. Die Programmstruktur
Programme in CNAPS-C sind grundsätzlich wie ANSI-C Programme aufgebaut,
mit zwei wichtigen Ausnahmen:
In CNAPS-C ist das Konzept einer main-Funktion, die den Startpunkt eines
Programms definiert, nicht implementiert. Eine Funktion kann zwar den Namen
„main“ haben, sie hat allerdings keine besondere Bedeutung. Statt dessen
können Funktionen als entry points definiert werden. Ein CNAPS-C Programm
wird durch Aufrufen einer dieser entry points gestartet, weshalb mindestens eine
Funktion als entry point definiert sein muß.
entry void IrgendeinName(void)
{
}
Da es kein Konzept einer main-Funktion gibt, entfällt auch der Mechanismus
der Parameterübergabe durch argc und argv[]. Deshalb können auch Variablen
als entry points definiert werden und somit zur Parameterübergabe an einen
Algorithmus verwendet werden:
entry const int Anfangswert = 100;
Durch das Schlüsselwort const wird nur vermieden, daß die Variable zur
Laufzeit geändert werden kann. Die Variable Anfangswert kann jedoch
durch einen CNapi-Aufrufe geändert werden. Die Zuweisung des Wertes 100
wird als Defaultwert benutzt.
Referat: Programmieren in CNAPS-C
Seite: 4
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
3. Domänen und Parallelität
Domänen stellen dem Programmierer den Mechanismus zur Verfügung, in dem
die Fähigkeit zur Parallelverarbeitung implementiert ist. Domänen sind
vergleichbar mit dem C-Datentyp struct, mit der Besonderheit, daß in einer
Domäne eine logische Gruppe von Prozessoren zusammengefaßt wird, mit
denen eine Parallelverarbeitung durchgeführt wird. Eine Domäne kann
Mitgliedsvariablen und -funktionen beinhalten.
Instanzen sind die konkreten Ausprägungen einer Domäne. Instanzen sind
vergleichbar mit den Objekten einer C++ Klasse. Eine Domäne kann mehrere
Instanzen haben, die jeweils mit einer Gruppe von Prozessoren assoziiert sind.
Dennoch unterscheiden Domänen sich von C++ Klassen in folgenden Punkten:
 Domänen haben keinen Mechanismus zur Vererbung.
 Mitgliedsvariablen und –funktionen können nicht als private deklariert
werden. Sie sind immer public.
 Alle Mitgliedsvariablen und –funktionen einer Domäne können parallel
verarbeitet bzw. ausgeführt werden.
 Prozessoren können nicht dynamisch zugewiesen werden.
Referat: Programmieren in CNAPS-C
Seite: 5
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
3.1 Organisation der Daten
Um den Vorteil der Parallelverarbeitung nutzen zu können, müssen die Daten
vor der Verarbeitung organisiert werden. Organisation bedeutet dabei die
"geschickte" Einteilung der Daten in Stränge, die parallel von einer Gruppe von
Prozessoren verarbeitet werden können.
Verdeutlicht werden soll dies am Beispiel einer Multiplikation einer 3x3 Matrix
mit einem 3-spaltigen Vektor:
Referat: Programmieren in CNAPS-C
Seite: 6
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
3.2 Der Datentyp domain
Eine Domäne wird mit dem Schlüsselwort domain deklariert. Die Deklaration
muß mit einem Semikolon abgeschlossen werden.
Bei der Deklaration von Domänen muß darauf geachtet werden, daß die Anzahl
der zugewiesenen PNs nicht die Anzahl der physikalisch vorhandenen PNs
übersteigt.
Syntax 1:
domain DOMAINNAME {
// Deklaration der Mitgliedsvariablen
} INSTANZNAME[KONSTANTE_ANZAHL_PN];
Syntax 2:
domain DOMAINNAME {
// Deklaration der Mitgliedsvariablen
};
domain DOMAINNAME INSTANZNAME[KONSTANTE_ANZAHL_PN];
Referat: Programmieren in CNAPS-C
Seite: 7
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
3.3 poly- und mono-Datentypen
Die Schlüsselwörter mono und poly sind sogenannte "qualifier", die angeben,
ob ein Datentyp in einer Domäne nur einmal für alle Prozessoren existiert, oder
ob jeder Prozessor mit seiner eigenen Kopie dieser Variablen arbeitet.
Außerhalb von parallelem Code gibt es nur mono-Datentypen und innerhalb
parallelen Codes sind die Datentypen defaultmäßig poly. Einfache Zählvariablen
sollten daher mit mono deklariert werden.
Referat: Programmieren in CNAPS-C
Seite: 8
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
3.4 Paralleler Code
CNAPS-C Programme sind immer eine Mischung aus seriellem und parallelem
Code. Nur ganz bestimmte Teile eines CNAPS-C Programms werden parallel
ausgeführt. In CNAPS-C gibt es zwei verschiedene Möglichkeiten, eine
Parallelverarbeitung zu implementieren.
Syntax 1 - Paralleler Code in Mitgliedsfunktion implementiert:
Deklaration
void DOMAINNAME::FUNKTIONSNAME(PARAMETER) {
// Parallel auszuführenden Code hier einfügen.
}
Aufruf
[domain DOMAINNAME].FUNKTIONSNAME();
Syntax 2 - Paralleler Code in serieller Funktion implementiert:
Deklaration
void serielle_funktion(void)
{
// Hier steht nur serieller Code.
[domain DOMAINNAME].{
// Parallelen Code hier einfügen.
}
// Hier steht wieder nur serieller Code.
}
Aufruf
serielle_funktion();
Referat: Programmieren in CNAPS-C
Seite: 9
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
3.5 Ablaufsteuerung in parallelem Code
Innerhalb von domain execution statements können natürlich auch
Befehle wie if, while, do und for eingesetzt werden.
Beziehen sich diese Befehle nur auf mono-Variablen, so ist die Ablaufsteuerung
für alle PNs gleich.
Unter Berücksichtigung von poly-Variablen, werden beispielsweise die PNs,
deren poly-Variable einen if-test nicht bestehen, inaktiv und warten mit dem
Programmablauf, bis die aktiven Prozessoren ihren if-Block beendet haben. Ein
Beispiel soll dies verdeutlichen:
domain Beispiel {
mono i;
poly Wert;
} Proz[10]
[domain Beispiel].{
if (i == 0) {
// Wenn i=0 (mono) ist, dann führen
// alle PNs (Proz[0..9]) diesen Block aus.
}
else {
// Ansonsten führen alle PNs diesen
// Block aus.
}
if (Wert <= 100) {
// Nur die PNs der Variable Wert<=100
// (poly) ist führen diesen Block aus.
// Alle anderen PNs dieser Domäne sind
// inaktiv und warten.
}
}
Referat: Programmieren in CNAPS-C
Seite: 10
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
3.6 Verschachtelte domain execution statements
Ein domain execution statement kann auch in bereits-parallelem
Code auftauchen. Die Auswirkungen zeigt das folgende Beispiel:
domain Beipiel {
mono i;
poly WertA;
poly WertB;
} Proz[10];
[ domain Beispiel ].{
if (WertA < 10) {
// Hier sind nur die PNs aktiv, deren
// Variable WertA kleiner als 10 ist.
[domain Beispiel].{
// Hier sind aber alle wieder aktiv.
WertB = 5;
}
}
}
Referat: Programmieren in CNAPS-C
Seite: 11
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
3.7 Namensräume (name spaces)
Jede Domäne hat einen eigenen Namensraum für ihre Bezeichner. Dadurch
können in verschiedenen Domänen Variablen mit gleichem Namen existieren.
Auch die "mono"-Domäne hat einen eigenen Namensraum:
int abc = 1;
int xyz = 2;
// Beides mono-Typen
domain Eins {
mono int abc;
poly int ijk;
} EinsProz[10];
domain Zwei {
mono int abc;
poly int rst;
} ZweiProz[10];
[ domain Eins ].{
abc = 1;
// abc von Domäne Eins
Zwei::abc = 2;
// abc von Domäne Zwei
void::abc = 3;
// globales abc der mono-Domäne
EinsProz[3].ijk = 10; // ijk von PN3
}
Referat: Programmieren in CNAPS-C
Seite: 12
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
4. Datentypen, Zeiger, Operatoren
4.1 Größe von Datentypen
Datentyp
Größe
int, short
16 bit
char
8 bit
long
32 bit
float, double
nicht verfügbar
scaled
8 oder 16 bit
zeiger auf poly-Objekt
16 bit
zeiger auf mono-Objekt
32 bit
zeiger auf ein domain-Objekt
16 bit
Referat: Programmieren in CNAPS-C
Seite: 13
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
4.2 scaled – Skalierbare Fixpunktdatentypen
Mit dem Schlüsselwort scaled kann man Fixpunkt-Datentypen definieren.
Dabei werden die Bits für den Ganzahl- und den Nachkommateil angegeben.
typedef scaled 4 12 fpvar;
Was man in dieser Definition noch nicht sehen kann, ist die Tatsache, daß der
Datentyp noch drei weitere Standardeigenschaften hat:
signed / unsigned
Der Datentyp ist "signed"
Standardmäßig sind alle numerischen Datentypen vorzeichenbehaftet.
jammed / unjammed
Der Datentyp ist "unjammed"
Verliert ein jammed-Datentype niederwertige Bits z.B. durch shiften, casten
oder Multiplikation, so wird der Wert der Variablen auf den "ungeraden" Wert
gesetzt, der dem eigentlichen Ergebnis am nächsten kommt. Mit ungerade ist
gemeint, daß das niederwertigste Bit auf 1 gesetzt ist.
saturated / unsaturated
Der Datentyp ist "unsaturated"
Tritt bei einer Operation ein Überlauf bzw. Unterlauf auf, so ist der Wert der
Variablen undefiniert. Mit dem Schlüsselwort saturated wird ein Datentyp
angewiesen, den größt- bzw. kleinstmöglichen darstellbaren Wert anzunehmen.
Eine Mögliche Deklaration wäre auch
typedef scaled 8 8 unsigned saturated jammed fpvar2;
Referat: Programmieren in CNAPS-C
Seite: 14
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
4.3 Zeiger
Durch die CNAPS-C-Erweiterungen hinsichtlich der Parallelverarbeitung
ergeben sich 4 verschiedene Arten von Zeigern:
Referat: Programmieren in CNAPS-C
Seite: 15
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
4.4 Deklaration von Zeigern
domain abc {
poly int z;
} Proz[3];
[domain abc].{
mono int i;
mono int array[3];
mono
poly
mono
poly
int
int
int
int
*mono
*mono
*poly
*poly
monoPtrToMonoInt;
monoPtrToPolyInt;
polyPtrToMonoInt;
polyPtrToPolyInt;
monoPtrToMonoInt
monoPtrToPolyInt
polyPtrToMonoInt
polyPtrToPolyInt
=
=
=
=
&i;
&z;
&array[1];
&z;
}
Referat: Programmieren in CNAPS-C
Seite: 16
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
4.5 Einige neue Operatoren
>?
Ermittelt den Maximalwert zweier Operanden
<?
Ermittelt den Minimalwert zweier Operanden
>?=
Weist den Maximalwert einer poly-Variablen einer mono-Variablen zu
<?=
Weist den Minimalwert einer poly-Variablen einer mono-Variablen zu.
,=
Weist einen zufällig ausgewählten Wert einer poly-Variablen einer monoVariablen zu. (Wird verwendet, wenn es egal ist, welcher Prozessor diesen Wert
enthält, z.B. weil man weiß, daß nur 1 Prozessor aktiv ist.)
Beispiel:
domain abc {
mono int max_Wert;
poly int poly_Wert;
} Proz[10];
[domain abc].{
// Irgendwelche Berechnungen auf poly_Wert.
.
.
.
// Absolutbetrag von poly_Wert.
max_Wert >?= (poly_Wert >? –poly_Wert);
};
Referat: Programmieren in CNAPS-C
Seite: 17
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
4.6 Neue Bedeutung einiger Operatoren mit poly-Variablen
x ist eine poly-Variable, y ist eine mono-Variable
y += x
Summiert die Werte von x aller aktiven PNs.
y -= x
Summiert die negierten Werte x aller aktiven PNs.
y *= x
Multipliziert die Werte x der aktiven PNs.
y &= x
Bitweises UND aller Werte x der aktiven PNs.
y |= x
Bitweises ODER aller Werte x der aktiven PNs.
y ^= x
Bitweises XOR aller Werte x der aktiven PNs.
Referat: Programmieren in CNAPS-C
Seite: 18
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
5. File I/O
5.1 Die Bibliothek cnio.h
Die Daten die von einem CNAPS-C Algorithmus bearbeitet werden sollen
müssen in Eingabedateien bereitgestellt werden. Die Ergebnisse werden dann
nach der Verarbeitung in Ausgabedateien geschrieben. Die Unterstützung für die
Ein- und Ausgabe von Daten bietet die Bibliothek cnio.h, die in jedem
CNAPS-C Programm eingebunden sein sollte.
Für einen Dateizugriff muß zunächst eine Datei mit dem FILE()-Befehl
deklariert werden:
Mit den Befehlen open() und connect() muß die Datei geöffnet und mit
der physikalischen Datei im Filememory verbunden werden, bevor man Leseoder Schreiboperationen ausführen kann. Es gilt, daß zwar mehrere Dateien mit
open() geöffnet sein können, aber es kann immer nur eine Datei zum Lesen
und eine zum Schreiben mit connect() verbunden sein:
open (EINGABE_DATEI);
open (AUSGABE_DATEI);
connect (EINGABE_DATEI);
connect (AUSGABE_DATEI);
// Leseoperationen
a = getchar();
// Schreiboperationen;
putchar(a);
close (EINGABE_DATEI);
close (AUSGABE_DATEI);
Referat: Programmieren in CNAPS-C
Seite: 19
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
5.2 Zusammenfassung der File I/O-Operationen
Operation Beschreibung
close()
Schließt eine geöffnete Datei.
connect()
Verknüpft eine Datei mit einem I/O-Kanal
(1 Eingabe und 1 Ausgabe).
FILE()
Deklariert eine Datei.
flush()
Schreibt den Pufferinhalt in die Datei.
getchar(), Liest binäre Eingabedaten.
getnum(),
getword()
open()
Öffnet eine Datei.
putchar(), Schreibt Daten im Binärformat.
putnum(),
putword()
rewind()
Setzt den Datenzeiger auf den Anfang der
Datei.
Referat: Programmieren in CNAPS-C
Seite: 20
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
6. Die asm Deklaration
Mit der asm Deklaration ist es möglich CPL-Code direkt in ein CNAPS-C
Programm einzubinden. Innerhalb dieser Deklarationen darf nur CPL-Code
verwendet werden, da diese Abschnitte von CNAPS-C Präprozessor ignoriert
werden.
asm [ register xxx = 5 ]
{ <<<
// CPL-Code hier einfügen.
>>>
}
Beispiel:
entry void ptrIndirection(void) {
char xl[10];
char *ptr = xl;
/* This in-line assembly code does *ptr = 2 */
asm [ register plow,phigh = ptr;
register tl;
{ <<<
CTLdefault;
LITERAL 0 lo;
phigh rega shiftr4 LITERAL 7 inB and;
logicA Areg t1;
# t1 = phigh & 0x0700
plow regA shiftr8;
# logic = plow >> 8
logicA AaddL t1 regB BaddRL; #add = pnid of mono ptr
rpnid regA Alogiclatch addB xor; # logic = add ^ pnid
omitx iflogic0;
# xflag = (add == pnid)
LITERAL 255 inA Alogiclatch plow regB and;
LITERAL 255 lo logicA Areg tl;
LITERAL 15 inA Alogiclatch phigh regB and;
logicA AaddL t1 regB BaddRL; # add = offset
addA Abase;
# base = offset
LITERAL 2 inA Amem cndx;
# if (ptrPnid == pnid)
# then *base = 2
>>> } ];
}
Referat: Programmieren in CNAPS-C
Seite: 21
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
7. Restriktionen CNAPS-C vs. ANSI-C
Folgende Eigenschaften sind in einem CNAPS-C Programm nicht verfügbar
bzw. eingeschränkt:
 Division (/) und Modulo (%)
 float- und double-Typen
 Zeiger auf Funktionen
 Bitfelder in structs und Unions
 Speicherallokation (z.B. malloc()).
 "main"-Funktion
 Programmgröße ist auf 64KB begrenzt
Referat: Programmieren in CNAPS-C
Seite: 22
Peter Wendzioch
CNAPS-Projekt SS98
24.05.98
8. Listing of matmul.cn
#define num_cols 3
#define num_rows 3
#define num_elem 3
#include <cnio.h>
// DEFINITION DER DOMÄNE matrix_calc UND DER INSTANZ MAT[]
domain matrix_calc {
poly int matrix_row[num_cols];
poly int sum;
};
domain matrix_calc MAT[num_rows];
// INITIALISIERUNG FILE I/O
mono int i,j;
mono int vector[num_elem];
FILE (MATFILE, inword, "*.dat", NULL, NULL);
FILE (VECFILE, inword, "*.dat", NULL, NULL);
FILE (RESFILE, outword,"*.dat", NULL, NULL);
// LESEROUTINEN FÜR MATRIX UND VEKTOR
void matrix_calc::readMatrix(int matrix_row[])
{
mono int r, c;
open (MATFILE);
connect (MATFILE);
for (r=O;r<num_rows;r++) {
for (c=O;c<num_cols;c++)
MAT[r].matrix_row[c] = getword();
}
close (MATFILE);
}
void readVector();
{
mono int v;
open (VECFILE);
connect (VECFILE);
for (v=O;v<num_elem;v++)
vector[v] = getword();
close (VECFILE);
}
// BERECHNUNG UND AUSGABE DER ERGEBNISSE
entry void main(void)
{
mono int j;
[domain matrix_calc].(
readMatrix(matrix_row);
readVector();
sum = 0;
for (j=0; j<num_cols; j++)
sum = sum + (matrix_row[j] * vector[j]);
open (RESFILE);
connect (RESFILE);
for (j=0; j<num_rows; j++) {
putword (MAT[j].sum);
}
}
}
Referat: Programmieren in CNAPS-C
Seite: 23
Herunterladen