Procesy i wątki Krzysztof Banaś Obliczenia równoległe 1
Procesy i wątki Proces: ciąg rozkazów (wątek główny) i ewentualnie inne wątki stos (wątku głównego) przestrzeń adresowa dodatkowe elementy tworzące m.in. kontekst procesu Wątek ciąg rozkazów stos niektóre z elementów tworzących kontekst procesu Tworzenie wątku (Linux): int clone(int (*fn)(void *), void *child_stack, int flags, void *arg) Przyczyna wprowadzenia wątków: łatwość komunikacji przy użyciu pamięci wspólnej i wydajność przełączania kontekstu Krzysztof Banaś Obliczenia równoległe 2
Wątki pthreads Specyfikacja POSIX (IEEE 1003.1, 1995, 2001) Operacje na wątkach: określanie atrybutów ( odłączalność, adres i rozmiar stosu, itp.) tworzenie i uruchamianie (pthread_create) porównywanie identyfikatorów (pthread_equal, pthread_self) zabijanie i przesyłanie sygnałów (pthread_cancel, pthread_kill) odłączanie (pthread_detach) oczekiwanie na zakończenie (pthread_join) int pthread_create(pthread_t *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void * arg) int pthread_join(pthread_t th, void **thread_return) Krzysztof Banaś Obliczenia równoległe 3
Tworzenie wątków main(){ int arg_1, arg_2; wyn_1 = pthread_create(& tid_1, NULL, wątek, &arg_1); wyn_2 = pthread_create(& tid_2, NULL, wątek, &arg_2); wyn_1 = pthread_join( tid_1, NULL); wyn_2 = pthread_join( tid_2, NULL); } void * wątek (void * arg_wsk){ int moj_arg; moj_arg = *( (int *) arg_wsk ); } Krzysztof Banaś Obliczenia równoległe 4
Przesyłanie argumentów do wątków typedef struct { int a; double b;} struktura; main(){ struktura s; s.a = 1; s.b = 3.14; pthread_create(& tid, NULL, funkcja_w, (void *) &s);... } void * funkcja_w (void * arg_wsk){ struktura s_lok = *((struktura *)wsk); // struktura lokalna! // dostęp do zmiennych lokalnych: printf("watek: s_lok.a = %d, s_lok.b = %lf\n", s_lok.a, s_lok.b); // dostęp do zmiennych nie lokalnych kopiowanie wskaźnika z rzutowaniem typu struktura * s_wsk = (struktura *) arg_wsk; printf("zewn.: "s_zewn.a = %d, s_zewn.b = %lf\n, s_wsk >a, s_wsk >b);... } Krzysztof Banaś Obliczenia równoległe 5
Komunikacja między wątkami Komunikacja między wątkami odbywa się głównie za pomocą pamięci wspólnej W celu realizacji modelu SPMD można do wielu wątków wykonujących ten sam kod przesłać inne dane jako argumenty pierwotnie wywoływanej procedury częstym przypadkiem jest przesłanie identyfikatora wątku każdy wątek posiada indywidualny identyfikator i na jego podstawie może: zlokalizować dane, na których dokonuje przetwarzania dane[ f(my_id) ] wybrać ścieżkę wykonania programu if(my_id ==...){...} określić iteracje pętli, które ma wykonać for( i=f1(my_id); i< f2(my_id); i += f3(my_id) ){... } Krzysztof Banaś Obliczenia równoległe 6
Komunikacja między wątkami Komunikacja za pomocą pamięci wspólnej ma charakter rozgłaszania: zapis wartości zmiennej wspólnej przez pojedynczy wątek oznacza możliwość odczytania wartości przez wszystkie wątki intuicyjnie widać, że poprawne działanie komunikacji wymaga synchronizacji działania wątków (zapis musi poprzedzać odczyt) problemy programowania równoległego biorą się między innymi stąd, że pierwotnie w modelach wykonania w językach programowania wszystkie zmienne znajdowały się w pamięci operacyjnej (w pojedynczym egzemplarzu), podczas gdy w rzeczywistości w systemie komputerowym występują w wielu kopiach na różnych poziomach pamięci (rejestry, pamięć podręczna, DRAM) powstaje problem jak synchronizować dostępy do wielu kopii jednej zmiennej Krzysztof Banaś Obliczenia równoległe 7
Model pamięci Problem synchronizacji operacji na zmiennych dotyczy takich problemów jak np.: kiedy kompilator może dokonywać operacji wyłącznie na rejestrach, a kiedy musi dokonać zapisu do pamięci jak utrzymać spójność kopii danych w pamięci podręcznej z wartością w pamięci głównej czy kompilator i procesor mogą zmieniać kolejność wykonywanych operacji (w tym operacji zapisu i odczytu) W obliczeniach sekwencyjnych zagadnienie synchronizacji operacji na kopiach wartości zmiennych jest problemem głównie wydajności kompilatory i procesory są zobowiązane działać tak, aby efekt działania systemu komputerowego był zgodny z zapisem w kodzie źródłowym (czyli złudzeniem istnienia tylko jednej kopii danych) nie dotyczy to działania debugerów, które śledzą nie ostateczne efekty działania kodu, ale stan systemu po każdej linii kodu Krzysztof Banaś Obliczenia równoległe 8
Model pamięci W obliczeniach równoległych zagadnienie synchronizacji operacji na kopiach wartości zmiennych wpływa na poprawność programów: brak wymuszenia operacji zapisu może powodować, że różne wątki widzą różne wartości tej samej zmiennej wspólnej rozmaite środowiska wprowadzają dodatkowe konstrukcje (memory fences, operacje flush) wymuszające zapis do pamięci niejawne wymuszenie zapisu jest także związane z szeregiem operacji synchronizacji (bariery, protokoły sekcji krytycznych) W miejsce dotychczasowych umownych (C,C++) lub mało ścisłych specyfikacji (Java) wprowadza się w ostatnich latach w językach programowania ścisły model pamięci regulujący powyższe kwestie Środowiska programowania równoległego wprowadzają także własne modele spójności pamięci Krzysztof Banaś Obliczenia równoległe 9
Modele spójność pamięci Modele spójności pamięci model spójności sekwencyjnej (sequential consistency) modele spójności osłabionej (relaxed consistency) Paradoks pracy współczesnych procesorów procesory ze względu na optymalizacje (kompilatora, samego procesora) nie spełniają prostych modeli spójności, np. spójności sekwencyjnej Krzysztof Banaś Obliczenia równoległe 10