Pergunta

Então, eu só terminei de assistir esta palestra sobre o Python global Interpreter Lock (GIL) http://blip.tv/ arquivo / 2232410 .

A essência do que é que o GIL é um projeto muito bom para sistemas de núcleo único (Python essencialmente deixa o manuseio thread / programando-se para o sistema operacional). Mas que isso pode seriamente virar em sistemas multi-core e você acaba com fios intensivos IO sendo fortemente bloqueada por tópicos intensivo da CPU, a despesa de troca de contexto, o problema ctrl-C [*] e assim por diante.

Assim, uma vez que o GIL nos limita a, basicamente, executar um programa Python em uma CPU meu pensamento é por que não aceitar isso e simplesmente usar taskset no Linux para definir a afinidade do programa para um núcleo certa / cpu no sistema (especialmente em uma situação com múltiplos Python aplicativos rodando em um sistema multi-core)?

Assim, em última análise, a minha pergunta é esta: alguém já tentou usar taskset no Linux com aplicações Python (especialmente ao executar vários aplicativos em um sistema Linux para que os múltiplos núcleos podem ser usados ??com uma ou duas aplicações Python ligados a um núcleo específico) e em caso afirmativo, quais foram os resultados? é que vale a pena fazer? Faz coisas piores para determinadas cargas de trabalho? Eu pretendo fazer isso e testá-lo (basicamente ver se o programa leva mais ou menos tempo para correr), mas gostaria de ouvir de outros como às suas experiências.

A adição: David Beazley (o cara dando o que falar no vídeo vinculado) apontou que alguns C extensões / C ++ liberar manualmente o bloqueio GIL e se essas extensões são otimizados para multi-core (ou seja, análise de dados científicos ou numérica / etc .), então ao invés de receber os benefícios de multi-core para processamento de números a extensão seria efetivamente aleijado na medida em que se limita a um único núcleo (assim potencialmente retardando o seu programa para baixo significativamente). Por outro lado, se você não estiver usando extensões como este

A razão que eu não estou usando o módulo de multiprocessamento é que (neste caso) parte do programa é fortemente / S de rede ligado (HTTP pedidos) assim que ter um pool de threads de trabalho é uma ótima maneira de aperto desempenho de uma caixa desde um segmento incêndios fora de uma solicitação HTTP e, em seguida, uma vez que está à espera de I / o desiste da GIL e outro segmento pode fazê-lo de coisa, de modo que parte do programa pode facilmente executar 100+ tópicos sem ferir a CPU muito e deixe me realmente usar a largura de banda de rede que está disponível. Quanto stackless Python / etc Eu não estou muito interessado em reescrever o programa ou substituir a minha stack Python (disponibilidade também seria uma preocupação).

[*] Só o segmento principal pode receber sinais por isso, se você enviar um ctrl-C o interpretador Python, basicamente, tenta fazer com que o segmento principal para executar para que ele possa lidar com o sinal, mas uma vez que não controlam diretamente qual thread é executado (isto é deixado para o sistema operacional) que basicamente diz ao sistema operacional para manter tópicos de comutação até que finalmente atinge o segmento principal (que se você é azarado pode demorar um pouco).

Foi útil?

Solução

Eu nunca ouvi falar de alguém usando taskset para um ganho de desempenho com Python. Não significa que não pode acontecer no seu caso, mas definitivamente publicar seus resultados para que outros possam criticar seus métodos de avaliação comparativa e fornecer validação.

Pessoalmente, porém, gostaria de dissociar seu I / O tópicos dos tópicos ligados CPU usando uma fila de mensagens. Dessa forma, o front end é agora a rede I completamente / O vinculados (alguns com HTTP interface, alguns com interface de fila de mensagens) e ideal para a sua situação threading. Em seguida, a CPU intensos processos pode usar multiprocessamento ou ser apenas processos individuais à espera de trabalho para chegar na fila de mensagens.

A longo prazo, você pode também querer considerar substituindo seu rosca / O front-end I com torcida ou alguma coisa como eventlets porque, mesmo que eles não vão desempenho ajuda que deve melhorar a escalabilidade. Seu back-end é agora já escalável porque você pode executar o seu fila de mensagens através de qualquer número de máquinas + cpus conforme necessário.

Outras dicas

Outra solução é: http://docs.python.org/library/multiprocessing.html

Nota 1:. Esta é não uma limitação da linguagem Python, mas de implementação CPython

Nota 2:. Com relação à afinidade, seu sistema operacional não deve ter um problema de fazer isso em si

Uma solução interessante é o experimento relatado por Ryan Kelly em seu blog: http://www.rfk.id.au/blog/entry/a-gil-adventure-threading2/

Os resultados parece muito satisfatório.

Eu encontrei o seguinte regra de ouro suficiente ao longo dos anos: Se os trabalhadores são dependentes de algum estado compartilhado, eu uso um processo de multiprocessamento por núcleo (CPU bound), e por núcleo uma piscina correção de segmentos de trabalho (I / O ligado). O novo sistema vai cuidar de assigining os diferentes processos Python para os núcleos.

O Python GIL é por interpretador Python. Isso significa que a única para evitar problemas com que ao fazer multiprocessamento é simplesmente a partir múltiplos intérpretes (isto é, utilizando processos separados, em vez de fios para a simultaneidade) e, em seguida, utilizando algum outro IPC primitiva de comunicação entre os processos (tais como tomadas). Dito isto, a GIL não é um problema quando se utiliza fios com o bloqueio de chamadas de I / O.

O principal problema do GIL como mencionado anteriormente é que você não pode executar 2 threads diferentes código Python ao mesmo tempo. Um fio de bloqueio de um bloqueio de chamadas de I / O é bloqueada e, por conseguinte, não executin código pitão. Isso significa que ele não está bloqueando o GIL. Se você tem duas tarefas intensivas de CPU em tópicos python separado, que é onde o GIL mata multi-processamento em Python (apenas a implementação CPython, como apontado anteriormente). Porque o GIL pára CPU # 1 de executar um fio python enquanto CPU # 0 é ocupado executando o outro segmento python.

Até o momento em que a GIL é removido do Python, co-rotinas pode ser usado no lugar de threads. Eu tê-lo em boa autoridade que esta estratégia foi implementada por duas start-ups de sucesso, usando greenlets em pelo menos um caso.

Esta é uma questão bastante antiga, mas desde sempre que eu pesquisar sobre informações relacionadas com python e desempenho em sistemas multi-core este post é sempre na lista de resultados, eu não iria deixar esse passado diante de mim um não compartilhar meus pensamentos.

Você pode usar o módulo de multiprocessamento que ao invés de criar tópicos para cada tarefa, ele cria outro processo de Compier CPython interpretar seu código. Não faria sua aplicação para tirar proveito dos múltiplos núcleos sistemas. O único problema que eu vejo nessa abordagem é que você vai ter uma sobrecarga considerável, criando toda uma nova pilha de processo na memória. ( http://en.wikipedia.org/wiki/Thread_(computing)#How_threads_differ_from_processes )

Python multiprocessamento módulo: http://docs.python.org/dev/library/multiprocessing.html

"A razão que eu não estou usando o módulo de multiprocessamento é que (neste caso) parte do programa é fortemente / S de rede ligado (HTTP pedidos) assim que ter um pool de threads de trabalho é uma ótima maneira de espremer desempenho fora de uma caixa ... "

Sobre isso, eu acho que você pode ter também uma piscina de processo demasiado: http://docs.python.org/dev/library/multiprocessing.html#using-a-pool-of-workers

Att, Leo

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