Pergunta

Erlang é conhecido por poder apoiar muitos processos leves; Pode fazer isso porque não são processos no sentido tradicional, ou mesmo threads como em p-threads, mas threads inteiramente no espaço do usuário.

Isso é bom e bom (realmente fantástico). Mas como então os threads Erlang são executados em paralelo em um ambiente multicore/multiplocessador? Certamente eles precisam ser mapeados para os threads do kernel para serem executados em núcleos separados?

Supondo que seja esse o caso, como isso é feito? Muitos processos leves são mapeados para um único tópico do kernel?

Ou há outra maneira de contornar esse problema?

Foi útil?

Solução

A resposta depende da VM que é usada:

1) não-smp: Há um agendador (Thread OS), que executa todos os processos de Erlang, retirados do Pool de processos executáveis (ou seja, aqueles que não estão bloqueados por por exemplo receive)

2) Smp: Há K Agendadores (Threads OS, k é geralmente vários núcleos de CPU), que executa processos de Erlang a partir do Fila de processos compartilhados. É uma fila FIFO simples (com bloqueios para permitir acesso simultâneo de vários threads do sistema operacional).

3) SMP em R13b e mais recente: Haverá K Agendadores (como antes) que executa os processos de Erlang de várias filas de processo. Cada agendador tem sua própria fila, então processo Lógica de migração De um agendador para outro será adicionado. Esta solução melhorará o desempenho, evitando o bloqueio excessivo na fila de processos compartilhados.

Para mais informações, veja esse documento Preparado por Kenneth Lundin, Ericsson AB, para Erlang User Conference, Estocolmo, 13 de novembro de 2008.

Outras dicas

Eu quero ampliar respostas anteriores.

Erlang, ou melhor, o sistema Erlang Runtime (ERS), padrão o número de agendadores (threads) e o número de runqueues para o número de elementos de processamento em sua plataforma. Isso é núcleos de processadores ou threads de hardware. Você pode alterar essas configurações no tempo de execução usando:

erlang:system_flag(schedulers_online, NP) -> PrevNP

Os processos de Erlang ainda não têm afinidade com nenhum agendador. A lógica equilibrando os processos entre os agendadores segue duas regras. 1) Um agendador faminto roubará o trabalho de outro agendador. 2) Os caminhos de migração são configurados para empurrar processos de agendadores com muitos processos para os agendadores com menos trabalho. Isso é feito para garantir a justiça na contagem de redução (tempo de execução) para cada processo.

Os agendadores, no entanto, podem ser bloqueados em elementos de processamento específicos. Isso não é feito por padrão. Para permitir que o ERS faça o agendador-> Use de afinidade do núcleo:

erlang:system_flag(scheduler_bind_type, default_bind) -> PrevBind

Vários outros tipos de ligação podem ser encontrados na documentação. Usar a afinidade pode melhorar bastante o desempenho em situações de carga pesada! Especialmente em situações de alta disputa de bloqueio. Além disso, o kernel Linux não pode lidar com hiperthreads para dizer o mínimo. Se você possui hiperthreads em sua plataforma, deve realmente usar esse recurso em Erlang.

Estou apenas adivinhando aqui, mas imagino que há um pequeno número de threads, que escolhem processos de um pool de processos comuns para execução. Depois que um processo atinge uma operação de bloqueio, o encadeamento executando -o de lado e escolhe outro. Quando um processo que está sendo executado faz com que outro processo seja desbloqueado, esse processo recém -bloqueado é colocado no pool. Suponho que um thread também possa interromper a execução de um processo, mesmo quando não está bloqueado em determinados pontos para atender a outros processos.

Eu gostaria de adicionar alguma contribuição ao que foi descrito na resposta aceita.

O Scheduler Erlang é a parte essencial do sistema de tempo de execução do Erlang e fornece sua própria abstração e implementação da concepção de processos leves no topo dos encadeamentos do sistema operacional.

Cada agendador é executado em um único thread do sistema operacional. Normalmente, existem tantos agendadores quanto a CPU (núcleos) estão no hardware dele (é configurável e, naturalmente, não agrega muito valor quando o número de agendadores excede os dos núcleos de hardware). O sistema também pode ser configurado para que o agendador não entre entre os threads do sistema operacional.

Agora, quando o processo de Erlang está sendo criado, é inteiramente de responsabilidade do ERTS e do agendador para gerenciar o ciclo de vida e o consumo de recursos, bem como sua pegada de memória etc.

Um dos detalhes da implementação principal é que cada processo tem um orçamento de tempo de reduções de 2000 disponíveis quando o agendador retomar esse processo na fila de execução. Cada progresso no sistema (mesmo E/S) tem garantia de ter um orçamento de redução. É isso que realmente faz do ERTS um sistema com multitarefa preventiva.

Eu recomendaria um ótimo post sobre esse tópico de Jesper Louis Andersen http://jlouisramblings.blogspot.com/2013/01/how-erlang-does-scheduling.html

Como a resposta curta: os processos Erlang não são threads e não mapeiam diretamente para eles. Os agendadores de Erlang são o que é executado nos threads do sistema operacional e fornecem implementação inteligente de processos de Erlang de granulação mais finamente escondidos esses detalhes por trás dos olhos do programador.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top