1 pontos por GN⁺ 2024-05-18 | 1 comentários | Compartilhar no WhatsApp
  • Bend é uma linguagem de programação de alto nível que oferece suporte a processamento massivamente paralelo
  • Ao contrário de alternativas de baixo nível como CUDA e Metal, Bend oferece a sensação e os recursos de linguagens expressivas como Python e Haskell
  • Inclui alocação rápida de objetos, funções de ordem superior com suporte completo a closures, recursão sem restrições e até continuações
  • Ainda assim, roda em hardware massivamente paralelo como GPUs, mostrando ganhos de velocidade quase lineares de acordo com o número de núcleos
  • Nenhuma anotação explícita de paralelismo é necessária: não é preciso criação de threads, locks, mutexes ou operações atômicas
  • Bend é impulsionada pelo runtime HVM2

Demonstração rápida

Usando Bend

No momento, não funciona no Windows; é preciso usar WSL2 como alternativa.

  • Primeiro, é preciso instalar o Rust nightly.
  • Em seguida, é preciso instalar HVM2 e Bend:
    cargo +nightly install hvm  
    cargo +nightly install bend-lang  
    
  • Por fim, você pode escrever um arquivo Bend e executá-lo com um dos seguintes comandos:
    bend run   # usa o interpretador Rust (sequencial)  
    bend run-c  # usa o interpretador C (paralelo)  
    bend run-cu  # usa o interpretador CUDA (massivamente paralelo)  
    
  • Você também pode compilar Bend em arquivos C/CUDA independentes usando gen-c e gen-cu para obter desempenho máximo. No entanto, a geração de código ainda está em estágio inicial e não é tão madura quanto compiladores de ponta como GCC ou GHC.

Programação paralela em Bend

  • Para escrever programas paralelos em Bend... não é preciso fazer nada. Basta escrevê-los de forma que não sejam inerentemente sequenciais.
  • Por exemplo, a expressão abaixo não pode ser executada em paralelo:
    (((1 + 2) + 3) + 4)  
    
    porque +4 depende de +3, e +3 depende de (1+2).
  • Já a expressão abaixo pode ser executada em paralelo:
    ((1 + 2) + (3 + 4))  
    
    porque (1+2) e (3+4) são independentes. De acordo com o princípio básico de Bend, tudo o que pode ser executado em paralelo será executado em paralelo.

Código de exemplo

  • Como exemplo mais completo, considere o código abaixo:

    # rede de ordenação = rotações de árvore  
    def sort(d, s, tree):  
      switch d:  
        case 0:  
          return tree  
        case _:  
          (x, y) = tree  
          lft = sort(d-1, 0, x)  
          rgt = sort(d-1, 1, y)  
          return rots(d, s, lft, rgt)  
    
    # rotações de subárvore  
    def rots(d, s, tree):  
      switch d:  
        case 0:  
          return tree  
        case _:  
          (x, y) = tree  
          return down(d, s, warp(d-1, s, x, y))  
    
  • Esse arquivo implementa um bitonic sorter usando rotações de árvore imutáveis. Não é um algoritmo que se esperaria que rodasse rapidamente em GPUs. No entanto, como usa uma abordagem de divisão e conquista, ele é inerentemente paralelo. Bend o executa com multithreading. Alguns benchmarks:

    • CPU, Apple M3 Max, 1 thread: 12.15 segundos
    • CPU, Apple M3 Max, 16 threads: 0.96 segundos
    • GPU, NVIDIA RTX 4090, 16k threads: 0.21 segundos
    • 57x de ganho de velocidade sem fazer nada. Não há gerenciamento explícito de criação de threads, locks ou mutexes. Apenas foi pedido ao Bend que executasse o programa na RTX.

Suporte a diversos sistemas paralelos

  • Bend não se limita a paradigmas específicos como tensores ou matrizes. É possível emular em Bend todo tipo de sistema paralelo, de shaders ao modelo de atores ao estilo Erlang.

  • Por exemplo, para renderizar imagens em tempo real, é possível alocar árvores imutáveis para cada frame:

    # dado um shader, retorna uma imagem quadrada  
    def render(depth, shader):  
      bend d = 0, i = 0:  
        when d < depth:  
          color = (fork(d+1, i*2+0), fork(d+1, i*2+1))  
        else:  
          width = depth / 2  
          color = shader(i % width, i / width)  
      return color  
    
    # dada uma posição, retorna uma cor  
    # nesta demo, apenas roda um loop ocupado  
    def demo_shader(x, y):  
      bend i = 0:  
        when i < 5000:  
          color = fork(i + 1)  
        else:  
          color = 0x000001  
      return color  
    
    # renderiza uma imagem 256x256 usando demo_shader  
    def main:  
      return render(16, demo_shader)  
    
  • E isso realmente funciona. Até algoritmos complexos são bem paralelizados em Bend. A comunicação de longa distância é feita por redução beta global (de acordo com o cálculo de interações) e sincronizada de forma correta e eficiente pelo linker atômico do HVM2.

Materiais adicionais

  • Para começar imediatamente, confira o GUIDE.md do Bend.
  • Para ver a lista de recursos, confira o FEATURES.md.
  • Para entender a tecnologia do Bend, confira o artigo do HVM2.
  • Bend é desenvolvido pela HigherOrderCO.com - entre no Discord.

Opinião do GN⁺

  • Simplificação da programação paralela: Bend simplifica muito a programação paralela, permitindo que até engenheiros de software iniciantes tenham acesso fácil. Isso reduz bastante a barreira de entrada para programação paralela.
  • Suporte a diferentes hardwares: Bend pode rodar com eficiência não só em CPUs, mas também em GPUs, o que permite seu uso em diversos ambientes de hardware.
  • Linguagem expressiva: Ao combinar as vantagens de Python e Haskell, é possível escrever código expressivo. Isso melhora a legibilidade e a manutenção do código.
  • Geração de código em estágio inicial: Atualmente, a geração de código do Bend ainda está em estágio inicial, então seu desempenho pode ficar abaixo do de compiladores maduros. Isso ainda precisa evoluir no futuro.
  • Suporte a diversos sistemas paralelos: Bend não se limita a um paradigma específico e dá suporte a vários sistemas paralelos, permitindo programação flexível. Isso possibilita o uso do Bend em várias áreas de aplicação.

1 comentários

 
GN⁺ 2024-05-18
Comentários do Hacker News

Resumo da coletânea de comentários do Hacker News

  • Comparação de desempenho entre Python e PyPy

    • Ao executar o mesmo código em Python e PyPy, o PyPy foi muito mais rápido.
    • Compartilhamento de resultados de benchmark no Apple M3 Max e na NVIDIA RTX 4090.
    • O desempenho no Intel i7-1270P foi muito lento.
    • É necessário testar também em outras plataformas além de Mac.
  • Feedback positivo

    • Considerando que o projeto está em estágio inicial, elogiam os resultados.
    • Em comparação com o Futhark, é uma pena que não ofereça suporte a vários targets.
    • Os problemas de desempenho parecem ser solucionáveis.
  • Opiniões críticas

    • Mesmo sendo uma versão inicial, está recebendo muitas críticas.
    • O site é intuitivo e fácil de entender.
    • Mencionam a diferença entre a expectativa e a realidade em relação aos algoritmos paralelos.
  • Expectativas sobre programação paralela

    • Expressam expectativa em relação ao futuro da programação paralela.
    • Compartilham experiências de experimentação com programação paralela por meio de Rust e Shadertoy.
    • Há expectativa por uma linguagem paralela de uso geral que aproveite GPU.
  • Comparação de desempenho

    • Um loop simples escrito em C++ mostra desempenho semelhante ao do Bend.
    • Código C++ otimizado é muito mais rápido.
  • Expectativa pelo avanço do projeto

    • Elogiam o fato de ter superado a dificuldade da paralelização automática.
    • Demonstram expectativa pelo desenvolvimento do projeto.
  • Visão cética

    • Apontam as características de DSL limitada do Bend.
    • Enfatizam que o desempenho não é bom.
    • Mencionam que arrays são importantes na computação paralela real de alto desempenho.
    • Mostram ceticismo quanto à utilidade do Bend.
  • Perspectiva positiva

    • Mencionam a possibilidade de o Bend maximizar o uso de GPU.
    • Esperam várias possibilidades de uso de GPU além de LLMs.
  • Características da linguagem Bend

    • Elogiam a simplicidade de uso do Bend e a melhora de desempenho.
    • É uma pena que só ofereça suporte a inteiros de 24 bits.
    • Mencionam a necessidade de suporte a inteiros com maior número de bits.