Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Alguns loop paralelos não exigem que todos os iterações foram executadas.Por exemplo, um algoritmo que procura por um valor pode finalizar depois que o valor for encontrado.OpenMP não fornece um mecanismo para quebrar de um loop paralelo.No entanto, você pode usar um valor Booleano, ou o sinalizador, para ativar uma iteração do loop para indicar que a solução esteve encontrada.O tempo de execução de simultaneidade fornece funcionalidade que permite uma tarefa cancelar outras tarefas que ainda não seguir o iniciarão.
Este exemplo mostra como converter um loop de OpenMP paralelapara que não requer que todas as iterações executem para usar o mecanismo de cancelamento de tempo de execução de simultaneidade.
Exemplo
Este exemplo usa OpenMP e o tempo de execução de simultaneidade para implementar uma versão paralela do algoritmo de std::any_of .A versão de OpenMP este exemplo usa um sinalizador para coordenar entre todas as iterações paralelas do loop que a condição esteve satisfeita.A versão que usa o tempo de execução de simultaneidade usa o método de concurrency::structured_task_group::cancel para interromper a operação total quando a condição seja satisfeita.
// concrt-omp-parallel-any-of.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <array>
#include <random>
#include <iostream>
using namespace concurrency;
using namespace std;
// Uses OpenMP to determine whether a condition exists in
// the specified range of elements.
template <class InIt, class Predicate>
bool omp_parallel_any_of(InIt first, InIt last, const Predicate& pr)
{
typedef typename std::iterator_traits<InIt>::value_type item_type;
// A flag that indicates that the condition exists.
bool found = false;
#pragma omp parallel for
for (int i = 0; i < static_cast<int>(last-first); ++i)
{
if (!found)
{
item_type& cur = *(first + i);
// If the element satisfies the condition, set the flag to
// cancel the operation.
if (pr(cur)) {
found = true;
}
}
}
return found;
}
// Uses the Concurrency Runtime to determine whether a condition exists in
// the specified range of elements.
template <class InIt, class Predicate>
bool concrt_parallel_any_of(InIt first, InIt last, const Predicate& pr)
{
typedef typename std::iterator_traits<InIt>::value_type item_type;
structured_task_group tasks;
// Create a predicate function that cancels the task group when
// an element satisfies the condition.
auto for_each_predicate = [&pr, &tasks](const item_type& cur) {
if (pr(cur)) {
tasks.cancel();
}
};
// Create a task that calls the predicate function in parallel on each
// element in the range.
auto task = make_task([&]() {
parallel_for_each(first, last, for_each_predicate);
});
// The condition is satisfied if the task group is in the cancelled state.
return tasks.run_and_wait(task) == canceled;
}
int wmain()
{
// The length of the array.
const size_t size = 100000;
// Create an array and initialize it with random values.
array<int, size> a;
generate(begin(a), end(a), mt19937(42));
// Search for a value in the array by using OpenMP and the Concurrency Runtime.
const int what = 9114046;
auto predicate = [what](int n) -> bool {
return (n == what);
};
wcout << L"Using OpenMP..." << endl;
if (omp_parallel_any_of(begin(a), end(a), predicate))
{
wcout << what << L" is in the array." << endl;
}
else
{
wcout << what << L" is not in the array." << endl;
}
wcout << L"Using the Concurrency Runtime..." << endl;
if (concrt_parallel_any_of(begin(a), end(a), predicate))
{
wcout << what << L" is in the array." << endl;
}
else
{
wcout << what << L" is not in the array." << endl;
}
}
O exemplo produz a seguinte saída.
Na versão do que usa OpenMP, todas as iterações do loop executam, mesmo quando o sinalizador é definido.Além disso, se uma tarefa não ter quaisquer tarefas filhos, o parâmetro também precisará estar disponível 2 essas tarefas filhos comunicar cancelamento.Em tempo de execução de concorrência, quando um grupo de trabalho é cancelado, o tempo de execução cancela a árvore inteira de trabalho, incluindo tarefas filhos.As tarefas dos usos do algoritmo de concurrency::parallel_for_each realizar trabalho.Como consequência, quando uma iteração do loop cancela a tarefa de raiz, toda a árvore de computação também é cancelada.Quando uma árvore de trabalho é cancelado, o tempo de execução não começa novas tarefas.No entanto, o tempo de execução permite as tarefas que já têm introdução para concluir.Como consequência, no caso do algoritmo de parallel_for_each , as iterações ativos do loop podem limpar os recursos.
Em ambas as versões deste exemplo, se a matriz contém mais de uma cópia do valor para procurar por, várias iterações do loop podem acessar cada definem simultaneamente o resultado e cancelarem a operação total.Você pode usar uma primitiva de sincronização, como uma seção crítica, se seu problema que requer apenas uma tarefa o trabalho é executado quando uma condição seja satisfeita.
Você também pode usar tratamento de exceções para cancelar as tarefas que usam o PPL.Para obter mais informações sobre o botão, consulte Cancelar o PPL.
Para obter mais informações sobre parallel_for_each e outros algoritmos paralelos, consulte Algoritmos paralelos.
Compilando o código
Copie o código de exemplo e cole-o em um projeto do Visual Studio, ou cole em um arquivo denominado concrt-omp-parallel-any-of.cpp e execute o seguinte comando em uma janela de prompt de comando do Visual Studio.
cl.exe /EHsc /openmp concrt-omp-parallel-any-of.cpp