Übersicht über die Concurrency Runtime

Dieses Dokument enthält eine Übersicht über die Concurrency Runtime. Es beschreibt die Vorteile der Concurrency Runtime, wann sie verwendet wird und wie ihre Komponenten untereinander, mit dem Betriebssystem und mit den Anwendungen interagieren.

Abschnitte

Dieses Dokument enthält folgende Abschnitte:

  • Bedeutung der Laufzeit für die Parallelität

  • Architektur

  • Lambda-Ausdrücke (C++)

  • Voraussetzungen

Bedeutung der Laufzeit für die Parallelität

Mit der Laufzeit für die Parallelität können Sie die Einheitlichkeit und Vorhersagbarkeit für gleichzeitig ausgeführte Anwendungen und Anwendungskomponenten sicherstellen. Die kooperative Aufgabenplanung und die kooperative Blockierung sind zwei Beispiele für die Vorteile der Concurrency Runtime.

Die Concurrency Runtime verwendet einen kooperativen Taskplaner, der die Arbeit mithilfe eines Arbeitsübernahme-Algorithmus effizient zwischen den Computerressourcen verteilt. Beispiel: Eine Anwendung mit zwei Threads, die von der gleichen Laufzeit verwaltet werden. Wenn die geplante Aufgabe eines Threads beendet ist, kann dieser Thread Arbeit von dem anderen Thread übernehmen. Durch diesen Mechanismus wird die Gesamtarbeitsauslastung der Anwendung gleichmäßig verteilt.

Die Concurrency Runtime stellt außerdem Synchronisierungsprimitiven bereit, die den Zugriff auf Ressourcen mithilfe der kooperativen Blockierung synchronisieren. Beispiel: Eine Aufgabe, die exklusiven Zugriff auf eine freigegebene Ressource erfordert. Durch die kooperative Blockierung kann die Runtime das verbleibende Quantum zur Ausführung einer anderen Aufgabe nutzen, während die erste Aufgabe auf die Ressource wartet. Durch diesen Mechanismus wird die maximale Auslastung der Computerressourcen optimiert.

[Nach oben]

Architektur

Die Concurrency Runtime setzt sich aus vier Komponenten zusammen: Parallel Patterns Library (PPL), Asynchronous Agents Library, Taskplaner und Ressourcen-Manager. Diese Komponenten befinden sich zwischen dem Betriebssystem und den Anwendungen. Die folgende Abbildung zeigt die Interaktion der Concurrency Runtime-Komponenten zwischen dem Betriebssystem und den Anwendungen:

Architektur der Concurrency Runtime

Die Architektur von Concurrency Runtime

Die Concurrency Runtime ist hochgradig zusammensetzbar, d h. Sie können die vorhandenen Funktionen kombinieren und erhalten dadurch weitere Vorteile. Die Concurrency Runtime setzt viele Funktionen von Komponenten auf niedrigerer Ebene zusammen, z. B. parallele Algorithmen.

Die Concurrency Runtime stellt außerdem Synchronisierungsprimitiven bereit, die den Zugriff auf Ressourcen mithilfe der kooperativen Blockierung synchronisieren. Weitere Informationen zu diesen Synchronisierungsprimitiven finden Sie unter Synchronisierungsdatenstrukturen.

Die folgenden Abschnitte bieten einen kurzen Überblick über die Vorteile und die Verwendung der Funktionalität der einzelnen Komponenten.

Parallel Patterns Library

Die Parallel Patterns Library (PPL) stellt allgemeine Container und Algorithmen zum Ausführen differenzierter Parallelitäten bereit. Die PPL aktiviert die obligatorische Datenparallelität mittels paralleler Algorithmen, die Berechnungen für Auflistungen und Datensätze auf die Computerressourcen verteilen. Darüber hinaus aktiviert sie die Aufgabenparallelität mittels Aufgabenobjekten, die mehrere unabhängige Vorgänge auf die Computerressourcen verteilen.

Verwenden Sie die Parallel Patterns Library, wenn Sie mit lokalen Berechnungen arbeiten, die mittels paralleler Ausführung optimiert werden können. Sie können beispielsweise den Concurrency::parallel_for-Algorithmus verwenden, um eine vorhandene for-Schleife für die parallele Ausführung zu transformieren.

Weitere Informationen zur Parallel Patterns Library finden Sie unter Parallel Patterns Library (PPL).

Asynchronous Agents Library

Die Asynchronous Agents Library (oder einfach Agents Library) stellt sowohl ein akteurbasiertes Programmiermodell als auch Meldungsübergabeschnittstellen für differenzierten Datenfluss und Pipelineaufgaben bereit. Asynchrone Agents ermöglichen Ihnen, Latenzzeiten produktiv zu nutzen, indem Aufgaben ausgeführt werden, während andere Komponenten auf Daten warten.

Verwenden Sie die Agents Library, wenn Sie über mehrere Entitäten verfügen, die asynchron miteinander kommunizieren. Sie können z. B. einen Agent erstellen, der Daten von einer Datei oder einer Netzwerkverbindung liest und dann die Meldungsübergabeschnittstellen verwendet, um diese Daten an einen anderen Agent zu senden.

Weitere Informationen zur Agents Library finden Sie unter Asynchronous Agents Library.

Taskplaner

Der Taskplaner plant und koordiniert Aufgaben zur Laufzeit. Der kooperative Taskplaner sorgt mit einem Arbeitsübernahme-Algorithmus für die maximale Auslastung der Verarbeitungsressourcen.

Die Concurrency Runtime stellt einen Standardplaner bereit, sodass Sie keine Infrastrukturdetails verwalten müssen. Um die Qualitätsanforderungen Ihrer Anwendung zu erfüllen, können Sie aber auch eine eigene Planungsrichtlinie bereitstellen oder bestimmte Planer bestimmten Aufgaben zuordnen.

Weitere Informationen zum Taskplaner finden Sie unter Taskplaner (Concurrency Runtime).

Ressourcen-Manager

Der Ressourcen-Managers dient zur Verwaltung von Computerressourcen wie Prozessoren und Arbeitsspeicher. Der Ressourcen-Manager reagiert auf die Änderung von Arbeitslasten zur Laufzeit, indem Ressourcen möglichst effizient zugeteilt werden.

Der Ressourcen-Manager stellt eine Abstraktionsebene für die Computerressourcen dar und interagiert primär mit dem Taskplaner. Sie können den Ressourcen-Manager zwar auch zur Optimierung der Leistung Ihrer Bibliotheken und Anwendungen verwenden, in der Regel nutzen Sie jedoch die von der Parallel Patterns Library, der Agents Library und dem Taskplaner bereitgestellte Funktionalität. Diese Bibliotheken nutzen den Ressourcen-Manager für den dynamischen Ressourcenausgleich, wenn sich Arbeitslasten ändern.

[Nach oben]

Lambda-Ausdrücke (C++)

Viele der Typen und Algorithmen, die von der Concurrency Runtime definiert werden, werden als C++-Vorlagen implementiert. Einige dieser Typen und Algorithmen nehmen eine Routine, die Arbeiten ausführt, als Parameter an. Bei diesem Parameter kann es sich um eine Lambda-Funktion, ein Funktionsobjekt oder einen Funktionszeiger handeln. Diese Entitäten werden auch als Arbeitsfunktionen oder Arbeitsroutinen bezeichnet.

Lambda-Ausdrücke sind eine wichtige neue Sprachfunktion in Visual C++, da sie eine kompakte Möglichkeit bieten, Arbeitsfunktionen für die Parallelverarbeitung zu definieren. Mit Funktionsobjekten oder Funktionszeigern können Sie die Concurrency Runtime mit dem vorhandenen Code verwenden. Es empfiehlt sich jedoch, Lambda-Ausdrücke zu verwenden, wenn Sie neuen Code schreiben, da diese Sicherheits- und Produktivitätsvorteile bieten.

Im folgenden Beispiel wird die Syntax von Lambda-Funktionen, Funktionsobjekten und Funktionszeigern in mehreren Aufrufen des Concurrency::parallel_for_each-Algorithmus verglichen. Bei jedem Aufruf von parallel_for_each wird eine andere Technik für die Berechnung des Quadrats der einzelnen Elemente in einem std::array-Objekt verwendet.

// comparing-work-functions.cpp
// compile with: /EHsc
#include <ppl.h>
#include <array>
#include <iostream>

using namespace Concurrency;
using namespace std;

// Function object (functor) class that computes the square of its input.
template<class Ty>
class SquareFunctor
{
public:
   void operator()(Ty& n) const
   {
      n *= n;
   }
};

// Function that computes the square of its input.
template<class Ty>
void square_function(Ty& n)
{
   n *= n;
}

int wmain()
{
   // Create an array object that contains 5 values.
   array<int, 5> values = { 1, 2, 3, 4, 5 };

   // Use a lambda function, a function object, and a function pointer to 
   // compute the square of each element of the array in parallel.

   // Use a lambda function to square each element.
   parallel_for_each(values.begin(), values.end(), [](int& n){n *= n;});

   // Use a function object (functor) to square each element.
   parallel_for_each(values.begin(), values.end(), SquareFunctor<int>());

   // Use a function pointer to square each element.
   parallel_for_each(values.begin(), values.end(), &square_function<int>);

   // Print each element of the array to the console.
   for_each(values.begin(), values.end(), [](int& n) { 
      wcout << n << endl;
   });
}

Folgende Ergebnisse werden zurückgegeben:

1
256
6561
65536
390625

Weitere Informationen zu Lambda-Funktionen in C++ finden Sie unter Lambda Expressions in C++.

[Nach oben]

Voraussetzungen

In der folgenden Tabelle sind die Headerdateien aufgeführt, die den einzelnen Komponenten der Concurrency Runtime zugeordnet sind:

Komponente

Headerdateien

Parallel Patterns Library (PPL)

ppl.h

concurrent_queue.h

concurrent_vector.h

Asynchronous Agents Library

agents.h

Taskplaner

concrt.h

Ressourcen-Manager

concrtrm.h

Die Concurrency Runtime wird im Concurrency-Namespace deklariert. Der Namespace Concurrency::details unterstützt das Concurrency Runtime-Framework und ist nicht zur direkten Verwendung im Code vorgesehen.

Die Concurrency Runtime wird als Teil der C Runtime Library (CRT) bereitgestellt. Weitere Informationen zum Erstellen einer Anwendung, die die CRT verwendet, finden Sie unter C Run-Time Libraries.

[Nach oben]

Änderungsprotokoll

Datum

Versionsgeschichte

Grund

Juli 2010

Inhalt neu strukturiert.

Informationsergänzung.