Acelere o numpy, o scikit e os pandas 100 vezes com Rust e LLVM: entrevista com o desenvolvedor Weld

Olá Habr! Apresento a você a tradução do artigo "Entrevista com o principal colaborador de Weld: acelerando numpy, scikit e pandas em até 100x com Rust e LLVM" .

Depois de trabalhar por várias semanas com ferramentas de ciência de dados em Python e R, comecei a pensar se há alguma representação intermediária (IR) como CUDA que possa ser usada em diferentes idiomas. Deve haver algo melhor do que a reimplementação e otimização dos mesmos métodos em cada idioma. Além disso, seria bom ter um tempo de execução comum para otimizar todo o programa, em vez de cada função individualmente.

Após vários dias pesquisando e testando vários projetos, encontrei o Weld(você pode ler o artigo acadêmico ).

Para minha surpresa, um dos autores Weld é Matei Zaharia (Matei Zaharia), o criador do Spark.

Então, entrei em contato com Shoumik Palkar , o principal colaborador de Weld, e o entrevistei. Showmick é um estudante de graduação no Departamento de Ciência da Computação da Universidade de Stanford, onde seguiu os conselhos de Matey Zakharia.

A solda ainda não está pronta para uso industrial, mas é muito promissora. Se você está interessado no futuro da ciência de dados e do Rust em particular, vai adorar esta entrevista.

Anúncio do autor do artigo original
image
«Not a Monad Tutorial», Weld . !

, mail@fcarrone.com @unbalancedparen.

Para que foi projetado o Weld, para quais problemas ele resolve?


O objetivo da Weld é aumentar a produtividade de aplicativos que usam APIs de alto nível, como NumPy e Pandas. O principal problema que ele resolve são as otimizações interfuncionais e entre bibliotecas que não são fornecidas por outras bibliotecas atualmente. Em particular, muitas bibliotecas amplamente usadas têm implementações modernas de algoritmos para funções individuais (por exemplo, o algoritmo de junção rápida implementado no Pandas por C ou a multiplicação rápida de matrizes no NumPy), mas não oferecem a possibilidade de otimizar a combinação dessas funções. Por exemplo, impedindo varreduras desnecessárias de memória ao executar a multiplicação de matrizes seguida pela agregação.

O Weld fornece um ambiente de tempo de execução comum que permite que as bibliotecas expressem cálculos em uma representação intermediária comum (IR). Esse IR pode ser otimizado usando o otimizador de compilador e compilado em tempo real (JIT) em código de máquina paralelo com otimizações como mesclagem de loop, vetorização etc. O RI da Weld é inicialmente paralelo; portanto, os programas nele expressos sempre podem ser trivialmente paralelos.

Também temos um novo projeto chamado anotações Split, que será integrado ao Weld e projetado para reduzir a barreira à inclusão de tais otimizações nas bibliotecas existentes.

Não seria mais fácil otimizar numpy, pandas e scikit? Quão rápido é?


O Weld fornece uma otimização da combinação de funções nessas bibliotecas, enquanto a otimização das bibliotecas pode acelerar as chamadas de apenas funções individuais. De fato, muitas dessas bibliotecas já estão muito bem otimizadas para cada função individual, mas fornecem desempenho abaixo dos limites dos equipamentos modernos, porque não usam paralelismo ou não usam a hierarquia de memória com eficiência.

Por exemplo, muitas funções do NumPy para matrizes multidimensionais (ndarray) são implementadas no idioma C de baixo nível, mas uma chamada para cada função requer uma varredura completa dos dados de entrada. Se essas matrizes não couberem nos caches da CPU, a maior parte do tempo de execução poderá ser gasta carregando dados da memória principal, em vez de executar cálculos. O Weld pode visualizar chamadas de funções individuais e executar otimizações, como combinar loops que armazenam dados em caches ou registros de CPU. Essas otimizações podem melhorar o desempenho em mais de uma ordem de magnitude em sistemas com vários núcleos, uma vez que oferecem melhor escalabilidade.

imagem

As integrações dos protótipos do Weld com Spark (canto superior esquerdo), NumPy (canto superior direito) e TensorFlow (canto inferior esquerdo) mostram uma melhoria de até 30 vezes em relação às implementações de sua própria infraestrutura, sem alterar o código do aplicativo do usuário. A otimização entre bibliotecas de Pandas e NumPy (canto inferior direito) pode melhorar o desempenho em duas ordens de magnitude.

O que é o Baloo?


O Baloo é uma biblioteca que implementa um subconjunto da API do Pandas usando o Weld. Foi desenvolvido por Radu Jica, um mestre em CWI (Centrum Wiskunde & Informatica, Amsterdã). O objetivo do Baloo é aplicar os tipos de otimização acima ao Pandas para melhorar o desempenho de thread único, reduzir o uso de memória e garantir a simultaneidade.

O Weld / Baloo suporta operações externas (como, por exemplo, o Dask) para processar dados que não cabem na memória?


Atualmente, Weld e Baloo não suportam operações externas (fora do núcleo, memória externa), embora tenhamos o maior prazer em receber desenvolvimento de código-fonte aberto nessa direção!

Por que você escolheu Rust e LLVM para implementar o Weld? Você veio para Rust imediatamente?


Escolhemos Rust porque:

  • Ele tem um tempo de execução mínimo (na verdade, simplesmente verifica os limites das matrizes) e é fácil de incorporar em outras linguagens como Java e Python.
  • Ele contém paradigmas de programação funcional, como correspondência de padrões, que facilitam a escrita de código, por exemplo, para otimizar o compilador de correspondência de padrões.
  • ( Rust crates), .

Escolhemos o LLVM porque é uma estrutura de compilação de código aberto amplamente usada e suportada. Como geramos LLVM diretamente em vez de C / C ++, não precisamos do compilador C. Ele também reduz o tempo de compilação, pois não analisamos o código C / C ++.

Rust não era o primeiro idioma em que o Weld foi implementado. A primeira implementação foi no Scala, que foi escolhido devido aos seus tipos de dados algébricos e à presença de um recurso tão poderoso como a correspondência de padrões. Isso simplificou a gravação do otimizador, que é a parte principal do compilador. Nosso otimizador original foi criado como o Catalyst, um otimizador extensível no Spark SQL.

Nós nos afastamos do Scala porque era muito difícil incorporar o idioma baseado na JVM em outros tempos de execução e idiomas.

Weld CPU GPU, RAPIDS, data science Python GPU?


A principal diferença entre o Weld e sistemas como o RAPIDS é que ele visa otimizar aplicativos que contêm kernels diferentes (funções nos termos da CUDA), compilando em tempo real, e não otimizando implementações de funções individuais. Por exemplo, o back-end do Weld GPU compilará um único núcleo CUDA otimizado para o aplicativo final, em vez de chamar kernels separados.

Além disso, o Weld IR é independente de hardware, o que permite que seja usado tanto para a GPU quanto para a CPU, além de equipamentos não padrão, como processadores vetoriais.
Obviamente, o Weld se cruza com outros projetos no mesmo campo, incluindo o RAPIDS, e é criado sob sua influência.

Ambientes de tempo de execução como Bohrium (implementa computação lenta no NumPy) e Numba (biblioteca Python, compilador de código JIT) compartilham os objetivos de alto nível do Weld. E sistemas otimizadores como o Spark SQL influenciam diretamente o design do Weld.

O Weld tem outros usos além das otimizações da biblioteca de ciência de dados?


Um dos aspectos mais interessantes do IR de solda é o suporte nativo à simultaneidade de dados. Isso significa que a paralelização de loop no IR de solda é sempre segura. Isso torna o Weld IR atraente para novos tipos de equipamentos.

Por exemplo, os funcionários da NEC usaram o Weld para executar cargas de trabalho Python em um processador vetorial personalizado de alta largura de banda, simplesmente adicionando um novo back-end a um Weld IR existente.

O IR também pode ser usado para implementar uma camada de operações físicas em um banco de dados. E planejamos adicionar recursos que também nos permitirão compilar um subconjunto do Python no código do Weld.

As bibliotecas estão prontas para uso em projetos reais? E se não, quando você pode esperar um resultado final?


Muitos dos exemplos e benchmarks nos quais testamos essas bibliotecas são extraídos da carga de trabalho real. Portanto, gostaríamos realmente que os usuários experimentassem a versão atual em seus aplicativos e deixassem seus comentários. E, o melhor de tudo, eles propuseram seus próprios patches.

Em geral, no momento não se pode dizer que, em aplicações reais, tudo funcione imediatamente.

Nossos próximos lançamentos nos próximos meses se concentrarão exclusivamente na usabilidade e confiabilidade das bibliotecas Python. Nosso objetivo é tornar as bibliotecas boas o suficiente para serem incluídas em projetos reais. E também a capacidade de usar versões de bibliotecas que não são do Weld em locais onde o suporte ainda não foi adicionado.

Como observei na primeira pergunta, o projeto de anotações Split ( código fonte e artigo acadêmico ) deve simplificar essa transição.

Dividir anotações é um sistema que permite adicionar anotações ao código existente para determinar como dividir, transformar e paralelizar. Ele fornece a otimização que consideramos mais eficaz no Weld (armazenamento de pedaços de dados nos caches da CPU entre chamadas de função, em vez de varrer todo o conjunto de dados). Porém, as anotações de divisão são muito mais fáceis de integrar do que o Weld, porque elas usam o código de biblioteca existente sem depender do compilador de IR. Ele também facilita a manutenção e a depuração, o que melhora a confiabilidade.

As bibliotecas que ainda não possuem suporte completo ao Weld podem usar anotações Split. Isso nos permitirá adicionar gradualmente o suporte ao Weld com base no feedback do usuário, incorporando novas otimizações.

All Articles