Documente Academic
Documente Profesional
Documente Cultură
Laboratorul de Calcul paralel se desfoar ntr-un cluster Linux (din salile B125a sau
B138) precum i n clusterul HPC (High Performance Computer)-Dell PowerEdge.
Un cluster de calculatoare este compus dintr-un grup de calculatoare independente,
conectate printr-o reea de interconectare local (LAN Local Area Network) care poate oferi (n
functie de numrul i capacitatea calculatoarelor conectate) performante foarte ridicate, pn la
nivel de supercalculatoare.
ntr-adevar, cel mai performant supercalculator actual (din lista top500/ noiembrie 2013)
este clusterul Tianhe-2 (MilkyWay-2) cu 3,120,000 procesoare Intel E5, cu putere de calcul ~ 33
PFLOPS, instalat n China.
n fiecare nod al clustrerelor ruleaz un sistem de operare, care asigur gestiunea resurselor
locale ale nodului respectiv i interfaa cu alte componente software (middleware) i aplicatiile din
cluster. Cele mai folosite sisteme de operare n clustere sunt sistemele Linux (n diferite distributii
ca RedHat, Suse etc.), care acoper un procent de peste 90% din supercalculatoarele listate n
www.top500.org/lists/2013/11 (din care majoritatea sunt clustere). Sistemele de operare Unix (n
diferite variante: AIX, IRIX, HP-UX, Solaris, Tru64 Unix, Super-UX etc.), sunt folosite intr-o
proportie mult mai mic (aproximatiiv 6%), iar sistemele Windows au o utilizare de sub 1%.
1.1.1 Clusterele Linux
Clusterele din laboratoarele B125a si B138 sunt compuse din 12-15 calculatoare desktop cu
procesoare CPU cu 2 (respectiv 4) cores fiecare, conectate printr-o reea 1 GB Ethernet.
Pe fiecare staie este instalat sistemul Linux - Ubuntu 12.04 (LTS), bibliotecile i toolseturile necesare pentru dezvoltarea urmtoarelor categorii de aplicaii paralele:
Aplicaii paralele cu memorie partajat: se pot folosi numai cele 2 (respectiv 4) cores
care acceseaz memoria partrajat din fiecare nod. Pentru astfel de aplicaii s-au folosit
bibliotecile Pthread (POSIX Threads) i OpenMP (Open Multi-Processing).
Aplicaii paralele cu transfer de mesaje: se pot folosi toate nodurile din fiecare cluster i
toate procesoarele (cores) din fiecare nod, ntre care datele se comunic prin transfer de
mesaje. Pentru astfel de aplicaii s-a folosit biblioteca MPI (Massage Passing Interface),
n implementarea open-source OpenMPI.
Aplicaii R i Parallel-R.
Reeaua de noduri ale clusterului, dintre care un nod este nod de control iar celelalte 3
sunt noduri de calcul, conectate printr-o reea (switch intern) de 10 GB
Fiecare nod (de control i de calcul) conine cte 2 procesoare Intel Xeon (fiecare cu cte
8 cores) i 64 GB RAM.
Fiecare nod de calcul mai conine cte 2 procesoare GPU Nvidia Tesla M2090 cu cte
512 CUDA cores (655 Gflops/GPU), astfel nct performana unui astfel de nod ajunge
la 1.6 Tflops
1
- -
Adaptor de reea Ethernet pentru conexiuni externe (switch extern cu 2 porturi 1Gbit si
22 porturi 10/100 Mbit)
n clusterul HPC Dell PowerEdge sunt instalate aceleai biblioteci pentru aplicaii paralele
ca i n clusterele Linux:
PTHREAD biblioteca de thread-uri POSIX
OpenMP biblioteca de calcul paralel n multiprocesoare
OpenMPI biblioteca de transfer de mesaje
Platforma R si bibliotecile Parallel-R
n plus, n clusterul HPC mai este instalat biblioteca CUDA 5 toolkit si Nvidia drivers care
permit execuia programelor paralele n procesoarele GPU ale nodurilor de calcul.
Majoritatea bibliotecilor i toolset-urilor de calcul paralel sunt disponibile sub sistemele de
operare Unix/Linux, de aceea laboratorul se desfoar n sisteme Linux i prima lucrare face o
introducere n aspectele de baz ale sistemelor de operare Unix/Linux.
- -
:numele - specific utilizatorul ntr-un mod unic i este format din litere, cifre, '.' sau '_';
:UID - ID-ul utilizatorului, un numr asociat numelui;
:GID - ID-ul grupului de utilizatori implicit;
parola - parola este un ir de caractere pe care l cunoate numai utilizatorul;
numele real - alte informaii despre utilizator, n mod obinuit numele ntreg;
directorul de baz - este directorul implicit iniial; fiecare utilizator trebuie s aib un
director de baz, de obicei n /home, al crui proprietar trebuie s fie;
shell pentru login - programul pornit de sistem pentru utilizator dup ce acesta este
admis n sistem; de cele mai multe ori este un interpretor de comenzi (shell);
Crearea unui nou utilizator poate fi fcut numai de ctre superuser folosind comenzi care
pot diferi de la un sistem la altul. n sistemul Linux se utilizeaz comanda #adduser. Aceasta
stabilete n dialogul cu administratorul sistemului toate elementele care caracterizeaz noul
utilizator: nume, numr, apartenena la un grup, parola, shell-ul utilizat, etc. Tot superuser-ul este
cel care poate terge un utilizator din sistem folosind comanda #rmuser.
5
- -
Nodul de control are numele hpc.intern i mai multe adrese de reea interne, i este accesibil
pe portul 2222 al adresei translatate (cu NAT) 141.85.254.57. Conectarea la nodurile de calcul se
face din nodul de control compute-0-1 (respectiv compute-0-2, compute-0-3) astfel:
[user@hpc ~]$ ssh compute-0-1
Metoda de mai sus necesit folosirea explicit a unui fiier intermediar temporar
(lista_fisiere) ctre care este direcionat ieirea comenzii ls, precum i execuia succesiv a
unor comenzi. O soluie mai bun este oferit de shell i se numete prelucrare n conduct
(pipelining). Prelucrarea n conduct permite s se conecteze un ir de comenzi n care ieirea
standard a fiecreia dintre ele este conectat direct la intrarea standard a celei care urmeaz. Aceast
conectare ntre o ieire i o intrare este simbolizat de caracterul "|". Astfel lista sortat este obinut
prin conectarea n conduct a comenzii ls i a programului sort.
$ ls | sort -r
7
- -
$
$
$
$
Pe unele sisteme cu resurse reduse (memorie intern, spaiu pe disc) sistemul de manuale este
nlocuit cu un help mai puin consumator de resurse, dar cu mai puine informaii:
$ help who - se obin informaii despre opiunile comenzii who;
Editarea programelor
n sesiunile care pot folosi interfaa grafic a sistemului, editarea fiierelor surs se face cel
mai simplu cu utilitarul gedit.
$ gedit nume_fisier
Comenzile acestuia se gsesc n meniu i sunt asemantoare cu ale oricrui alt editor de text.
n sesiunile care nu pot folosi interfaa grafic (cum este conectarea ssh la HPC), pentru
editarea fiierelor sursa se poate folosi unul dintre urmtoarele editoare : vi, joe, jed. De
exemplu, cel mai simplu i mai folosit mod de a apela vi este:
$ vi nume_fisier
unde nume_fiier este numele fiierului de editat. Dup introducerea acestei linii de comand,
pe ecran vor fi afiate liniile de nceput ale fiierului. Pe ultima linie a ecranului apare un mesaj care
const din numele fiierului i dimensiunea sa n cazul n care fiierul exist pe disc sau numele
fiierului i mesajul No such file or directory sau New file n funcie de versiunea de vi.
Dialogul utilizator/vi se desfoar fie n modul comand fie n modul introducere text. La
terminarea introducerii textului se apas <ESC> pentru trecerea n modul comand. Exemple de
comenzi vi:
Dac nu se specific parametrul [-o nume] compilatorul produce ca ieire executabilul a.out.
Alte opiuni ale compilatorului gcc se pot gsi prin comanda:
$ man gcc
De exemplu:
-O sau -O3 realizeaz optimizarea codului executabil, este bine s se foloseasc n special dac se
urmrete viteza de execuie i nu lungimea codului;
-c realizeaz numai compilarea, care n combinaie cu -o genereaz mai multe fiiere obiect care apoi
vor fi link-edit-ate ntr-un singur executabil;
-l[biblioteca] introduce la link-edit-are biblioteca cerut, n desfurarea lucrrilor de laborator se
va utiliza biblioteca matematic (-lm) i pthread (-lpthread);
-L/path d indicaii asupra localizrii bibliotecilor suplimentare, nu cele implicite ale compilatorului;
-I/path d indicaii asupra localizrii header-elor suplimentare.
Exemplul 1.4
Secvena de comenzi:
$ gcc -c p1.c -o p1.o -I/home/user/include
$ gcc -c p2.c -o p2.o -I/usr/local/include
$ gcc p1.o p2.o main.c -L/usr/local/lib -L/home/user/lib -lmylib -luser
-o program
- -
1.4.
Procese Linux
programul (codul)
datele asociate programului
starea fiierelor deschise (tabela descriptorilor de fiiere utilizator)
catalogul de lucru
Pentru a putea fi gestionate de nucleu, n UNIX procesele primesc identificatori numii piduri (n generalo, numere ntregi) prin care sunt, la un moment dat, unic determinate n sistem.
La nivelul sistemului UNIX, fiecrui proces i se aloc o intrare ntr-o tabel sistem (tabela
de procese). Dimensiunea acestei tabele este dat de constanta sistem NPRCC, iar numrul maxim
de procese active care pot fi asociate unui acelai utilizator este MAXUPROC. Pid-ul este de fapt
indicele intrrii asociate procesului n tabel. O intrare n tabel conine informaii necesare
nucleului sistemului de operare, ca de exemplu starea procesului sau numele utilizatorului care
execut procesul.
Spaiul de adrese al unui proces cuprinde mai multe segmente cu rol diferit, funcie de
natura informaiilor pe care le conin:
zona antet (numita i zona user sau zona U), inaccesibil procesului, conine structuri de
date importante prin care nucleul gestioneaz procesul i-i ofer servicii prin intermediul
apelurilor sistem.
segmentul de cod pur (text) este protejat la scriere i adesea partajat; folosind opiunea n, compilatorul poate genera programe avnd segmente text reentrante. Cnd acest
segment este partajat de ctre mai multe procese, el nu sufer operaia de swapping.
segmentul de date poate fi scris de ctre procesul utilizatorului care nu este nici partajat
nici accesibil celorlalte procese; el conine date alocate static sau dinamic de ctre
proces; cuprinde zona de date data, zona de rezervri bss (date neiniializate) i zona de
alocare dinamic heap.
n execuie (running) - n mod utilizator sau n mod nucleu, dac procesul execut o
funcie sistem;
n UNIX procesele au caracter dinamic. Ele se creeaz la execuia unei comenzi, putnd da
natere altor procese i dispar. n felul acesta se creeaz o ierarhie dinamic de procese n sistem,
care ncepe cu procesul 0 (swapper), continu cu procesul 1 (init), proces care d natere unor
procese fiu (unele dintre ele sunt shell-uri), care la rndul lor dau natere altor procese fiu.
1.4.1. Comenzi shell referitoare la gestiunea proceselor
Pentru a obine starea la un moment dat a proceselor sistem se poate utiliza comanda:
$ ps [optiuni]
Dac nu se specific alte opiuni se afieaz numai lista de procese asociate terminalului
curent. Cteva din opiunile posibile:
Tot pentru vizualizarea proceselor din sistem se poate folosi programul top:
$ top [opiuni] [fiier]
Programul permite monitorizarea n timp real a proceselor din sistem i a altor parametrii cum ar fi
ncrcarea sau utilizarea memoriei. Lista opiunilor:
k - distruge un proces;
i - afieaz doar procesele active;
n sau # - modific numrul proceselor afiate;
r modific prioritatea (vezi nice) a unui proces;
S - schimb modul cumulativ; totalizeaz sau nu i timpul proceselor;
s - schimba intervalul de actualizare a datelor pe ecran;
f sau F - adaug sau scade cmpuri afiate;
o sau O - modific ordinea de afiare a informaiilor;
Utilizatorul are posibilitatea s determine terminarea forat a unor procese care lucreaz,
dureaz mult, nu evolueaz conform ateptrilor, sunt blocate n ateptarea unor condiii care nu se
vor ndeplini niciodat, etc. Pentru aceasta el are la dispoziie comanda:
$ kill [numr_semnal] identificator_proces
Comanda kill poate controla ntr-un mod mai complex execuia proceselor, mod
dependent chiar de procesele controlate. Procesele pot primi din exterior semnale i pot reaciona la
acestea n modul n care programatorul crede de cuviin. Semnalul SIGKILL (cu numrul 9) nu
poate fi tratat de procese i efectul va fi ca procesul dispare. Opiunea -l tiprete o list a
semnalelor disponibile n sistem pentru comunicarea cu procesele. Utilizarea cea mai frecvent este:
$ kill -SIGTERM 5678
11
- -
Mecanismul fundamental prin care se creeaz noi procese este apelul funciei de sistem:
pid_t fork()
care creeaz un nou proces prin copierea identic a procesului apelant; n raport cu fork(), primul
proces este procesul printe iar cel creat n urma apelului este procesul fiu.
Valoarea returnat de funcia fork() este:
ntreaga imagine a procesului printe este motenit de fiu, cu excepia segmentului de cod
pur care nu se duplic ci se utilizeaz n comun. Procesul fiu continu execuia instruciunii
urmtoare apelului funciei fork().
Orice proces poate afla propriul pid i pid-ul printelui apelnd funciile:
pid_t getpid( ) - returneaz pid-ul procesului curent
pid_t getppid() returneaz pid-ul procesului printe
Exemplul 1.5.
// Hello_Process.c
#include <stdio.h>
int main(){
if (fork()== 0)
printf("Hello FIU pid = %d ppid = %d\n",getpid(),getppid());
else {
printf("Hello PARINTE pid = %d ppid = %d\n", \
getpid(),getppid());
sleep(2);
}
return 0;
}
Compilare: $ gcc Hello_Process.c o Hello_Process
Executie: $ ./Hello_Process
Afiseaza: Hello PARINTE pid = 6416 ppid = 4489
Hello FIU pid = 6417 ppid = 6416
n exemplul de mai sus, procesul printe creeaz un proces fiu, cele dou procese vor afia
la consol cte un mesaj, printele ateapt terminarea fiului apelnd funcia sleep(), apoi se
termin i el.
De remarcat c nu exist o ordine prestabilit de apariie a mesajelor, deoarece execuia este
determinat de planificarea executat de sistem, iar ident. (pid) se modific de la o execuie la alta.
14.3
Dup crearea unuia sau a mai multor fii prin apelul funciei fork(), procesul printe poate
atepta ca unul din procesele fiu create s-i termine execuia, prin apelul funciei wait(), care
are prototipul:
pid_t wait(int *status)
Procesul care apeleaz wait() este suspendat pn se termin unul dintre fiii si. n cazul
execuiei normale funcia wait() returneaz pid-ul procesului fiu care i-a terminat execuia; n
12
cazul n care nu mai exist nici un fiu, wait() returneaz -1. Starea obinut n status este
valoarea returnat (de instruciunea return sau funcia exit()) de procesul care s-a terminat.
Exemplul 1.6.
n acest exemplu un proces iniial apeleaz funcia fork() ntr-o bucl for. Fiecare nou proces
creat ntr-o iteraie continu execuia n bucl i n iteraia urmtoare creeaz, la rndul lui un alt
proces, obinndu-se un arbore de procese. Dup fiecare fork(), dac execuia este n fiu se
afieaz un mesaj, dac este n printe se ateapt terminarea fiului (cu wait())
// Tree.c
#include <stdio.h>
#include <sys/wait.h>
int main(){
int i;
printf("PARINTE pid = %d \n",getpid());
for (i = 0; i < 3; i++){
if (fork()== 0) {
// Executie in fiu
printf("i = %d FIU pid = %d ppid = %d \n" ,i, \
getpid(),getppid());
sleep (1);
}
else wait(0);
// Executie in parinte
}
return 0;
}
6546
= 6547
= 6548
= 6549
= 6550
= 6551
= 6552
= 6553
ppid
ppid
ppid
ppid
ppid
ppid
ppid
=
=
=
=
=
=
=
6546
6547
6548
6547
6546
6551
6546
- -
este similar cu funcia wait() cu deosebirea c i se transmite ca parametru pid-ul procesului care
se dorete ateptat.
Funciile wait i waitpid sunt declarate n header-ele stdlib.h i sys/wait.h.
Dac procesul printe se termin nainte de terminarea fiilor si, atunci procesul init (cu
pid = 1) va deveni printele acestora. Termenul de zombie denumete acele procese UNIX care au
fost lansate de ctre un proces printe i printele nu a ateptat terminarea procesului fiu; un proces
fiu care s-a terminat este trecut de ctre nucleu n starea zombie pn cnd printele execut wait.
ncepnd cu UNIX System v Release 4, s-a introdus o posibilitate simpl de evitare a
apariiei proceselor zombie. Este suficient ca n partea de iniializare s apar secvena de mai jos:
#include <signal.h>
. . . .
signal(SIGCHLD,SIG_IGN);
Prin apelul signal se cere procesului respectiv s ignore (SIG_IGN) semnalul de terminare
a proceselor fii (SIGCHLD). Acest mecanism este de asemenea valabil pentru toate versiunile de
sistem de operare Linux.
Cnd este executat o comand, shell-ul ateapt n background, prin apelul funciei
wait(), care permite shell-ului s atepte terminarea procesului lansat (ca proces fiu).
Dac utilizatorul plaseaz & la sfritul comenzii (pentru a indica shell-ului c procesul se
va execut n background), shell-ul nu ateapt pn cnd se termin execuia comenzii (fiului) i
revine imediat cu prompt-ul caracteristic.
Cnd comanda s-a executat, a fost ntors un cod de retur prin apelul funciei exit() sau
return. ntregul returnat de aceste apeluri este disponibil procesului printe prin argumentul
status al funciei sistem wait(). n cazul liniei de comand (shell-ului), codul de retur este
pstrat ntr-o variabil sistem numit status. Aceasta poate fi inspectat prin comanda:
# echo $status
14
precum i argumentele liniei de comand pentru funcia main (int argc, char** argv): caracterul l
indic o list de parametri (terminat cu null); caracterul v indic vector de parametri; caracterul
p indic faptul ca primul parametru este calea fiierului cu codul executabil (path). De exemplu,
prototipul funciei execlp este:
int execlp (
const char *path,
const char *arg0,
const char *arg1,
................,
const char * argn,
char * /* NULL */);
Exemplul 1.7.
// Parent.c
#include <stdio.h>
#include <sys/types.h>
int main(){
char arg1[4];
pid_t pid = getpid();
sprintf(arg1,"%4d", pid);
printf("Proces Parinte pid = %d\n", pid);
if (fork() == 0) execlp("./Child","Child",arg1,(char*)0);
wait(0);
return 0;
}
// Child.c
#include <stdio.h>
// Argumentul primit in argv[1] este pid-ul parintelui
int main(int argc, char** argv){
int arg1 = atoi(argv[1]);
printf("Procesul Fiu a primit argumentul: %d \
si are pid = %d ppid = %d \n", arg1, getpid(), getppid());
return 0;
}
n acest exemplu:
Procesul printe (programul Parent.c) creeaz un proces fiu prin apelul funciei fork()
i ateapt terminarea acestuia (prin apelul funciei wait)
Procesul fiu creat nlocuiete imaginea motenit cu o nou imagine (fiierul executabil
Child, creat prin compilarea programului Child.c), apelnd execlp() cu argumentele:
Calea relativ (path) (./Child ) a fiierului executabil
Numele fiieului executabil (argv[0]) Child
Un argument (arg1) care conine pid-ul procesului printe
ppid = 7086
15
- -
Exerciii
E1.1. Scriei si executai toate exemplele prezentate n lucrare.
E1.2. Creeai un proces printe care s execute o bucl for cu 0 i < 4. n iteraiile pare fiecare
proces creeaz un fiu cruia i nlocuiete imaginea cu un program executabil cruia i transmite ca
argumente calea (path), numele fiierului executabil i contorul i al buclei. Creai programele,
executai i explicai rezultatele obinute.
E1.3. Creeai un proces printe care s execute o bucl for cu 0 i < 3. n fiecare iteraie creeaz
un fiu cruia i nlocuiete imaginea cu un program executabil cruia i transmite ca argument calea
(path) i numele fiierului executabil. Creai programele, executai i explicai rezultatele obinute.
Bibliografie
1. Documentatia instalata Linux man
2. L. Greenfield, Linux User Guide
3. P. Cobbaut, Linux Fundamentals
4. Felicia Ionescu, Calcul paralel, 2014, slide-uri publicate pe site-ul moodle ETTI.
5. Felicia Ionescu, Calcul paralel, Anexe, publicate pe site-ul moodle ETTI.
6. B. Barney, Introduction to Parallel Programming, Lawrence Livermore National Laboratory,
2013, https://computing.llnl.gov/tutorials/parallel_comp/
16