Enquanto Você Debugava um Print, Esse Dev Deixou a IA Otimizar um Kernel GPU por 14 Dias
Imagina o seguinte cenário: você coloca um agente de IA para rodar, vai dormir, e quando acorda o kernel que levava 419 mil microssegundos está rodando em 1.805. Parece mentira, mas foi exatamente o que aconteceu na competição de otimização de kernels do GPU Mode, onde um desenvolvedor chamado Sankalp usou o OpenAI Codex como copiloto autônomo e alcançou um speedup de 232x sobre o baseline da Nvidia.
O mais interessante não é o resultado em si. É o método. Ele chama de “auto-research”, ou “loop engineering”: você configura um agente de IA com um objetivo claro, dá acesso a ferramentas de profiling, e deixa o modelo iterar sozinho. Por horas. Às vezes por dias inteiros.
Essa história mostra uma tendência que está mudando a forma como devs de alto nível trabalham: em vez de escrever código manualmente, eles estão virando “gerentes de loops”. E o resultado, pelo menos nesse caso, foi absurdo.
O Problema: Decomposição QR em Lote na GPU
A competição do GPU Mode exigia implementar uma decomposição QR de Householder compacta em lote usando CUDA. Pra quem não vive no mundo de álgebra linear: a decomposição QR pega uma matriz e a fatoriza em duas partes (Q e R), e é usada em tudo, de machine learning a simulações de física.
O detalhe: o desafio rodava em hardware NVIDIA B200, com matrizes de vários tamanhos (32×32 até 4096×4096), e a implementação precisava retornar uma representação compacta de Householder, uma matriz H com o triângulo superior sendo R e o inferior armazenando os vetores de Householder, mais um vetor tau de coeficientes.
O baseline era o torch.geqrf, que usa o cuSolver da Nvidia por baixo dos panos. Tempo dele: ~419.000 microssegundos. O objetivo era bater isso. Bater feio.
O Setup: Codex Como Pesquisador Autônomo
Sankalp não sentou e escreveu CUDA kernel por kernel. Ele montou um sistema onde o OpenAI Codex (rodando no modo agente) recebia:
- Um arquivo
AGENTS.mdcom as regras do problema - Acesso ao leaderboard via CLI para submissão automática
- Ferramentas de profiling (
torch.profiler,nsys, NCU) - Acesso ao Modal para rodar benchmarks em GPUs reais
A ideia era simples na teoria: o Codex propõe uma otimização, compila, submete ao leaderboard, vê o resultado, e decide o próximo passo. Tudo sozinho. O Sankalp chamava isso de /goal: ele escrevia algo como “bater o tempo do n=512 sem usar cuSolver” e ia fazer outra coisa.
# Exemplo simplificado do loop de auto-research
while not goal_achieved:
optimization = codex.propose_change(current_code, profiling_data)
new_code = apply_optimization(optimization)
result = submit_to_leaderboard(new_code)
profiling_data = profile_kernel(new_code)
if result.score < best_score:
best_score = result.score
current_code = new_code
Em 14 dias, foram mais de 1.500 submissões ao leaderboard. Não é erro de digitação. Mil e quinhentas.
As Otimizações: De 419ms para 1.8ms
A jornada de 232x não aconteceu de uma vez. Foi uma série de otimizações incrementais, cada uma construída sobre a anterior. Aqui estão as que fizeram mais diferença:
Blocked Householder QR com Representação WY
A primeira grande sacada foi trocar o processamento coluna por coluna por um algoritmo em blocos. Em vez de aplicar cada refletor de Householder individualmente (o que é lento na GPU por ser sequencial), o Codex agrupou refletores em painéis de largura b=32 ou b=64 e os comprimiu em uma única atualização de rank-b:
I - V * T * V^T
Isso transformou a atualização do bloco restante em três operações GEMM (multiplicação de matrizes), que é exatamente o tipo de operação onde GPUs brilham:
W = V^T * A_trail # projeção
Z = T^T * W # aplicação do fator triangular
A_trail = A_trail - V * Z # atualização
| Etapa | Tempo (µs) | Melhoria | Técnica | |
|---|---|---|---|---|
| ——- | ———– | ———- | ——— | |
| Baseline (torch.geqrf) | 419.000 | – | cuSolver | |
| Blocked QR generalizado | 10.168 | 90,7% | Blocos em todas as shapes | |
| Kernels Triton especializados | 4.261 | 58,1% | panel16/32 customizados | |
| CUDA Graph Replay | 3.850 | 2,5% | Elimina overhead de launch | |
| Assembly V/T fundido | 2.752 | 7,3% | Funde cópias e alocações | |
| Kernels fixed-shape | 2.021 | 4,2% | Dimensões hardcoded | |
| Superpainéis compostos | 1.805 | Final | V256/T256 + Cholesky-ORHR |
Cholesky-ORHR para Matrizes Grandes
Para matrizes de 4096×4096, o Codex descobriu que a abordagem clássica de Householder não escala bem. A solução: computar a matriz de Gram, aplicar fatoração de Cholesky, e reconstruir os refletores a partir dos fatores ortogonais. Isso é contra-intuitivo (parece mais trabalho), mas na prática reduz drasticamente o número de operações sequenciais.
CUDA Graph Replay
Um insight que parece bobo mas rendeu 2,5%: gravar o caminho de execução dos kernels e repeti-lo sem overhead de launch do Python/CUDA. Cada vez que você chama um kernel CUDA, existe um custo de “lançamento” que na maioria dos casos ninguém percebe. Mas quando você está otimizando na casa de microssegundos, cada fração conta.
Especialização por Dimensão
No fim, cada tamanho de matriz (32, 512, 1024, 2048, 4096) ganhou seu próprio kernel customizado. Nada de código genérico com if/else em runtime. O Codex hardcodou dimensões, eliminou condicionais, e fundiu operações de redução específicas para cada shape.
Isso vai contra tudo que aprendemos sobre “código limpo” e “DRY”. Mas quando você está competindo por microssegundos numa GPU, abstrações custam caro. Cada if que o compilador não consegue eliminar vira um branch divergente no warp, e warps divergentes são o pesadelo de qualquer kernel CUDA. O Codex entendeu isso sozinho depois de algumas iterações: o profiling mostrava que os condicionais de runtime eram responsáveis por uma fatia significativa do tempo total. A solução bruta (um kernel por shape) foi a solução certa.
Assembly V/T Fundido
Uma otimização que parece mundana mas rendeu 7,3% no geomean: fundir todas as operações de cópia de slice, concatenação e preenchimento com zeros em um único kernel. Antes, montar as matrizes V e T exigia vários kernels pequenos, cada um com seu overhead de lançamento e tráfego de memória. Depois da fusão, uma única chamada faz tudo. Menos tráfego, menos launches, mais throughput.
Loop Engineering: A Nova Forma de Programar?
O que o Sankalp fez tem um nome que está ganhando tração em 2026: loop engineering. A ideia é que, em vez de você escrever prompts isolados para um LLM, você projeta um sistema que mantém o agente rodando em loop com feedback automático.
A Meta já faz isso internamente com o KernelEvolve, um sistema agente que otimiza kernels de IA e comprime semanas de engenharia especializada em horas de busca automatizada. Pesquisadores do MLSys 2026 identificaram isso como uma das três tendências mais importantes da conferência.
O padrão é sempre o mesmo:
- Agente planeja a otimização baseado em profiling
- Agente implementa a mudança
- Sistema testa automaticamente (benchmark, testes de corretude)
- Feedback volta para o agente com métricas
- Repete até atingir o objetivo ou ficar preso
# Fluxo real usado pelo Sankalp no Codex
# 1. Define o objetivo
/goal "Beat n=512 without cuSolver"
# 2. Codex roda sozinho por horas
# 3. Verifica progresso sem interromper
/btw "What structural changes did you make?"
# 4. Injeta conhecimento de domínio a cada 2-3 horas
/side "Try WY representation for panel factorization"
A parte mais contraintuitiva: Sankalp percebeu que verificar o progresso com muita frequência atrapalhava. O agente performava melhor quando tinha liberdade para explorar sem interrupções constantes. Parece gerência de equipe, não programação.
O Que Diferencia Isso de “Vibe Coding”
Tem uma diferença enorme entre pedir pro ChatGPT “cria um app de to-do pra mim” e o que aconteceu aqui. No auto-research:
- O desenvolvedor estudou o domínio antes (álgebra linear, representação WY, fatoração de Cholesky)
- Os objetivos eram quantitativos e mensuráveis (“bater 5000µs no n=512”)
- O feedback era automático e preciso (benchmarks, profiling de GPU)
- O humano intervinha com insights de domínio, não com micromanagement
Sankalp deixou isso claro: “domain knowledge amplifies LLM capability”. Converter “desconhecidos desconhecidos” em “desconhecidos conhecidos” (estudando o problema antes) tornava os prompts dramaticamente mais eficazes.
Isso não é substituir o programador. É dar ao programador uma ferramenta que multiplica sua capacidade por um fator absurdo. Mas só funciona se o programador sabe o que está pedindo.
Triton vs. CUDA: Quem Venceu?
Um detalhe técnico interessante: o Sankalp usou principalmente Triton (a linguagem de kernel da OpenAI) para escrever os kernels, com CUDA como secundário. O resultado final dele ficou em 12º lugar entre 183 participantes.
O primeiro lugar (competidor “gum”) alcançou 1.097 microssegundos usando CUDA puro. Os dois primeiros lugares usavam CUDA, enquanto os próximos usavam Triton. A diferença: mais de 600µs.
| Posição | Tempo (µs) | Linguagem | |
|---|---|---|---|
| ——— | ———– | ———– | |
| 1º (gum) | 1.097 | CUDA | |
| 2º | ~1.200 | CUDA | |
| 3º-4º | ~1.700+ | Triton | |
| 12º (Sankalp) | 1.805 | Triton + CUDA |
Isso confirma algo que a galera de HPC já sabe: Triton é incrível para prototipagem e para 90% dos casos de uso, mas quando o objetivo é espremer cada microssegundo, CUDA puro ainda tem vantagem. O acesso direto ao hardware, sem a camada de abstração do Triton, permite otimizações que simplesmente não são possíveis em Triton.
Por outro lado, o fato de Triton ter chegado tão perto (1.805 vs 1.097) com um dev que não é especialista em CUDA é impressionante. E com auto-research, a velocidade de iteração compensa parte da desvantagem.
Os Aprendizados Que Valem Ouro
Depois de 14 dias e 1.500 submissões, Sankalp documentou lições que qualquer dev pode aplicar:
1. Objetivos quantitativos são melhores que vagos
“Otimize esse kernel” funciona pior que “bata 5000µs no n=512 usando blocked QR”. Quanto mais específico o objetivo, melhor o agente performa.
2. Solte o controle
Checar o progresso a cada 15 minutos atrapalha. O modelo precisa de espaço para explorar caminhos que parecem errados mas podem levar a insights. Intervir a cada 2-3 horas com informação de domínio foi o sweet spot.
3. Cada shape precisa de seu kernel
A tentação de ter um kernel genérico é forte, mas na prática, cada tamanho de matriz tem características diferentes de acesso à memória e utilização de SMs. Especializar valeu mais que generalizar.
4. Launch overhead importa
O gargalo não era compute nem memória. Era o custo de lançar kernels. Técnicas como CUDA Graph Replay, que parecem incrementais (2,5%), se acumulam quando você tem dezenas de kernels por batch.
5. FP16 interno, FP32 externo
Usar precisão reduzida internamente (FP16 ou até FP8) com validação em FP32 permitiu otimizações agressivas sem comprometer a corretude numérica.
O Futuro: Agentes Que Otimizam Enquanto Você Dorme
O auto-research do Sankalp não é um caso isolado. Em 2026, estamos vendo uma explosão de ferramentas nesse espaço:
- KernelEvolve (Meta): otimiza kernels de ranking em produção, economizando semanas de engenharia
- AutoResearch (Andrej Karpathy): rodou 700 experimentos de ML sozinho e encontrou 20 melhorias de treinamento
- AlphaLab: sistema multi-agente para pesquisa autônoma em domínios de otimização
- SpecGen: usa geração especulativa para acelerar a busca por kernels ótimos
O padrão que está emergindo é claro: o papel do engenheiro está mudando de “escrever código” para “projetar loops de feedback e injetar conhecimento de domínio”. Quem entender isso primeiro vai ter uma vantagem competitiva absurda.
Não estou dizendo que todo dev vai otimizar kernels GPU amanhã. Mas a mesma ideia se aplica a qualquer domínio onde você tem um benchmark automatizado: testes de performance, otimização de queries SQL, tuning de hiperparâmetros, até refatoração de código com métricas de qualidade.
A pergunta não é mais “você sabe programar?”. É “você sabe projetar um loop que programa por você?”.
Se eu fosse apostar, diria que daqui a dois anos a maioria das vagas de engenharia de performance vai exigir experiência com loop engineering, do mesmo jeito que hoje exigem experiência com CI/CD. O ciclo é sempre o mesmo: ferramenta obscura vira vantagem competitiva, depois vira requisito, depois vira commodity. Quem entra cedo, ganha.
E se você está pensando “isso é só pra quem mexe com GPU”: o Andrej Karpathy rodou o AutoResearch para otimizar treinamento de modelos e encontrou 20 melhorias em 700 experimentos. A Meta usa o KernelEvolve em produção para modelos de ranking. O princípio é o mesmo: defina a métrica, monte o loop, injete conhecimento, e deixe o agente trabalhar. A GPU é só o domínio onde isso ficou mais visível primeiro.
Fonte de inspiração: Auto-research with codex: How I achieved a 232x Faster Kernel (Sankalp’s Blog)













