Comparando o Runtime de Simultaneidade com outros modelos de simultaneidade

Este documento descreve as diferenças entre os recursos e os modelos de programação do Runtime de Simultaneidade e outras tecnologias. Ao entender como os benefícios do Runtime de Simultaneidade se comparam aos benefícios de outros modelos de programação, você pode selecionar a tecnologia que melhor atende aos requisitos de seus aplicativos.

Se você estiver usando outro modelo de programação, como o pool de threads do Windows ou o OpenMP, há situações em que pode ser apropriado migrar para o Runtime de Simultaneidade. Por exemplo, o tópico Migrando do OpenMP para o Runtime de Simultaneidade descreve quando pode ser apropriado migrar do OpenMP para o Runtime de Simultaneidade. No entanto, se você estiver satisfeito com o desempenho do aplicativo e o suporte à depuração atual, a migração não será necessária.

Use os recursos e os benefícios de produtividade do Runtime de Simultaneidade para complementar seu aplicativo existente que usa outro modelo de simultaneidade. O Runtime de Simultaneidade não pode garantir o balanceamento de carga quando vários agendadores de tarefas competem pelos mesmos recursos de computação. No entanto, quando as cargas de trabalho não se sobrepõem, esse efeito é mínimo.

Seções

Comparando agendamento preemptivo o com agendamento cooperativo

O modelo preemptivo e os modelos de agendamento cooperativo são duas maneiras comuns de habilitar várias tarefas para compartilhar recursos de computação, por exemplo, processadores ou threads de hardware.

Agendamento Preemptivo e Cooperativo

O agendamento preemptivo é um mecanismo baseado em prioridade que fornece a cada tarefa acesso exclusivo a um recurso de computação por um determinado período de tempo e, em seguida, alterna para outra tarefa. O agendamento preemptivo é comum em sistemas operacionais multitarefa, como o Windows. O agendamento cooperativo é um mecanismo que fornece a cada tarefa acesso exclusivo a um recurso de computação até que a tarefa seja concluída ou até que a tarefa gere seu acesso ao recurso. O Runtime de Simultaneidade usa o agendamento cooperativo em conjunto com o agendador preemptivo do sistema operacional para obter o uso máximo de recursos de processamento.

Diferenças entre Agendadores Preemptivo e Cooperativo

Agendadores preemptivos buscam dar a vários threads acesso igual aos recursos de computação para garantir que cada thread progrida. Em computadores que têm muitos recursos de computação, garantir o acesso justo torna-se menos problemático, no entanto, garantir a utilização eficiente dos recursos torna-se mais problemático.

Um agendador preemptivo de modo kernel requer que o código do aplicativo confie no sistema operacional para tomar decisões de agendamento. Por outro lado, um agendador cooperativo do modo de usuário permite que o código do aplicativo tome suas próprias decisões de agendamento. Como o agendamento cooperativo permite que muitas decisões de agendamento sejam tomadas pelo aplicativo, isso reduz grande parte da sobrecarga associada à sincronização do modo kernel. Um agendador cooperativo normalmente adia as decisões de agendamento para o kernel do sistema operacional quando não tem nenhum outro trabalho a ser agendado. Um agendador cooperativo também adia para o agendador do sistema operacional quando há uma operação de bloqueio que é comunicada ao kernel, mas essa operação não é comunicada ao agendador do modo de usuário.

Agendamento cooperativo e eficiência

Para um agendador preemptivo, todo o trabalho que tem o mesmo nível de prioridade é igual. Um agendador preemptivo normalmente agenda threads na ordem em que eles são criados. Além disso, um agendador preemptivo fornece a cada thread uma fatia de tempo de maneira round-robin, com base na prioridade do thread. Embora esse mecanismo forneça imparcialidade (cada thread avança), ele tem algum custo de eficiência. Por exemplo, muitos algoritmos com uso intensivo de computação não exigem imparcialidade. Em vez disso, é importante que as tarefas relacionadas sejam concluídas no menor tempo geral. O agendamento cooperativo permite que um aplicativo agende trabalho com mais eficiência. Por exemplo, considere um aplicativo que tem muitos threads. Agendar threads que não compartilham recursos para serem executados simultaneamente pode reduzir a sobrecarga de sincronização e, assim, aumentar a eficiência. Outra maneira eficiente de agendar tarefas é executar pipelines de tarefas (em que cada tarefa atua na saída da anterior) no mesmo processador para que a entrada de cada estágio de pipeline já seja carregada no cache de memória.

Usando o agendamento preemptivo e cooperativo juntos

O agendamento cooperativo não resolve todos os problemas de agendamento. Por exemplo, tarefas que não se rendem de forma justa a outras tarefas podem consumir todos os recursos de computação disponíveis e impedir que outras tarefas progridam. O Runtime de Simultaneidade usa os benefícios de eficiência do agendamento cooperativo para complementar as garantias de imparcialidade do agendamento preemptivo. Por padrão, o Runtime de Simultaneidade fornece um agendador cooperativo que usa um algoritmo de roubo de trabalho para distribuir com eficiência o trabalho entre os recursos de computação. No entanto, o agendador de Runtime de Simultaneidade também depende do agendador preemptivo do sistema operacional para distribuir recursos de forma justa entre os aplicativos. Você também pode criar agendadores personalizados e políticas de agendador em seus aplicativos para produzir um controle refinado sobre a execução de thread.

[Parte superior]

Comparando o Runtime de Simultaneidade com a API do Windows

A interface de programação de aplicativos do Microsoft Windows, que normalmente é conhecida como a API do Windows (e anteriormente conhecida como Win32), fornece um modelo de programação que permite simultaneidade em seus aplicativos. O Runtime de Simultaneidade baseia-se na API do Windows para fornecer modelos de programação adicionais que não estão disponíveis no sistema operacional subjacente.

O Runtime de Simultaneidade se baseia no modelo de thread da API do Windows para executar um trabalho paralelo. Ele também usa o gerenciamento de memória da API do Windows e os mecanismos de armazenamento local de thread. No Windows 7 e no Windows Server 2008 R2, ele usa o suporte à API do Windows para threads e computadores programáveis pelo usuário que têm mais de 64 threads de hardware. O Runtime de Simultaneidade estende o modelo de API do Windows fornecendo um agendador de tarefas cooperativo e um algoritmo de roubo de trabalho para maximizar o uso de recursos de computação e habilitando várias instâncias do agendador simultâneas.

Linguagens de programação

A API do Windows usa a linguagem de programação C para expor o modelo de programação. O Runtime de Simultaneidade fornece uma interface de programação C++ que aproveita os recursos mais recentes na linguagem C++. Por exemplo, as funções lambda fornecem um mecanismo sucinto e seguro de tipo para definir funções de trabalho paralelas. Para obter mais informações sobre os recursos mais recentes do C++ que o Runtime de Simultaneidade usa, consulte Visão geral.

Threads e Pools de Threads

O mecanismo de simultaneidade central na API do Windows é o thread. Normalmente, você usa a função CreateThread para criar threads. Embora os threads sejam relativamente fáceis de criar e usar, o sistema operacional aloca uma quantidade significativa de tempo e outros recursos para gerenciá-los. Além disso, embora cada thread tenha a garantia de receber o mesmo tempo de execução que qualquer outro thread no mesmo nível de prioridade, a sobrecarga associada requer que você crie tarefas suficientemente grandes. Para tarefas menores ou mais refinadas, a sobrecarga associada à simultaneidade pode superar o benefício de executar as tarefas em paralelo.

Os pools de threads são uma maneira de reduzir o custo do gerenciamento de threads. Pools de thread personalizados e a implementação do pool de threads fornecida pela API do Windows permitem que pequenos itens de trabalho sejam executados com eficiência em paralelo. O pool de threads do Windows mantém itens de trabalho em uma fila FIFO (primeiro a entrar e sair). Cada item de trabalho é iniciado na ordem em que foi adicionado ao pool.

O Runtime de Simultaneidade implementa um algoritmo de roubo de trabalho para estender o mecanismo de agendamento FIFO. O algoritmo move tarefas que ainda não começaram a threads que ficam sem itens de trabalho. Embora o algoritmo de roubo de trabalho possa equilibrar cargas de trabalho, ele também pode fazer com que os itens de trabalho sejam reordenados. Esse processo de reordenação pode fazer com que um item de trabalho seja iniciado em uma ordem diferente do que foi enviado. Isso é útil com algoritmos recursivos, em que há mais chances de que os dados sejam compartilhados entre tarefas mais recentes do que entre as mais antigas. Obter os novos itens a serem executados primeiro significa menos erros de cache e, possivelmente, menos falhas de página.

Do ponto de vista do sistema operacional, o roubo de trabalho é injusto. No entanto, quando um aplicativo implementa um algoritmo ou tarefa a ser executado em paralelo, a imparcialidade entre as subtarefas nem sempre importa. O que importa é a rapidez com que a tarefa geral é concluída. Para outros algoritmos, FIFO é a estratégia de agendamento apropriada.

Comportamento em vários sistemas operacionais

No Windows XP e no Windows Vista, os aplicativos que usam o Runtime de Simultaneidade se comportam de forma semelhante, exceto que o desempenho do heap é aprimorado no Windows Vista.

No Windows 7 e no Windows Server 2008 R2, o sistema operacional dá suporte à simultaneidade e escalabilidade. Por exemplo, esses sistemas operacionais dão suporte aos computadores com mais de 64 threads de hardware. Um aplicativo existente que usa a API do Windows deve ser modificado para aproveitar esses novos recursos. No entanto, um aplicativo que usa o Runtime de Simultaneidade usa automaticamente esses recursos e não requer modificações.

base.user-mode_scheduling

[Parte superior]

Comparando o Runtime de Simultaneidade com o OpenMP

O Runtime de Simultaneidade habilita uma variedade de modelos de programação. Esses modelos podem se sobrepor ou complementar os modelos de outras bibliotecas. Esta seção compara o Runtime de Simultaneidade ao OpenMP.

O modelo de programação OpenMP é definido por um padrão aberto e tem associações bem definidas para as linguagens de programação Fortran e C/C++. As versões 2.0 e 2.5 do OpenMP, são adequadas para algoritmos paralelos que são iterativos, ou seja, executam iteração paralela em uma matriz de dados. O OpenMP é mais eficiente quando o grau de paralelismo é predeterminado e corresponde aos recursos disponíveis no sistema. O modelo OpenMP é uma correspondência especialmente boa para computação de alto desempenho, em que problemas computacionais muito grandes são distribuídos entre os recursos de processamento de um único computador. Nesse cenário, o ambiente de hardware é conhecido e o desenvolvedor pode razoavelmente esperar ter acesso exclusivo aos recursos de computação quando o algoritmo é executado.

No entanto, outros ambientes de computação menos restritos podem não ser uma boa correspondência para o OpenMP. Por exemplo, problemas recursivos (como o algoritmo quicksort ou a pesquisa de uma árvore de dados) são mais difíceis de implementar usando o OpenMP. O Runtime de Simultaneidade complementa os recursos do OpenMP fornecendo a PPL (Biblioteca Paralela de Padrões) e a Biblioteca de Agentes Assíncronos. Ao contrário do OpenMP, o Runtime de Simultaneidade fornece um agendador dinâmico que se adapta aos recursos disponíveis e ajusta o grau de paralelismo à medida que as cargas de trabalho são alteradas.

Muitos dos recursos no Runtime de Simultaneidade podem ser estendidos. Você também pode combinar recursos existentes para compor novos. Como o OpenMP depende de diretivas do compilador, ele não pode ser estendido facilmente.

Para obter mais informações sobre como o Runtime de Simultaneidade se compara ao OpenMP e como migrar o código OpenMP existente para usar o Runtime de Simultaneidade, consulte Migrando do OpenMP para o Runtime de Simultaneidade.

[Parte superior]

Confira também

Runtime de Simultaneidade
Visão geral
Biblioteca de padrões paralelos (PPL)
Biblioteca de agentes assíncronos
OpenMP