Freigeben über


3. Laufzeitbibliotheksfunktionen

In diesem Abschnitt werden die Funktionen der OpenMP C- und C++-Laufzeitbibliothek beschrieben. Der Header <omp.h> deklariert zwei Typen, mehrere Funktionen, die zum Steuern und Abfragen der parallelen Ausführungsumgebung verwendet werden können, und Sperrfunktionen, die zum Synchronisieren des Zugriffs auf Daten verwendet werden können.

Der Typ omp_lock_t ist ein Objekttyp, der darstellt, dass eine Sperre verfügbar ist oder dass ein Thread eine Sperre besitzt. Diese Sperren werden als einfache Sperren bezeichnet.

Der Typ ist ein Objekttyp omp_nest_lock_t , der entweder darstellt, dass eine Sperre verfügbar ist, oder die Identität des Threads, der die Sperre und eine Schachtelungsanzahl besitzt (siehe unten). Diese Sperren werden als verschachtelbare Sperren bezeichnet.

Die Bibliotheksfunktionen sind externe Funktionen mit "C"-Verknüpfung.

Die Beschreibungen in diesem Kapitel sind in die folgenden Themen unterteilt:

3.1 Ausführungsumgebungsfunktionen

Die in diesem Abschnitt beschriebenen Funktionen wirken sich auf Threads, Prozessoren und die parallele Umgebung aus:

3.1.1 omp_set_num_threads Funktion

Die omp_set_num_threads Funktion legt die Standardanzahl der Threads fest, die für spätere parallele Bereiche verwendet werden sollen, die keine Klausel angeben num_threads . Das Format ist wie folgt:

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

Der Wert des Parameters num_threads muss eine positive ganze Zahl sein. Der Effekt hängt davon ab, ob die dynamische Anpassung der Anzahl der Threads aktiviert ist. Eine umfassende Reihe von Regeln zur Interaktion zwischen der omp_set_num_threads Funktion und der dynamischen Anpassung von Threads finden Sie unter Abschnitt 2.3.

Diese Funktion hat die oben beschriebenen Effekte, wenn sie aus einem Teil des Programms aufgerufen wird, in dem die omp_in_parallel Funktion Null zurückgibt. Wenn sie aus einem Teil des Programms aufgerufen wird, in dem die omp_in_parallel Funktion einen Wert ungleich Null zurückgibt, wird das Verhalten dieser Funktion nicht definiert.

Dieser Aufruf hat Vorrang vor der OMP_NUM_THREADS Umgebungsvariable. Der Standardwert für die Anzahl der Threads, die durch Aufrufen omp_set_num_threads oder Festlegen der OMP_NUM_THREADS Umgebungsvariable eingerichtet werden können, kann durch Angeben der num_threads Klausel explizit für eine einzelne parallel Direktive überschrieben werden.

Weitere Informationen finden Sie unter omp_set_dynamic.

Querverweise

  • omp_set_dynamic-Funktion
  • omp_get_dynamic-Funktion
  • OMP_NUM_THREADS Umgebungsvariable
  • num_threads-Klausel

3.1.2 omp_get_num_threads Funktion

Die omp_get_num_threads Funktion gibt die Anzahl der Threads zurück, die sich derzeit im Team befinden und den parallelen Bereich ausführen, aus dem sie aufgerufen wird. Das Format ist wie folgt:

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

Die num_threads Klausel, die omp_set_num_threads Funktion und die OMP_NUM_THREADS Umgebungsvariable steuern die Anzahl der Threads in einem Team.

Wenn die Anzahl der Threads vom Benutzer nicht explizit festgelegt wurde, wird die Standardimplementierung definiert. Diese Funktion bindet an die am nächsten eingeschlossene parallel Direktive. Wenn sie aus einem seriellen Teil eines Programms oder aus einem geschachtelten parallelen Bereich aufgerufen wird, der serialisiert wird, gibt diese Funktion 1 zurück.

Weitere Informationen finden Sie unter omp_set_dynamic.

Querverweise

3.1.3 omp_get_max_threads Funktion

Die omp_get_max_threads Funktion gibt eine ganze Zahl zurück, die garantiert mindestens so groß ist wie die Anzahl der Threads, die verwendet werden würden, um ein Team zu bilden, wenn an diesem Punkt im Code ein paralleler Bereich ohne Klausel num_threads zu sehen wäre. Das Format ist wie folgt:

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

Im Folgenden wird eine untere Grenze für den Wert von omp_get_max_threads:

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

Beachten Sie, dass, wenn eine andere parallele Region die num_threads Klausel verwendet, um eine bestimmte Anzahl von Threads anzufordern, die Garantie für die untere Grenze des Ergebnisses nicht omp_get_max_threads mehr enthält.

Der Rückgabewert der omp_get_max_threads Funktion kann verwendet werden, um dynamisch ausreichend Speicherplatz für alle Threads im Team zuzuweisen, die im nächsten parallelen Bereich gebildet wurden.

Querverweise

3.1.4 omp_get_thread_num Funktion

Die omp_get_thread_num Funktion gibt die Threadnummer innerhalb des Teams des Threads zurück, der die Funktion ausführt. Die Threadnummer liegt zwischen 0 und omp_get_num_threads()-1 einschließlich. Der Masterthread des Teams ist Thread 0.

Das Format ist wie folgt:

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

Wenn aus einem seriellen Bereich aufgerufen wird, omp_get_thread_num wird 0 zurückgegeben. Wenn diese Funktion aus einem geschachtelten parallelen Bereich aufgerufen wird, der serialisiert wird, gibt diese Funktion "0" zurück.

Querverweise

  • omp_get_num_threads-Funktion

3.1.5 omp_get_num_procs

Die omp_get_num_procs Funktion gibt die Anzahl der Prozessoren zurück, die zum Zeitpunkt des Aufrufs der Funktion für das Programm verfügbar sind. Das Format ist wie folgt:

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

3.1.6 omp_in_parallel Funktion

Die omp_in_parallel Funktion gibt einen Wert ungleich Null zurück, wenn er innerhalb des dynamischen Umfangs eines parallel ausgeführten parallel ausgeführten parallelen Bereichs aufgerufen wird. Andernfalls wird 0 zurückgegeben. Das Format ist wie folgt:

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

Diese Funktion gibt einen Wert ungleich Null zurück, wenn er innerhalb eines Bereichs aufgerufen wird, der parallel ausgeführt wird, einschließlich geschachtelter Regionen, die serialisiert sind.

3.1.7 omp_set_dynamic

Die omp_set_dynamic Funktion aktiviert oder deaktiviert die dynamische Anpassung der Anzahl der Threads, die für die Ausführung paralleler Bereiche verfügbar sind. Das Format ist wie folgt:

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

Wenn dynamic_threads einen Wert ungleich Null auswertet, kann die Anzahl der Threads, die für die Ausführung anstehender paralleler Regionen verwendet werden, automatisch von der Laufzeitumgebung angepasst werden, um Systemressourcen optimal zu verwenden. Dies hat zur Folge, dass die Anzahl der vom Benutzer angegebenen Threads die maximale Threadanzahl ist. Die Anzahl der Threads im Team, in dem ein paralleler Bereich ausgeführt wird, bleibt für die Dauer dieses parallelen Bereichs fest und wird von der omp_get_num_threads Funktion gemeldet.

Wenn dynamic_threads als 0 ausgewertet wird, wird die dynamische Anpassung deaktiviert.

Diese Funktion hat die oben beschriebenen Effekte, wenn sie aus einem Teil des Programms aufgerufen wird, in dem die omp_in_parallel Funktion Null zurückgibt. Wenn sie aus einem Teil des Programms aufgerufen wird, in dem die omp_in_parallel Funktion einen Wert ungleich Null zurückgibt, wird das Verhalten dieser Funktion nicht definiert.

Ein Aufruf hat omp_set_dynamic Vorrang vor der OMP_DYNAMIC Umgebungsvariable.

Die Standardeinstellung für die dynamische Anpassung von Threads ist implementierungsdefiniert. Daher sollten Benutzercodes, die von einer bestimmten Anzahl von Threads für die korrekte Ausführung abhängen, explizit dynamische Threads deaktivieren. Implementierungen sind nicht erforderlich, um die Möglichkeit zu bieten, die Anzahl der Threads dynamisch anzupassen, aber sie müssen die Schnittstelle bereitstellen, um die Portabilität auf allen Plattformen zu unterstützen.

Microsoft-spezifisch

Die aktuelle Unterstützung von omp_get_dynamic und omp_set_dynamic ist wie folgt:

Der Eingabeparameter, omp_set_dynamic der sich nicht auf die Threadingrichtlinie auswirkt und die Anzahl der Threads nicht ändert. omp_get_num_threads gibt immer entweder die benutzerdefinierte Zahl zurück, sofern diese festgelegt ist, oder die Standardthreadnummer. Deaktiviert in der aktuellen Microsoft-Implementierung das dynamische Threading, omp_set_dynamic(0) sodass der vorhandene Satz von Threads für den folgenden parallelen Bereich wiederverwendet werden kann. omp_set_dynamic(1)aktiviert dynamische Threading Karte durch Dising der vorhandenen Threads und Erstellen eines neuen Satzes für die anstehende parallele Region. Die Anzahl der Threads im neuen Satz entspricht dem alten Satz und basiert auf dem Rückgabewert von omp_get_num_threads. Verwenden Sie omp_set_dynamic(0) daher für optimale Leistung die vorhandenen Threads wiederverwenden.

Querverweise

3.1.8 omp_get_dynamic Funktion

Die omp_get_dynamic Funktion gibt einen Wert ungleich Null zurück, wenn die dynamische Anpassung von Threads aktiviert ist und andernfalls 0 zurückgibt. Das Format ist wie folgt:

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

Wenn die Implementierung keine dynamische Anpassung der Anzahl von Threads implementiert, gibt diese Funktion immer 0 zurück. Weitere Informationen finden Sie unter omp_set_dynamic.

Querverweise

  • Eine Beschreibung der dynamischen Threadanpassung finden Sie unter omp_set_dynamic.

3.1.9 omp_set_nested Funktion

Die omp_set_nested Funktion aktiviert oder deaktiviert geschachtelte Parallelität. Das Format ist wie folgt:

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

Wenn geschachtelte Werte auf 0 ausgewertet werden, ist der geschachtelte Parallelismus deaktiviert, der Standardwert und geschachtelte parallele Bereiche werden serialisiert und vom aktuellen Thread ausgeführt. Andernfalls ist geschachtelte Parallelität aktiviert, und parallele Bereiche, die geschachtelt sind, stellen möglicherweise zusätzliche Threads zum Erstellen von geschachteltes Team bereit.

Diese Funktion hat die oben beschriebenen Effekte, wenn sie aus einem Teil des Programms aufgerufen wird, in dem die omp_in_parallel Funktion Null zurückgibt. Wenn sie aus einem Teil des Programms aufgerufen wird, in dem die omp_in_parallel Funktion einen Wert ungleich Null zurückgibt, wird das Verhalten dieser Funktion nicht definiert.

Dieser Aufruf hat Vorrang vor der OMP_NESTED Umgebungsvariable.

Wenn geschachtelte Parallelität aktiviert ist, wird die Anzahl der Threads, die zum Ausführen geschachtelter paralleler Bereiche verwendet werden, implementierungsdefiniert. Daher können openMP-kompatible Implementierungen geschachtelte parallele Regionen auch dann serialisieren, wenn geschachtelte Parallelität aktiviert ist.

Querverweise

3.1.10 omp_get_nested Funktion

Die omp_get_nested Funktion gibt einen Wert ungleich Null zurück, wenn geschachtelte Parallelität aktiviert ist, und 0, wenn sie deaktiviert ist. Weitere Informationen zum geschachtelten Parallelismus finden Sie unter omp_set_nested. Das Format ist wie folgt:

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

Wenn eine Implementierung keine geschachtelte Parallelität implementiert, gibt diese Funktion immer "0" zurück.

3.2 Sperrfunktionen

Die in diesem Abschnitt beschriebenen Funktionen bearbeiten sperren, die für die Synchronisierung verwendet werden.

Für die folgenden Funktionen muss die Sperrvariable typ omp_lock_tsein. Auf diese Variable darf nur über diese Funktionen zugegriffen werden. Für alle Sperrfunktionen ist ein Argument erforderlich, für das ein Zeiger eingegeben werden soll omp_lock_t .

Für die folgenden Funktionen muss die Sperrvariable typ omp_nest_lock_tsein. Auf diese Variable darf nur über diese Funktionen zugegriffen werden. Für alle verschachtelten Sperrfunktionen ist ein Argument erforderlich, das einen Zeiger zum omp_nest_lock_t Eingeben hat.

Die OpenMP-Sperrfunktionen greifen so auf die Sperrvariable zu, dass sie immer den aktuellen Wert der Sperrvariable lesen und aktualisieren. Daher ist es nicht erforderlich, dass ein OpenMP-Programm explizite flush Direktiven enthält, um sicherzustellen, dass der Wert der Sperrvariable unter verschiedenen Threads konsistent ist. (Möglicherweise müssen flush Direktiven die Werte anderer Variablen konsistent machen.)

3.2.1 omp_init_lock- und omp_init_nest_lock funktionen

Diese Funktionen stellen die einzige Möglichkeit zum Initialisieren einer Sperre bereit. Jede Funktion initialisiert die dem Parametersperr zugeordnete Sperre für die Verwendung in anstehenden Aufrufen. Das Format ist wie folgt:

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

Der Anfangszustand ist entsperrt (d. a. kein Thread besitzt die Sperre). Bei einer verschachtelten Sperre ist die anfängliche Schachtelungsanzahl null. Es ist nicht konform, eine dieser Routinen mit einer Sperrvariable aufzurufen, die bereits initialisiert wurde.

3.2.2 omp_destroy_lock- und omp_destroy_nest_lock funktionen

Diese Funktionen stellen sicher, dass die sperrungsvariable Sperre nicht initialisiert ist. Das Format ist wie folgt:

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

Es ist nicht konform, eine dieser Routinen mit einer Sperrvariable aufzurufen, die nicht initialisiert oder entsperrt ist.

3.2.3 omp_set_lock- und omp_set_nest_lock funktionen

Jede dieser Funktionen blockiert den Thread, der die Funktion ausführt, bis die angegebene Sperre verfügbar ist, und legt dann die Sperre fest. Eine einfache Sperre ist verfügbar, wenn sie entsperrt ist. Eine verschachtelte Sperre ist verfügbar, wenn sie entsperrt ist oder bereits im Besitz des Threads ist, der die Funktion ausführt. Das Format ist wie folgt:

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

Bei einer einfachen Sperre muss das Argument auf die omp_set_lock Funktion auf eine initialisierte Sperrvariable verweisen. Der Besitz der Sperre wird dem Thread gewährt, der die Funktion ausführt.

Bei einer verschachtelten Sperre muss das Argument auf omp_set_nest_lock eine initialisierte Sperrvariable verweisen. Die Schachtelungsanzahl wird erhöht, und der Thread wird gewährt oder behält den Besitz der Sperre.

3.2.4 funktionen omp_unset_lock und omp_unset_nest_lock

Diese Funktionen bieten die Möglichkeit, den Besitz einer Sperre freizugeben. Das Format ist wie folgt:

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

Das Argument auf jede dieser Funktionen muss auf eine initialisierte Sperrvariable verweisen, die dem Thread gehört, der die Funktion ausführt. Das Verhalten ist nicht definiert, wenn der Thread diese Sperre nicht besitzt.

Bei einer einfachen Sperre gibt die omp_unset_lock Funktion den Thread frei, der die Funktion vom Besitz der Sperre ausführt.

Bei einer verschachtelten Sperre erhöht die omp_unset_nest_lock Funktion die Schachtelungsanzahl und gibt den Thread frei, der die Funktion vom Besitz der Sperre ausführt, wenn die resultierende Anzahl null ist.

3.2.5 funktionen omp_test_lock und omp_test_nest_lock

Diese Funktionen versuchen, eine Sperre festzulegen, aber die Ausführung des Threads nicht zu blockieren. Das Format ist wie folgt:

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

Das Argument muss auf eine initialisierte Sperrvariable verweisen. Diese Funktionen versuchen, eine Sperre auf die gleiche Weise festzulegen wie omp_set_lock und omp_set_nest_lock, mit der Ausnahme, dass sie die Ausführung des Threads nicht blockieren.

Bei einer einfachen Sperre gibt die omp_test_lock Funktion einen Wert ungleich Null zurück, wenn die Sperre erfolgreich festgelegt wurde. Andernfalls wird null zurückgegeben.

Bei einer verschachtelten Sperre gibt die omp_test_nest_lock Funktion die neue Schachtelungsanzahl zurück, wenn die Sperre erfolgreich festgelegt wurde. Andernfalls wird null zurückgegeben.

3.3 Timing-Routinen

Die in diesem Abschnitt beschriebenen Funktionen unterstützen einen tragbaren Wall-Clock-Timer:

3.3.1 omp_get_wtime Funktion

Die omp_get_wtime Funktion gibt einen Gleitkommawert mit doppelter Genauigkeit zurück, der der verstrichenen Wanduhrzeit in Sekunden seit einigen "Zeiten in der Vergangenheit" entspricht. Die tatsächliche "Zeit in der Vergangenheit" ist willkürlich, aber es wird garantiert nicht während der Ausführung des Anwendungsprogramms geändert. Das Format ist wie folgt:

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

Es wird erwartet, dass die Funktion verwendet wird, um verstrichene Zeiten zu messen, wie im folgenden Beispiel gezeigt:

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

Die zurückgegebenen Zeiten sind "pro Threadzeiten", mit denen sie nicht global in allen Threads konsistent sein müssen, die an einer Anwendung teilnehmen.

3.3.2 omp_get_wtick Funktion

Die omp_get_wtick Funktion gibt einen Gleitkommawert mit doppelter Genauigkeit zurück, der der Anzahl der Sekunden zwischen aufeinander folgenden Taktstrichen entspricht. Das Format ist wie folgt:

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