Skocz do: nawigacji, wyszukiwania

MICLAB:PThreads


Środowisko i modele programowania

dr inż. Łukasz Szustak, Politechnika Częstochowska, IITiS
mgr inż. Kamil Halbiniak, Politechnika Częstochowska, IITiS



Standard POSIX Threads


POSIX Threads (pThreads) jest zdefiniowanym w standardzie POSIX zestawem funkcji, typów oraz stałych, który oferuje szeroką gammę mechanizmów umożliwiających zarządzanie wątkami w językach C oraz C++. Pozwala on na tworzenie wielowątkowych aplikacji przeznaczonych dla procesorów ogólnego przeznaczenia oraz koprocesorów bazujących na archiekturze Intel MIC. POSIX Threads dostarcza niższy poziom abstrakcji, aniżeli standardy takie jak OpenMP, Intel Cilk Plus czy Intel TBB. W standardzie tym nazewnictwo oraz kolejność zmiennych na liście argumentów funkcji cechują się niezmiennym schematem. Nazwy funkcji typów oraz stałych rozpoczynają się od słowa pthread_, jednakże w przypadku stałych jest ono pisane dużymi literami (PTHREAD_).


W standardzie tym, programista jawnie definiuje zadania, które będą wykonywane równolegle przez wątki. Jest to realizowane poprzez definiowanie funkcji z zadaniami, które mają zostać wykonane przez poszczególne wątki. Funkcja ta zawsze przyjmuje oraz zwraca wartości typu void*. Koncepcja uruchamiania wątków w POSIX Threads jest zbliżona do modelu programowania fork-join.


Każdy program zrównoleglony przy pomocy standardu POSIX Threads posiada główny wątek działający w obrębie całego programu. Uruchamianie wątków w standardzie pThreads możliwe jest przy użyciu dedykowanej do tego celu funkcji pthread_create. Aby utworzyć nowy wątek jako argumenty funkcji pthread_create, należy przekazać:

  • identyfikator wątku, będący obiektem klasy pthread_t;
  • atrybuty wątku jako obiekt klasy pthread_attr_t;
  • adres funkcji, która ma zostać wykonana przez dany wątek;
  • adres przekazywanych do danego wątku argumentów.
POSIX Threads dopuszcza możliwość wykorzystania jednej funkcji do utworzenia wielu wątków. W standardzie tym, minimalna liczba wymaganych argumentów funkcji pthread_create ogranicza się do następujących:
  • identyfikatora wątku;
  • adresu funkcji, która ma zostać wykonana przez wątek.
Pozostałe argumenty mogą przyjmować wartość NULL.


Zakończenie pracy wątków wymaga jawnego wywołania funkcji pthread_join, która synchronizuje je, a następnie zabija. Wątki w standardzie POSIX Threads mają możliwość zwracania wartości po wykonaniu obliczeń. Funkcja pthread_join przyjmuje dwa argumenty:

  • identyfikator zabijanego wątku (obiekt pthread_t);
  • adres zmiennej, do której przypisana zostanie wartość zwrócona przez wątek.
W przypadku kiedy wątek nie zwraca żadnej wartości drugi argument funkcji przyjmuje wartość NULL. Uruchomienie większej liczby wątków wymaga zastosowania tablic lub typów generycznych przechowujących ich identyfikatory (obiekty klasy pthread_t). Przykład kodu zrównoleglonego przy pomocy standardu POSIX Threads zaprezentowano na Listingu 1.


#include <stdio.h>
#include <pthread.h>

void* DoWork(void* args)
{
   int threadNum = *((int*)args);
   printf("Hello World! Watek: %d\n", threadNum); 
}

int main()
{
   const int numThreads = 5;
   pthread_t threads[numThreads];

   for(int i=0; i<numThreads; ++i)
   {
      pthread_create(&threads[i], NULL, DoWork, (void*)i);
   }

   for(int i=0; i<numThreads; ++i)
   {
      pthread_join(threads[i], NULL);
   }

   return 0;
}
Listing 1. Zrównoleglenie w standardzie pThreads


W standardzie pThreads wątki nie posiadają dyspozytora pętli. Za zrównoważenie obliczeń odpowiedzialny jest programista, który definiuje sposób podziału pętli pomiędzy uruchomione wątki. Najczęściej do tego celu wykorzystuje się identyfikator danego wątku oraz liczbę wszystkich wszystkich uruchomionych w danym momencie. Jednakże, zazwyczaj okazuj się, że rozwiązanie to jest to trudne oraz czasochłonne zadanie.


Oprócz mechanizmów odpowiedzialnych za tworzenie wątków POSIX Threads oferuje szeroką gammę innych funkcji oraz obiektów. Zalicza się do nich między innymi mechanizmy synchronizacji, możliwość asynchronicznego kończenia wątków, mechanizm pozwalający na zabijanie wątku z poziomu innego wątku oraz mechanizm wykorzystywany do ustawiania priorytetów danego wątku. Podobnie jak w przypadku OpenMP, standard pThreads posiada własny mechanizm wykorzystywany do określenia sposobu przypisania wątków do logicznych rdzeni. POSIX Threads przewiduje możliwość kilkukrotnego uruchamiania wątków w obrębie jednego programu, gdzie ich liczba może być dowolna.



< Standardy programowania równoległego - C++ 11 Threads

Standardy programowania równoległego - Intel TBB >