- Este é um experimento sobre se, ao solicitar repetidamente ao LLM que escreva "um código melhor" durante a escrita de código, o código melhora de fato.
- O caso original foi inspirado no meme do ChatGPT de DALL-E de "faça ficar mais ~".
Experimento de prompt de repetição simples
- Foi fornecido ao Claude 3.5 Sonnet um prompt de programação em Python para resolver um problema simples que pode ser otimizado.
- Implementação base
- Encontrar a diferença entre o menor e o maior número com soma dos dígitos igual a 30 entre um milhão de inteiros aleatórios entre 1 e 100.000.
- A implementação simples levou 657 ms (utilizando conversão de
str em Python).
- Iteration #1
- Foi pedido ao Claude para "escrever um código melhor" e melhorar o código.
- O Claude refatorou o código em uma classe Python, tornando-o orientado a objetos e pré-computando o digit sum para todos os números.
- 2,7x mais rápido.
- Iteration #2
- O Claude otimizou ainda mais o código usando multithreading e operações numpy vetorizadas.
- 5,1x mais rápido.
- Iteration #3
- O código ficou mais complexo e houve regressão para conversão de string.
- 4,1x mais rápido.
- Iteration #4
- O código chamou o compilador JIT da biblioteca Python numba e implementou paralelização com o asyncio do Python.
- Ganho de desempenho de até 100x.
- Em vez da frase "o código fica cósmico", virou um código superengenheirado no nível "enterprise".
Aplicação de engenharia de prompts
- É necessário fazer engenharia de prompts para otimizar a saída do LLM.
- O Claude 3.5 Sonnet tem forte capacidade de seguir prompts, então é possível obter melhores resultados com diretrizes claras.
- Em vez de simplesmente dizer "escrever um código melhor", usamos um prompt de sistema com instruções mais detalhadas.
- Prompt inicial
- Definiu-se de forma detalhada o que significa um "código otimizado" (algoritmo, paralelização, minimizar código desnecessário etc.).
- Do primeiro resultado com otimização de digit sum usando Numba, houve 59x de ganho.
- Iteration #1
- O Claude adicionou paralelização, mas introduziu uma operação de bit shift estranha (para hexadecimal), causando bug.
- O desempenho caiu para 9,1x.
- Iteration #2
- O Claude tentou usar operações SIMD para melhorar o desempenho, mas ainda usou a operação de bit shift errada.
- A execução ficou 65x mais rápida que a implementação inicial.
- Iteration #3
- O Claude otimizou o desempenho usando uma tabela hash.
- A execução ficou 100x mais rápida que a implementação inicial.
- Iteration #3
- O Claude corrigiu a operação de bit shift incorreta e reduziu um pouco o desempenho.
- A execução ficou 95x mais rápida que a implementação inicial.
Conclusão
- Até mesmo com o prompt vago de "código melhor", é possível fazer melhorias incrementais.
- Ao definir claramente a direção desejada (operações numéricas, JIT, paralelização etc.) com engenharia de prompts, obtém-se um código mais evoluído mais rapidamente.
- Ideias de otimização automatizadas podem servir para descobrir novas ferramentas (como numba), mas ainda é necessário que um engenheiro valide e use essas sugestões de forma seletiva.
- Em sistemas de produção reais, é grande a necessidade de validação e de considerar restrições específicas de domínio para não aplicar diretamente tudo o que o LLM sugere.
- O experimento foi baseado em código Python, mas há grande chance de as ideias de otimização do LLM também se aplicarem a integrações com outras linguagens, como Rust (via PyO3).
1 comentários
Opinião do Hacker News
Na otimização de código, é eficaz testar primeiro se um número é menor que o mínimo ou maior que o máximo. Isso pode ser feito antes de calcular a soma de dígitos e pode aumentar a velocidade em até 5,5x. Esse trabalho também pode ser feito com numpy sem usar o Numba.
LLMs como o GPT costumam fornecer resultados medianos inicialmente. Defende-se que é possível obter melhores resultados com uma técnica específica de direcionamento.
O LLM é um mecanismo de simulação contextual, simulando um modelo do mundo real por meio de previsão de texto. Para uma previsão de texto precisa, é necessário um modelo preciso do mundo real.
O LLM tende a produzir código com viés de iniciante; é eficaz especificar os pacotes e pedir código simples.
No Android/Kotlin, o ChatGPT é ineficiente e chama com frequência métodos inválidos ou descontinuados.
É importante começar a sessão de codificação com "planejamento aberto" em vez de "escrever código". É importante esclarecer as suposições do LLM e corrigir o plano antes de escrever o código.
Explica como remover totalmente o PostgreSQL no Debian e reinstalar, preservando o diretório de dados para manter o banco de dados existente.
Otimizar código cedo pode não ser bom; o ideal é otimizar apenas quando necessário.
Repetir "escrever código melhor" pode reduzir o desempenho. Isso pode fazer a solução deixar de funcionar.
No LiveCode, o cálculo é mais rápido que em Python e descreve como calcular a soma usando loops.