Share via


Contêiner e objetos paralelos

O paralelo padrões PPL (biblioteca) inclui vários recipientes e objetos que fornecem acesso de thread-safe para seus elementos.

A simultânea contêiner fornece acesso seguro de simultaneidade para as operações mais importantes.A funcionalidade desses recipientes parecido com aqueles que são fornecidos pelo modelo Biblioteca de STL (Standard).Por exemplo, o concurrency::concurrent_vector classe semelhante a std:: Vector classe, exceto que o concurrent_vector classe permite acrescentar elementos em paralelo.Use recipientes simultâneas quando tiver código paralelo que requer acesso de leitura e gravação ao mesmo recipiente.

A objeto simultâneo compartilhada simultaneamente entre componentes.Um processo que calcula o estado de um objeto simultâneo em paralelo produz o mesmo resultado que outro processo que calcula o mesmo estado em série.O concurrency::combinable classe é um exemplo de um tipo de objeto simultâneas.O combinable classe permite realizar cálculos em paralelo e, em seguida, combinar esses cálculos em um resultado final.Use objetos simultâneos quando você usaria um mecanismo de sincronização, por exemplo, um mutex para sincronizar o acesso a uma variável compartilhada ou recurso.

Seções

Este tópico descreve os seguintes recipientes paralelas e objetos em detalhes.

Recipientes simultâneas:

  • Classe concurrent_vector

    • Diferenças entre concurrent_vector e vetor

    • Operações com segurança de simultaneidade

    • Segurança de exceção

  • Classe concurrent_queue

    • Fila e diferenças entre concurrent_queue

    • Operações com segurança de simultaneidade

    • Suporte de iterador

  • Classe concurrent_unordered_map

    • Unordered_map e concurrent_unordered_map as diferenças entre

    • Operações com segurança de simultaneidade

  • Classe concurrent_unordered_multimap

  • Classe concurrent_unordered_set

  • Classe concurrent_unordered_multiset

Objetos simultâneos:

  • Classe podem ser combinada

    • Métodos e recursos

    • Exemplos

Classe concurrent_vector

O concurrency::concurrent_vector classe é uma classe de contêiner de seqüência que, assim como o std:: Vector classe, permite acessar seus elementos aleatoriamente.O concurrent_vector elemento e permite classe acrescentar simultaneidade seguro acessam as operações.Acrescentar operações não invalidar ponteiros existentes ou iteradores.Operações de acesso e Travessia do iterador também são seguros de simultaneidade.

Dd504906.collapse_all(pt-br,VS.110).gifDiferenças entre concurrent_vector e vetor

O concurrent_vector classe parecida com a vector classe.A complexidade de acrescentar, elemento acesso e operações de acesso de iterador em uma concurrent_vector objeto são o mesmo para uma vector objeto.Os pontos a seguir ilustram onde concurrent_vector difere do vector:

  • Acrescentar, elemento access, acesso do iterador e operações de Travessia do iterador em uma concurrent_vector objeto são seguros de simultaneidade.

  • Você pode adicionar elementos somente ao final de um concurrent_vector objeto.O concurrent_vector classe não oferece o insert método.

  • A concurrent_vector não usa o objeto move semântica quando anexado a ele.

  • O concurrent_vector classe não oferece o erase ou pop_back métodos.Como com vector, use o desmarque método para remover todos os elementos de um concurrent_vector objeto.

  • O concurrent_vector classe não armazenar seus elementos de forma contígua na memória.Portanto, você não pode usar o concurrent_vector classe de todas as maneiras que você pode usar uma matriz.Por exemplo, para uma variável chamada v do tipo concurrent_vector, a expressão &v[0]+2 produz um comportamento indefinido.

  • O concurrent_vector classe define a grow_by e grow_to_at_least métodos.Esses métodos ser semelhante a Redimensionar método, exceto que eles são seguros de simultaneidade.

  • A concurrent_vector objeto não realocar seus elementos quando você acrescentá-la ou redimensioná-la.Isso permite que os ponteiros existentes e iteradores permanecem válidos durante operações simultâneas.

  • O runtime não define uma versão especializada do concurrent_vector tipo de bool.

Dd504906.collapse_all(pt-br,VS.110).gifOperações com segurança de simultaneidade

Todos os métodos que acrescentar ou aumentam o tamanho de um concurrent_vector objeto ou acessar um elemento em um concurrent_vector de objeto, são aceitas de simultaneidade.A exceção a essa regra é o resize método.

A tabela a seguir mostra o comum concurrent_vector métodos e operadores que são seguros de simultaneidade.

em

fim

operador]

início

frontal

push_back

Voltar

grow_by

rbegin

capacidade

grow_to_at_least

rend

vazio

max_size

tamanho

Operações que o runtime fornece compatibilidade com a STL, por exemplo, reserve, não são seguras de simultaneidade.A tabela a seguir mostra os métodos e operadores que não são seguras de simultaneidade comum.

atribuir

reservar

Limpar

redimensionar

operador =

shrink_to_fit

Operações que modificar o valor de elementos existentes não são seguras de simultaneidade.Usar um objeto de sincronização, como um reader_writer_lock o objeto para sincronizar a leitura simultânea e operações de gravação para o mesmo elemento de dados.Para obter mais informações sobre objetos de sincronização, consulte Estruturas de dados de sincronização.

Quando você converter o código existente que usa vector usar concurrent_vector, operações simultâneas podem causar o comportamento do seu aplicativo para alterar.Por exemplo, considere o seguinte programa executa simultaneamente duas tarefas em um concurrent_vector objeto.A primeira tarefa acrescenta elementos adicionais para um concurrent_vector objeto.A segunda tarefa calcula a soma de todos os elementos no mesmo objeto.

// parallel-vector-sum.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_vector.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create a concurrent_vector object that contains a few
   // initial elements.
   concurrent_vector<int> v;
   v.push_back(2);
   v.push_back(3);
   v.push_back(4);

   // Perform two tasks in parallel.
   // The first task appends additional elements to the concurrent_vector object.
   // The second task computes the sum of all elements in the same object.

   parallel_invoke(
      [&v] { 
         for(int i = 0; i < 10000; ++i)
         {
            v.push_back(i);
         }
      },
      [&v] {
         combinable<int> sums;
         for(auto i = begin(v); i != end(v); ++i) 
         {
            sums.local() += *i;
         }     
         wcout << L"sum = " << sums.combine(plus<int>()) << endl;
      }
   );
}

Embora o end método é seguro de simultaneidade, uma chamada simultânea para o push_back método faz com que o valor retornado por end para alterar.O número de elementos que atravessa o iterador é indeterminado.Portanto, este programa pode produzir um resultado diferente cada vez que executá-lo.

Dd504906.collapse_all(pt-br,VS.110).gifSegurança de exceção

Se uma operação de crescimento ou atribuição lança uma exceção, o estado do concurrent_vector o objeto se torna inválido.O comportamento de um concurrent_vector objeto que está em estado inválido é indefinido, salvo indicação em contrário.No entanto, o destruidor sempre libera a memória que aloca o objeto, mesmo se o objeto está em um estado inválido.

Tipo de dados de elementos do vetor, _Ty, deve atender aos seguintes requisitos.Caso contrário, o comportamento de concurrent_vector classe é indefinido.

  • O destruidor não deve lançar.

  • Se o construtor padrão ou copiar lança, o destruidor não deve ser declarado usando a virtual palavra-chave e ele devem funcionar corretamente com memória inicializada para zero.

Top

Classe concurrent_queue

O concurrency::concurrent_queue classe, como o std::queue classe, permite acesso frontal e elementos de volta.O concurrent_queue classe permite seguro simultaneidade enqueue e dequeue operações.O concurrent_queue classe também fornece suporte de iterador não é seguro de simultaneidade.

Dd504906.collapse_all(pt-br,VS.110).gifFila e diferenças entre concurrent_queue

O concurrent_queue classe parecida com a queue classe.Os pontos a seguir ilustram onde concurrent_queue difere do queue:

  • Enqueue e dequeue operações em um concurrent_queue objeto são seguros de simultaneidade.

  • O concurrent_queue classe fornece suporte de iterador não é seguro de simultaneidade.

  • O concurrent_queue classe não oferece o front ou pop métodos.O concurrent_queue classe substitui esses métodos, definindo a try_pop método.

  • O concurrent_queue classe não oferece o back método.Portanto, você não pode referenciar o final da fila.

  • O concurrent_queue classe fornece o unsafe_size método em vez do size método.O unsafe_size o método não é seguro de simultaneidade.

Dd504906.collapse_all(pt-br,VS.110).gifOperações com segurança de simultaneidade

Todos os métodos que enfileirar para ou retirar de um concurrent_queue objeto são seguros de simultaneidade.

A tabela a seguir mostra o comum concurrent_queue métodos e operadores que são seguros de simultaneidade.

vazio

envio

get_allocator

try_pop

Embora o empty método é seguro simultaneidade, uma operação simultânea pode causar a fila aumente ou diminua antes de empty método retorna.

A tabela a seguir mostra os métodos e operadores que não são seguras de simultaneidade comum.

Limpar

unsafe_end

unsafe_begin

unsafe_size

Dd504906.collapse_all(pt-br,VS.110).gifSuporte de iterador

O concurrent_queue fornece iteradores não são seguras de simultaneidade.Recomendamos que você use esses iteradores de depuração somente.

A concurrent_queue iterador percorre os elementos na direção progressiva.A tabela a seguir mostra os operadores cada iterador oferece suporte.

Operator

Descrição

operador + +

Avança para o próximo item na fila.Este operador é sobrecarregado para fornecer a semântica pre-increment e post-increment.

operador *

Recupera uma referência para o item atual.

operador - >

Recupera um ponteiro para o item atual.

Top

Classe concurrent_unordered_map

O concurrency::concurrent_unordered_map classe é uma classe de contêiner associativa que, assim como o std::unordered_map da classe, que controla uma seqüência de comprimento variando de elementos do tipo std::pair < chave const, Ty >.Imagine um mapa desordenado como um dicionário que você pode adicionar um par de chave e valor para ou pesquisar um valor por chave.Essa classe é útil quando você tem vários threads ou tarefas que precisam acessar um recipiente compartilhado simultaneamente, inserir nele ou atualizá-lo.

O exemplo a seguir mostra a estrutura básica para o uso de concurrent_unordered_map.Este exemplo insere teclas de caracteres no intervalo ['a', ' i'].Como a ordem das operações é indeterminada, o valor final para cada chave também é indeterminado.No entanto, é seguro executar as inserções em paralelo.

// unordered-map-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_map.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain() 
{
    //
    // Insert a number of items into the map in parallel.

    concurrent_unordered_map<char, int> map; 

    parallel_for(0, 1000, [&map](int i) {
        char key = 'a' + (i%9); // Geneate a key in the range [a,i].
        int value = i;          // Set the value to i.
        map.insert(make_pair(key, value));
    });

    // Print the elements in the map.
    for_each(begin(map), end(map), [](const pair<char, int>& pr) {
        wcout << L"[" << pr.first << L", " << pr.second << L"] ";
    });
}
/* Sample output:
    [e, 751] [i, 755] [a, 756] [c, 758] [g, 753] [f, 752] [b, 757] [d, 750] [h, 754]
*/

Para obter um exemplo que usa concurrent_unordered_map para realizar um mapa e reduzir a operação em paralelo, consulte Como: executar o mapa e reduzir as operações em paralelo.

Dd504906.collapse_all(pt-br,VS.110).gifUnordered_map e concurrent_unordered_map as diferenças entre

O concurrent_unordered_map classe parecida com a unordered_map classe.Os pontos a seguir ilustram onde concurrent_unordered_map difere do unordered_map:

  • The erase, bucket, bucket_count, and bucket_size methods are named unsafe_erase, unsafe_bucket, unsafe_bucket_count, and unsafe_bucket_size, respectively.O unsafe_ convenção indica que esses métodos não são seguras de simultaneidade.Para obter mais informações sobre segurança de simultaneidade, consulte Operações com segurança de simultaneidade.

  • Operações de inserção não invalidar ponteiros existentes ou iteradores nem mudarem a ordem dos itens que já existe no mapa.Insira e desviar as operações podem ocorrer simultaneamente.

  • concurrent_unordered_mapoferece suporte a iteração somente para frente.

  • Inserção não invalidar ou atualizar os iteradores retornados por equal_range.Inserção pode acrescentar itens desiguais no final do intervalo.O iterador begin aponta para um item igual.

Para ajudar a evitar o deadlock, nenhum método de concurrent_unordered_map mantém um bloqueio quando ele chama o alocador de memória, funções de hash ou outro código definido pelo usuário.Além disso, você deve garantir que a função de hash sempre avalia chaves iguais para o mesmo valor.As melhores funções de hash distribuem chaves uniformemente entre o espaço de código de hash.

Dd504906.collapse_all(pt-br,VS.110).gifOperações com segurança de simultaneidade

O concurrent_unordered_map classe permite operações de inserção e o acesso ao elemento seguro de simultaneidade.Operações de inserção não invalidar ponteiros existentes ou iteradores.Operações de acesso e Travessia do iterador também são seguros de simultaneidade.A tabela a seguir mostra comumente usadas concurrent_unordered_map métodos e operadores que são seguros de simultaneidade.

em

count

find

key_eq

begin

empty

get_allocator

max_size

cbegin

end

hash_function

operador]

cend

equal_range

Inserir

size

Embora o count método pode ser chamado com segurança de threads em execução simultaneamente, diferentes threads podem receber resultados diferentes se um novo valor simultaneamente é inserido no recipiente.

A tabela a seguir mostra os métodos comumente usados e operadores que não são seguras de simultaneidade.

clear

max_load_factor

rehash

load_factor

operador =

troca

Com esses métodos, qualquer método começa com unsafe_ também não é seguro de simultaneidade.

Top

Classe concurrent_unordered_multimap

O concurrency::concurrent_unordered_multimap classe parecida com a concurrent_unordered_map , exceto que ele permite que vários valores mapear para a mesma chave de classe.Ele também difere do concurrent_unordered_map das seguintes maneiras:

  • O concurrent_unordered_multimap::insert método retorna um iterador em vez de std::pair<iterator, bool>.

  • O concurrent_unordered_multimap classe não oferece operator[] nem at método.

O exemplo a seguir mostra a estrutura básica para o uso de concurrent_unordered_multimap.Este exemplo insere teclas de caracteres no intervalo ['a', ' i'].concurrent_unordered_multimappermite que uma chave para ter vários valores.

// unordered-multimap-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_map.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain() 
{
    //
    // Insert a number of items into the map in parallel.

    concurrent_unordered_multimap<char, int> map; 

    parallel_for(0, 10, [&map](int i) {
        char key = 'a' + (i%9); // Geneate a key in the range [a,i].
        int value = i;          // Set the value to i.
        map.insert(make_pair(key, value));
    });

    // Print the elements in the map.
    for_each(begin(map), end(map), [](const pair<char, int>& pr) {
        wcout << L"[" << pr.first << L", " << pr.second << L"] ";
    });
}
/* Sample output:
    [e, 4] [i, 8] [a, 9] [a, 0] [c, 2] [g, 6] [f, 5] [b, 1] [d, 3] [h, 7]
*/

Top

Classe concurrent_unordered_set

O concurrency::concurrent_unordered_set classe parecida com a concurrent_unordered_map , exceto que ele gerencia valores em vez de pares de chave e valor de classe.O concurrent_unordered_set classe não oferece operator[] nem at método.

O exemplo a seguir mostra a estrutura básica para o uso de concurrent_unordered_set.Este exemplo insere valores de caractere no intervalo ['a', ' i'].É seguro executar as inserções em paralelo.

// unordered-set-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_set.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain() 
{
    //
    // Insert a number of items into the set in parallel.

    concurrent_unordered_set<char> set; 

    parallel_for(0, 10000, [&set](int i) {
        set.insert('a' + (i%9)); // Geneate a value in the range [a,i].
    });

    // Print the elements in the set.
    for_each(begin(set), end(set), [](char c) {
        wcout << L"[" << c << L"] ";
    });
}
/* Sample output:
    [e] [i] [a] [c] [g] [f] [b] [d] [h]
*/

Top

Classe concurrent_unordered_multiset

O concurrency::concurrent_unordered_multiset classe parecida com a concurrent_unordered_set de classe, exceto que ela permite valores duplicados.Ele também difere do concurrent_unordered_set das seguintes maneiras:

  • O concurrent_unordered_multiset::insert método retorna um iterador em vez de std::pair<iterator, bool>.

  • O concurrent_unordered_multiset classe não oferece operator[] nem at método.

O exemplo a seguir mostra a estrutura básica para o uso de concurrent_unordered_multiset.Este exemplo insere valores de caractere no intervalo ['a', ' i'].concurrent_unordered_multisetpermite que um valor ocorrer várias vezes.

// unordered-set-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_set.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain() 
{
    //
    // Insert a number of items into the set in parallel.

    concurrent_unordered_multiset<char> set; 

    parallel_for(0, 40, [&set](int i) {
        set.insert('a' + (i%9)); // Geneate a value in the range [a,i].
    });

    // Print the elements in the set.
    for_each(begin(set), end(set), [](char c) {
        wcout << L"[" << c << L"] ";
    });
}
/* Sample output:
    [e] [e] [e] [e] [i] [i] [i] [i] [a] [a] [a] [a] [a] [c] [c] [c] [c] [c] [g] [g]
    [g] [g] [f] [f] [f] [f] [b] [b] [b] [b] [b] [d] [d] [d] [d] [d] [h] [h] [h] [h]
*/

Top

Classe podem ser combinada

O concurrency::combinable classe fornece armazenamento reutilizável, local de thread que permite realizar cálculos precisos e mesclar esses cálculos em um resultado final.Você pode pensar um combinable o objeto como uma variável de redução.

O combinable classe é útil quando você tiver um recurso compartilhado entre vários threads ou tarefas.O combinable classe ajuda a eliminar o estado compartilhado, fornecendo acesso a recursos compartilhados de forma livre de bloqueio.Portanto, essa classe fornece uma alternativa ao uso de um mecanismo de sincronização, por exemplo, um mutex para sincronizar o acesso aos dados compartilhados de vários threads.

Dd504906.collapse_all(pt-br,VS.110).gifMétodos e recursos

A tabela a seguir mostra alguns dos métodos importantes do combinable classe.Para obter mais informações sobre todos os combinable métodos de classe, consulte classe combinável.

Método

Descrição

local

Recupera uma referência para a variável local que está associada com o contexto do thread atual.

Limpar

Remove todas as variáveis de segmento locais do combinable objeto.

combinar

combine_each

Usa a função de combinar fornecido para gerar um valor final do conjunto de todos os cálculos de segmento local.

O combinable classe é uma classe de modelo parametrizada no resultado final mesclado.Se você chamar o construtor padrão, o _Ty tipo de parâmetro de modelo deve ter um construtor padrão e um construtor de cópia.Se o _Ty tipo de parâmetro de modelo não tem um construtor padrão, chame a versão sobrecarregada do construtor que leva a uma função de inicialização como seu parâmetro.

Você pode armazenar dados adicionais em um combinable objeto depois de chamar o combinar ou combine_each métodos.Você também pode chamar o combine e combine_each métodos várias vezes.Se nenhum valor local em um combinable objeto alterações, o combine e combine_each métodos produzem o mesmo resultado sempre que são chamados.

Dd504906.collapse_all(pt-br,VS.110).gifExemplos

Para obter exemplos sobre como usar o combinable da classe, consulte os seguintes tópicos:

Top

Tópicos relacionados

Referência

concurrent_vector classe

concurrent_queue classe

concurrent_unordered_map classe

concurrent_unordered_multimap classe

concurrent_unordered_set classe

concurrent_unordered_multiset classe

classe combinável