Ü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 miteinander und mit dem Betriebssystem und den Anwendungen interagieren.

Abschnitte

Dieses Dokument enthält folgende Abschnitte:

Implementierungsverlauf der Parallelitätslaufzeit

In Visual Studio 2010 bis 2013 wurde die Concurrency Runtime in msvcr100.dll über msvcr120.dll integriert. Als die UCRT-Umgestaltung in Visual Studio 2015 erfolgte, wurde diese DLL in drei Teile umgestaltet:

  • ucrtbase.dll – C-API, in Windows 10 ausgeliefert und über Windows Update gewartet.

  • vcruntime140.dll – Compilerunterstützungsfunktionen und EH-Runtime, ausgeliefert über Visual Studio

  • concrt140.dll – Concurrency Runtime, ausgeliefert über Visual Studio. Erforderlich für parallele Container und Algorithmen wie z concurrency::parallel_for. B. . Außerdem erfordert die STL diese DLL unter Windows XP, um Grundtypen für die Synchronisierung zu aktivieren, da Windows XP keine Bedingungsvariablen aufweist.

In Visual Studio 2015 und höher ist der Concurrency Runtime-Taskplaner nicht mehr der Planer für die Aufgabenklasse und verwandte Typen in „ppltasks.h“. Diese Typen verwenden jetzt den Windows-Threadpool für eine bessere Leistung und Interoperabilität mit Windows-Synchronisierungsprimitiven.

Warum eine Laufzeit für Parallelität wichtig ist

Eine Laufzeit für die Parallelität bietet die Einheitlichkeit und Vorhersagbarkeit für Anwendungen und Anwendungskomponenten, die gleichzeitig ausgeführt werden. Zwei Beispiele für die Vorteile der Concurrency Runtime sind kooperative Aufgabenplanung und kooperative Blockierung.

Die Concurrency Runtime verwendet einen kooperativen Aufgabenplaner, der einen Arbeitsübernahme-Algorithmus implementiert, um die Arbeit effizient auf die Computerressourcen zu verteilen. Betrachten Sie beispielsweise eine Anwendung mit zwei Threads, die beide von der gleichen Laufzeit verwaltet werden. Wenn ein Thread die geplante Aufgabe abgeschlossen hat, kann dieser die Arbeit des anderen Threads auslagern. Dieser Mechanismus gleicht die gesamte Arbeitsauslastung der Anwendung aus.

Die Concurrency Runtime stellt außerdem Synchronisierungsprimitiven zur Verfügung, die die kooperative Blockierung zum Synchronisieren des Zugriffs auf die Ressourcen nutzen. Betrachten Sie z. B. eine Aufgabe, bei der der exklusive Zugriff auf eine freigegebene Ressource gewährleistet sein muss. Durch die kooperative Blockierung kann die Laufzeit das verbleibende Quantum verwenden, um eine andere Aufgabe ausführen, während die erste Aufgabe auf die Ressource wartet. Durch diesen Mechanismus wird die maximale Auslastung der Computerressourcen hochgestuft.

[Nach oben]

Aufbau

Die Concurrency Runtime ist in vier Komponenten unterteilt: die Parallel Patterns Library (PPL), die Asynchronous Agents Library, der Taskplaner und der Ressourcen-Manager. Diese Komponenten befinden sich zwischen dem Betriebssystem und den Anwendungen. Die folgende Abbildung zeigt, wie die Concurrency Runtime-Komponenten zwischen dem Betriebssystem und den Anwendungen interagieren:

Parallelitäts-Runtime-Architektur

The Concurrency Runtime Architecture.

Wichtig

Die Komponenten "Vorgangsplaner" und "Ressourcen-Manager" sind nicht in einer Universelle Windows-Plattform-App (UWP) verfügbar oder wenn Sie die Aufgabenklasse oder andere Typen in ppltasks.h verwenden.

Die Parallelitätslaufzeit ist sehr komponierbar, d. h., Sie können vorhandene Funktionen kombinieren, um mehr zu tun. Die Concurrency Runtime kombiniert viele Funktionen aus Komponenten auf niedrigerer Ebene, wie z. B. parallele Algorithmen.

Die Concurrency Runtime stellt außerdem Synchronisierungsprimitiven zur Verfügung, die die kooperative Blockierung zum Synchronisieren des Zugriffs auf die Ressourcen nutzen. Weitere Informationen zu diesen Synchronisierungsgrundtypen finden Sie unter "Synchronisierungsdatenstrukturen".

Die folgenden Abschnitte bieten einen kurzen Überblick über die jeweilige Komponente und deren Verwendung.

Parallel Patterns Library

Die Parallel Patterns Library (PPL) bietet allgemeine Container und Algorithmen zum Ausführen der differenzierten Parallelität. Die PPL ermöglicht imperative Datenparallelität , indem parallele Algorithmen bereitgestellt werden, die Berechnungen für Sammlungen oder Datensätze über Computerressourcen hinweg verteilen. Sie ermöglicht auch die Parallelität von Aufgaben, indem Aufgabenobjekte bereitgestellt werden, die mehrere unabhängige Vorgänge über Computerressourcen verteilen.

Verwenden Sie die Parallel Patterns Library bei lokalen Berechnungen, die von der parallelen Ausführung profitieren können. Sie können z. B. die Parallelität::p arallel_for-Algorithmus verwenden, um eine vorhandene for Schleife zu transformieren, um parallel zu agieren.

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

Asynchronous Agents Library

Die asynchrone Agents-Bibliothek (oder nur die Agents-Bibliothek) bietet sowohl ein akteurbasiertes Programmiermodell als auch Nachrichtenübergabeschnittstellen für grobkörnige Datenflow- und Pipeliningaufgaben. Asynchrone Agents ermöglichen es Ihnen, die Latenz produktiv zu nutzen, indem Sie Arbeiten ausführen, während andere Komponenten auf die Daten warten.

Verwenden Sie die Agents Library, wenn Sie über mehrere Entitäten verfügen, die miteinander asynchron kommunizieren. Beispielsweise können Sie einen Agent erstellen, der die Daten aus einer Datei oder einer Netzwerkverbindung liest und anschließend die Schnittstellen der Meldungsübergabe verwendet, um diese Daten an einen anderen Agent zu senden.

Weitere Informationen zur Agents-Bibliothek finden Sie unter "Asynchrone Agents"-Bibliothek.

Aufgabenplanung

Der Taskplaner plant und koordiniert die Aufgaben zur Laufzeit. Der Taskplaner ist kooperativ und verwendet einen Arbeitsübernahme-Algorithmus, um die maximale Auslastung der Verarbeitungsressourcen zu erreichen.

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 jedoch auch Ihre eigene Planungsrichtlinie zur Verfügung stellen oder bestimmten Planern bestimmte Aufgaben zuordnen.

Weitere Informationen zum Taskplaner finden Sie unter "Task Scheduler".

Ressourcenmanager

Die Aufgabe des Ressourcen-Managers besteht darin, die Computerressourcen, wie beispielsweise Prozessoren und Arbeitsspeicher, zu verwalten. Der Ressourcen-Manager reagiert auf Arbeitslasten, die sich zur Laufzeit ändern, indem die Ressourcen dorthin zugewiesen werden, wo sie am effektivsten sind.

Der Ressourcen-Manager stellt eine Abstraktionsebene für die Computerressourcen dar und interagiert in erster Linie mit dem Aufgabenplaner. Obwohl Sie den Ressourcen-Manager zur Optimierung der Leistung Ihrer Bibliotheken und Anwendungen verwenden können, verwenden Sie in der Regel die Funktionalität, die von der Parallel Patterns Library, der Agents Library und dem Aufgabenplaner bereitgestellt wird. Diese Bibliotheken verwenden den Ressourcen-Manager, um die Ressourcen dynamisch neu zu verteilen, wenn sich die Arbeitslasten ändern.

[Nach oben]

C++-Lambda-Ausdrücke

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

Die Lambda-Ausdrücke sind eine wichtige neue Sprachfunktion in Visual C++, da sie eine kompakte Art und Weise zum Definieren von Arbeitsfunktionen für die Parallelverarbeitung bieten. Funktionsobjekte und Funktionszeiger ermöglichen Ihnen die Verwendung der Concurrency Runtime mit dem vorhandenen Code. Microsoft empfiehlt jedoch, Lambdaausdrücke beim Schreiben von neuem Code zu verwenden, da diese bezüglich der Sicherheit und Produktivität viele Vorteile bieten.

Im folgenden Beispiel wird die Syntax von Lambdafunktionen, Funktionsobjekten und Funktionszeigern in mehreren Aufrufen der Parallelität::p arallel_for_each Algorithmus verglichen. Jeder Aufruf verwendet parallel_for_each eine andere Technik, um das Quadrat jedes Elements in einem std::array-Objekt zu berechnen.

// 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(begin(values), end(values), [](int& n){n *= n;});

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

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

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

Ausgabe

1
256
6561
65536
390625

Weitere Informationen zu Lambda-Funktionen in C++ finden Sie unter Lambda-Ausdrücke.

[Nach oben]

Anforderungen

Die folgende Tabelle zeigt die Headerdateien, die jeder einzelnen Komponente der Concurrency Runtime zugeordnet sind:

Komponente Header Files
Parallel Patterns Library (PPL) ppl.h

concurrent_queue.h

concurrent_vector.h
Asynchronous Agents Library agents.h
Aufgabenplanung concrt.h
Ressourcenmanager concrtrm.h

Die Concurrency Runtime wird im Concurrency-Namespace deklariert. (Sie können auch die Parallelität verwenden, bei der es sich um einen Alias für diesen Namespace handelt.) Der concurrency::details Namespace unterstützt das Concurrency-Runtime-Framework und soll nicht direkt aus Ihrem Code verwendet werden.

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

[Nach oben]