Kera e o trabalho de reduzir
The bug report that was not a bug
The story usually starts with a number that is nearly right. Not wildly wrong. Not broken in a way that makes the dashboard red. Nearly right in the expensive way: the sort of wrong that lets one team ship, another team hesitate, and an auditor ask why the answer changed when the same model moved from one machine to another.
One build runs on an x86 server and produces a value. The next build runs on an ARM laptop and produces a value close enough that ademo survives. A GPU path is faster but rounds through the computation differently. An FPGA path is attractive for timing but suddenly the software team is having a hardware conversation. Everyone can explain a small piece of the difference. Nobody owns the whole path from source to result.
That is the space Kera is built for. Not the model idea, not the marketing slide, not a paper about a future compiler, but the compiler work that begins once a team says the same computation must run on different machines andstill mean the same thing. That obligation needs an owner. The compiler promise is not that lowering is elegant. The promise is that lowering is treated as work.
Lowering is the part of a compiler where nice language intent becomes instructions that a target can execute. It is also where vague claims become visible. If the result is supposed to be bit for bit identical across CPU, GPU, FPGA, and WebAssembly, then the compiler cannot shrug at target differences. It has to carry enough structure to decide what maychange and what must not change. It has to know memory spaces, effects, opcodes, data movement, target limits, and the receipts that prove two builds are the same computation.
The tempting version of the story is to call this a portability layer. That is too small. Portability says the program runs elsewhere. Kera is aiming at the harder statement: the program is represented as a content-addressed graph, compiled to a .keg artifact, lowered to multiple backends, and still produces the same answer. The kitchen changes. The recipe does not.
The middle nobody wants to sell
The first conversation with a serious buyer rarely begins with syntax. It begins with a mess. There is a model that matters. There is a simulation that used to be research and has become operational. There is a risk calculation whose result is no longer allowed to vary by machine. There is an edge deployment that cannot carry the full cloud runtime. There is a team that wants an accelerator but cannot afford a rewrite every time the accelerator changes.
Most tooling makes this look like a deployment problem. Choose the target, export the model, patch the runtime, accept some variance, then write a document explaining the exceptions. The document grows. The test matrix grows. The number of specialists grows. Eventually the organisation is paying for heterogeneity twice: once when it buys the hardware, again when it tries to prove the hardware did the same work.
Kera starts from the opposite end. The Kera page calls it a statically typed systems language with a graph-native, content-addressed IR. That phrase matters because the graph is not a decorative compiler diagram. It is the executable object. Source code lowers into directed acyclic graphs of operations, stored as .keg files. Each node carries defined structure. Duplicate work can be eliminated structurally. The same graph can be lowered to CPU, GPU, FPGA, and WASM without treating every target as a separate little universe.
É por isso que a Kera tem de se comportar como infraestrutura séria de compilador, e não como um diagrama. O meio desconfortável é onde o cliente vive. A tokenização tem de preservar posições de bytes. A análise sintática tem de alimentar ferramentas e também a compilação. A verificação de tipos tem de rejeitar incompatibilidades de forma e de aresta antes de se tornarem eventos em tempo de execução. A verificação de empréstimos tem de compreender a propriedade entre memória do anfitrião, do dispositivo, fixada e unificada. A otimização tem de ser repetível. A serialização tem de dar à organização um artefacto que possa guardar.
Nada disto faz um título dramático. É muito mais útil do que um título. Significa que, quando uma carga de trabalho passa do desenvolvimento para a produção, ou de uma base de CPU para um caminho de GPU, o compilador tem algo estável para comparar: a impressão digital do grafo. Se a impressão digital corresponder, o trabalho é o mesmo trabalho. Esse é um ponto de controlo partilhado que um engenheiro, um comprador e um auditor conseguem todos compreender.
Um grafo é um recibo, não uma imagem
A forma antiga de explicar um programa é mostrar o código-fonte e pedir ao leitor que confie no compilador. A página da Kera continua a voltar a um objeto diferente: o grafo. Cada operação é um nó. As arestas expressam dependências. O grafo tem conteúdo. O conteúdo tem um hash. O hash torna-se uma impressão digital que viaja através da compilação.
Isto parece maquinaria interna até estares ao lado de uma equipa de conformidade. Uma equipa de conformidade não quer saber se um fornecedor tem uma bela arquitetura de compilador. Quer saber se o cálculo aprovado no mês passado é o cálculo que está a correr hoje. A impressão digital do grafo é a ponte entre esses mundos. Não é uma captura de ecrã do compilador. É uma forma compacta de dizer: este conjunto de operações, estes tipos, estas entradas, estes atributos, esta estrutura de dependências.
O modelo de nós é deliberadamente rigoroso. Um nó é uma versão de esquema, um opcode, descritores de saída, hashes de entrada e mapas de atributos dispostos em ordem canónica. Os bytes são submetidos a hash com SHA3-256 sob prefixos separados por domínio, para que os hashes de nó, região e grafo vivam em espaços de nomes separados. Se dois nós tiverem o mesmo opcode, entradas e atributos, têm o mesmo hash. Inserir um duplicado devolve a entrada existente. A eliminação de subexpressões comuns torna-se uma consequência da representação, não uma passagem heroica adicionada mais tarde.
É esse tipo de detalhe que transforma um sistema de engenharia em algo em que as pessoas podem confiar. Um comprador não está a comprar um diagrama de compilador. Um comprador está a comprar menos discussões sobre se um cálculo mudou. Um programador não está a comprar um slogan sobre IA determinística. Um programador está a comprar um formato de grafo onde a igualdade pode ser verificada, armazenada e usada por ferramentas. O ficheiro .keg não é, portanto, uma reflexão tardia da implementação. É um registo portátil do trabalho.
As oito pequenas portas antes de aparecer um alvo
When people imagine a compiler, they often jump straight to the backend. They picture the moment code becomes AVX, PTX, Verilog, or WASM. That moment matters, but it is late in the story. Most of the compiler work has already happened by then, in quiet stages that decide whether the backend can be trusted.
Kera begins with a UTF-8-aware lexer that converts source into tokens with full trivia tracking and error recovery. That sounds like editor plumbing, and it is. It is also toolchain reliability. If every byte position is preserved, diagnostics, formatting, incremental reparsing, and language server behavior can line up with what the user actually wrote.A compiler that loses the source shape early pays for that loss everywhere else.
The parser is event-based: recursive descent with Pratt expression parsing emits Start, Token, Finish, and Error events rather than building a single AST that everyone has toshare. The event stream feeds the tree builder, formatter, and language server independently. The green tree is lossless, preserving tokens and trivia. The graph builder then walks that tree, maintains name resolution, and creates a Region node per function.
Only after that does the source become the graph the compiler carries. Structural type checking validates compatibility across operation edges and tensor shape constraints. Types match only when their canonical hashes are identical. The borrow checker enforces one owner per value, no aliased mutable references, and ownership rules across memory spaces. Effect annotations are checked for consistency. Side effects are not left to taste or convention.
The optimisation pass manager then does the recognisable compiler work: constant folding, common subexpression elimination, dead code elimination, inlining, vectorisation, and loop fusion in a fixed-point loop. The important phrase is not the list of passes. It is what happens after every pass: a graph invariant validatorchecks hash consistency and dependency integrity. Optimisation is allowed to improve the graph, not make it mysterious.
Finally, target-specific code generators emit native code, PTX, Verilog, or WASM, and the optimised graph is serialized to a .keg file with a section table. The file starts with the magic bytes KEG\0 and carries sections for strings, types, attributes, nodes, regions, and exports. That is the path a team has to own before it can honestly talk about targets.
Targets are not stickers on aslide
A target list is easy to write and hard to deserve. CPU, GPU, FPGA, and WASM fit neatly in a product card. Lowering to them is where the invoice hides. Each target has its own habits, strengths, and failure modes. A compiler that wants deterministic heterogeneous execution cannot treat those habits as somebody else’s problem.
Em CPUs, a Kera emite código de máquina nativo para x86-64 e ARM64, com RISC-V Vector na ficha técnica. O caminho x86 seleciona SSE2, AVX2 ou AVX-512; o caminho ARM usa NEON; o alocador de registos e o escalonador são partilhados. A alegação do produto não é apenas que existe um binário. A alegação é que os kernels SIMD específicos do alvo são selecionados enquanto o grafo permanece o mesmo cálculo.
Em GPUs, o material de origem nomeia a geração de PTX para CUDA e ROCm, com núcleos tensor usados quando a forma do kernel o permite. Essa última cláusula está a fazer trabalho. A aceleração de hardware não é pó mágico. Uma forma de kernel ou cabe num caminho de núcleos tensor ou não cabe. O compilador tem de expor isso honestamente, mover dados entre o anfitrião e o dispositivo quando necessário, e ainda manter a impressão digital do grafo como prova do que está a ser executado.
Em FPGA, o caminho de lowering torna-se uma conversa de hardware: síntese Verilog, estimativa de recursos, análise de temporização e escalonamento de pipelines para um comportamento previsível e exato ao ciclo. Este é o tipo de alvo onde o gesto vago é especialmente caro. Se o comprador precisa de tempo real rígido, a superfície do compilador tem de falar em ciclos, recursos e pipelines, não apenas em velocidade. A história da Kera faz do FPGA um backend do mesmo grafo em vez de uma reescrita por outra equipa.
Em WASM, a página nomeia SIMD de 128 bits para implantação na edge e no navegador. Isso importa porque a edge é onde a realidade da implantação muitas vezes colide com a pureza. Um navegador, um pequeno dispositivo ou um runtime restrito nem sempre podem alojar a mesma stack que um servidor. Um caminho de lowering nativo do grafo dá à equipa uma forma de levar o mesmo cálculo para esse ambiente sem transformar a edge num segundo produto.
O determinismo tem de sobreviver ao sucesso
O determinismo é fácil de prometer numa sala pequena. Torna-se mais difícil quando o produto tem sucesso. Chegam mais utilizadores. Aparece mais hardware. Um modelo passa de um chip para outro. Uma linha de base de teste escrita para um parque tem de cobrir outro. Uma otimização que parece inofensiva muda a ordem de uma redução. Um caminho rápido aparece num runtime mas não noutro.
A página da Kera apresenta o determinismo como bit a bit entre plataformas. Não se trata de uma afirmação cosmética. Isso altera as obrigações do produto. A aritmética primitiva tem semântica de precisão definida em todos os alvos. As reduções têm desempate definido para que o agendamento e o hardware não alterem o resultado. Os primitivos de redes neuronais têm implementações determinísticas em CPU, GPU, FPGA e WASM. O grafo significa o mesmo em qualquer lugar onde é executado.
É por isso que o comportamento indefinido, as pausas do coletor de lixo e os efeitos secundários implícitos não são pequenas preferências de linguagem. São fissuras na superfície de execução. A página da Kera afirma que não há dependência de LLVM, nem coletor de lixo, nem comportamento indefinido. Tipos explícitos, efeitos explícitos e propriedade entre espaços de memória são controlos do produto. Reduzem o número de lugares onde um resultado pode mudar enquanto todos olham para outro lado.
Há também um lado humano nisto. Quando um controlador de robótica muda de comportamento entre dispositivos, quando um fluxo de trabalho financeiro arredonda um cêntimo de forma diferente, quando um resultado científico não pode ser repetido por um revisor, ou quando uma simulação de jogo diverge entre alvos, o argumento não é realmente sobre teoria de compiladores. É sobre confiança institucional. O texto de consumo da Kera usa histórias simples porque o problema subjacente é simples de sentir: as mesmas instruções, a mesma resposta, em qualquer computador que possua.
Essa confiança tem de sobreviver à aceleração. Se o desempenho exigir que as equipas abandonem o determinismo, o produto apenas moveu o risco. A Kera tenta manter o desempenho e o determinismo no mesmo contrato, tornando o grafo a unidade de significado e o caminho do alvo a unidade de execução.
A segurança faz parte da redução
As discussões sobre compiladores isolam frequentemente a segurança como trabalho em tempo de execução. O material de origem da Kera não o faz. Fala de segurança baseada em capacidades, de um SecurityManager, de um portão de negação por omissão, de um PolicyBuilder, de seccomp BPF, de namespaces Linux e de um registo de auditoria à prova de adulteração e seguro para threads num buffer circular de capacidade fixa. Essas palavras pertencem à história da engenharia porque a redução não termina quando as instruções são emitidas. O trabalho emitido ainda tem de ser executado com limites.
Os tokens de capacidade são concedidos no arranque. As ações privilegiadas exigem uma capacidade explícita. As regras de acesso são declaradas antecipadamente. Um filtro BPF restringe as chamadas de sistema. O isolamento por namespaces separa as vistas de processo, montagem e rede. Os eventos relevantes para a segurança são registados no registo de auditoria. A frase curta é: nada é permitido por omissão.
Isso é importante para a execução heterogénea porque os alvos criam superfícies. Um processo de CPU, uma transferência de GPU, um caminho de FPGA, um runtime de browser e um trabalho distribuído não falham da mesma forma. Um produto tem de manter a política ligada ao trabalho à medida que este se move. Se o grafo diz o que é o cálculo, os controlos do runtime dizem o que o cálculo pode fazer.
Há também uma razão operacional para trazer a segurança para a história do compilador. As equipas não querem um produto para a compilação, outro para a política, outro para o registo e outro para a explicação, se as costuras entre eles se tornarem o lugar onde os incidentes se escondem. A página da Kera não afirma resolver toda a segurança. Faz algo mais restrito e mais útil: torna as permissões explícitas e auditadas no ambiente de execução que o compilador alimenta.
O trabalho distribuído ainda é redução
A ficha técnica menciona a execução distribuída, o allreduce em anel e a recuperação de pontos de verificação. Noutro produto, esses poderiam ser itens de brochura. Na Kera, pertencem à mesma conversa sobre redução porque o paralelismo muda a forma de um cálculo. O paralelismo de dados, de modelo e de pipeline não são apenas formas de ir mais rápido. São formas de dividir o trabalho sem perder o significado do grafo original.
Se um trabalho grande for executado em muitas máquinas e um nó falhar, recuperar a partir de um checkpoint não é uma conveniência. Faz parte de tornar a computação operacional. Se os resultados forem agregados de forma fiável, a semântica da agregação tem de ser definida. Se um grafo for endereçado por conteúdo, o caminho distribuído tem de preservar a identidade do grafo em vez de inventar uma segunda realidade assim que o trabalho sai de uma máquina.
É aqui que a interpretação do produto se torna clara. A Kera não é uma camada de sintaxe com um complemento distribuído. Ela tenta tornar a computação portável tanto na forma como no hardware: um programa, um grafo, múltiplos alvos de execução e um registo que pode ser verificado. A execução distribuída é mais um lugar onde a redução tem de transportar o contrato de execução.
Também muda a história do pessoal. Sem um caminho de compilação partilhado, um erro que aparece apenas numa plataforma pode exigir pessoas que conheçam o chip, a toolchain e o runtime ao mesmo tempo. Com um grafo e um caminho partilhado, a questão é mais precisa: o grafo mudou, o caminho de redução mudou ou o alvo violou a semântica definida? Melhores perguntas não eliminam o trabalho difícil. Impedem que o trabalho difícil se espalhe aleatoriamente.
Porque é que alguém tem de ser dono do caminho
A redução não pode ficar sem dono quando transporta resultados em que as pessoas confiam. Um grafo que corre em CPU, GPU, FPGA e WASM precisa de mais do que uma representação inteligente. Precisa de documentação, diagnósticos, afirmações sobre alvos, comportamento do editor, geração de código, controlos de segurança, conversas de suporte e uma forma de dizer ao comprador exatamente o que mudou quando um resultado muda.
Isso não torna o trabalho menos técnico. Torna o trabalho técnico mais vinculativo. A Kera é atualmente um produto comercial da Dweve, não um lançamento de código aberto: todos os direitos reservados, disponível sob licença comercial, feito nos Países Baixos e destinado a organizações que precisam do caminho do grafo suportado em vez de meramente publicado. Se a página diz Rust 2021, IR de grafo, JIT personalizado, sem LLVM, CPU/GPU/FPGA/WASM, rastreio de efeitos, propriedade entre espaços de memória, segurança por capacidades, execução distribuída, incorporação em C e Python, fluxos de trabalho CLI, suporte de editor e ferramentas LSP, esses não são detalhes internos decorativos. São obrigações que têm de sobreviver à avaliação por cargas de trabalho reais.
A ficha de capacidades é cuidadosa quanto a isto. Descreve alvos de design e diz para verificar contra a sua carga de trabalho. Essa contenção é importante. É muito mais saudável do que fingir que todos os números de benchmark viajam. O sistema deve dar às equipas uma forma de medir, inspecionar e comparar no seu próprio ambiente, não pedir-lhes que aceitem uma história universal de velocidade.
Alguém tem de ser dono desse caminho porque cada alvo tenta tornar a fonte menos universal. A Kera é o lugar onde essas diferenças de alvo se tornam trabalho explícito de compilador em vez de folclore passado depois do relatório de erro.
O dia em que o grafo se torna o contrato
Imagine novamente o relatório de erro original, mas com a Kera já no fluxo de trabalho. Uma equipa financeira aprova um cálculo de risco. A impressão digital do grafo é registada. A primeira implementação corre em CPU. Mais tarde, um caminho GPU é introduzido para análise de carteiras. Mais tarde ainda, um caminho FPGA é usado para preços de menor latência. A questão em cada passo não é se o novo hardware parece impressionante. A questão é se o mesmo grafo está a ser reduzido e se a semântica do alvo mantém o resultado idêntico.
A conversa muda. A equipa de plataforma pode falar sobre agendamento e custo. A equipa de compiladores pode falar sobre backends. A equipa de conformidade pode falar sobre a impressão digital. O dono do negócio pode perguntar se mudar de hardware é uma decisão operacional ou uma reescrita. O produto dá a todos eles um objeto para apontar.
Esse é o valor silencioso de um IR endereçado por conteúdo. Transforma a execução multiplataforma de uma série de explicações persuasivas num registo. Torna o grafo num recibo. Permite que o mesmo .keg alimente todos os backends. Dá à organização uma base que pertence à computação e não a uma única máquina.
Nenhum compilador pode eliminar a necessidade de bom senso em engenharia. As equipas ainda precisam de selecionar os alvos com cuidado, testar as cargas de trabalho com honestidade, compreender os limites dos alvos e decidir quais os domínios que exigem igualdade bit a bit. Mas a Kera pode tornar essas decisões explícitas. Pode impedir que uma migração de desempenho se torne, por acidente, numa migração semântica.
A lição da redução
A Kera é importante porque a parte difícil não é ter uma ideia engenhosa de redução. A parte difícil é levar essa ideia por todos os lugares monótonos onde a engenharia ou se torna digna de confiança ou se torna folclore: diagnósticos, árvores verdes, hashes de tipos, verificação de empréstimos, otimização de ponto fixo, validação de invariantes, serialização .keg, emissão de backend, política de segurança, registos de auditoria, suporte de editores e execução específica de cada alvo.
Reduzir é trabalho porque cada alvo tenta tornar a fonte menos universal. A engenharia de compiladores determinística é a disciplina de recusar que isso aconteça em silêncio. A CPU quer vetores. A GPU quer kernels. A FPGA quer ciclos. A WASM quer restrições. A organização quer uma única resposta. O trabalho da Kera é preservar o significado da computação enquanto permite que cada alvo faça aquilo em que é bom.
Isso é uma forma de engenharia, não uma abstração de papel. Tem um comprador, um modo de falha, um formato de ficheiro, um caminho de compilador e consequências operacionais. A promessa não é que o hardware se torne simples. A promessa é que a complexidade é representada, reduzida, verificada e assumida.
Quando chegar o próximo número quase certo, a equipa não deverá ter de começar pelo folclore sobre qual máquina executou o quê. Deverá começar pelo grafo. A impressão digital coincidiu? Qual backend emitiu o código? Que capacidades foram concedidas? Que semânticas de alvo foram aplicadas? Que artefacto foi armazenado? Essas são perguntas de produto. A Kera existe porque também são perguntas de compilador.