Preview only show first 10 pages with watermark. For full document please download

2 On 1 - Lehrstuhl "betriebssysteme Und Verteilte Systeme"

   EMBED


Share

Transcript

Parallel Processing WS 2016/17 Roland Wismuller ¨ ¨ Siegen Universitat .d [email protected] e rolanda Tel.: 0271/740-4050, Buro: ¨ H-B 8404 Stand: November 14, 2016 Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (1/15) i Parallel Processing (6/15) 339 Parallel Processing WS 2016/17 5 Appendix Roland Wismuller ¨ Betriebssysteme / verteilte Systeme 5.1 Tutorial: C/C++ for Java Programmers 5.1.1 Fundamentals of C++ ➥ Commonalities between C++ and Java: ➥ imperative programming language ➥ syntax is mostly identical ➥ Differences between C++ and Java: ➥ C++ is not purely object oriented ➥ C++ programs are translated directly to machine code (no virtual machine) ➥ Usual file structure of C++ programs: ➥ header files (*.h) contain declarations ➥ types, classes, constants, ... ➥ source files (*.cpp) contain implementations ➥ methods, functions, global variables Roland Wismuller ¨ Betriebssysteme / verteilte Systeme 340 Parallel Processing (6/15) 5.1.1 Fundamentals of C++ ... Compilation of C++ programs Initialisation code init memory call main() return result x.h Header files (Include files) Pre− x.cpp processor Source file(s) Linker Compiler Source file(s) x.o hello Object file(s) Executable program ➥ Preprocessor: embedding of files, expansion of macros ➥ Linker: binds together object files and libraries Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 341 5.1.1 Fundamentals of C++ ... Compilation of C++ programs ... ➥ Invocation of the compiler in the lab room H-A 4111: ➥ g++ -Wall -o ➥ executes preprocessor, compiler and linker ➥ -Wall: report all warnings ➥ -o : name of the executable file ➥ Additional options: ➥ -g: enable source code debugging ➥ -O: enable code optimization ➥ -l: link the given library ➥ -c: do not execute the linker ➥ later: g++ -o Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 342 5.1.1 Fundamentals of C++ ... An example: Hello World! (☞ 05/hello.cpp) #include using namespace std; Preprocessor directive: inserts contents of file ’iostream’ (e.g., declaration of cout) Use the namespace ’std’ Function definition void sayHello() { cout << "Hello World\n"; Output of a text } Main program int main() { sayHello(); Return from main program: return 0; 0 = OK, 1,2,...,255: error } ➥ Compilation: g++ -Wall -o hello hello.cpp ➥ Start: ./hello Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 343 5.1.1 Fundamentals of C++ ... Syntax ➥ Identical to Java are among others: ➥ declaration of variables and parameters ➥ method calls ➥ control statements (if, while, for, case, return, ...) ➥ simple data types (short, int, double, char, void, ...) ➥ deviations: bool instead of boolean; char has a size of 1 Byte ➥ virtually all operators (+, *, %, <<, ==, ?:, ...) ➥ Very similar to Java are: ➥ arrays ➥ class declarations Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 344 5.1.2 Data types in C++ Arrays ➥ Declaration of arrays ➥ only with fixed size, e.g.: int ary1[10]; double ary2[100][200]; int ary3[] = { 1, 2 }; // int array with 10 elements // 100 ∗ 200 array // int array with 2 elements ➥ for parameters: size can be omitted for first dimension int funct(int ary1[], double ary2[][200]) { ... } ➥ Arrays can also be realized via pointers (see later) ➥ then also dynamic allocation is possible ➥ Access to array elements ➥ like in Java, e.g.: a[i][j] = b[i] * c[i+1][j]; ➥ but: no checking of array bounds!!! Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 345 5.1.2 Data types in C++ ... Classes and objects ➥ Declaration of classes (typically in .h file): class Example { private: // private attributes/methods int attr1; // attribute void pmeth(double d); // method public: // public attributes/methods Example(); // default constructor Example(int i); // constructor Example(Example &from); // copy constructor ~Example(); // destructor int meth(); // method int attr2; // attribute static int sattr; // class attribute }; Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 346 5.1.2 Data types in C++ ... Classes and objects ... ➥ Definition of class attributes and methods (*.cpp file): int Example::sattr = 123; // class attribute Example::Example(int i) { // constructor this->attr1 = i; } int Example::meth() { // method return attr1; } ➥ specification of class name with attributes and methods ➥ separator :: instead of . ➥ this is a pointer (☞ 5.1.3), thus this->attr1 ➥ alternatively, method bodies can also be specified in the class definition itself Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 347 5.1.2 Data types in C++ ... Classes and objects ... ➥ Declaration of objects: { Example ex1; // initialisation using default constructor Example ex2(10); // constructor with argument ... } // now the destructor for ex1, ex2 is called ➥ Access to attributes, invocation of methods ex1.attr2 = ex2.meth(); j = Example::sattr; // class attribute ➥ Assignment / copying of objects ex1 = ex2; // object is copied! Example ex3(ex2); // initialisation using copy constructor Roland Wismuller ¨ Betriebssysteme / verteilte Systeme 348 Parallel Processing (6/15) 5.1.3 Pointers (Zeiger) Variables in memory ➥ Reminder: variables are stored in main mamory short int myVar = 42; RAM 00101010 00000000 100 101 102 103 104 105 Address ➥ a variable gives a name and a type to a memory block ➥ here: myVar occupies 2 bytes (short int) starting with address 102 ➥ A pointer is a memory address, together with a type ➥ the type specifies, how the memory block is interpreted Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 349 5.1.3 Pointers (Zeiger) ... Declaration and use of pointers ➥ Example: int myAge = 25; int *pAge; pAge = &myAge; *pAge = 37; // an int variable // a pointer to int values // pAge now points to myAge // myAge now has the value 37 pAge myAge 37 ➥ The address operator & determines the adress of a variable ➥ The access to *pAge is called dereferencing pAge ➥ Pointers (nearly) always have a type ➥ e.g. int *, Example *, char **, ... Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 350 5.1.3 Pointers (Zeiger) ... Passing parameters by reference ➥ Pointers allow to pass parameters by reference ➥ Instead of a value, a pointer to the values is passed: void byReference(Example *e, *result = e->attr2; } int main() { Example obj(15); int res; byReference(&obj, &res); ... int *result) { // obj is more efficiently // passed by reference // res is a result parameter ➥ short notation: e->attr2 means (*e).attr2 Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 351 5.1.3 Pointers (Zeiger) ... void pointers and type conversion ➥ C++ also allows the use of generic pointers ➥ just a memory addess without type information ➥ declared type is void * (pointer to void) ➥ Dereferencing only possible after a type conversion ➥ caution: no type safety / type check! ➥ Often used for generic parameters of functions: void bsp(int type, void *arg) { if (type == 1) { double d = *(double *)arg; // arg must first be converted // to double * } else { int i = *(int *)arg; // int argument Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 352 5.1.3 Pointers (Zeiger) ... Arrays and pointers ➥ C++ does not distinguish between one-dimensional arrays and pointers (with the exception of the declaration) ➥ Consequences: ➥ array variables can be used like (constant) pointers ➥ pointer variables can be indexed int int int int int a[3] = { 1, 2, 3 }; b = *a; // equivalent to: b = a[0] c = *(a+1); // equivalent to: c = a[1] *p = a; // equivalent to: int *p = &a[0] d = p[2]; // d = a[2] Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 353 5.1.3 Pointers (Zeiger) ... Arrays and pointers ... ➥ Consequences ...: ➥ arrays as parameters are always passed by reference! void swap(int a[], int i, int j) { int h = a[i]; // swap a[i] and a[j] a[i] = a[j]; a[j] = h; } int main() { int ary[] = { 1, 2, 3, 4 }; swap(ary, 1, 3); // now: ary[1] = 4, ary[3] = 2; } Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 354 5.1.3 Pointers (Zeiger) ... Dynamic memory allocation ➥ Allocation of objects and arrays like in Java Example *p = new Example(10); int *a = new int[10]; // a is not initialised! int *b = new int[10](); // b is initialised (with 0) ➥ allocation of multi-dimensional arrays does not work in this way ➥ Important: C++ does not have a garbage collection ➥ thus explicit deallocation is necessary: delete p; // single object delete[] a; // array ➥ caution: do not deallocate memory multiple times! Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 355 5.1.3 Pointers (Zeiger) ... Function pointers ➥ Pointers can also point to functions: void myFunct(int arg) { ... } void test1() { void (*ptr)(int) = myFunct; // function pointer + init. (*ptr)(10); // function call via pointer ➥ Thus, functions can, e.g., be passed as parameters to other functions: void callIt(void (*f)(int)) { (*f)(123); // calling the passed function } void test2() { callIt(myFunct); // function as reference parameter Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 356 5.1.4 Strings and Output ➥ Like Java, C++ has a string class (string) ➥ sometimes also the type char * is used ➥ For console output, the objects cout and cerr are used ➥ Both exist in the name space (packet) std ➥ for using them without name prefix: using namespace std; // corresponds to ’import std.*;’ in Java ➥ Example for an output: double x = 3.14; cout << "Pi ist approximately " << x << "\n"; ➥ Special formatting functions for the output of numbers, e.g.: cout << setw(8) << fixed << setprecision(4) << x << "\n"; ➥ output with a field length of 8 and exacly 4 decimal places Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 357 5.1.5 Further specifics of C++ ➥ Global variables ➥ are declared outside any function or method ➥ live during the complete program execution ➥ are accessible by all functions ➥ Global variables and functions can be used only after the declaration ➥ thus, for functions we have function prototypes int funcB(int n); int funcA() { return funcB(10); } int funcB(int n) { return n * n; } Roland Wismuller ¨ Betriebssysteme / verteilte Systeme // function prototype // function definition // function definition Parallel Processing (6/15) 358 5.1.5 Further specifics of C++ ... ➥ Keyword static used with the declaration of gloabal variables or functions static int number; static void output(char *str) { ... } ➥ causes the variable/function to be usable only in the local source file ➥ Keyword const used with the declaration of variables or parameters const double PI = 3.14159265; void print(const char *str) { ... } ➥ causes the variables to be read-only ➥ roughly corresponds to final in Java ➥ (note: this description is extremely simplified!) Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 359 5.1.5 Further specifics of C++ ... ➥ Passing command line arguments: int main(int argc, char **argv) { if (argc > 1) cout << "Argument 1: " << argv[1] << "\n"; } Example invocation: bslab1% ./myprog -p arg2 Argument 1: -p ➥ argc is the number of arguments (incl. program name) ➥ argv is an array (of length argc) of strings (char *) ➥ in the example: argv[0] = "./myprog" argv[1] = "-p" argv[2] = "arg2" ➥ important: check the index against argc Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 360 5.1.6 C/C++ Libraries Overview ➥ There are several (standard) libraries for C/C++, which always come with one or more header files, e.g.: Header file iostream string stdlib.h sys/time.h math.h pthread.h mpi.h Library Description (g++ option) input/output C++ strings standard funct. time functions -lm math functions -lpthread threads -lmpich MPI Roland Wismuller ¨ Betriebssysteme / verteilte Systeme contains, e.g. cout, cerr string exit() gettimeofday() sin(), cos(), fabs() pthread create() MPI Init() Parallel Processing (6/15) 361 5.1.7 The C Preprocessor Functions of the preprocessor: ➥ Embedding of header file #include #include "myhdr.h" // searches only in system directories // also searches in current directory ➥ Macro expansion #define #define #define ... int i int a int b BUFSIZE VERYBAD GOOD 100 i + 1; (BUFSIZE+1) = BUFSIZE; = 2*VERYBAD = 2*GOOD; // Constant // Extremely bad style !! // Parenthesis are important! // becomes // becomes // becomes Roland Wismuller ¨ Betriebssysteme / verteilte Systeme int i = 100; int a = 2*i + 1; int a = 2*(100+1); Parallel Processing (6/15) 362 5.1.7 The C Preprocessor ... Functions of the preprocessor: ... ➥ Conditional compliation (e.g., for debugging output) int main() { #ifdef DEBUG cout << "Program has started\n"; #endif ... } ➥ output statement normally will not be compiled ➥ to activate it: ➥ either #define DEBUG at the beginning of the program ➥ or compile with g++ -DDEBUG ... Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 363 5.2 Tutorial: OpenMP ¨ 5.2.1 Ubersetzung und Ausfuhrung ¨ ¨ ➥ Ubersetzung: mit gcc (g++) ➥ typ. Aufruf: g++ -fopenmp myProg.cpp -o myProg’ ➥ OpenMP 3.0 ab gcc 4.4, OpenMP 4.0 ab gcc 4.9 ➥ Ausfuhrung: ¨ Start wie bei sequentiellem Programm ➥ z.B.: ./myProg ➥ (maximale) Anzahl der Threads muß vorher uber ¨ Umgebungsvari- able OMP_NUM_THREADS festgelegt werden ➥ z.B.: export OMP_NUM_THREADS=4 ➥ gilt dann fur ¨ alle Programme im selben Kommandofenster ➥ Auch moglich: ¨ ¨ temporares (Um-)Setzen von OMP_NUM_THREADS ➥ z.B.: OMP_NUM_THREADS=2 ./myProg Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 364 5.2.2 Debugging ➥ Es gibt nur wenige Debugger, die OpenMP voll unterstutzen ¨ ➥ z.B. Totalview ➥ erfordert enge Zusammenarbeit zw. Compiler und Debugger ➥ Auf den PCs im Labor H-A 4111: ➥ g++/ddd erlauben halbwegs vernunftiges ¨ Debugging ➥ unterstutzen ¨ mehrere Threads ➥ gdb: textueller Debugger (Standard LINUX debugger) ➥ ddd: graphisches Front-End fur ¨ gdb ➥ komfortabler, aber ”‘schwergewichtiger”’ ➥ Auf dem HorUS Cluster: totalview ➥ graphischer Debugger ➥ unterstutzt ¨ OpenMP und MPI Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 365 5.2.2 Debugging ... ¨ ➥ Voraussetzung: Ubersetzung mit Debugging-Information ➥ sequentiell: g++ -g -o myProg myProg.cpp ➥ mit OpenMP: g++ -g -fopenmp ... ¨ ➥ Debugging ist auch eingeschrankt(!) in Verbindung mit ¨ Optimierung moglich ➥ teilweise jedoch unerwartetes Verhalten des Debuggers ➥ falls moglich: ¨ Optimierungen abschalten ➥ g++ -g -O0 ... Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 366 5.2.2 Debugging ... Wichtige Funktionen eines Debuggers (Beispiele fur ¨ gdb): ➥ Starten des Programms: run arg1 arg2 ➥ Setzen von Haltepunkten auf Code-Zeilen: break file.cpp:35 ➥ Setzen von Haltepunkten auf Funktionen: break myFunc ➥ Ausgabe des Prozeduraufruf-Kellers: where ➥ Navigation im Prozeduraufruf-Keller: up bzw. down ➥ Ausgabe von Variableninhalten: print i ¨ von Variablen: set variable i=i*15 ➥ Andern ➥ Weiterfuhren ¨ des Programms (nach Haltepunkt): continue ➥ Einzelschitt-Abarbeitung: step bzw. next Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 367 5.2.2 Debugging ... Wichtige Funktionen eines Debuggers (Beispiele fur ¨ gdb): ... ➥ Anzeige aller Threads: info threads ➥ Auswahl eines Threads: thread 2 ➥ Kommandos wirken i.a. nur auf den ausgewahlten ¨ Thread ➥ Quellcode-Listing: list ➥ Hilfe: help ➥ Beenden: quit ¨ ➥ Alle Kommandos konnen im gdb auch abgekurzt ¨ werden Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 368 5.2.2 Debugging ... Beispielsitzung mit gdb (sequentiell) bsclk01> g++ -g -O0 -o ross ross.cpp ← Option -g fur ¨ Debugging bsclk01> gdb ./ross GNU gdb 6.6 Copyright 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public ... (gdb) b main ← Haltepunkt auf Prozedur main setzen Breakpoint 1 at 0x400d00: file ross.cpp, line 289. (gdb) run 5 5 0 ← Programm mit diesen Argumenten starten Starting program: /home/wismueller/LEHRE/pv/ross 5 5 0 Breakpoint 1, main (argc=4, argv=0x7fff0a131488) at ross.cpp:289 289 if (argc != 4) { (gdb) list ← Listing um die aktuelle Zeile 284 285 /* 286 ** Get and check the command line arguments Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 369 5.2.2 Debugging ... 287 */ 288 289 if (argc != 4) { 290 cerr << "Usage: ross ... 291 cerr << " : size... 292 cerr << " : 0 = compute one ... 293 cerr << " 1 = compute all ... (gdb) b 315 ← Haltepunkt auf Zeile 35 setzen Breakpoint 2 at 0x400e59: file ross.cpp, line 315. (gdb) c ← Programm fortfuhren ¨ Continuing. Breakpoint 2, main (argc=4, argv=0x7fff0a131488) at ross.cpp:315 315 num_moves = Find_Route(size_x, size_y, moves); ¨ Programmzeile (hier: 315) ausfuhren ¨ (gdb) n ← Nachste 320 if (num_moves >= 0) { (gdb) p num moves ← Variable num moves ausgeben $1 = 24 Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 370 5.2.2 Debugging ... (gdb) where ← Wo steht das Programm gerade? #0 main (argc=4, argv=0x7fff0a131488) at ross.cpp:320 (gdb) c ← Programm fortfuhren ¨ Continuing. Solution: ... Program exited normally. (gdb) q ← gdb beenden bsclk01> Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 371 5.2.2 Debugging ... Beispielsitzung mit gdb (OpenMP) bslab03> g++ -fopenmp -O0 -g -o heat heat.cpp solver-jacobi.cpp bslab03> gdb ./heat GNU gdb (GDB) SUSE (7.5.1-2.1.1) ... (gdb) run 500 ... Program received signal SIGFPE, Arithmetic exception. 0x0000000000401711 in solver._omp_fn.0 () at solver-jacobi.cpp:58 58 b[i][j] = i/(i-100); (gdb) info threads Id Target Id Frame 4 Thread ... (LWP 6429) ... in ... at solver-jacobi.cpp:59 3 Thread ... (LWP 6428) ... in ... at solver-jacobi.cpp:59 2 Thread ... (LWP 6427) ... in ... at solver-jacobi.cpp:63 * 1 Thread ... (LWP 6423) ... in ... at solver-jacobi.cpp:58 (gdb) q Roland Wismuller ¨ Betriebssysteme / verteilte Systeme 372 Parallel Processing (6/15) 5.2.2 Debugging ... Beispielsitzung mit ddd Haltepunkt Listing (Kommandos über rechte Maustaste) Aktuelle Position Menu Ein−/Ausgabe (auch Eingabe von gdb−Kommandos) Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 373 5.2.2 Debugging ... Beispielsitzung mit totalview Kommandos Variablen Aufrufkeller Haltepunkt Listing (Kommandos über rechte Maustaste) Aktuelle Position Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Threads Parallel Processing (6/15) 374 Notes for slide 374: Totalview wird wie gdb unter Angabe der ausfuhrbaren ¨ Datei gestartet: gl930@slc2:~/code> totalview ./heat Die Kommandozeilen-Argumente mussen ¨ dann in dem Fenster ”‘Startup Parameters”’, das automatisch erscheint, im Reiter ”‘Arguments”’ angegeben werden. Das Fen¨ ster kann spater auch wieder uber ¨ den Menupunkt ”‘Process / Startup Parameters”’ ¨ geoffnet werden. Eine Besonderheit bei Totalview ist, daß die uber ¨ die Symbolleiste gestarteten Kommandos auf eine ganze Gruppe von Threads oder Prozessen wirken (siehe Auswahlbox links daneben und/oder das Group-Menue). Ebenso kann man sich z.B. den Inhalt einer Variablen fur ¨ alle Thread oder Prozesse auflisten lassen. 374-1 5.2 Tutorial: OpenMP ... 5.2.3 Leistungsanalyse ➥ Typisch: Instrumentierung des erzeugten Programmcodes ¨ bei/nach der Ubersetzung ➥ Einfugen ¨ von Code an wichtigen Stellen des Programms ➥ zur Erfassung relevanter Ereignisse ➥ z.B. Beginn/Ende von parallelen Regionen, Barrieren, ... ➥ Wahrend ¨ der Ausfuhrung ¨ werden dann die Ereignisse ➥ einzeln in eine Spurdatei (Trace file) protokolliert ➥ oder bereits zu einem Profile zusammengefasst ➥ Auswertung erfolgt nach Programmende ➥ vgl. Abschnitt 1.9.6 ➥ Im H-A 4111 und auf HorUS-Cluster: Scalasca Roland Wismuller ¨ Betriebssysteme / verteilte Systeme 375 Parallel Processing (6/15) 5.2.3 Leistungsanalyse ... Leistungsanalyse mit Scalasca ➥ Pfade setzen (im H-A 4111; HorUS: siehe 5.2.4) ➥ export PATH=/opt/dist/scorep-1.4.1/bin:\ /opt/dist/scalasca-2.2.1/bin:$PATH ¨ des Programms: ➥ Ubersetzen ➥ scalasca -instrument g++ -fopenmp ... barrier.cpp ➥ Ausfuhren ¨ des Programms: ➥ scalasca -analyze ./barrrier ➥ legt Daten in einem Verzeichnis scorep barrier 0x0 sum ab ➥ 0x0 zeigt Thread-Anzahl an (0 = Default) ➥ Verzeichnis darf noch nicht existieren, ggf. loschen ¨ ➥ Interaktive Analyse der aufgezeichneten Daten: ➥ scalasca -examine scorep barrier 0x0 sum Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 376 5.2.3 Leistungsanalyse ... Leistungsanalyse mit Scalasca: Beispiel von Folie 217 Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 377 5.2.3 Leistungsanalyse ... Leistungsanalyse mit Scalasca: Beispiel von Folie 217 ... ➥ Im Beispiel kann durch die Option nowait bei der ersten Schleife die Wartezeit in Barrieren drastisch reduziert werden: Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 378 Notes for slide 378: Bei der Interpretation der von Scalasca angezeigten Zeiten ist folgendes zu beachten: ➥ Die fur ¨ einen Eintrag angezeigte Metrik (hier: Zeit) ist immer exklusive der sicht¨ baren Untereintrage. Wind im Bild z.B. der Punkt ”‘7.97 Execution”’ im Metric tree eingeklappt, zeigt Scalasca ”‘8.12 Execution”’ an (0.15s Ausfuhrungszeit ¨ fur ¨ OMP + 7.97s fur ¨ die restliche Ausfuhrung). ¨ Im Beispiel kann man erkennen, daß durch die Option nowait der Zeitantail fur ¨ OpenMP (Synchronisation) deutlich kleiner geworden ist (0.15s statt 5.62s), die reine Ausfuhrungszeit ¨ aber etwas gestiegen ist (von 7.21s auf 7.97s), evtl. aufgrund von Konkurrenz um den Speicher. ➥ Die Zeit, die Scalasca anzeigt, ist die aufsummierte Ausfuhrungszeit ¨ aller ¨ Threads, inklusive Wartezeiten. Im Beispiel ist das Programm tatsachlich nach 1.3s beendet. ➥ Scalasca zeigt immer noch ein Lastungleichgewicht (Computational imbalance) an, da z.B. Thread 7 in der ersten Schleife immer noch viel mehr rechnet als Thread 1. Daß sich dies mit dem entsprechenden Ungleichgewicht in der zweiten Schleife gerade aufhebt, kann Scalasca nicht erkennen. 378-1 5.2.4 Nutzung des HorUS-Clusters Architektur des HorUS-Clusters ➥ 34 Dell PowerEdge C6100 Systeme mit je 4 Knoten ➥ 136-Compute-Knoten ➥ CPU: 2 x Intel Xeon X5650, 2.66 GHz, 6 Cores pro CPU, 12 MB Cache ➥ Hauptspeicher: 48 GB (4GB je Core, 1333 MHz DRR3) ➥ Festplatte: 500 GB SATA (7,2k RPM, 3,5 Zoll) ➥ Insgesamt: 272 CPUs, 1632 Cores, 6,4 TB RAM, 40 TB Platte ➥ Paralleles Dateisystem: 33 TB, 2.5 GB/s ➥ Infiniband-Netzwerk (40 GBit/s) ➥ Peak-Performance: 17 TFlop/s Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 379 5.2.4 Nutzung des HorUS-Clusters ... Zugang ¨ ➥ Uber SSH: ssh -X g-Kennung @slc2.zimt.uni-siegen.de ➥ Im Labor H-A 4111: ➥ Weiterleitung der SSH-Verbindung durch Labor-Gateway ➥ ssh -X -p 22222 g-Kennung @bslabgate1.lab.bvs ➥ Am besten Nutzung der Datei $HOME/.ssh/config: ➥ Host horus user g-Kennung hostname bslabgate1.lab.bvs ForwardX11 yes HostKeyAlias horus port 22222 ➥ Dann einfach: ssh horus Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 380 5.2.4 Nutzung des HorUS-Clusters ... Aufsetzen der SSH im H-A 4111 ➥ Erzeugen eines SSH-Schlussels: ¨ ➥ ssh-keygen -b 2048 -t rsa (oder -b 4096) ➥ bei Frage "Enter file ..." einfach Return drucken ¨ ➥ sichere Passphrase fur ¨ ¨ privaten Schlussel ¨ wahlen! ¨ ➥ Anfugen ¨ des offentlichen Schlussels ¨ an die Liste autorisierter Schlussel: ¨ ➥ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys ➥ Damit ist auch ein Einloggen auf andere Laborrechner ohne ¨ dauernde Passworteingabe moglich Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 381 5.2.4 Nutzung des HorUS-Clusters ... Aufsetzen der Umgebung auf dem HorUS ➥ SSH-Schlussel ¨ auf den HorUS kopieren ➥ ssh-copy-id -i ~/.ssh/id_rsa.pub horus ➥ Wichtig: achten Sie darauf, Ihr Paßwort korrekt einzutippen! ¨ ➥ Auf dem HorUS benotigte Module definieren: module module module module export load openmpi/gcc/64/1.8.1 für Scalasca load gcc/4.8.4 load scalasca/2.2 load scorep/gcc-openmpi_4.8.4-1.8.1/1.4 PATH=$PATH:/cm/shared/ZIMT/apps/cube/4.3/gcc/bin ➥ am besten an ~/.bashrc anfugen ¨ ➥ fur ¨ OpenMP 4.0: Modul gcc/5.1.0 statt gcc/4.8.4 laden ➥ Scalasca kann nicht mehr verwendet werden! Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 382 Notes for slide 382: ¨ Falls das Kommando ssh-copy-id nicht installiert ist, kann man den offentlichen SSHSchlussel ¨ auch mit cat ~/.ssh/id_rsa.pub |\ ssh horus ’umask 077; cat >> ~/.ssh/authorized_keys’ kopieren. 382-1 5.2.4 Nutzung des HorUS-Clusters ... Zur praktischen Nutzung des HorUS ➥ Mounten des HorUS-Dateisystems auf die Laborrechner ➥ Verzeichnis fur ¨ Mount-Punkt anlegen: mkdir ~/mnt ➥ Mounten des HorUS-Dateisystems: sshfs horus: ~/mnt ➥ Unmount: fusermount -u ~/mnt ➥ Start von Programmen auf dem HorUS ➥ Nutzung des Batch-Queueing-Systems SLURM ➥ siehe https://computing.llnl.gov/linux/slurm ➥ Start eines OpenMP-Programms, z.B.: ➥ export OMP_NUM_THREADS=8 salloc --exclusive --partition debug \ $HOME/GAUSS/heat 500 Roland Wismuller ¨ Betriebssysteme / verteilte Systeme 383 Parallel Processing (6/15) Notes for slide 383: Das Kommando salloc allokiert Knoten auf dem Cluster und fuhrt ¨ dann das angegebene Kommando aus. Dabei blockiert salloc so lange, bis das Kommando fertig abgearbetet ist. Die Parameter im Beispiel bedeuten: ➥ --exclusive: keine anderen Nutzer/Prozesse auf dem Knoten ➥ --partition debug: Name der Partition (debug: Default-Laufzeit 5 Minuten, max. Laufzeit 20 Minuten) ➥ --time: maximale Laufzeit in Minuten ¨ Als Alternative zur Partition debug konnen Sie auch die Partition short verwenden (Default-Laufzeit 1 Stunde, max. Laufzeit 2 Stunden) Neben diesem Kommando gibt es z.B. ein Kommando sbatch, das einen Job als ¨ Batch-Job im Hintergrund ablaufen lasst. Mit squeue kann man sich den Inhalt der Batch-Queues oder den Zustand eines bestimmten Jobs ausgeben lassen. Mit scancel ¨ kann man submittierte Jobs wieder loschen. 383-1 ¨ 5.3 Praktikum: Sokoban-Loser (Animated slide) Hintergrund ➥ Sokoban: japanisch fur ¨ ”‘Lagerhausverwalter”’ ➥ Computerspiel von 1982, entwickelt von Hiroyuki Imabayashi ➥ Ziel: Spielfigur muss alle Objekte (Kisten) auf die Zielpositionen schieben ➥ Kisten konnen ¨ nur geschoben, nicht gezogen werden ➥ gleichzeitiges Verschieben mehrerer Kisten nicht moglich ¨ Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 384 ¨ 5.3 Praktikum: Sokoban-Loser ... (Animated slide) Wie findet man die Zugfolge? ➥ Konfiguration: Zustand des Spielfelds ➥ Positionen der Kisten ➥ Position der Spielfigur (Zusammenhangskomponente) ➥ Jede Konfiguration hat eine Menge von Nachfolge-Konfigurationen ➥ Konfigurationen mit Nachfolger-Relation bilden einen gerichteten Graphen ➥ keinen Baum, da Zyklen moglich! ¨ ➥ Gesucht: kurzester ¨ Weg von der Wurzel desGraphen zur Zielkonfiguration ➥ d.h. kleinste Zahl von Kisten- verschiebungen Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 385 ¨ 5.3 Praktikum: Sokoban-Loser ... Wie findet man die Zugfolge? ... ➥ Zwei Alternativen: ➥ Tiefensuche ➥ Probleme: ➥ Breitensuche ➥ Probleme: ➥ Zyklen ➥ ➥ Behandlung unterschiedlich langer Wege Rekonstruktion des Wegs zu einem Knoten ➥ Speicherplatzbedarf Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 386 ¨ 5.3 Praktikum: Sokoban-Loser ... Backtracking-Algorithmus fur ¨ Tiefensuche: DepthFirstSearch(conf ) // conf = aktuelle Konfiguration ¨ Fuge ¨ conf an Losungspfad an ¨ Falls conf Losungskonfiguration: ¨ Losungspfad gefunden return ¨ ¨ Falls Tiefe großer als die der bisher besten Losung: ¨ Letztes Element vom Losungspfed entfernen // Durchsuchung dieses Zweigs abbrechen return ¨ Fur ¨ alle moglichen Nachfolgekonfigurationen c von conf : Falls c noch nicht in kleinerer/gleicher Tiefe gefunden wurde: Neue Tiefe fur ¨ c merken // Rekursion DepthFirstSearch(c) ¨ Letztes Element vom Losungspfad entfernen // backtrack return Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 387 ¨ 5.3 Praktikum: Sokoban-Loser ... Algorithmus fur ¨ Breitensuche: BreadthFirstSearch(conf ) // conf = Start-Konfiguration Fuge ¨ conf an Warteschlange der Tiefe 0 an depth = 1; Solange Warteschlange der Tiefe depth-1 nicht leer: Fur ¨ alle Konfigurationen conf in dieser Warteschlange: ¨ Fur ¨ alle moglichen Nachfolgekonfigurationen c von conf : Falls Konfiguration c noch nicht besucht wurde: ¨ Konfiguration c mit Vorganger conf in Menge besuchter Konfigurationen und in Warteschlagen der Tiefe depth aufnehmen ¨ Falls c Losungskonfiguration: ¨ Losungspfad zu c bestimmen ¨ return // Losung gefunden depth = depth+1 ¨ return // keine Losung Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 388 ¨ 5.3 Praktikum: Sokoban-Loser ... (Animated slide) Beispiel zum Backtracking-Algorithmus Konfiguration mit möglichen Zügen Möglicher Zug Gewählter Zug Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 389 5.4 Tutorial: MPI (MPICH2) ¨ 5.4.1 Ubersetzung und Ausfuhrung ¨ Verwendete MPI-Implementierungen ➥ MPICH2 1.2.1 (im H-A 4111), OpenMPI 1.8.1 (HorUS) ➥ Portable Implementierungen des MPI-2 Standards ¨ u.a. Visualisierungswerkzeug jumpshot ➥ MPICH2 enthalt ¨ Ubersetzung von MPI-Programmen: mpic++ ➥ mpic++ -o myProg myProg.cpp ➥ kein eigener Compiler fur ¨ MPI, lediglich ein Skript, das ¨ zusatzliche Compileroptionen setzt: ➥ Include- und Linker-Pfade, MPI-Bibliotheken, ... ➥ Option -show zeigt die ausgefuhrten ¨ Compiler-Aufrufe Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 390 ¨ 5.4.1 Ubersetzung und Ausfuhrung ¨ ... Start von MPI-Programmen: mpiexec ➥ mpiexec -n 3 myProg arg1 arg2 ➥ startet myProg arg1 arg2 mit 3 Prozessen ➥ myProg muss im Suchpfad liegen oder mit Pfadnamen (absolut oder relativ) angegeben werden ➥ Auf welchen Knoten starten die Prozesse? ➥ implementierungs- und plattformabhangig ¨ ➥ in MPICH2 (mit Hydra Prozessmanager): Festlegung uber ¨ ¨ eine Konfigurationsdatei moglich: mpiexec -n 3 -machinefile machines myProg arg1 arg2 ➥ Konfigurationsdatei enthalt ¨ Liste von Rechnernamen, z.B.: ← einen Prozess auf bslab03 starten bslab01 bslab05:2 ← zwei Prozesse auf bslab05 starten Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 391 ¨ 5.4.1 Ubersetzung und Ausfuhrung ¨ ... Verwendung von MPICH2 im H-A 4111 ¨ ➥ Ggf. zunachst Pfad setzen (in ~/.bashrc): ➥ export PATH=/opt/dist/mpich2-1.2.1/bin:$PATH ➥ Hinweise zu mpiexec: ➥ Die MPI-Programme starten auf den anderen Rechnern im selben Verzeichnis, in dem mpiexec aufgerufen wurde ➥ mpiexec startet per ssh einen Hilfsprozess auf jedem Rechner, der in der Konfigurationsdatei genannt wird ➥ auch wenn gar nicht so viele MPI-Prozesse gestartet werden sollen ➥ Eintrag localhost in der Konfigurationsdatei vermeiden ➥ fuhrt ¨ zu Problemen mit ssh ➥ Sporadisch werden Programme mit relativem Pfadnamen (./myProg) nicht gefunden, dann $PWD/myProg angeben Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 392 5.4 Tutorial: MPI (MPICH2) ... 5.4.2 Debugging ¨ gdb und totalview ➥ MPICH2 und OpenMPI unterstutzen ➥ MPICH2 allerdings nur mit dem MPD Prozessmanager ➥ ”‘Hack”’ im H-A 4111: starte einen gdb / ddd fur ¨ jeden Prozeß ➥ Aufruf fur ¨ gdb: mpiexec -enable-x -n ... /opt/dist/mpidebug/mpigdb myProg args ➥ gdb startet jeweils in eigenem Textfenster ➥ Aufruf fur ¨ ddd: mpiexec -enable-x -n ... /opt/dist/mpidebug/mpiddd myProg args ➥ Prozesse mit continue weiterlaufen lassen (nicht run ...) ¨ ➥ Voraussetzung: Ubersetzung mit Debugging-Information ➥ mpic++ -g -o myProg myProg.cpp Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 393 Notes for slide 393: Im H-A 4111 gibt es mit dem Debugging-”‘Hack”’ und dem Hydra-Prozessmanager manchmal Probleme: Beim Start erscheinen Fehlermeldungen bezuglich ¨ ”‘error in locking authority file”’ und als Folge ”‘Can’t open display”’. Abhilfen / Workarounds: ➥ Verwendung des ”‘gefixten”’ Hydra-Prozessmanagers mpiexec.fix, der aber die Prozesse deutlich langsamer startet. ➥ Verwendung des gforker Prozessmanagers (der alle Prozesse lokal startet): mpiexec.gforker -n 2 /opt/dist/mpidebug/mpigdb myProg args In diesem Fall fallen die Option -enable-x und -machinefile weg. 393-1 5.4 Tutorial: MPI (MPICH2) ... 5.4.3 Leistungsanalyse mit Scalasca ¨ OpenMP ➥ Prinzipiell genauso wie fur ¨ ➥ Ubersetzen des Programms: ➥ scalasca -instrument mpic++ -o myprog myprog.cpp ➥ Ausfuhren ¨ des Programms: ➥ scalasca -analyze mpiexec -n 4 ... ./myprog ➥ legt Verzeichnis scorep myprog 4 sum an ➥ 4 zeigt Zahl der Prozesse an ➥ Verzeichnis darf noch nicht existieren, ggf. loschen ¨ ➥ Interaktive Analyse der aufgezeichneten Daten: ➥ scalasca -examine scorep myprog 4 sum Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 394 5.4 Tutorial: MPI (MPICH2) ... 5.4.4 Leistungsanalyse und Visualisierung mit Jumpshot ➥ MPICH unterstutzt ¨ die Erzeugung von Ereignisspuren ➥ Ereignisse: MPI-Aufrufe und -Ruckkehr, ¨ Senden, Empfangen, ... ➥ Einschalten der Funktion uber ¨ Optionen von mpic++ ➥ mpic++ -mpe=mpitrace -o myProg myProg.cpp ➥ Ausgabe der Ereignisse auf den Bildschirm ➥ mpic++ -mpe=mpilog -o myProg myProg.cpp ➥ Ausgabe der Ereignisse in Spurdatei myProg.clog2 ➥ eine gemeinsame Spurdatei fur ¨ alle Prozesse ➥ Analyse der Spurdatei mit jumpshot: ➥ Formatwandlung: clog2TOslog2 myProg.clog2 ➥ Visualisierung: jumpshot myProg.slog2 Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 395 5.4.4 Leistungsanalyse und Visualisierung mit Jumpshot ... Beispiel: Ping-Pong Programm ➥ Modifikation im Programm: Prozeß 0 fuhrt ¨ zwischen Senden und Empfangen eine Berechnung durch ➥ damit das Beispiel interessanter wird ... ➥ Kommandos: mpic++ -mpe=mpilog -o pingpong pingpong.cpp ➥ bindet Code zur Erzeugung von Spurdateien mit ein mpiexec -n 2 -machinefile machines ./pingpong 5 100000 ➥ hinterlaßt ¨ Spurdatei pingpong.clog2 clog2TOslog2 pingpong.clog2 ➥ wandelt pingpong.clog2 in pingpong.slog2 um jumpshot pingpong.slog2 Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 396 5.4.4 Leistungsanalyse und Visualisierung mit Jumpshot ... Beispiel: Ping-Pong Programm ... Eingefügte Berechnung zw. Senden und Empfangen MPI_Send blockiert, bis Nachricht empfangen! Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 397 5.4 Tutorial: MPI (MPICH2) ... 5.4.5 Nutzung des HorUS Clusters ¨ SLURM, z.B. mit: ➥ Start von MPI-Programmen uber ➥ salloc --exclusive --partition short --nodes=4 \ --ntasks=16 mpiexec $HOME/GAUSS/heat 500 ➥ wichtige Optionen von salloc: ➥ --nodes=4: Zahl der zu allokierenden Knoten ➥ --ntasks=16: Gesamtzahl der zu startenden Prozesse ➥ Zur Leistungsanalyse: Scalasca ➥ salloc ... scalasca -analyze mpiexec $HOME/GAUSS... ➥ Zum Debugging: Totalview ➥ salloc ... mpiexec -debug $HOME/GAUSS/heat 500 Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 398 5.5 Praktikum: Jacobi und Gauss/Seidel mit MPI (Animated slide) ¨ Grundsatzliche Vorgehensweise 0. Matrix mit Temperaturwerten 0 1 2 1 1. Aufteilung der Matrix in Streifen Jeder Prozeß speichert lokal nur einen Teil der Matrix 2. Einführung von Überlappungsbereichen 1 2 2 1 2 3 Jeder Prozeß speichert an den Schnitt− kanten jeweils eine Zeile zusätzlich 3. Nach jeder Iteration werden die Über− lappungsbereiche mit den Nachbar− prozessen ausgetauscht Z.B. erst nach unten (1), dann nach oben (2) Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 399 5.5 Praktikum: Jacobi und Gauss/Seidel mit MPI ... ¨ Grundsatzliche Vorgehensweise ... int nprocs, myrank; double a[LINES][COLS]; MPI_Status status; MPI_Comm_size(MPI_COMM_WORLD, &nprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); /∗ Schritt 1: Sende nach unten, Empfange von oben ∗/ if (myrank != nprocs-1) MPI_Send(a[LINES-2], COLS, MPI_DOUBLE, myrank+1, 0, MPI_COMM_WORLD); if (myrank != 0) MPI_Recv(a[0], COLS, MPI_DOUBLE, myrank-1, 0, MPI_COMM_WORLD, &status); Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 400 5.5 Praktikum: Jacobi und Gauss/Seidel mit MPI ... Aufteilung der Daten ¨ ➥ Geschlossene Formel zur gleichmaßigen Aufteilung eines Feldes ¨ der Lange n auf np Prozesse: ➥ start(p) = n ÷ np · p + max(p − (np − n mod np), 0) ➥ size(p) = (n + p) ÷ np ➥ Prozess p erhalt ¨ size(p) Elemente ab Index start(p) ➥ Damit ergibt sich folgende Indextransformation: ➥ tolocal(i) = (p, i − start(p)) mit p ∈ [0, np − 1] so, daß 0 ≤ i − start(p) < size(p) ➥ toglobal(p, i) = i + start(p) ¨ ¨ ➥ Bei Jacobi und Gauss/Seidel sind zusatzlich noch die Uberlappungsbe zu berucksichtigen! ¨ Roland Wismuller ¨ Betriebssysteme / verteilte Systeme Parallel Processing (6/15) 401 5.5 Praktikum: Jacobi und Gauss/Seidel mit MPI ... Aufteilung der Berechnungen ➥ Aufteilung i.a. nach Owner computes-Regel ➥ der Prozeß, der ein Datenelement schreibt, fuhrt ¨ auch die entsprechende Berechnungen durch ¨ ➥ Zwei Moglichkeiten zur technischen Realisierung: ➥ Index-Transformation und bedingte Ausfuhrung ¨ ➥ z.B. bei der Ausgabe der Kontrollwerte der Matrix if ((x-start >= 0) && (x-start < size)) cout << "a[" << x << "]=" << a[x-start] << "\n"; ➥ Anpassung der umgebenden Schleifen ➥ z.B. bei der Iteration oder der Intialisierung der Matrix for (i=0; i