Partilhar via


Visão geral do ambiente de execução da concorrência

Este documento fornece uma visão geral do Concurrency Runtime. Ele descreve os benefícios do Concurrency Runtime, quando usá-lo e como seus componentes interagem entre si e com o sistema operacional e aplicativos.

Secções

Este documento contém as seguintes secções:

Histórico de implementação do Concurrency Runtime

No Visual Studio de 2010 a 2013, o Concurrency Runtime foi incorporado no msvcr100.dll até msvcr120.dll. Quando a refatoração UCRT ocorreu no Visual Studio 2015, essa DLL foi refatorada em três partes:

  • ucrtbase.dll – C API, fornecida no Windows 10 e mantida no nível inferior via Windows Update-

  • vcruntime140.dll – Funções de suporte do compilador e tempo de execução EH, fornecido via Visual Studio

  • concrt140.dll – Concurrency Runtime, fornecido via Visual Studio. Necessário para contêineres paralelos e algoritmos, como concurrency::parallel_for. Além disso, a STL requer essa DLL no Windows XP para alimentar primitivas de sincronização, porque o Windows XP não tem variáveis de condição.

No Visual Studio 2015 e versões posteriores, o Agendador de Tarefas de Tempo de Execução de Simultaneidade deixou de ser o agendador para a classe de tarefa e os tipos relacionados no ppltasks.h. Esses tipos agora usam o Windows ThreadPool para melhor desempenho e interoperabilidade com primitivos de sincronização do Windows.

Por que um tempo de execução para simultaneidade é importante

Um tempo de execução para simultaneidade fornece uniformidade e previsibilidade para aplicativos e componentes de aplicativos que são executados simultaneamente. Dois exemplos dos benefícios do Concurrency Runtime são o agendamento cooperativo de tarefas e o bloqueio cooperativo.

O Concurrency Runtime usa um agendador de tarefas cooperativo que implementa um algoritmo de roubo de trabalho para distribuir eficientemente o trabalho entre os recursos de computação. Por exemplo, considere um aplicativo que tenha dois threads que são gerenciados pelo mesmo tempo de execução. Se um thread terminar sua tarefa agendada, ele poderá descarregar o trabalho do outro thread. Este mecanismo equilibra a carga de trabalho global da aplicação.

O Concurrency Runtime também fornece primitivas de sincronização que usam o bloqueio cooperativo para sincronizar o acesso aos recursos. Por exemplo, considere uma tarefa que deve ter acesso exclusivo a um recurso compartilhado. Ao bloquear cooperativamente, o sistema em tempo real pode usar o quantum restante para executar outra tarefa enquanto a primeira tarefa espera pelo recurso. Este mecanismo promove a utilização máxima dos recursos informáticos.

[Topo]

Arquitetura

O Concurrency Runtime é dividido em quatro componentes: a Biblioteca de Padrões Paralelos (PPL), a Biblioteca de Agentes Assíncronos, o Agendador de Tarefas e o Gerenciador de Recursos. Esses componentes residem entre o sistema operacional e os aplicativos. A ilustração a seguir mostra como os componentes do Concurrency Runtime interagem entre o sistema operacional e os aplicativos:

Arquitetura de Tempo de Execução Concorrente

A arquitetura de tempo de execução simultaneidade.

Importante

Os componentes Agendador de Tarefas e Gerenciador de Recursos não estão disponíveis em um aplicativo da Plataforma Universal do Windows (UWP) ou quando você usa a classe de tarefa ou outros tipos em ppltasks.h.

O Concurrency Runtime é altamente composable, ou seja, você pode combinar a funcionalidade existente para fazer mais. O Concurrency Runtime compõe muitos recursos, como algoritmos paralelos, a partir de componentes de nível inferior.

O Concurrency Runtime também fornece primitivas de sincronização que usam o bloqueio cooperativo para sincronizar o acesso aos recursos. Para obter mais informações sobre essas primitivas de sincronização, consulte Estruturas de dados de sincronização.

As seções a seguir fornecem uma breve visão geral do que cada componente fornece e quando usá-lo.

Biblioteca de padrões paralelos

A Biblioteca de Padrões Paralelos (PPL) fornece contêineres e algoritmos de uso geral para executar paralelismo refinado. O PPL permite o paralelismo de dados imperativo , fornecendo algoritmos paralelos que distribuem cálculos em coleções ou em conjuntos de dados entre recursos de computação. Ele também permite o paralelismo de tarefas , fornecendo objetos de tarefa que distribuem várias operações independentes entre recursos de computação.

Use a Biblioteca de Padrões Paralelos quando tiver uma computação local que possa se beneficiar da execução paralela. Por exemplo, pode-se usar o algoritmo concurrency::parallel_for para transformar um loop existente for para ser executado em paralelo.

Para obter mais informações sobre a Biblioteca de Padrões Paralelos, consulte Biblioteca de Padrões Paralelos (PPL).

Biblioteca de agentes assíncronos

A Biblioteca de Agentes Assíncronos (ou apenas Biblioteca de Agentes) fornece um modelo de programação baseado em atores e interfaces de passagem de mensagens para tarefas de fluxo de dados e pipelining de grão grosso. Os agentes assíncronos permitem que você faça uso produtivo da latência executando trabalho enquanto outros componentes aguardam dados.

Use a Biblioteca de Agentes quando tiver várias entidades que se comunicam entre si de forma assíncrona. Por exemplo, você pode criar um agente que lê dados de um arquivo ou conexão de rede e, em seguida, usa as interfaces de passagem de mensagem para enviar esses dados para outro agente.

Para obter mais informações sobre a Biblioteca de agentes, consulte Biblioteca de agentes assíncronos.

Agendador de Tarefas

O Agendador de Tarefas agenda e coordena tarefas em tempo de execução. O Agendador de Tarefas é cooperativo e usa um algoritmo de roubo de trabalho para obter o máximo uso de recursos de processamento.

O Concurrency Runtime fornece um agendador padrão para que você não precise gerenciar detalhes da infraestrutura. No entanto, para atender às necessidades de qualidade do seu aplicativo, você também pode fornecer sua própria política de agendamento ou associar agendadores específicos a tarefas específicas.

Para obter mais informações sobre o Agendador de Tarefas, consulte Agendador de Tarefas.

Resource Manager

A função do Resource Manager é gerenciar recursos de computação, como processadores e memória. O Resource Manager responde às cargas de trabalho à medida que elas mudam em tempo de execução, atribuindo recursos para onde elas podem ser mais eficazes.

O Resource Manager serve como uma abstração sobre recursos de computação e interage principalmente com o Agendador de Tarefas. Embora você possa usar o Gerenciador de Recursos para ajustar o desempenho de suas bibliotecas e aplicativos, normalmente usa a funcionalidade fornecida pela Biblioteca de Padrões Paralelos, pela Biblioteca de Agentes e pelo Agendador de Tarefas. Essas bibliotecas usam o Gerenciador de Recursos para reequilibrar dinamicamente os recursos à medida que as cargas de trabalho mudam.

[Topo]

Expressões do C++ Lambda

Muitos dos tipos e algoritmos definidos pelo Concurrency Runtime são implementados como modelos C++. Alguns desses tipos e algoritmos tomam como parâmetro uma rotina que executa o trabalho. Esse parâmetro pode ser uma função lambda, um objeto de função ou um ponteiro de função. Estas entidades são também referidas como funções de trabalho ou rotinas de trabalho.

As expressões do Lambda são um novo recurso importante da linguagem Visual C++ porque fornecem uma maneira sucinta de definir funções de trabalho para processamento paralelo. Objetos de função e ponteiros de função permitem que utilize o Concurrency Runtime com o seu código existente. No entanto, recomendamos que você use expressões lambda ao escrever um novo código devido aos benefícios de segurança e produtividade que elas oferecem.

O exemplo a seguir compara a sintaxe de funções lambda, objetos de função e ponteiros de função em diversas chamadas com o algoritmo concurrency::parallel_for_each. Cada chamada para parallel_for_each usa uma técnica diferente para calcular o quadrado de cada elemento em um objeto std::array .

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

Realização

1
256
6561
65536
390625

Para obter mais informações sobre funções do lambda em C++, consulte Expressões do Lambda.

[Topo]

Requerimentos

A tabela a seguir mostra os arquivos de cabeçalho associados a cada componente do Concurrency Runtime:

Componente Arquivos de cabeçalho
Biblioteca de padrões paralelos (PPL) ppl.h

concurrent_queue.h

concurrent_vetor.h
Biblioteca de agentes assíncronos agentes.h
Agendador de Tarefas concrt.h
Resource Manager concrtrm.h

O Concurrency Runtime é declarado no namespace Concurrency . (Você também pode usar concorrência, que é um alias para esse namespace.) O concurrency::details namespace suporta a estrutura Concurrency Runtime e não se destina a ser usado diretamente no seu código.

O Concurrency Runtime é fornecido como parte da C Runtime Library (CRT). Para obter mais informações sobre como criar um aplicativo que usa o CRT, consulte Recursos da biblioteca CRT.

[Topo]