1 pontos por GN⁺ 3 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • WASTE é um motor de inferência em C que converte o modelo completo de pesos abertos Kimi K3, com 2,78 trilhões de parâmetros, sem redução, em um contêiner de 982 GiB para executá-lo em notebooks de consumo
  • Mantém na memória apenas o tronco residente do modelo e lê do NVMe cerca de 4% dos pesos de especialistas ativados a cada token; a RAM restante é usada como um cache de especialistas com tamanho limitado
  • O Kimi K3 abre com no mínimo 29,05 GB de RAM em contexto de 4K, mas a configuração prática é um orçamento de 46 GB em um MacBook Pro de 64 GB, onde registra 0,45~0,62 tok/s
  • Sobrepõe leitura de especialistas e computação para uma melhora de cerca de 1,6×, e executa o roteador da próxima camada um residual à frente para elevar a taxa de acerto do cache de 14% para 38%, sem alterar o total lido nem os logits
  • Permite executar localmente um modelo gigantesco sem conexão à internet, custo por token nem envio de dados externos, mas exige NVMe interno e cerca de 1 TB de armazenamento; com orçamento de RAM de 52 GB ou mais, pode ficar drasticamente mais lento por causa de paginação do sistema operacional

Objetivo e forma de implementação do WASTE

  • WASTE(Weight-Aware Streaming Tensor Engine) é um motor de inferência em C embutível, sem dependências externas em tempo de execução
    • Usa apenas libwaste.a e o executável waste, e não precisa de BLAS, CUDA, ONNX nem Python além de libc e pthreads
    • Python é usado apenas para conversão do modelo e validação contra a referência em PyTorch, e não entra no caminho de inferência
    • A API pública é composta por 26 funções e oferece suporte a abrir modelo, definir limite de RAM, gerar, salvar sessão e encerrar
  • O alvo atualmente validado é o modelo completo Kimi K3 2.78T
    • A fonte pública original tem 1,42 TB, e o contêiner após a conversão tem 982 GiB
    • Não é uma versão destilada, podada nem reduzida
    • O Kimi-Linear 48B também registra, com o mesmo motor e formato, contêiner de 19 GiB, mínimo de 1,87 GB de RAM e 10,7 tok/s
  • O nome do projeto vem do objetivo de reduzir situações em que modelos que poderiam rodar em hardware sobre a mesa são executados em datacenters de nuvem, consumindo custo por token e energia ao mesmo tempo

Estrutura de streaming a partir do disco

  • Como o K3 usa uma estrutura Mixture of Experts, apenas cerca de 4% do modelo é ativado por token; por isso, os pesos inativos são organizados para serem acessados no momento necessário, sem precisar residir na RAM
  • O contêiner .waste é composto por manifesto JSON, tronco residente e bancos de especialistas por camada
    • Cada registro de especialista é alinhado a 4 KiB
    • As matrizes gate, up e down são colocadas de forma contígua para ler um especialista inteiro exatamente com um único pread
    • O page cache é contornado com F_NOCACHE no macOS, O_DIRECT no Linux e FILE_FLAG_NO_BUFFERING no Windows
  • Sem contornar o page cache, contêineres de teste menores que a RAM podem entrar no cache do sistema operacional e produzir taxas de acerto que não se reproduzem no modelo de 982 GiB
  • Ao ler registros, magic, ID do especialista e intervalo de offsets são sempre verificados para evitar que bancos truncados ou combinados incorretamente respondam com pesos errados
    • A verificação crc32 do payload é ativada com --verify
    • O custo de verificação é de cerca de 5% no Kimi-Linear e cerca de 1% no K3; por padrão fica desligada
    • Recomenda-se verificar uma vez contêineres copiados, baixados ou colocados em discos não confiáveis
    • O tronco e os codebooks não têm checksum

Leitura antecipada e previsão do roteador

  • Quando o roteador de uma camada decide 16 IDs de especialistas, cada leitura é solicitada em uma thread separada, e a computação consome os dados à medida que chegam
    • A sobreposição de leitura e computação melhora cerca de 1,6× no K3
    • O trabalho executado e as estatísticas de cache são iguais antes e depois de ativar o recurso
  • Antes que o hidden state real da próxima camada seja produzido, o próximo roteador residente é executado com o hidden state atual para buscar antecipadamente 6 especialistas
    • A previsão um residual à frente tem 92% de acurácia em rank 1 e 81% entre os 6 principais
    • A saída é mantida exatamente correta porque o roteador real decide os especialistas finais
    • A demand hit rate sobe de 14% para 38%, e o total de bytes lidos não muda
    • Pode ser desativado com WASTE_LOOKAHEAD=0
  • A implementação que aplicava a mesma técnica ao prefill foi removida
    • A camada de decode ocupa 16 slots de cache, mas a camada de chunk ocupa cerca de 550
    • Os registros lidos antecipadamente eram despejados antes do uso, aumentando as leituras em 6,9% sem reduzir o tempo

Quantização e precisão

  • Os pesos de especialistas são armazenados com quantização vetorial residual em 3 estágios, com codebook de 256 itens para vetores de 8 dimensões, usando 3,00 bits por peso
    • Sem restaurar a matriz inteira, cria uma tabela de produtos internos parciais e processa cada linha com 3 consultas à tabela e 2 somas
  • O tronco mantém 4 bits e 8 bits
    • Como o modelo foi treinado com consciência de quantização apenas para especialistas, a saída colapsa com tronco de 3 bits
    • A previsão de cache acertava, mas o throughput também não melhorava, então foi removida
  • Todas as camadas são comparadas com a implementação de referência em PyTorch
    • A diferença final de logits é 3.6e-06
    • A torre de visão fica em 2.3e-06 contra sua própria referência
    • A conversão do cache latent KV mantém logits idênticos no nível de 1.2e-05

Orçamento de RAM e faixa estreita de desempenho

  • O K3 usa 16 especialistas em cada uma de 92 camadas, criando um conjunto de trabalho de 17,0 GB por token
    • Se o cache for menor que esse tamanho, especialistas armazenados em um token são despejados antes do próximo token, e a taxa de acerto vira 0%
  • Resultados medidos em um sistema de 64 GB mostram que alocar mais RAM nem sempre acelera
    • Orçamento de 32 GB · cache de 3,32 GB: taxa de acerto 0%, 0,50 tok/s
    • Orçamento de 46 GB · cache de 17,32 GB: taxa de acerto anterior 17%, 0,53~0,55 tok/s
    • Orçamento de 52 GB · cache de 23,32 GB: 0,04~0,15 tok/s, não reproduzível
    • Orçamento de 58 GB · cache de 29,32 GB: 0,02~0,03 tok/s
  • O lookahead do roteador eleva a taxa de acerto em 46 GB de cerca de 14% para 38%, mas o colapso com 52 GB ou mais não é por cache miss, e sim por paginação do sistema operacional
    • Em 58 GB, mesmo com taxa de acerto maior, fica cerca de 20 vezes mais lento que em 46 GB
    • Depois de colocar o sistema em estado de paginação com um orçamento grande, até medições em 46 GB podem cair para 0,02 tok/s
  • O orçamento padrão é escolhido abaixo de 7/8 da RAM física, reduzido em unidades do conjunto de trabalho por token
    • Em um MacBook Pro de 64 GB, usa 46,24 GB e aloca 17,56 GB ao cache de especialistas
    • Se o orçamento especificado for menor que o mínimo, ele recusa iniciar em vez de prosseguir com swapping
    • Em sistemas de 128 GB, é possível usar o orçamento total recomendado, equivalente ao tronco mais 3 vezes o conjunto de trabalho

Desempenho do K3 e requisitos de hardware

  • O sistema de medição é um MacBook Pro M5 Pro de 64 GB com SSD interno
    • RAM mínima para contexto de 4K: 29,05 GB
    • 32K: 30,54 GB, 128K: 35,63 GB, 1M: 83,21 GB
    • Tronco residente: 27,28 GB
    • Carregamento do modelo: 20 segundos
    • Decode: 0,45~0,62 tok/s no orçamento padrão
    • Prefill: chunked 0,47 tok/s, sequencial 0,29 tok/s
  • Embora o modelo possa ser aberto com o mínimo de 29,05 GB, sistemas de 32 GB podem paginar severamente, então 64 GB é a especificação realmente recomendada
  • Em estado cold, lê 17,0 GB de especialistas por token; com taxa de acerto de 38% do lookahead, lê 10,5 GB
  • O SSD interno foi medido em 12,78 GB/s, e um gabinete USB externo em 0,94 GB/s
    • Como um token lê 17 GB de especialistas, o mesmo processamento leva cerca de 13 segundos em armazenamento externo
    • O download original pode ficar em um disco externo, mas o contêiner convertido deve ficar no NVMe interno
  • São necessários 982 GiB para o contêiner convertido e 1,42 TB para staging dos shards originais; o espaço de staging pode ser liberado após a conversão

Attention e processamento multimodal

  • A attention do K3 combina Kimi Delta Attention e gated multi-head latent attention na proporção 3:1
    • O KDA mantém um recurrent state de tamanho fixo em vez de um KV cache crescente
    • O MLA faz cache de um latent de largura 512, sem expandir keys/values por head
  • Ao absorver kv_b_proj na query e na output, o cache para contexto de 4K cai de 11,25 GB para 0,21 GB
    • Uma redução de 53 vezes em relação ao formato anterior
    • Em 128K, o layout expandido exige 360 GB, e o layout latent exige 7,2 GB
  • O caminho multimodal oferece suporte a um ViT de 401M parâmetros, 27 camadas e patch 14
    • A codificação de imagem com 1024 patches leva 15,7 segundos
    • Imagens de 896×896 ocupam 256 posições de sequência na configuração padrão
    • Como os embeddings de imagem também passam pelas 92 camadas MoE, a maior parte do custo é igual ao prefill de texto, não à torre de visão
    • Reduzir max_patches em vision.json pela metade também reduz pela metade o número de posições de prompt
  • Suporta PNG, JPEG, GIF, BMP, TGA e PSD, e imagens podem ser usadas em run, chat e eval
    • Em uma conversa, as posições de imagens codificadas permanecem no attention state e não são recodificadas no turno seguinte
    • A torre de visão só é carregada quando há imagem, usando 434 MB de pesos e 1,12 GB de memória reservada total

Conversão, execução e servidor

  • O build exige apenas um compilador C11 e make
    • make check passa em 23 testes e pula 11 com um contêiner sintético, sem modelo real
    • Com os dois contêineres reais, o total de testes é 36
  • A conversão do K3 usa diretamente os 96 shards safetensors públicos de moonshotai/Kimi-K3
    • Leva cerca de 4,7 horas em um M5 Pro com 3 processos
    • O encoder em PyTorch puro leva 23,7 horas
    • Pode ser retomada por camada, então em caso de interrupção apenas a camada em andamento é reprocessada
    • O downloader oferece retomada de arquivos parciais, exponential backoff e jitter, verificação de Content-Length e registro do estado de shards concluídos
  • A CLI oferece run, chat, eval, plan etc., e com --json imprime resultados de eval, tokenize, plan, info e bench em formato legível por máquina
  • serve/ é um servidor HTTP compatível com OpenAI que chama a API C pública via ctypes
    • Oferece /v1/chat/completions, /v1/completions, /v1/models e /health
    • Processa streaming, definições e resultados de ferramentas, typed call arguments, esquema de resposta JSON, tool_choice, think channel, thinking_effort e imagens
    • O renderer de prompts portou o encoding_k3.py do lançamento do K3 e, quando há diretório de pesos, compara 38 conversas em nível de segmento

Plataformas e limitações atuais

  • macOS arm64, Linux arm64 e Linux x86_64 registram 23 pass e 11 skip nos mesmos testes independentes de modelo, além de passar em sanitizer e 400 casos de fuzz
  • Windows x86_64 foi compilado cruzado com MinGW-w64 e validado com contêiner sintético, CLI e forward pass, mas não foi executado com contêiner de modelo real
    • MSVC e Windows ARM64 não são suportados
    • O contorno do page cache no Windows foi confirmado apenas no filesystem de CI, não sob carga de um contêiner real maior que a RAM
  • O SIMD em x86 escolhe AVX-512 ou AVX2 conforme CPUID, mas o caminho AVX-512 ainda não foi executado em CPU com suporte real
  • O backend Metal é correto, mas, pelo formato da carga com centenas de pequenos matvecs dependentes, é 22% mais lento que a CPU e fica desativado por padrão
  • A API ainda não está fixa, e a conversão automática de chat format atualmente só dá suporte ao K3
    • O Kimi-Linear roda em modo raw, sem tentar inferir o template
  • Não será introduzida alocação não uniforme de bits por especialista
    • O valor do terceiro bit varia no máximo 1,15× entre especialistas dentro de uma camada e apenas 1,01× entre camadas, então a alocação ótima não trouxe ganho
    • A alocação baseada em routing frequency também reduz o espaço de armazenamento, mas quase não reduz o gargalo de I/O
  • A licença é Apache 2.0

1 comentários

 
GN⁺ 3 시간 전
Comentários do Hacker News
  • Muito legal. Não é um projeto tentando ser mais prático que um provedor de nuvem agora; é um projeto mostrando os limites do possível
    Se a melhoria na eficiência dos modelos e o avanço do desempenho do hardware local se combinarem, um dia modelos locais de alta qualidade também poderão se tornar economicamente viáveis

  • 0,5 token por segundo me parece inútil para qualquer tarefa longa. Eu preferiria gastar dinheiro e usar 2 placas 4060 Ti de 16GB com paralelismo de tensores
    Daqui a 20 anos, talvez combine com robôs lentos em estilo cyberpunk movidos a energia solar, cortando grama ou limpando calçadas, ou com um robô no jardim mal conseguindo acompanhar a velocidade de crescimento de um bonsai enquanto faz a poda

    • Quase não serve para uso real agora, mas é bom ver esse tipo de projeto continuar melhorando, porque é assim que eventualmente se chega a uma versão prática
  • Dizem que é desperdício pagar pelo token e deixar o provedor de inferência pagar a conta de luz, mas não vejo como isso seria diferente de comprar pepinos e o agricultor pagar água e fertilizante. Espero que LLM seja só uma lógica improvisada depois do fato
    A ideia em si é interessante, e eu gostaria de testar com modelos menores. Se ele gera 0,5 token por segundo enquanto lê vários GB por segundo do SSD, ainda é grande demais para um notebook comum, mas pode até ser mais prático para modelos de 250~500GiB

    • Se você cultivar seus próprios tomates, pode conseguir tomates grátis. Talvez não o suficiente para fazer um BLT, mas pelo menos não vieram do supermercado, então você salvou um pouco o mundo /s
  • Assumindo uso contínuo de 42W e eletricidade a 20 centavos por kWh, isso dá cerca de 5 dólares por 1 milhão de tokens, sem contar outros custos como hardware

    • Um mês tem cerca de 2,6 milhões de segundos, e a 0,5 token por segundo isso gera 1,3 milhão de tokens por mês. Mesmo considerando custos adicionais, ainda parece razoável estimar que o custo mensal de operar o equipamento equivale ao custo por 1 milhão de tokens
    • Fico curioso sobre como essa conta mudaria com energia solar
  • O llama.cpp padrão também consegue fazer mmap do GGUF, então as partes que não cabem na memória ficam no disco, e o cache de páginas do kernel mantém o chunk residente que é usado com frequência. Fico curioso sobre qual seria a vantagem de implementar isso por conta própria

    • A mesma pergunta apareceu num projeto parecido alguns dias atrás, e disseram que tentaram mmap primeiro, depois fizeram uma implementação própria e ela ficou 10 vezes mais rápida
      É o mesmo motivo de engines de banco de dados implementarem o próprio cache. A paginação do kernel é genérica e baseada em requisição, mas se você conhece o padrão real de acesso, pode ler os dados necessários com antecedência e montar um pipeline
    • Nessa escala, usar SSD como swap pode facilmente consumir a durabilidade total de escrita em poucos meses. Gostaria de ver os números de escrita acumulada e desgaste no SMART quando isso rodar por mais do que um teste de curto prazo
      Para um modelo que cabe inteiro em RAM, eu tive resultados melhores executando o llama-server com --no-mmap. Claro, para carregar o Kimi K3 completo e contexto de 1 milhão de tokens seria preciso um servidor com 2TB
  • O README passa muito a sensação de texto escrito por LLM; fico curioso se o codebase também foi escrito por LLM

    • Não quero diminuir de forma superficial, mas a documentação se contradiz sobre se o modelo realmente roda em precisão original. A quantização de 3 bits alegada pode ser interessante, mas o K3 tem cerca de 115GB só de parâmetros densos em precisão original, mais cerca de 25GB de especialistas esparsos ativos por token, além do cache KV, então é difícil entender a afirmação de 2 segundos por token com 29GB de RAM
    • Eu mesmo escrevi muito software e até criei uma linguagem de programação: https://github.com/marcobambini/gravity
      Agora uso minhas habilidades para coordenar LLMs e agentes e escrever código melhor muito mais rápido. Desenvolvedores têm duas escolhas: se adaptar às novas tecnologias ou ficar para trás
    • Eu gostaria que os autores ao menos lessem o README gerado por LLM. LLMs não entendem bem a perspectiva do leitor e assumem que leitores externos já conhecem todo o contexto do projeto e o processo de tomada de decisão
      Decisões internas importantes para o usuário, mas irrelevantes para quem vê o produto pronto, e também a terminologia obscura típica do Claude, acabam entrando no texto como estão. Eu uso LLM com frequência e reconheço que é muito útil para escrever código complexo, mas a qualidade de rascunho do texto é péssima
    • Como há claude na lista de contribuidores, nem é preciso adivinhar. Se chegaram ao ponto de deixar o Claude fazer commits, parece improvável que o código tenha sido revisado diretamente
    • No README é onde o estilo típico do Claude fica mais evidente. Assim como reconhecemos o jeito de escrever de cada pessoa, parece que agora também existe na minha cabeça uma categoria separada para aquele estilo curto, entrecortado e excessivamente ritmado que o Claude gera por padrão
  • Isso pode ganhar valor se a tecnologia evoluir a ponto de permitir escolher com precisão o modelo certo para cada tarefa. Dá para imaginar um futuro em que, no processo de exploração automática, um modelo grande rode só uns 30 minutos por dia e o resto do tempo se usem modelos pequenos

    • Acho que esse futuro não vai chegar. Só dá para saber quanto tempo levou depois que até o item do backlog foi concluído; não existe como prever a complexidade da tarefa sem realmente executá-la