PyPy - Como ele pode vencer o CPython?

264

No Blog de código aberto do Google :

PyPy é uma reimplementação do Python no Python, usando técnicas avançadas para tentar obter melhor desempenho do que o CPython. Muitos anos de trabalho duro finalmente foram recompensados. Nossos resultados de velocidade geralmente superam o CPython, variando de um pouco mais lento, a acelerações de até 2x no código real do aplicativo, a acelerações de até 10x em pequenos benchmarks.

Como isso é possível? Qual implementação de Python foi usada para implementar o PyPy? CPython ? E quais são as chances de um PyPyPy ou PyPyPyPy superar sua pontuação?

(Em uma nota relacionada ... por que alguém tentaria algo assim?)

Agnel Kurian
fonte
43
Nitpick: PyPy é PyPyPy. Pense no prefixo Py- * como um operador de projeção.
U0b34a0f6ae
Está bem. então PyPy deve ser preferido do que CPython? tem algum inconveniente?
22412
10
O PyPy é excelente na otimização do tempo de execução, mas suas diferentes entranhas o tornam incompatível com várias extensões C populares.
Cees Timmerman
4
Quase todo mundo está perdendo a pergunta, sobre como um ganho de velocidade é teoricamente possível. Mas pense bem: o Python pode fazer qualquer coisa, como uma máquina de Turing. gccAfinal, pode ligar . Portanto, você também pode escrever algum código python que é executado no CPython, que interpreta outro código python, o converte em C, executa gcce executa o programa compilado. E poderia ser mais rápido, se o código for chamado com bastante frequência.
Osa

Respostas:

155

Q1 Como isso é possível?

O gerenciamento manual de memória (que é o que o CPython faz com sua contagem) pode ser mais lento que o gerenciamento automático em alguns casos.

As limitações na implementação do interpretador CPython impedem certas otimizações que o PyPy pode fazer (por exemplo, bloqueios refinados).

Como Marcelo mencionou, o JIT. Ser capaz de confirmar rapidamente o tipo de um objeto pode poupar a necessidade de fazer várias desreferências de ponteiros para finalmente chegar ao método que você deseja chamar.

Q2 Qual implementação de Python foi usada para implementar o PyPy?

O interpretador PyPy é implementado no RPython, que é um subconjunto estatístico do Python (a linguagem e não o interpretador CPython). - Consulte https://pypy.readthedocs.org/en/latest/architecture.html para obter detalhes.

Q3 E quais são as chances de um PyPyPy ou PyPyPyPy superar sua pontuação?

Isso dependeria da implementação desses intérpretes hipotéticos. Se um deles, por exemplo, pegou a fonte, fez algum tipo de análise e a converteu diretamente em um código de assembly específico de destino apertado depois de executar por um tempo, imagino que seria muito mais rápido que o CPython.

Atualização: Recentemente, em um exemplo cuidadosamente criado , o PyPy superou um programa C semelhante, compilado gcc -O3. É um caso artificial, mas apresenta algumas idéias.

Q4. Por que alguém tentaria algo assim?

Do site oficial. https://pypy.readthedocs.org/en/latest/architecture.html#mission-statement

Nosso objetivo é fornecer:

  • uma estrutura comum de tradução e suporte para produzir
    implementações de linguagens dinâmicas, enfatizando uma
    separação clara entre especificação de idiomas e
    aspectos de implementação . Chamamos isso de RPython toolchain_.

  • uma implementação compatível, flexível e rápida da linguagem Python_ que usa a cadeia de ferramentas acima para permitir novos recursos avançados de alto nível sem ter que codificar os detalhes de baixo nível.

Ao separar as preocupações dessa maneira, nossa implementação do Python - e outras linguagens dinâmicas - é capaz de gerar automaticamente um compilador Just-in-Time para qualquer linguagem dinâmica. Ele também permite uma abordagem de combinação e combinação de decisões de implementação, incluindo muitas que estão fora do controle de um usuário, como plataforma de destino, modelos de memória e encadeamento, estratégias de coleta de lixo e otimizações aplicadas, incluindo a necessidade ou não de um JIT em primeiro lugar.

O compilador C gcc é implementado em C, o compilador Haskell GHC é escrito em Haskell. Você tem algum motivo para o interpretador / compilador Python não ser escrito em Python?

Noufal Ibrahim
fonte
82
Esta resposta está completamente ausente da explicação principal de como o PyPy é rápido; embora mencione que o PyPy não é realmente implementado no Python, mas no RPython, ele não indica que o código do RPython é estaticamente compilado e otimizado para produzir o interpretador PyPy (por acaso também é um código Python válido que pode ser executado no topo). do CPython muito mais lentamente). O que eles implementaram no "Python normal" é o "compilador" do RPython (a estrutura de tradução referida na citação em bloco).
Ben
12
Isso está enterrando o lede. A maior parte do desempenho vem da tradução para C (que torna o intérprete não muito mais lento que o CPython) e JIT, que torna os caminhos quentes muito mais rápidos.
Tobu
4
"Atualização: Recentemente, em um exemplo cuidadosamente criado, o PyPy superou um programa C semelhante, compilado com o gcc -O3." E se você ler o primeiro comentário abaixo dessa postagem, verá que o autor dessa postagem não conhece a otimização do tempo do link. Com a otimização do tempo do link ativada, o código C é executado mais rapidamente.
Ali
2
Bem, a postagem do blog foi em 2011 e essa resposta em 2014. Além disso, o comentário menciona bibliotecas compartilhadas. Não sei quanto disso é válido (resposta e postagem no blog). Todas as tecnologias envolvidas mudaram muito nos últimos anos.
Noufal Ibrahim
1
Nos dois exemplos cuidadosamente criados de Pypy sendo mais rápido que o equivalente C, cada um é mais rápido no benchmark por um conjunto muito específico de razões. A primeira, porque o Pypy é inteligente o suficiente para perceber que a contagem de loop apertado nunca utiliza essa contagem; portanto, ela pode ser excluída completamente (aprovação do JIT); a segunda para uma combinação de: porque o Jpy do Pypy pode "alinhar através dos limites da biblioteca", dado o exemplo da função "printf" sendo especializada para literalmente apenas conseguir emitir um número inteiro e elimina malloc repetido (sobrecarga de alocação de memória).
Amcgregor 29/05/19
291

"PyPy é uma reimplementação do Python no Python" é uma maneira bastante enganadora de descrever o PyPy, IMHO, embora seja tecnicamente verdade.

Existem duas partes principais do PyPy.

  1. A estrutura de tradução
  2. O intérprete

A estrutura de tradução é um compilador. Ele compila o código RPython até C (ou outros destinos), adicionando automaticamente aspectos como coleta de lixo e um compilador JIT. Ele não pode manipular código Python arbitrário, apenas RPython.

RPython é um subconjunto do Python normal; todo o código RPython é código Python, mas não o contrário. Não existe uma definição formal de RPython, porque o RPython é basicamente apenas "o subconjunto do Python que pode ser traduzido pela estrutura de tradução do PyPy". Mas, para ser traduzido, o código RPython precisa ser digitado estaticamente (os tipos são inferidos, você não os declara, mas ainda é estritamente um tipo por variável), e você não pode fazer coisas como declarar / modificar funções / classes em tempo de execução também.

O intérprete é então um intérprete Python normal escrito em RPython.

Como o código RPython é normal, você pode executá-lo em qualquer interpretador Python. Porém, nenhuma das reivindicações de velocidade da PyPy é executada dessa maneira; isso é apenas para um ciclo de teste rápido, porque a tradução do intérprete leva muito tempo tempo.

Com isso entendido, deve ser imediatamente óbvio que especulações sobre PyPyPy ou PyPyPyPy não fazem realmente nenhum sentido. Você tem um intérprete escrito em RPython. Você o traduz para o código C que executa o Python rapidamente. Aí o processo para; não há mais RPython para acelerar processando-o novamente.

Assim, "Como é possível que o PyPy seja mais rápido que o CPython" também se torna bastante óbvio. O PyPy tem uma implementação melhor, incluindo um compilador JIT (geralmente não é tão rápido sem o compilador JIT, acredito, o que significa que o PyPy é apenas mais rápido para programas suscetíveis à compilação JIT). O CPython nunca foi projetado para ser uma implementação altamente otimizada da linguagem Python (embora eles tentem torná-la uma implementação altamente otimizada , se você seguir a diferença).


A parte realmente inovadora do projeto PyPy é que eles não escrevem esquemas sofisticados de GC ou compiladores JIT manualmente. Eles escrevem o intérprete de maneira relativamente direta no RPython, e para todo o RPython é de nível inferior ao Python, ainda é uma linguagem de coleta de lixo orientada a objetos, muito mais alta que C. Então a estrutura de tradução adiciona automaticamente coisas como GC e JIT. Portanto, a estrutura de tradução é uma enorme, mas se aplica igualmente bem ao intérprete PyPy python, no entanto, eles mudam sua implementação, permitindo muito mais liberdade na experimentação para melhorar o desempenho (sem se preocupar em introduzir bugs do GC ou atualizar o compilador JIT para lidar com as mudanças). Isso também significa que, quando eles implementarem um interpretador Python3, obterá automaticamente os mesmos benefícios. E quaisquer outros intérpretes escritos com a estrutura PyPy (dos quais existem vários em diferentes estágios de polimento). E todos os intérpretes que usam a estrutura PyPy suportam automaticamente todas as plataformas suportadas pela estrutura.

Portanto, o verdadeiro benefício do projeto PyPy é separar (o máximo possível) todas as partes da implementação de um intérprete independente de plataforma eficiente para uma linguagem dinâmica. E, em seguida, crie uma boa implementação deles em um só lugar, que possa ser reutilizada em muitos intérpretes. Não é uma vitória imediata como "meu programa Python roda mais rápido agora", mas é uma grande perspectiva para o futuro.

E pode executar o seu programa Python mais rápido (talvez).

Ben
fonte
4
Eu não poderia seguir a diferença :(
polvoazul
37
@polvoazul A diferença entre uma implementação de linguagem otimizada e uma otimizada ? Bem, quando digo que o CPython é uma implementação bem otimizada, quero dizer que os desenvolvedores tentam fazer com que os algoritmos internos do próprio intérprete e as estruturas de dados integradas sejam executadas com eficiência. Uma implementação otimizada , a OTOH, analisaria o código do usuário final e tentaria descobrir maneiras de transformá-lo para executar com mais eficiência.
Ben
23

O PyPy é implementado no Python, mas implementa um compilador JIT para gerar código nativo em tempo real.

O motivo para implementar o PyPy em cima do Python provavelmente é que ela é simplesmente uma linguagem muito produtiva, especialmente porque o compilador JIT torna o desempenho da linguagem host um tanto irrelevante.

Marcelo Cantos
fonte
O JIT gera código Python em execução no mesmo nível que o PyPy ou gera código nativo real em execução no nível de qual implementação do Python estiver executando o PyPy?
Edmund
3
Código nativo real (veja aqui ); Código x86 de 32 bits para ser mais preciso.
Marcelo Cantos
11

PyPy é escrito em Python restrito. Ele não roda em cima do interpretador CPython, tanto quanto eu sei. Python restrito é um subconjunto da linguagem Python. AFAIK, o interpretador PyPy é compilado no código da máquina; portanto, quando instalado, ele não utiliza um interpretador python em tempo de execução.

Sua pergunta parece esperar que o interpretador PyPy esteja sendo executado em cima do CPython durante a execução do código. Edit: Sim, para usar o PyPy, você primeiro converte o código PyPy python, para C e compila com gcc, para código de jvm byte ou para .net CLI. Consulte Introdução

bobpaul
fonte
8
O PyPy será executado em cima do CPython, mas nesse modo ele não fornece os ganhos de velocidade desejados. :-) codespeak.net/pypy/dist/pypy/doc/...
Frank V