Forjar e pesquisar que merece a sua prova

Kernels otimizados à mão são geralmente folclore com um benchmark anexado. A Forge trata o desempenho como um problema de pesquisa que ainda tem de passar...

Forjar e pesquisar que merece a sua prova

The old trick problem

Every serious software system has a few pieces of code that matter far more than their size suggests. A loop that runs millions of times. A bit operation in a compression path. A small matrix routine. A modular arithmetic kernel. The sort of thing that looks harmless in code review and then quietly decides the energy bill, the latency budget, or the number of machines you need to buy. Very democratic, software. One tiny function can ruin the meeting for everyone.

Historically, those kernels are improved by people. A senior engineer remembers a trick from a paper. Someone digs through an old forum post. A benchmark suite is written. A few candidates are tried. The fastest one wins if it still appears correct. Then the organization freezes it, because touching it again feels like poking a sleeping transformer with a fork.

Forge is research into a better version of that process. It is a program synthesis engine for small, critical implementations: give it a typed specificationand properties, let it search candidate programs, measure and compare tradeoffs, verify equivalence, then lower the discovered implementation to targets that matter. The important word is not search. The important word is still. It still has to be correct.

This is why Forge lives in research. It is not a public product button where someone types make faster and receives a miracle. It is a synthesis workbench for partner experiments, kernel discovery, and research on how far automated search can go when it is tied to verification instead of benchmark theatre.

Forge is not guessing in prose. The engine explores candidate programs against a typed contract, and the search strategy changes how that space is visited.

A specification is the starting line

Optimization without a specification is just gambling with nicer variable names. The moment a clever candidate appears, the team needs to know what it is meant to preserve. Does it handle every input or only the friendly ones from the benchmark? Does itrespect overflow behaviour? Is the algebraic identity valid under the representation actually used? Does it keep the same semantics when lowered to a different backend?

Forge starts from typed expressions and properties because the search needs a boundary. The boundary says what counts as equivalent. Without it, the engine can find something astonishingly fast by deleting half the work. Computers are excellent at malicious compliance when the contract is vague.

The search side is deliberately plural. Enumerative search is useful when the space is small enough to cover. CEGIS is useful when counterexamples can guide refinement. Genetic programming and MCTS explore differently. ML-guided search can learn cost models and prioritize promising regions. None of these is universally best. That is not a weakness. It is how search behaves in the real world. If one hammer solved every kernel, toolboxes would be very boring and hardware vendors would be unemployed.

The research question is how to combine those engines with enough proof pressure that the result is not merely clever. A synthesized kernel has to survive both the happy-path benchmark and the unhappy-path verifier. Otherwise the improvement is not engineering. It is a magic trick with a maintenance cost.

The verifier is the adult in the room

Forge usa uma pilha de verificação porque nenhuma verificação isolada é suficiente para todos os domínios. Exemplos rápidos são baratos e úteis. Testes de propriedades encontram classes amplas de erros e reduzem contracxemplos a algo que um humano consegue ler. Solucionadores SMT como Z3 e CVC5 conseguem provar equivalência quando a codificação é tratável. A verificação exaustiva é prática para domínios pequenos. A saturação de igualdade de e-graphs oferece outra via para a equivalência algébrica.

A pilha é importante porque os kernels falham de maneiras irritantes. Um candidato pode passar em todos os benchmarks comuns e ainda assim estar errado num caso limite. Pode estar correto para entradas sem sinal e errado para entradas com sinal. Pode estar correto num campo matemático e errado depois de a representação escolhida transbordar. Pode estar correto antes da redução e sutilmente errado depois de uma decisão de seleção de instruções. O verificador existe porque otimismo não é uma estratégia de teste. Verificámos. Repetidamente. Continua a ser verdade.

A verificação deve tornar-se mais rigorosa à medida que os candidatos se tornam mais tentadores. Quanto mais rápido o candidato parecer, menos devemos confiar nele sem prova.

Há também uma razão prática para manter várias vias de prova. Os métodos formais são poderosos, mas não são gratuitos. Algumas codificações esgotam o tempo. Alguns domínios são demasiado grandes para verificação exaustiva. Algumas propriedades são mais fáceis de testar probabilisticamente primeiro e provar depois. Forge trata a verificação como um funil, não como um ritual de pureza. Verificações baratas rejeitam disparates óbvios. Verificações mais fortes protegem o candidato final.

Rápido não é um único número

O trabalho de desempenho torna-se ridículo quando se permite que uma métrica domine todas as conversas. A latência importa. A contagem de operações importa. O uso de memória importa. A pressão de registos importa. O tempo de compilação às vezes importa. A portabilidade importa quando o mesmo kernel tem de viver em mais do que um backend. Um candidato que ganha em latência ao queimar registos como uma pequena fogueira pode estar errado para o alvo real. Um candidato pequeno mas lento pode ser útil noutro lugar. O contexto continua imbatível.

Forge enquadra portanto a otimização como um problema de Pareto. O motor pode procurar entre objetivos em vez de fingir que existe uma pontuação universal entregue por uma folha de cálculo muito confiante. O resultado útil nem sempre é o candidato único mais rápido. Às vezes é uma família de candidatos com compromissos visíveis, para que um engenheiro possa escolher o que se ajusta à restrição de implantação.

Um kernel pode ser melhor de várias maneiras incompatíveis. Forge mantém esse compromisso visível em vez de o esconder numa pontuação heroica.

É também por isso que não gosto de alegações nuas de aceleração em publicações de blogue. A página de investigação pode descrever expectativas internas e objetivos experimentais, mas as alegações públicas precisam de execuções recentes, hardware atual, flags atuais do compilador e contexto exato de carga de trabalho. Caso contrário, o número torna-se uma recordação. Recordações são agradáveis. Não são arquitetura.

A alegação honesta é mais forte de qualquer forma: Forge trata de tornar a pesquisa reproduzível, comparável e verificável. Quando um candidato vence, devemos saber em que objetivo venceu, que candidatos derrotou, que verificador o aceitou e que backend visa. Isso é muito mais útil do que um número a flutuar por um conjunto de diapositivos com ar caro.

A redução é onde as provas vão ser testadas

Uma implementação descoberta só é útil se sobreviver à viagem até aos alvos reais. A investigação do Forge cobre a redução para backends como x86-64, RISC-V, WASM, caminhos de GPU Vulkan, C e Verilog. Essa lista de alvos não é decoração. Cada backend tem as suas próprias restrições, formas de instruções, comportamento de memória e modos de falha. A mesma especificação tem de manter o seu significado enquanto a implementação se torna algo que o alvo consegue realmente executar.

É aqui que a síntese se liga ao resto da stack Dweve. O Core quer loops internos eficientes. O Numerus preocupa-se com kernels numéricos determinísticos. O BitWeave quer operações binárias de vetores e matrizes que não desperdicem a CPU. O Kera trata de reduzir grafos de computação para hardware real. O Forge só pode alimentar essas camadas se a implementação gerada for mais do que rápida. Tem de ser equivalente, suficientemente portável para o alvo escolhido e inspecionável quando algo muda.

A prova tem de viajar com a implementação. A redução não é o lugar onde a equivalência é educadamente esquecida.

O que isto muda para as equipas

Para uma equipa, a mudança interessante não é que uma máquina possa descobrir um kernel mais rápido. É que o trabalho de kernels fica menos dependente do folclore. Em vez de um especialista se lembrar do truque certo, o processo passa a ser: declarar o contrato, explorar o espaço, medir candidatos, provar equivalência, registar o compromisso e gerar o código do alvo. Os humanos continuam a decidir. Simplesmente deixam de fazer toda a descoberta à mão.

Isto é importante para as operações, porque a dívida de desempenho é cara de uma forma que as organizações muitas vezes escondem. Um kernel lento traduz-se em mais servidores. Mais servidores traduzem-se em mais custo, mais energia, mais complexidade de implementação e mais ruído no planeamento. Uma otimização errada torna-se em incidentes. Um truque correto mas não documentado torna-se num risco futuro de migração. O Forge é investigação para reduzir essa pilha de disparates evitáveis.

Há também uma mudança cultural. O trabalho manual de desempenho muitas vezes recompensa o heroísmo. Alguém desaparece na caverna e volta com um truque engenhoso. Todos aplaudem, ninguém percebe completamente, e a empresa adquiriu um pequeno objeto sagrado. O Forge empurra o processo para a evidência: aqui está a especificação, aqui está o percurso de pesquisa, aqui estão os candidatos rejeitados, aqui está o verificador, aqui está o backend selecionado. Menos mitologia. Mais comprovativos.

Onde o trabalho ainda é difícil

Nada disto torna a síntese fácil. As especificações são difíceis. Se a especificação estiver errada, o motor pode descobrir fielmente a coisa errada. Os espaços de pesquisa podem explodir. Os solvers podem esgotar o tempo. Os modelos de custo podem enganar. Os backends podem expor detalhes que a expressão abstrata ignorava. A verificação pode ser forte num domínio e desajeitada noutro. Quem vende síntese de programas como uma máquina de venda automática de código ótimo está a saltar as partes difíceis ou a cobrar mais pela desilusão.

O Forge é interessante precisamente porque enfrenta essas partes difíceis diretamente. Combina várias estratégias de pesquisa. Mantém a verificação por perto. Trata os objetivos como compromissos. Tem como alvo backends reais. Continua a ser um programa de investigação porque ainda estamos a aprender onde fica a fronteira entre a descoberta automatizada, o julgamento humano, os limites dos solvers e a realidade da implementação.

Vale a pena explorar essa fronteira. A indústria de software tem demasiados loops quentes pequenos, demasiado folclore de desempenho duplicado e demasiadas otimizações que ninguém quer voltar a tocar. Se o Forge conseguir transformar mesmo parte desse trabalho num processo de evidência repetível, o resultado não é apenas código mais rápido. É código mais calmo. O código mais calmo é subvalorizado, principalmente por quem nunca foi chamado às 02:17.

O que uma boa execução do Forge precisa

Uma experiência séria com o Forge começa antes de o motor ser executado. A equipa tem de trazer um kernel real, não uma queixa vaga sobre desempenho. Precisa de entradas representativas, casos-limite conhecidos, hardware-alvo, benchmarks atuais e a razão de negócio para este kernel ser importante. Caso contrário, o motor de síntese pode passar muito tempo a resolver um problema que ninguém tem. As ferramentas de investigação não estão imunes a entradas inúteis. Apenas tornam a inspeção do lixo mais cara.

A entrada mais útil é um contrato pequeno e preciso. O que se espera que a função calcule? Que leis algébricas importam? Que comportamento de overflow é intencional? Que intervalos são impossíveis por construção, e quais simplesmente não ocorreram na última execução de testes? Que saídas toleram aproximação, e quais não toleram? Uma equipa que não consegue responder a essas perguntas provavelmente ainda não tem um problema de otimização. Tem um problema de clarificação de produto disfarçado de compilador.

Uma boa execução também precisa de uma postura-alvo. x86-64 e RISC-V não são a mesma coisa. WASM tem restrições diferentes. Os caminhos de GPU Vulkan preocupam-se com formas e movimento de memória. Verilog levanta questões de hardware que as equipas de aplicações normais raramente apreciam antes do café. O Forge pode explorar a redução ao alvo, mas não pode decidir prioridades organizacionais. Se a portabilidade importa mais do que a velocidade num único alvo, diga isso. Se a latência vence a memória, diga isso. Se a pressão de registos é o limite prático, diga isso também. O motor é poderoso, não é vidente.

A saída deve ser tratada como um pacote de evidências. Candidato, objetivo, percurso de prova, contracasos rejeitados, backend, contexto de benchmark e ressalvas em aberto. É esse pacote que permite aos humanos tomar uma decisão sensata. Por vezes, a jogada vencedora é adotar o candidato. Por vezes, é manter o kernel antigo porque a troca pela portabilidade não compensa. Por vezes, a descoberta é que a especificação era demasiado vaga. Os três resultados são úteis. Apenas um deles parece entusiasmante numa demonstração, e é por isso que as demonstrações são um mau substituto para a engenharia.

A lição

A lição do Forge é simples: o desempenho não deve ultrapassar a prova. A pesquisa é poderosa, mas um motor de pesquisa sem verificação é apenas uma forma muito enérgica de criar bugs. A verificação é poderosa, mas sem pesquisa espera que os humanos lhe tragam candidatos. O Forge junta as duas e pergunta que kernels podemos descobrir quando a máquina pode explorar, mas não pode mentir.

É essa a investigação que vale a pena fazer. Especificações tipadas, pesquisa de candidatos, funis de prova, objetivos de Pareto e redução ao backend. Não é magia. Não é um atalho de produto. É uma forma de criar melhor código pequeno com evidências anexadas.