Sdílet prostřednictvím


3. Funkce knihovny za běhu

Tato část popisuje funkce knihovny runtime OpenMP C a C++. Hlavička <omp.h> deklaruje dva typy, několik funkcí, které lze použít k řízení a dotazování prostředí paralelního spouštění, a funkce zámku, které lze použít k synchronizaci přístupu k datům.

Typ omp_lock_t je typ objektu schopný reprezentovat, že zámek je k dispozici, nebo že vlákno vlastní zámek. Tyto zámky se označují jako jednoduché zámky.

Typ omp_nest_lock_t je typ objektu, který může představovat buď to, že je k dispozici zámek, nebo identitu vlákna, které vlastní zámek, a počet vnořování (popsaný níže). Tyto zámky se označují jako vnořené zámky.

Funkce knihovny jsou externí funkce s propojením jazyka C.

Popisy v této kapitole jsou rozděleny do následujících témat:

3.1 Funkce spouštěcího prostředí

Funkce popsané v této části ovlivňují a monitorují vlákna, procesory a paralelní prostředí:

3.1.1 omp_set_num_threads funkce

Funkce omp_set_num_threads nastaví výchozí počet vláken, která se mají použít pro pozdější paralelní oblasti, které nezadávají klauzuli num_threads . Formát je následující:

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

Hodnota parametru num_threads musí být kladné celé číslo. Jeho účinek závisí na tom, zda je povolena dynamická úprava počtu vláken. Komplexní sadu pravidel týkajících se interakce mezi omp_set_num_threads funkcí a dynamickým nastavením vláken najdete v části 2.3.

Tato funkce má výše popsané účinky při zavolání z části programu, kde funkce vrátí nulu omp_in_parallel . Pokud je volána z části programu, kde omp_in_parallel funkce vrátí nenulovou hodnotu, chování této funkce není definováno.

Toto volání má přednost před proměnnou OMP_NUM_THREADS prostředí. Výchozí hodnota počtu vláken, která mohou být stanovena voláním omp_set_num_threads nebo nastavením OMP_NUM_THREADS proměnné prostředí, lze explicitně přepsat pro jednu parallel direktivu num_threads zadáním klauzule.

Další informace najdete v tématu omp_set_dynamic.

Křížové odkazy

  • omp_set_dynamic
  • omp_get_dynamic
  • OMP_NUM_THREADS proměnná prostředí
  • klauzule num_threads

3.1.2 omp_get_num_threads funkce

Funkce omp_get_num_threads vrátí počet vláken aktuálně v týmu, které spouští paralelní oblast, ze které se volá. Formát je následující:

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

Klauzule num_threads , omp_set_num_threads funkce a OMP_NUM_THREADS proměnná prostředí řídí počet vláken v týmu.

Pokud uživatel explicitně nenastavil počet vláken, výchozí hodnota je definovaná implementací. Tato funkce vytvoří vazbu k nejbližší nadřazené parallel direktivě. Pokud se volá ze sériové části programu nebo z vnořené paralelní oblasti serializované, vrátí tato funkce hodnotu 1.

Další informace najdete v tématu omp_set_dynamic.

Křížové odkazy

3.1.3 omp_get_max_threads funkce

Funkce omp_get_max_threads vrátí celé číslo, které je zaručeno, že bude alespoň tak velké jako počet vláken, která by se použila k vytvoření týmu, pokud by se v tomto okamžiku v kódu zobrazila paralelní oblast bez num_threads klauzule. Formát je následující:

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

Následující výraz vyjadřuje dolní mez hodnoty omp_get_max_threads:

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

Všimněte si, že pokud jiná paralelní oblast používá num_threads klauzuli k vyžádání určitého počtu vláken, záruka na dolní mez výsledku omp_get_max_threads již nebude obsahovat.

omp_get_max_threads Návratovou hodnotu funkce lze použít k dynamickému přidělení dostatečného úložiště pro všechna vlákna v týmu vytvořeném v další paralelní oblasti.

Křížové odkazy

3.1.4 omp_get_thread_num

Funkce omp_get_thread_num vrátí číslo vlákna ve svém týmu, které funkci spouští. Číslo vlákna leží mezi 0 a omp_get_num_threads()-1 včetně. Hlavním vláknem týmu je vlákno 0.

Formát je následující:

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

Pokud je volána ze sériové oblasti, omp_get_thread_num vrátí hodnotu 0. Pokud je volána z vnořené paralelní oblasti serializované, vrátí tato funkce hodnotu 0.

Křížové odkazy

  • omp_get_num_threads

3.1.5 omp_get_num_procs funkce

Funkce omp_get_num_procs vrátí počet procesorů, které jsou k dispozici programu v době, kdy je volána funkce. Formát je následující:

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

3.1.6 omp_in_parallel funkce

Funkce omp_in_parallel vrátí nenulovou hodnotu, pokud je volána v dynamickém rozsahu paralelního provádění paralelní oblasti. V opačném případě vrátí hodnotu 0. Formát je následující:

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

Tato funkce vrátí nenulovou hodnotu při volání z oblasti spuštěné paralelně, včetně vnořených oblastí, které jsou serializovány.

3.1.7 omp_set_dynamic funkce

Funkce omp_set_dynamic povolí nebo zakáže dynamické úpravy počtu vláken dostupných pro provádění paralelních oblastí. Formát je následující:

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

Pokud se dynamic_threads vyhodnotí jako nenulová hodnota, je možné automaticky upravit počet vláken používaných k provádění nadcházejících paralelních oblastí prostředím za běhu, aby bylo možné co nejlépe využít systémové prostředky. V důsledku toho je maximální počet vláken určených uživatelem. Počet vláken v týmu, které spouští paralelní oblast, zůstane pevný pro dobu trvání této paralelní oblasti a funkce ji hlásí omp_get_num_threads .

Pokud se dynamic_threads vyhodnotí na hodnotu 0, dynamické úpravy jsou zakázány.

Tato funkce má výše popsané účinky při zavolání z části programu, kde funkce vrátí nulu omp_in_parallel . Pokud je volána z části programu, kde omp_in_parallel funkce vrátí nenulovou hodnotu, chování této funkce není definováno.

Volání, které omp_set_dynamic má přednost před proměnnou OMP_DYNAMIC prostředí.

Výchozí nastavení dynamické úpravy vláken je definováno implementací. V důsledku toho by uživatelské kódy, které závisí na určitém počtu vláken pro správné spuštění, měly explicitně zakázat dynamické vlákna. Implementace se nevyžadují, aby poskytovaly možnost dynamicky upravovat počet vláken, ale vyžadují, aby rozhraní podporovalo přenositelnost napříč všemi platformami.

specifické pro společnost Microsoft

Aktuální podpora omp_get_dynamic a omp_set_dynamic je následující:

Vstupní parametr nemá vliv na omp_set_dynamic zásadu dělení na vlákna a nemění počet vláken. omp_get_num_threads vždy vrátí buď uživatelem definované číslo, pokud je nastaveno, nebo výchozí číslo vlákna. V aktuální implementaci Microsoftu vypne dynamické podprocesování, omp_set_dynamic(0) aby se existující sada vláken znovu použila pro následující paralelní oblast. omp_set_dynamic(1) zapne dynamické podprocesování zrušením stávající sady vláken a vytvořením nové sady pro nadcházející paralelní oblast. Počet vláken v nové sadě je stejný jako stará sada a je založen na návratové omp_get_num_threadshodnotě . Proto pro zajištění nejlepšího výkonu použijte omp_set_dynamic(0) opakované použití existujících vláken.

Křížové odkazy

3.1.8 omp_get_dynamic funkce

Funkce omp_get_dynamic vrátí nenulovou hodnotu, pokud je povolena dynamická úprava vláken, a v opačném případě vrátí hodnotu 0. Formát je následující:

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

Pokud implementace neimplementuje dynamické úpravy počtu vláken, vrátí tato funkce vždy hodnotu 0. Další informace najdete v tématu omp_set_dynamic.

Křížové odkazy

3.1.9 omp_set_nested funkce

Funkce omp_set_nested povolí nebo zakáže vnořený paralelismus. Formát je následující:

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

Pokud se vnořené vyhodnotí na hodnotu 0, je vnořený paralelismus zakázán, což je výchozí hodnota a vnořené paralelní oblasti jsou serializovány a spouštěny aktuálním vláknem. Jinak je povolený vnořený paralelismus a paralelní oblasti, které jsou vnořené, mohou nasadit další vlákna pro vytvoření vnořených týmů.

Tato funkce má výše popsané účinky při zavolání z části programu, kde funkce vrátí nulu omp_in_parallel . Pokud je volána z části programu, kde omp_in_parallel funkce vrátí nenulovou hodnotu, chování této funkce není definováno.

Toto volání má přednost před proměnnou OMP_NESTED prostředí.

Pokud je povolen vnořený paralelismus, počet vláken použitých ke spouštění vnořených paralelních oblastí je definován implementací. Výsledkem je, že implementace kompatibilní s OpenMP mohou serializovat vnořené paralelní oblasti i v případě, že je povolen vnořený paralelismus.

Křížové odkazy

3.1.10 omp_get_nested funkce

Funkce omp_get_nested vrátí nenulovou hodnotu, pokud je povolen vnořený paralelismus a hodnota 0, pokud je zakázaná. Další informace o vnořeném paralelismu najdete v tématu omp_set_nested. Formát je následující:

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

Pokud implementace neimplementuje vnořený paralelismus, vrátí tato funkce vždy hodnotu 0.

3.2 Funkce uzamčení

Funkce popsané v této části manipulují se zámky používanými k synchronizaci.

Pro následující funkce musí mít proměnná zámku typ omp_lock_t. Tato proměnná musí být přístupná pouze prostřednictvím těchto funkcí. Všechny zamykací funkce vyžadují argument, který má ukazatel na omp_lock_t typ.

Pro následující funkce musí mít proměnná zámku typ omp_nest_lock_t. Tato proměnná musí být přístupná pouze prostřednictvím těchto funkcí. Všechny vnořené funkce zámku vyžadují argument, který má ukazatel na omp_nest_lock_t typ.

Funkce zámku OpenMP přistupují k proměnné zámku takovým způsobem, že vždy čtou a aktualizují nejaktuálnější hodnotu proměnné zámku. Proto není nutné, aby program OpenMP obsahoval explicitní flush direktivy, aby se zajistilo, že hodnota proměnné zámku je konzistentní mezi různými vlákny. (Může být nutné, flush aby direktivy byly hodnoty jiných proměnných konzistentní.)

3.2.1 omp_init_lock a funkce omp_init_nest_lock

Tyto funkce poskytují jediný způsob inicializace zámku. Každá funkce inicializuje zámek přidružený k zámku parametru pro použití v nadcházejících voláních. Formát je následující:

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

Počáteční stav je odemknut (to znamená, že žádný vlákno nevlastní zámek). U vnořeného zámku je počáteční počet vnořování nulový. Nedodržuje se volání některé z těchto rutin s proměnnou zámku, která již byla inicializována.

3.2.2 omp_destroy_lock a omp_destroy_nest_lock funkce

Tyto funkce zajišťují, že není inicializována proměnná odkazující na zámek proměnné. Formát je následující:

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

Nedodržuje předpisy volání některé z těchto rutin s proměnnou zámku, která není inicializovaná nebo odemknutá.

3.2.3 funkce omp_set_lock a omp_set_nest_lock

Každá z těchto funkcí blokuje vlákno, které funkci spouští, dokud není zadaný zámek k dispozici, a pak zámek nastaví. Jednoduchý zámek je k dispozici, pokud je odemknutý. Zámek s možností vnoření je k dispozici, pokud je odemknutý nebo pokud už je vlastněn vláknem, které funkci spouští. Formát je následující:

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

U jednoduchého zámku musí argument funkce omp_set_lock odkazovat na inicializovanou proměnnou zámku. Vlastnictví zámku je uděleno vláknu, které funkci spouští.

U vnořeného zámku musí argument omp_set_nest_lock funkce odkazovat na inicializovanou proměnnou zámku. Počet vnoření se zvýší a vlákno se udělí nebo zachová vlastnictví zámku.

3.2.4 omp_unset_lock a omp_unset_nest_lock funkce

Tyto funkce poskytují prostředky uvolnění vlastnictví zámku. Formát je následující:

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

Argument pro každou z těchto funkcí musí odkazovat na inicializovanou proměnnou zámku vlastněnou vláknem, které funkci spouští. Toto chování není definováno, pokud vlákno tento zámek nevlastní.

Pro jednoduchý zámek omp_unset_lock funkce uvolní vlákno, které funkci spouští z vlastnictví zámku.

U vnořeného zámku omp_unset_nest_lock funkce sníží počet vnoření a uvolní vlákno, které funkci spouští z vlastnictví zámku, pokud je výsledný počet nulový.

3.2.5 omp_test_lock a omp_test_nest_lock funkce

Tyto funkce se pokusí nastavit zámek, ale neblokují provádění vlákna. Formát je následující:

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

Argument musí odkazovat na inicializovanou proměnnou zámku. Tyto funkce se pokusí nastavit zámek stejným způsobem jako omp_set_lock a omp_set_nest_lock, s tím rozdílem, že neblokují provádění vlákna.

U jednoduchého zámku vrátí funkce nenulovou hodnotu, omp_test_lock pokud je zámek úspěšně nastaven. V opačném případě vrátí nulu.

U vnořeného zámku vrátí funkce nový počet vnořování, omp_test_nest_lock pokud je zámek úspěšně nastaven. V opačném případě vrátí nulu.

3.3 Rutiny časování

Funkce popsané v této části podporují přenosný časovač hodinových hodin:

  • Funkce omp_get_wtime vrátí uplynulý čas hodinových hodin.
  • Funkce omp_get_wtick vrátí sekundy mezi po sobě jdoucími hodinovými značkami.

3.3.1 omp_get_wtime funkce

Funkce omp_get_wtime vrátí hodnotu s plovoucí desetinnou čárkou s dvojitou přesností, která se rovná uplynulým hodinovým časům v sekundách od doby "v minulosti". Skutečný čas v minulosti je libovolný, ale zaručuje se, že se během provádění aplikačního programu nezmění. Formát je následující:

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

Předpokládá se, že se funkce použije k měření uplynulých časů, jak je znázorněno v následujícím příkladu:

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);

Vrácené časy jsou "krát pro jednotlivá vlákna", což znamená, že nejsou nutné, aby byly globálně konzistentní ve všech vláknech zapojených do aplikace.

3.3.2 omp_get_wtick funkce

Funkce omp_get_wtick vrátí hodnotu s plovoucí desetinnou čárkou s dvojitou přesností, která se rovná počtu sekund mezi po sobě jdoucími hodinami. Formát je následující:

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