Ïàðàëëåëüíûå ïðîöåññû
Äëÿ ÷åãî íóæíû ïàðàëëåëüíûå ïðîöåññû è íèòè: îïòèìèçàöèÿ, óñêîðåíèå
Êàê ñîçäàåòñÿ ïðîöåññ: fork()
Êàê òåðìèíèðóåòñÿ ïðîöåññ: exit(), “kill -9 <pid>”, wait(NULL)
Êàê ñîçäàåòñÿ íèòü: phtread_create()
Êàê òåðìèíèðóåòñÿ íèòü: a) íèòü ñîçäàíà - çàêàí÷èâàåòñÿ ôóíêöèÿ íèòè b) îñí.íèòü — return (pthread_join())
Êàêèå òðóäíîñòè ó ïðîãðàììèðîâàíèÿ ïàðàëëåëüíûõ ïðîöåññîâ è íèòåé: âçàèìîäåéñòâèå, ñèíõðîíèçàöèÿ
×òî òàêîå ðàçäåëÿåìûå ðåñóðñû: îáùèå ðåñóðñû
Êàêèå ðàçäåëÿåìûå ðåñóðñû ó ïðîöåññîâ: ýêðàí, êëàâèàòóðà, ôàéëû, ðàçäåëÿåìàÿ ïàìÿòü, pipe, ...
Êàêèå ðàçäåëÿåìûå ðåñóðñû ó íèòåé: ýêðàí, êëàâèàòóðà, ôàéëû, îáùàÿ ïàìÿòü (ãëîáàëüíûå ïåðåìåííûå, îáùèå àäðåñà)
Ìåõàíèçìû ñèíõðîíèçàöèè ïðîöåññîâ: ñåìàôîðû, ôàéëû, ðàçäåëÿåìàÿ ïàìÿòü, pipe
Ìåõàíèçìû ñèíõðîíèçàöèè íèòåé: ìüþòåêñû, ñåìàôîðû
1. Ïðîöåññû: ìóëüòèçàäà÷íîñòü.
àçäåëåíèå ïðîöåññîðíîãî âðåìåíè. Êâàíò âðåìåíè. Ðåæèì îæèäàíèÿ.
Íàïîìèíàíèå:
3 ñîñòîÿíèÿ ïðîöåññà: âûïîëíåíèå, îæèäàíèå ðåñóðñà, ãîòîâ ê âûïîëíåíèþ
ÁÈÎÑ + ÎÑ
Ïðîöåññ — îñíîâíîå ïîíÿòèå ÎÑ
Îäèí ïðîöåññ ìîæåò ïîðîäèòü äðóãîé ïðîöåññ. Ðîäèòåëüñêèé → äî÷åðíèé
Ñîñòîÿíèå ïðîöåññà — ñîñòîÿíèå îáëàñòè ïàìÿòè, ñîñòîÿíèå ðåãèñòðîâ ïðîöåññîðà + ...
Ðåãèñòðû ïðîöåññîðà — PC (Program Counter), SP (Stack Pointer), ...
Àðõèòåêòóðû ïðîöåññîðîâ: RISC (Restricted Instruction Set) è EISC (Extended ...)
ARM (RISC) – 38 (16 * 2 + ...)
Ïàìÿòü (ïî ñòåïåíè óáûâàíèÿ áûñòðîäåéñòâèÿ, ïî ñòåïåíè óáûâàíèÿ ñòîèìîñòè, ïî ìåðå âîçðàñòàíèÿ îáúåìà): ðåãèñòðû ïðîöåññîðà, êýø ïàìÿòü, îïåðàòèâíàÿ ïàìÿòü, âíåøíÿÿ ïàìÿòü.
Ïðè ïåðåêëþ÷åíèè ïðîöåññîâ — ÷òî äåëàòü ñ ñîñòîÿíèåì ïðîöåññà, ÷òîáû åãî âîçîáíîâèòü. Ñîõðàíèòü. Ñîñòîÿíèå îáëàñòè ïàìÿòè — ñîõðàíÿåòñÿ àâòîìàòè÷åñêè.
Ñîñòîÿíèå ðåãèñòðîâ — íàäî ñîõðàíèòü.
Ñîçäàíèå ïðîöåññà (äî÷åðíåãî): êëîíèðîâàíèå
Ñîñòîÿíèå äî÷åðíåãî ïðîöåññà — âûäåëÿåòñÿ îáëàñòü ïàìÿòè, ñîäåðæèìîå èäåíòè÷íî ñîäåðæèìîìó ðîäèòåëüñêîãî ïðîöåññà, ñîñòîÿíèå ðåãèñòðîâ — òàêîå æå.
Ïðèìåð.
Ëèíóêñ — ñîçäàòü ïðîöåññ î÷åíü ïðîñòî: âûçâàòü ôóíêöèþ fork();
int main() {
int id;
id = fork(); /* Äëÿ ðîä.ïð. - èäåíòèôèêàòîð äî÷åðíåãî ïðîöåññà, äëÿ äî÷.ïð. - 0 */
if (id != 0) {
printf(“I am an original\n”);
} else {
printf(“I am a clone\n”);
exit(1);
}
return 0;
}
Ñèãíàëû — óáèòü (òåðìèíèðîâàòü) ïðîöåññ SIGKILL
$ ps
1090 a.exe
$ kill -9 1090
Íèòè — ïîäïðîöåññû âíóòðè ïðîöåññà. Threads – íèòè (ïîòîêè)
Çà÷åì íèòè?
1. Óñêîðåíèå ðàáîòû ïðîãðàììû — åñëè åñòü îæèäàíèå êàêîãî-òî ðåñóðñà, òî äðóãèå íèòè â ýòî âðåìÿ ìîãóò âûïîëíÿòü, íàïðèìåð, âû÷èñëèòåëüíûå äåéñòâèÿ.
2. Îïòèìèçàöèÿ ðàáîòû — ìîæíî ñîêðàùàòü âðåìÿ îæèäàíèÿ. Ïðèìåð — ñåðâåð. Äëÿ êàæäîãî êëèåíòà — îòäåëüíàÿ íèòü.
Ñòàíäàðò POSIX – pthread_create(), pthread_join()
6. Òðóäíîñòè
a) Ïðåäñòàâèòü ðàáîòó íèòåé è èõ âçàèìîäåéñòâèå
b) Ñèíõðîíèçèðîâàòü (íå àòîìàðíûé) äîñòóï ê ðàçäåëÿåìûì ðåñóðñàì
void run(void *arg);
int x=0;
pthread_t thread1, thread2;
int main() {
pthread_create(&thread1, NULL, run, NULL);
pthread_create(&thread2, NULL, run, NULL);
return 0;
}
void run(void *arg) {
++x;
}
Thread 1 |
R1 íèòè 1 |
x |
R1 íèòè 2 |
Thread 2 |
LDR R1, &x; INC R1;
STR R1, &x; |
0 1 |
0
1 1 |
0 1 |
LDR R1, &x; INC R1; STR R1, &x; |
Ïðàâèëüíûé îòâåò: 2.
Îòâåò íåâåðíûé, ò. ê. îïåðàöèÿ óâåëè÷åíèÿ x áûëà ïðåðâàíà íà ñåðåäèíå (íå àòîìàðíàÿ)
Âûâîä: äîñòóï ê ðàçäåëÿåìûì ðåñóðñàì íàäî ñèíõðîíèçèðîâàòü.
Ó íèòåé äëÿ ýòîãî èñïîëüçóåòñÿ ìüþòåêñ.
Mutex (âçàìîèñêëþ÷àþùèé)
Êîä, âûïîëíåíèå êîòîðîãî íåëüçÿ ïðåðûâàòü, íàçûâàåòñÿ êðèòè÷åñêàÿ ñåêöèÿ
Äëÿ òîãî, ÷òîáû èñêëþ÷èòü ïðåðûâàíèå âûïîëíåíèÿ êðèòè÷åñêîé ñåêöèè, ìîæíî îêðóæèòü åå âûçîâàìè ñëåäóþùèõ ôóíêöèé:
phtread_mutex_lock(); - âíóòðè ýòîé ôóíêöèè âûïîëíåíèå íèòè ìîæåò áûòü îñòàíîâëåíî
pthread_mutex_unlock(); - îòïóñòèòü ìüþòåêñ → âûïîëíåíèå ïðèîñòàíîâëåííîé íèòè âîçîáíîâëÿåòñÿ â ôóíêöèè phtread_mutex_lock(), ñëåäóþùàÿ ïî î÷åðåäè íèòü âûõîäèò èç ôóíêöèè è çàõîäèò â êðèòè÷åñêóþ ñåêöèþ.
Ïðèìåð ñ ìüþòåêñàìè: http://mech.math.msu.su/~nap/2/Threads/threadtst.cpp
Ïðèìåð ñ ñåìàôîðàìè: http://mech.math.msu.su/~nap/2/Threads/semExample.cpp
Ïðèìåð: 10 íèòåé äîëæíû ïî î÷åðåäè íàïå÷àòàòü ñâîé íîìåð.
Ñîçäàåì 10 ñåìàôîðîâ. Ïåðâîìó äàåò ñîñòîÿíèå 1, îñòàëüíûì 0.
Ôóíêöèÿ íèòè ìîæåò áûòü îäíà íà âñåõ.
sem_t sem[10];
void run(void *arg) {
int num = *((int*)arg);
sem_wait(&sem[num]);
print("%d\n", num);
num = (num + 1) % 10;
sem_post(&sem[num]); // Ïîäíèìàåì ñåìàôîð äëÿ ñëåäóþùåé íèòè
}
Ñåìàôîð äëÿ ïðîöåññîâ: ïðîöåññû íå âçàèìîäåéñòâóþò ÷åðåç ïàìÿòü. Îäèí è òîòò æå ñåìàôîð äëÿ ðàçëè÷íûõ ïðîöåññîâ ðàçäåëÿåòñÿ:
1) ëèáî ýòî ðîäèòåëüñêèé è äî÷åðíèé ïðîöåññû: ïîêà íå ðàçäåëèëèñü, òî ñåìàôîð îáùèé, à ïîñëå ðàçäåëåíèÿ ÎÑ ïîääåðæèâàåò ýòî âçàèìîäåéñòâèå
2) åñëè ýòî íå ñâÿçàííûå ïðîöåññû, òî ÷åðåç èìÿ ñåìàôîðà (èìåíîâàííûé ñåìàôîð).
Âçàèìîäåéñòâèå ïàðàëëåëüíûõ ïðîöåññîâ
Ïðîöåññû
ìîãóò âçàèìîäåéñòâîâàòü äðóã ñ äðóãîì ÷åðåç íåêîòîðûå îáúåêòû. Äëÿ
ýòîãî îíè äîëæíû âëàäåòü èíôîðìàöèåé îá ýòèõ îáúåêòàõ. Ýòà
èíôîðìàöèÿ:
1) Äëÿ âçàèìîäåéñòâèÿ ÷åðåç ôàéë - èìÿ ôàéëà;
2) Äëÿ âçàèìîäåéñòâèÿ ÷åðåç ðàçäåëÿåìóþ ïàìÿòü (shared memory) - èìÿ ðàçäåëÿåìîé ïàìÿòè;
3) Äëÿ âçàèìîäåéñòâèÿ ÷åðåç èìåíîâàííóþ «òðóáêó» pipe – èìÿ òðóáêè;
4) Äëÿ âçàèìîäåéñòâèÿ ÷åðåç áåçûìÿííóþ «òðóáêó» pipe – èäåíòèôèêàòîð îòêðûòîé áåçûìÿííîé «òðóáêè».  äàííîì ñëó÷àå â ìîìåíò ñîçäàíèÿ «òðóáêè» ïðîöåññû äîëæíû èìåòü îáùåå àäðåñíîå ïðîñòðàíñòâî, òî åñòü ýòî ðîäèòåëüñêèé è äî÷åðíèé ïðîöåññû (http://mech.math.msu.su/~nap/2/Threads/pipe.cpp)
5) Äëÿ âçàèìîäåéñòâèÿ ïî ñåòè - ñåòåâîé àäðåñ è íîìåð ïîðòà ñåòåâîãî ñîêåòà;
Èñïîëüçóÿ ýòó èíôîðìàöèþ, îíè ïîëó÷àþò äîñòóï ê íåêèì îáúåêòàì. Ýòè îáúåêòû, ðàçäåëÿåìûå ìåæäó ïðîöåññàìè, ÿâëÿþòñÿ èõ ðàçäåëÿåìûìè ðåñóðñàìè.
Ðàáîòû ñ ðàçäåëÿåìûå ðåñóðñàìè äîëæíà áûòü ñèíõðîíèçèðîâàíà, òî åñòü óïîðÿäî÷åíà. Äëÿ íåêîòîðûõ îáúåêòîâ ðàáîòà ñ íèìè óïîðÿäî÷åíà íà óðîâíå ñèñòåìû: ðàçäåëÿåìàÿ ïàìÿòü, ñîêåòû, ôàéëû. Äëÿ ðàáîòû ñ äðóãèìè ðàçäåëÿåìûìè îáúåêòàìè ïðîöåññû äîëæíû èñïîëüçîâàòü ñðåäñòâà ñèíõðîíèçàöèè. Íàïðèìåð, íèòè äëÿ ðàáîòû ñ ðàçäåëÿåìûì (òî åñòü ãëîáàëüíûìè) ïåðåìåííûìè ìîãóò èñïîëüçîâàòü ìüþòåêñû èëè ñåìàôîðû.
Çàäà÷à íà ñèíõðîíèçàöèþ íèòåé:
1. Ïðîãðàììà ñîçäàåò òðè íèòè. Äâå ãëîáàëüíûå ïåðåìåííûå ñíà÷àëà ñîäåðæàò çíà÷åíèÿ -1. Ïåðâàÿ è âòîðàÿ íèòü ãåíåðèðóþò ñëó÷àéíîå öåëîå ÷èñëî â äèàïàçîíå îò 0 äî 99 è çàïèñûâàþò èõ â ýòè äâå ãëîáàëüíûå ïåðåìåííûå. Ïîñëå ýòîãî òðåòüÿ íèòü íàõîäèò ÍÎÄ ýòèõ ÷èñåë, âûâîäèò íà ýêðàí îáà ÷èñëà è èõ ÍÎÄ è çàïèñûâàåò â ãëîáàëüíûå ïåðåìåííûå -1. Çàòåì ïåðâàÿ è âòîðàÿ íèòè ñíîâà çàïèñûâàþò ñëó÷àéíûå ÷èñëà â ãëîáàëüíûå ïåðåìåííûå è òàê äî áåñêîíå÷íîñòè.
(Ïåðâûå äâå íèòè æäóò -1 â ñâîèõ ïåðåìåííûõ, ïîòîì çàïèñûâàþò ñëó÷àéíûå ÷èñëà.
Òðåòüÿ íèòü æäåò >= 0 â îáåèõ ïåðåìåííûõ.)
(Ñèíõðîíèçèðóåòñÿ èçìåíåíèå ïåðåìåííûõ).
2. Ïðîãðàììà ñ÷èòûâàåò ñ êëàâèàòóðû äâà öåëûõ ÷èñëà, ïîìåùàåò èõ â äâå ãëîáàëüíûå öåëûå ïåðåìåííûå è âû÷èñëÿåò èõ ÍÎÄ ñëåäóþùèì îáðàçîì: äâå íèòè âû÷èòàþò èç áîëüøåãî ÷èñëà ìåíüøåå: ïåðâàÿ íèòü âû÷èòàåò èç ïåðâîé ïåðåìåííîé, âòîðàÿ — èç âòîðîé ïåðåìåííîé. Ïîñëå íàõîæäåíèÿ ÍÎÄ (òî åñòü êîãäà îáå ïåðåìåííûå ïðèíèìàþò îäèíàêîâîå çíà÷åíèå) íèòè çàêàí÷èâàþò ðàáîòó è ÍÎÄ âûâîäèòñÿ íà ýêðàí.
(Ìüþòåêñ çàõâàòûâàåòñÿ êàê äëÿ ïðîâåðêè çíà÷åíèÿ ïåðåìåííîé (???), òàê è äëÿ èçìåíåíèÿ çíà÷åíèÿ ïåðåìåííîé).