Udostępnij za pośrednictwem


3. Funkcje biblioteki czasu wykonywania

W tej sekcji opisano funkcje biblioteki środowiska uruchomieniowego OpenMP C i C++. Nagłówek <omp.h> deklaruje dwa typy, kilka funkcji, które mogą służyć do kontrolowania i wykonywania zapytań w środowisku wykonywania równoległego oraz funkcji blokowania, które mogą służyć do synchronizowania dostępu do danych.

Typ jest typem omp_lock_t obiektu, który może reprezentować, że blokada jest dostępna lub że wątek jest właścicielem blokady. Te blokady są nazywane prostymi blokadami.

Typ jest typem omp_nest_lock_t obiektu, który może reprezentować dostępną blokadę lub tożsamość wątku będącego właścicielem blokady i liczbę zagnieżdżeń (opisaną poniżej). Te blokady są określane jako zagnieżdżone blokady.

Funkcje biblioteki to funkcje zewnętrzne z połączeniem "C".

Opisy w tym rozdziale są podzielone na następujące tematy:

3.1 Funkcje środowiska wykonawczego

Funkcje opisane w tej sekcji mają wpływ na wątki, procesory i środowiska równoległe oraz monitorują je:

3.1.1, funkcja omp_set_num_threads

Funkcja omp_set_num_threads ustawia domyślną liczbę wątków do użycia w późniejszych regionach równoległych, które nie określają klauzuli num_threads . Format jest następujący:

#include <omp.h>
void omp_set_num_threads(int num_threads);

Wartość parametru num_threads musi być dodatnią liczbą całkowitą. Jego efekt zależy od tego, czy jest włączona dynamiczna korekta liczby wątków. Aby uzyskać kompleksowy zestaw reguł dotyczących interakcji między omp_set_num_threads funkcją a dynamiczną korektą wątków, zobacz sekcję 2.3.

Ta funkcja ma efekty opisane powyżej, gdy wywoływane z części programu, w której omp_in_parallel funkcja zwraca zero. Jeśli jest wywoływana z części programu, w której omp_in_parallel funkcja zwraca wartość niezerową, zachowanie tej funkcji jest niezdefiniowane.

To wywołanie ma pierwszeństwo przed zmienną OMP_NUM_THREADS środowiskową. Wartość domyślna liczby wątków, które mogą być ustanawiane przez wywołanie omp_set_num_threads lub przez ustawienie OMP_NUM_THREADS zmiennej środowiskowej, można jawnie zastąpić jedną parallel dyrektywą, określając klauzulę num_threads .

Aby uzyskać więcej informacji, zobacz omp_set_dynamic.

Odwołania krzyżowe

  • omp_set_dynamic, funkcja
  • funkcja omp_get_dynamic
  • zmienna środowiskowa OMP_NUM_THREADS
  • num_threads, klauzula

3.1.2, funkcja omp_get_num_threads

Funkcja omp_get_num_threads zwraca liczbę wątków aktualnie w zespole wykonujących region równoległy, z którego jest wywoływana. Format jest następujący:

#include <omp.h>
int omp_get_num_threads(void);

Klauzula num_threads omp_set_num_threads , funkcja i zmienna OMP_NUM_THREADS środowiskowa kontrolują liczbę wątków w zespole.

Jeśli liczba wątków nie została jawnie ustawiona przez użytkownika, wartość domyślna to zdefiniowana przez implementację. Ta funkcja wiąże się z najbliższą dyrektywą otaczającą parallel . W przypadku wywołania z części szeregowej programu lub z zagnieżdżonego regionu równoległego, ta funkcja zwraca wartość 1.

Aby uzyskać więcej informacji, zobacz omp_set_dynamic.

Odwołania krzyżowe

3.1.3, funkcja omp_get_max_threads

Funkcja omp_get_max_threads zwraca liczbę całkowitą, która ma być co najmniej tak duża, jak liczba wątków, które byłyby używane do utworzenia zespołu, jeśli region równoległy bez num_threads klauzuli miał być widoczny w tym momencie w kodzie. Format jest następujący:

#include <omp.h>
int omp_get_max_threads(void);

Następujące wyrażenie wyraża niższą granicę dla wartości :omp_get_max_threads

threads-used-for-next-team<= omp_get_max_threads

Należy pamiętać, że jeśli inny region równoległy używa num_threads klauzuli , aby zażądać określonej liczby wątków, gwarancja na dolnej granicy wyniku omp_get_max_threads nie jest już przechowywana.

omp_get_max_threads Wartość zwracana funkcji może służyć do dynamicznego przydzielania wystarczającego magazynu dla wszystkich wątków w zespole utworzonych w następnym regionie równoległym.

Odwołania krzyżowe

3.1.4, funkcja omp_get_thread_num

Funkcja omp_get_thread_num zwraca numer wątku w swoim zespole wątku wykonującego funkcję. Numer wątku mieści się w przedziale od 0 do omp_get_num_threads()-1 włącznie. Główny wątek zespołu to wątek 0.

Format jest następujący:

#include <omp.h>
int omp_get_thread_num(void);

W przypadku wywołania z regionu omp_get_thread_num szeregowego zwraca wartość 0. Jeśli jest wywoływana z poziomu zagnieżdżonego regionu równoległego, która jest serializowana, ta funkcja zwraca wartość 0.

Odwołania krzyżowe

  • omp_get_num_threads, funkcja

3.1.5, funkcja omp_get_num_procs

Funkcja omp_get_num_procs zwraca liczbę procesorów, które są dostępne dla programu w momencie wywołania funkcji. Format jest następujący:

#include <omp.h>
int omp_get_num_procs(void);

3.1.6, funkcja omp_in_parallel

Funkcja omp_in_parallel zwraca wartość niezerową, jeśli jest wywoływana w dynamicznym zakresie równoległego regionu wykonywanego równolegle. W przeciwnym razie zwraca wartość 0. Format jest następujący:

#include <omp.h>
int omp_in_parallel(void);

Ta funkcja zwraca wartość niezerową, gdy jest wywoływana z regionu wykonywanego równolegle, w tym zagnieżdżone regiony, które są serializowane.

3.1.7, funkcja omp_set_dynamic

Funkcja omp_set_dynamic włącza lub wyłącza dynamiczną korektę liczby wątków dostępnych do wykonywania regionów równoległych. Format jest następujący:

#include <omp.h>
void omp_set_dynamic(int dynamic_threads);

Jeśli dynamic_threads daje w wyniku wartość niezerową, liczba wątków używanych do wykonywania nadchodzących regionów równoległych może zostać automatycznie skorygowana przez środowisko czasu wykonywania, aby najlepiej wykorzystać zasoby systemowe. W związku z tym liczba wątków określonych przez użytkownika jest maksymalną liczbą wątków. Liczba wątków w zespole wykonujących region równoległy pozostaje stała na czas trwania tego regionu równoległego i jest zgłaszana przez omp_get_num_threads funkcję.

Jeśli dynamic_threads daje wartość 0, korekta dynamiczna jest wyłączona.

Ta funkcja ma efekty opisane powyżej, gdy wywoływane z części programu, w której omp_in_parallel funkcja zwraca zero. Jeśli jest wywoływana z części programu, w której omp_in_parallel funkcja zwraca wartość niezerową, zachowanie tej funkcji jest niezdefiniowane.

Wywołanie metody omp_set_dynamic ma pierwszeństwo przed zmienną OMP_DYNAMIC środowiskową.

Ustawieniem domyślnym dynamicznego dostosowania wątków jest zdefiniowana implementacja. W związku z tym kody użytkowników, które zależą od określonej liczby wątków do poprawnego wykonywania, powinny jawnie wyłączyć wątki dynamiczne. Implementacje nie są wymagane do zapewnienia możliwości dynamicznego dostosowywania liczby wątków, ale są one wymagane do zapewnienia interfejsu do obsługi przenośności na wszystkich platformach.

specyficzne dla firmy Microsoft

Bieżąca obsługa elementów omp_get_dynamic i omp_set_dynamic jest następująca:

Parametr omp_set_dynamic wejściowy nie ma wpływu na zasady wątkowania i nie zmienia liczby wątków. omp_get_num_threads Zawsze zwraca liczbę zdefiniowaną przez użytkownika, jeśli jest ustawiona lub domyślny numer wątku. W bieżącej implementacji firmy Microsoft wyłącza dynamiczne wątki, omp_set_dynamic(0) aby można było ponownie użyć istniejącego zestawu wątków dla następującego regionu równoległego. omp_set_dynamic(1) włącza wątki dynamiczne przez odrzucenie istniejącego zestawu wątków i utworzenie nowego zestawu dla nadchodzącego regionu równoległego. Liczba wątków w nowym zestawie jest taka sama jak stary zestaw i jest oparta na zwracanej wartości omp_get_num_threads. W związku z tym, aby uzyskać najlepszą wydajność, użyj polecenia , aby ponownie użyć omp_set_dynamic(0) istniejących wątków.

Odwołania krzyżowe

3.1.8, funkcja omp_get_dynamic

Funkcja omp_get_dynamic zwraca wartość niezerową, jeśli jest włączona dynamiczna korekta wątków i zwraca wartość 0 w przeciwnym razie. Format jest następujący:

#include <omp.h>
int omp_get_dynamic(void);

Jeśli implementacja nie implementuje dynamicznej korekty liczby wątków, ta funkcja zawsze zwraca wartość 0. Aby uzyskać więcej informacji, zobacz omp_set_dynamic.

Odwołania krzyżowe

  • Aby zapoznać się z opisem dynamicznego dostosowania wątku, zobacz omp_set_dynamic.

3.1.9, funkcja omp_set_nested

Funkcja omp_set_nested włącza lub wyłącza zagnieżdżone równoległości. Format jest następujący:

#include <omp.h>
void omp_set_nested(int nested);

Jeśli zagnieżdżona wartość daje wartość 0, zagnieżdżona równoległość jest wyłączona, co jest wartością domyślną, a zagnieżdżone regiony równoległe są serializowane i wykonywane przez bieżący wątek. W przeciwnym razie jest włączona zagnieżdżona równoległość, a zagnieżdżone regiony mogą wdrażać dodatkowe wątki w celu utworzenia zagnieżdżonych zespołów.

Ta funkcja ma efekty opisane powyżej, gdy wywoływane z części programu, w której omp_in_parallel funkcja zwraca zero. Jeśli jest wywoływana z części programu, w której omp_in_parallel funkcja zwraca wartość niezerową, zachowanie tej funkcji jest niezdefiniowane.

To wywołanie ma pierwszeństwo przed zmienną OMP_NESTED środowiskową.

Po włączeniu zagnieżdżonego równoległości liczba wątków używanych do wykonywania zagnieżdżonych regionów równoległych jest definiowana przez implementację. W związku z tym implementacje zgodne z protokołem OpenMP mogą serializować zagnieżdżone regiony równoległe nawet wtedy, gdy jest włączona zagnieżdżona równoległość.

Odwołania krzyżowe

3.1.10, funkcja omp_get_nested

Funkcja omp_get_nested zwraca wartość niezerową, jeśli zagnieżdżona równoległość jest włączona i 0, jeśli jest wyłączona. Aby uzyskać więcej informacji na temat zagnieżdżonego równoległości, zobacz omp_set_nested. Format jest następujący:

#include <omp.h>
int omp_get_nested(void);

Jeśli implementacja nie implementuje zagnieżdżonego równoległości, ta funkcja zawsze zwraca wartość 0.

3.2 Funkcje blokowania

Funkcje opisane w tej sekcji manipulują blokadami używanymi do synchronizacji.

W przypadku następujących funkcji zmienna blokady musi mieć typ omp_lock_t. Ta zmienna musi być dostępna tylko za pośrednictwem tych funkcji. Wszystkie funkcje blokady wymagają argumentu, który ma wskaźnik do omp_lock_t typu.

W przypadku następujących funkcji zmienna blokady musi mieć typ omp_nest_lock_t. Ta zmienna musi być dostępna tylko za pośrednictwem tych funkcji. Wszystkie funkcje zagnieżdżenia blokady wymagają argumentu, który ma wskaźnik do omp_nest_lock_t typu.

Funkcje blokady OpenMP uzyskują dostęp do zmiennej blokady w taki sposób, że zawsze odczytują i aktualizują najbardziej bieżącą wartość zmiennej blokady. W związku z tym nie jest konieczne, aby program OpenMP zawierał jawne flush dyrektywy, aby upewnić się, że wartość zmiennej blokady jest spójna między różnymi wątkami. (Może być konieczne flush wprowadzenie dyrektyw, aby wartości innych zmiennych były spójne).

Funkcje omp_init_lock i omp_init_nest_lock 3.2.1

Te funkcje zapewniają jedyny sposób inicjowania blokady. Każda funkcja inicjuje blokadę skojarzona z blokadą parametru do użycia w nadchodzących wywołaniach. Format jest następujący:

#include <omp.h>
void omp_init_lock(omp_lock_t *lock);
void omp_init_nest_lock(omp_nest_lock_t *lock);

Stan początkowy jest odblokowany (czyli żaden wątek nie jest właścicielem blokady). W przypadku zagnieżdżonej blokady początkowa liczba zagnieżdżeń wynosi zero. Nie jest zgodne, aby wywołać jedną z tych procedur ze zmienną blokady, która została już zainicjowana.

3.2.2 funkcje omp_destroy_lock i omp_destroy_nest_lock

Te funkcje zapewniają, że blokada zmiennej blokady jest niezainicjowana. Format jest następujący:

#include <omp.h>
void omp_destroy_lock(omp_lock_t *lock);
void omp_destroy_nest_lock(omp_nest_lock_t *lock);

Nie jest zgodne, aby wywołać jedną z tych procedur ze zmienną blokady, która jest niezainicjowana lub odblokowana.

Funkcje omp_set_lock i omp_set_nest_lock 3.2.3

Każda z tych funkcji blokuje wątek wykonujący funkcję, dopóki określona blokada nie będzie dostępna, a następnie ustawi blokadę. Prosta blokada jest dostępna, jeśli jest odblokowana. Blokada zagnieżdżona jest dostępna, jeśli jest odblokowana lub czy jest już własnością wątku wykonującego funkcję. Format jest następujący:

#include <omp.h>
void omp_set_lock(omp_lock_t *lock);
void omp_set_nest_lock(omp_nest_lock_t *lock);

W przypadku prostej blokady argument omp_set_lock funkcji musi wskazywać zainicjowaną zmienną blokady. Własność blokady jest przyznawana wątkowi wykonującemu funkcję.

W przypadku zagnieżdżonej blokady argument omp_set_nest_lock funkcji musi wskazywać zainicjowaną zmienną blokady. Liczba zagnieżdżeń jest zwiększana, a wątek jest udzielany lub utrzymuje własność blokady.

Funkcje omp_unset_lock i omp_unset_nest_lock 3.2.4

Te funkcje zapewniają środki zwalniania własności blokady. Format jest następujący:

#include <omp.h>
void omp_unset_lock(omp_lock_t *lock);
void omp_unset_nest_lock(omp_nest_lock_t *lock);

Argument dla każdej z tych funkcji musi wskazywać zainicjowaną zmienną blokady należącą do wątku wykonującego funkcję. Zachowanie jest niezdefiniowane, jeśli wątek nie jest właścicielem tej blokady.

W przypadku prostej blokady omp_unset_lock funkcja zwalnia wątek wykonujący funkcję z własności blokady.

W przypadku zagnieżdżonej blokady funkcja dekrementuje liczbę zagnieżdżeń i zwalnia wątek wykonujący funkcję z własności blokady, omp_unset_nest_lock jeśli wynikowa liczba wynosi zero.

Funkcje omp_test_lock i omp_test_nest_lock 3.2.5

Te funkcje próbują ustawić blokadę, ale nie blokują wykonywania wątku. Format jest następujący:

#include <omp.h>
int omp_test_lock(omp_lock_t *lock);
int omp_test_nest_lock(omp_nest_lock_t *lock);

Argument musi wskazywać zainicjowaną zmienną blokady. Te funkcje próbują ustawić blokadę w taki sam sposób jak omp_set_lock i omp_set_nest_lock, z tą różnicą, że nie blokują wykonywania wątku.

W przypadku prostej blokady omp_test_lock funkcja zwraca wartość niezerową, jeśli blokada została pomyślnie ustawiona. W przeciwnym razie zwraca zero.

W przypadku zagnieżdżonej blokady omp_test_nest_lock funkcja zwraca nową liczbę zagnieżdżeń, jeśli blokada została pomyślnie ustawiona. W przeciwnym razie zwraca zero.

3.3 Procedury chronometrażu

Funkcje opisane w tej sekcji obsługują przenośny zegar zegara:

3.3.1, funkcja omp_get_wtime

Funkcja omp_get_wtime zwraca wartość zmiennoprzecinkową o podwójnej precyzji równą czasowi zegara ściennego upłynął w sekundach od czasu "czasu w przeszłości". Rzeczywisty "czas w przeszłości" jest dowolny, ale gwarantowane jest, aby nie zmieniać się podczas wykonywania programu aplikacji. Format jest następujący:

#include <omp.h>
double omp_get_wtime(void);

Przewiduje się, że funkcja będzie używana do mierzenia czasu, który upłynął, jak pokazano w poniższym przykładzie:

double start;
double end;
start = omp_get_wtime();
... work to be timed ...
end = omp_get_wtime();
printf_s("Work took %f sec. time.\n", end-start);

Zwracane czasy to "godziny na wątek", co oznacza, że nie muszą być globalnie spójne we wszystkich wątkach uczestniczących w aplikacji.

3.3.2, funkcja omp_get_wtick

Funkcja omp_get_wtick zwraca wartość zmiennoprzecinkową o podwójnej precyzji równą liczbie sekund między kolejnymi znacznikami zegara. Format jest następujący:

#include <omp.h>
double omp_get_wtick(void);