Condividi tramite


3. Funzioni della libreria di runtime

Questa sezione descrive le funzioni della libreria di runtime C e C++ OpenMP. L'intestazione <omp.h> dichiara due tipi, diverse funzioni che possono essere usate per controllare ed eseguire query sull'ambiente di esecuzione parallela e funzioni di blocco che possono essere usate per sincronizzare l'accesso ai dati.

Il tipo è un tipo omp_lock_t di oggetto in grado di rappresentare che è disponibile un blocco o che un thread possiede un blocco. Questi blocchi sono definiti semplici blocchi.

Il tipo è un tipo omp_nest_lock_t di oggetto in grado di rappresentare che è disponibile un blocco o sia l'identità del thread proprietario del blocco che un conteggio annidamento (descritto di seguito). Questi blocchi sono detti blocchi annidabili.

Le funzioni di libreria sono funzioni esterne con collegamento "C".

Le descrizioni di questo capitolo sono suddivise negli argomenti seguenti:

3.1 Funzioni dell'ambiente di esecuzione

Le funzioni descritte in questa sezione influiscono sui thread, sui processori e sull'ambiente parallelo:

3.1.1 funzione omp_set_num_threads

La omp_set_num_threads funzione imposta il numero predefinito di thread da usare per aree parallele successive che non specificano una num_threads clausola. Il formato è il seguente:

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

Il valore del parametro num_threads deve essere un numero intero positivo. L'effetto dipende dal fatto che la regolazione dinamica del numero di thread sia abilitata. Per un set completo di regole sull'interazione tra la funzione e la omp_set_num_threads regolazione dinamica dei thread, vedere la sezione 2.3.

Questa funzione ha gli effetti descritti in precedenza quando viene chiamato da una parte del programma in cui la omp_in_parallel funzione restituisce zero. Se viene chiamato da una parte del programma in cui la omp_in_parallel funzione restituisce un valore diverso da zero, il comportamento di questa funzione non è definito.

Questa chiamata ha la precedenza sulla variabile di OMP_NUM_THREADS ambiente. Il valore predefinito per il numero di thread, che può essere stabilito chiamando omp_set_num_threads o impostando la OMP_NUM_THREADS variabile di ambiente, può essere sottoposto a override in modo esplicito su una singola parallel direttiva specificando la num_threads clausola .

Per altre informazioni, vedere omp_set_dynamic.

Riferimenti incrociati

3.1.2 funzione omp_get_num_threads

La omp_get_num_threads funzione restituisce il numero di thread attualmente presenti nel team che esegue l'area parallela da cui viene chiamata. Il formato è il seguente:

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

La num_threads clausola, la omp_set_num_threads funzione e la OMP_NUM_THREADS variabile di ambiente controllano il numero di thread in un team.

Se il numero di thread non è stato impostato in modo esplicito dall'utente, il valore predefinito è definito dall'implementazione. Questa funzione viene associata alla direttiva di inclusione parallel più vicina. Se viene chiamato da una parte seriale di un programma o da un'area parallela annidata serializzata, questa funzione restituisce 1.

Per altre informazioni, vedere omp_set_dynamic.

Riferimenti incrociati

3.1.3 funzione omp_get_max_threads

La omp_get_max_threads funzione restituisce un numero intero garantito che sia almeno pari al numero di thread che verrebbero usati per formare un team se un'area parallela senza una num_threads clausola dovesse essere visualizzata in quel punto del codice. Il formato è il seguente:

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

Di seguito viene espresso un limite inferiore sul valore di omp_get_max_threads:

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

Si noti che se un'altra area parallela usa la num_threads clausola per richiedere un numero specifico di thread, la garanzia sul limite inferiore del risultato di omp_get_max_threads non contiene più.

Il omp_get_max_threads valore restituito della funzione può essere usato per allocare in modo dinamico spazio di archiviazione sufficiente per tutti i thread del team formato nella successiva area parallela.

Riferimenti incrociati

3.1.4 funzione omp_get_thread_num

La omp_get_thread_num funzione restituisce il numero di thread, all'interno del relativo team, del thread che esegue la funzione. Il numero di thread è compreso tra 0 e omp_get_num_threads()-1, inclusi. Il thread master del team è thread 0.

Il formato è il seguente:

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

Se viene chiamato da un'area seriale, omp_get_thread_num restituisce 0. Se viene chiamato dall'interno di un'area parallela annidata serializzata, questa funzione restituisce 0.

Riferimenti incrociati

  • funzione omp_get_num_threads

3.1.5 funzione omp_get_num_procs

La omp_get_num_procs funzione restituisce il numero di processori disponibili per il programma al momento della chiamata della funzione. Il formato è il seguente:

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

3.1.6 funzione omp_in_parallel

La omp_in_parallel funzione restituisce un valore diverso da zero se viene chiamato all'interno dell'extent dinamico di un'area parallela in esecuzione in parallelo; in caso contrario, restituisce 0. Il formato è il seguente:

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

Questa funzione restituisce un valore diverso da zero quando viene chiamato dall'interno di un'area in esecuzione in parallelo, incluse le aree annidate serializzate.

3.1.7 omp_set_dynamic funzione

La omp_set_dynamic funzione abilita o disabilita la regolazione dinamica del numero di thread disponibili per l'esecuzione di aree parallele. Il formato è il seguente:

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

Se dynamic_threads restituisce un valore diverso da zero, il numero di thread usati per l'esecuzione di aree parallele future può essere modificato automaticamente dall'ambiente di runtime per usare al meglio le risorse di sistema. Di conseguenza, il numero di thread specificati dall'utente è il numero massimo di thread. Il numero di thread nel team che esegue un'area parallela rimane fisso per la durata dell'area parallela e viene segnalato dalla omp_get_num_threads funzione .

Se dynamic_threads restituisce 0, la regolazione dinamica è disabilitata.

Questa funzione ha gli effetti descritti in precedenza quando viene chiamato da una parte del programma in cui la omp_in_parallel funzione restituisce zero. Se viene chiamato da una parte del programma in cui la omp_in_parallel funzione restituisce un valore diverso da zero, il comportamento di questa funzione non è definito.

Una chiamata a omp_set_dynamic ha la precedenza sulla OMP_DYNAMIC variabile di ambiente.

Il valore predefinito per la regolazione dinamica dei thread è definito dall'implementazione. Di conseguenza, i codici utente che dipendono da un numero specifico di thread per l'esecuzione corretta devono disabilitare in modo esplicito i thread dinamici. Le implementazioni non sono necessarie per fornire la possibilità di regolare dinamicamente il numero di thread, ma sono necessarie per fornire l'interfaccia per supportare la portabilità in tutte le piattaforme.

Specifico di Microsoft

Il supporto corrente di omp_get_dynamic e omp_set_dynamic è il seguente:

Il parametro di input di omp_set_dynamic non influisce sui criteri di threading e non modifica il numero di thread. omp_get_num_threads restituisce sempre il numero definito dall'utente, se impostato o il numero di thread predefinito. Nell'implementazione omp_set_dynamic(0) microsoft corrente disattiva il threading dinamico in modo che il set esistente di thread possa essere riutilizzato per l'area parallela seguente. omp_set_dynamic(1) attiva il threading dinamico rimuovendo il set esistente di thread e creando un nuovo set per l'area parallela futura. Il numero di thread nel nuovo set è uguale al set precedente e si basa sul valore restituito di omp_get_num_threads. Pertanto, per ottenere prestazioni ottimali, usare omp_set_dynamic(0) per riutilizzare i thread esistenti.

Riferimenti incrociati

3.1.8 funzione omp_get_dynamic

La omp_get_dynamic funzione restituisce un valore diverso da zero se la regolazione dinamica dei thread è abilitata e restituisce 0 in caso contrario. Il formato è il seguente:

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

Se l'implementazione non implementa la regolazione dinamica del numero di thread, questa funzione restituisce sempre 0. Per altre informazioni, vedere omp_set_dynamic.

Riferimenti incrociati

  • Per una descrizione della regolazione dinamica del thread, vedere omp_set_dynamic.

3.1.9 funzione omp_set_nested

La omp_set_nested funzione abilita o disabilita il parallelismo annidato. Il formato è il seguente:

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

Se annidato restituisce 0, il parallelismo annidato è disabilitato, ovvero l'impostazione predefinita e le aree parallele annidate vengono serializzate ed eseguite dal thread corrente. In caso contrario, il parallelismo annidato è abilitato e le aree parallele annidate possono distribuire thread aggiuntivi per formare team annidati.

Questa funzione ha gli effetti descritti in precedenza quando viene chiamato da una parte del programma in cui la omp_in_parallel funzione restituisce zero. Se viene chiamato da una parte del programma in cui la omp_in_parallel funzione restituisce un valore diverso da zero, il comportamento di questa funzione non è definito.

Questa chiamata ha la precedenza sulla variabile di OMP_NESTED ambiente.

Quando il parallelismo annidato è abilitato, il numero di thread usati per eseguire aree parallele annidate è definito dall'implementazione. Di conseguenza, le implementazioni conformi a OpenMP possono serializzare aree parallele annidate anche quando è abilitato il parallelismo annidato.

Riferimenti incrociati

3.1.10 omp_get_nested funzione

La omp_get_nested funzione restituisce un valore diverso da zero se il parallelismo annidato è abilitato e 0 se è disabilitato. Per altre informazioni sul parallelismo annidato, vedere omp_set_nested. Il formato è il seguente:

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

Se un'implementazione non implementa il parallelismo annidato, questa funzione restituisce sempre 0.

3.2 Funzioni di blocco

Le funzioni descritte in questa sezione modificano i blocchi usati per la sincronizzazione.

Per le funzioni seguenti, la variabile lock deve avere il tipo omp_lock_t. Questa variabile deve essere accessibile solo tramite queste funzioni. Tutte le funzioni di blocco richiedono un argomento con un puntatore al omp_lock_t tipo.

Per le funzioni seguenti, la variabile lock deve avere il tipo omp_nest_lock_t. Questa variabile deve essere accessibile solo tramite queste funzioni. Tutte le funzioni di blocco annidabili richiedono un argomento con un puntatore al omp_nest_lock_t tipo.

Le funzioni di blocco OpenMP accedono alla variabile di blocco in modo da leggere e aggiornare sempre il valore più recente della variabile di blocco. Pertanto, non è necessario che un programma OpenMP includa direttive esplicite flush per assicurarsi che il valore della variabile di blocco sia coerente tra thread diversi. Potrebbe essere necessario che flush le direttive rendano coerenti i valori di altre variabili.

3.2.1 funzioni di omp_init_lock e omp_init_nest_lock

Queste funzioni forniscono l'unico mezzo per inizializzare un blocco. Ogni funzione inizializza il blocco associato al blocco dei parametri da usare nelle chiamate future. Il formato è il seguente:

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

Lo stato iniziale viene sbloccato (ovvero nessun thread è proprietario del blocco). Per un blocco annidabile, il numero di annidamento iniziale è zero. Non è conforme chiamare una di queste routine con una variabile di blocco già inizializzata.

3.2.2 funzioni di omp_destroy_lock e omp_destroy_nest_lock

Queste funzioni assicurano che il blocco della variabile di blocco puntato non sia inizializzato. Il formato è il seguente:

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

Non è conforme chiamare una di queste routine con una variabile di blocco non inizializzata o sbloccata.

3.2.3 funzioni di omp_set_lock e omp_set_nest_lock

Ognuna di queste funzioni blocca il thread che esegue la funzione fino a quando il blocco specificato non è disponibile e quindi imposta il blocco. Un blocco semplice è disponibile se è sbloccato. Un blocco annidabile è disponibile se è sbloccato o se è già di proprietà del thread che esegue la funzione. Il formato è il seguente:

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

Per un blocco semplice, l'argomento della omp_set_lock funzione deve puntare a una variabile di blocco inizializzata. La proprietà del blocco viene concessa al thread che esegue la funzione.

Per un blocco annidabile, l'argomento della omp_set_nest_lock funzione deve puntare a una variabile di blocco inizializzata. Il numero di annidamento viene incrementato e il thread viene concesso o mantiene la proprietà del blocco.

3.2.4 funzioni di omp_unset_lock e omp_unset_nest_lock

Queste funzioni forniscono i mezzi per rilasciare la proprietà di un blocco. Il formato è il seguente:

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

L'argomento di ognuna di queste funzioni deve puntare a una variabile di blocco inizializzata di proprietà del thread che esegue la funzione. Il comportamento non è definito se il thread non è proprietario di tale blocco.

Per un blocco semplice, la omp_unset_lock funzione rilascia il thread che esegue la funzione dalla proprietà del blocco.

Per un blocco annidabile, la omp_unset_nest_lock funzione decrementa il conteggio annidamento e rilascia il thread che esegue la funzione dalla proprietà del blocco se il conteggio risultante è zero.

3.2.5 funzioni di omp_test_lock e omp_test_nest_lock

Queste funzioni tentano di impostare un blocco ma non bloccano l'esecuzione del thread. Il formato è il seguente:

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

L'argomento deve puntare a una variabile di blocco inizializzata. Queste funzioni tentano di impostare un blocco nello stesso modo di omp_set_lock e omp_set_nest_lock, ad eccezione del fatto che non bloccano l'esecuzione del thread.

Per un blocco semplice, la omp_test_lock funzione restituisce un valore diverso da zero se il blocco è impostato correttamente; in caso contrario, restituisce zero.

Per un blocco annidabile, la omp_test_nest_lock funzione restituisce il nuovo conteggio annidamento se il blocco è impostato correttamente; in caso contrario, restituisce zero.

3.3 Routine di intervallo

Le funzioni descritte in questa sezione supportano un timer a parete portatile:

3.3.1 funzione omp_get_wtime

La omp_get_wtime funzione restituisce un valore a virgola mobile a precisione doppia uguale all'ora di clock del muro trascorsa in secondi da un "tempo in passato". Il "tempo effettivo in passato" è arbitrario, ma è garantito che non venga modificato durante l'esecuzione del programma dell'applicazione. Il formato è il seguente:

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

È previsto che la funzione venga usata per misurare i tempi trascorsi, come illustrato nell'esempio seguente:

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

I tempi restituiti sono "tempi per thread", ovvero non devono essere coerenti a livello globale in tutti i thread che partecipano a un'applicazione.

3.3.2 funzione omp_get_wtick

La omp_get_wtick funzione restituisce un valore a virgola mobile a precisione doppia uguale al numero di secondi tra i tick di clock successivi. Il formato è il seguente:

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