Hypura – agendador de inferência de LLM com reconhecimento da hierarquia de armazenamento para Apple Silicon
(github.com/t8)- Otimiza a alocação de tensores entre GPU, RAM e NVMe para executar grandes modelos de linguagem com um agendador de inferência com reconhecimento da hierarquia de armazenamento
- Em um Mac Mini com 32 GB, consegue executar o modelo Mixtral 8x7B (31 GB) a 2.2 tok/s e o modelo Llama 70B (40 GB) a 0.3 tok/s
- Analisa padrões de acesso e largura de banda do hardware para executar com estabilidade até modelos que excedem a memória física, incluindo modelos que antes falhavam por OOM no llama.cpp
- Usa roteamento de especialistas em arquitetura MoE, cache de neurônios e prefetch para reduzir o I/O em até 75% e alcançar taxa de acerto de cache de 99.5%
- Seleciona automaticamente os modos Full-resident, Expert-streaming e Dense FFN-streaming de acordo com o tamanho do modelo e o hardware, mantendo o melhor desempenho
- Oferece API HTTP compatível com Ollama para integração com OpenClaw e outros, e usa o SSD apenas para leitura, permitindo inferência baseada em NVMe sem degradar a vida útil
Visão geral
- Hypura é um agendador de inferência de LLM com reconhecimento da hierarquia de armazenamento para o ambiente Apple Silicon, uma ferramenta que realiza otimização da alocação de tensores entre GPU, RAM e NVMe
- Com base em padrões de acesso, custo de largura de banda e desempenho do hardware, distribui os tensores para executar com estabilidade grandes modelos que excedem a memória física
- Em um Mac Mini com 32 GB, consegue executar o modelo Mixtral 8x7B (31 GB) a 2.2 tok/s e o modelo Llama 70B (40 GB) a 0.3 tok/s
- No mesmo ambiente, o llama.cpp não consegue executar devido a OOM (Out of Memory)
Contexto do problema
- Macs para consumidores contam com memória unificada rápida e armazenamento NVMe, mas têm capacidade de memória limitada
- Por exemplo, um M1 Max com 32 GB não consegue carregar diretamente um modelo de 40 GB, causando swap excessivo e encerramento por OOM
- O Hypura resolve esse problema analisando a estrutura do modelo e aplicando a alocação ideal por camada
Alocação em camadas com base na estrutura do modelo
- Norms e Embeddings: são pequenos, mas acessados a cada token, então ficam fixos na GPU
- Roteamento de especialistas MoE: aproveita a esparsidade; apenas 2 especialistas entre 8 são ativados por token
- Intercepta o roteador para identificar os especialistas ativos e carregar do NVMe apenas as partes necessárias
- Redução de 75% no I/O e taxa de acerto de 99.5% no cache de neurônios
- Usa co-activation tracking para prever os próximos especialistas ativos e fazer prefetch antecipado
- Pesos de FFN densos: representam cerca de 60% do tamanho do modelo
- Faz streaming a partir do NVMe com um buffer pool dinâmico
- A profundidade de prefetch (prefetch lookahead depth) é ajustada automaticamente conforme a memória disponível
- Como resultado, modelos que travavam com a abordagem tradicional de mmap passam a ser executáveis, e modelos que cabem em memória operam na velocidade da GPU Metal sem overhead
Como funciona
- O Hypura lê arquivos GGUF e faz profiling da largura de banda de GPU, RAM e NVMe
- Cada tensor é colocado em uma das três camadas abaixo
- GPU (Metal): camadas de Attention, Norm e Embedding
- RAM: camadas de overflow que não cabem na GPU
- NVMe: demais camadas, com I/O direto via
F_NOCACHE+pread
- Seleciona automaticamente o modo de inferência de acordo com o tamanho do modelo e o hardware
- Full-resident: carrega o modelo inteiro em GPU+RAM, sem I/O em NVMe
- Expert-streaming: para modelos MoE, mantém na GPU apenas tensores não especialistas e faz streaming dos tensores especialistas pelo NVMe
- Dense FFN-streaming: para grandes modelos não-MoE, mantém Attention+Norm na GPU e faz streaming do FFN pelo NVMe
- Tamanho do buffer pool, profundidade de prefetch e orçamento de memória são calculados automaticamente com base no perfil do hardware
Desempenho
- Ambiente de teste: M1 Max, 32 GB de memória unificada, NVMe de 5.1 GB/s
- Principais resultados de benchmark
- Qwen 2.5 14B Q4_K_M (8.4 GB): totalmente carregado na GPU, 21 tok/s
- Mixtral 8x7B Q5_K_M (30.9 GB): modo Expert-streaming, 2.2 tok/s, taxa de acerto de cache de 99.5%
- Llama 3.3 70B Q4_K_M (39.6 GB): modo Dense FFN-streaming, 0.3 tok/s, pool de 24 slots, prefetch de 7 camadas
- Modelos que cabem em memória têm overhead zero, enquanto modelos maiores continuam executáveis graças ao Hypura
Instalação e execução
- Requer Rust 1.75+ e CMake
- Procedimento de instalação
git clone --recurse-submodules https://github.com/hypura/hypura.git cd hypura cargo build --release - Exemplos de execução
hypura profile hypura run ./model.gguf --prompt "Hello, world" hypura run ./model.gguf --interactive hypura bench ./model.gguf hypura inspect ./model.gguf - Para modelos ainda não validados, recomenda-se testar com
--max-tokens 10
Servidor compatível com Ollama
- O Hypura oferece uma API HTTP compatível com Ollama, sendo totalmente compatível com ferramentas baseadas em Ollama, como o OpenClaw
hypura serve ./model.gguf Endpoint: http://127.0.0.1:8080 API: /api/generate, /api/chat, /api/tags - Principais endpoints
Endpoint Função GET /Verificação de status GET /api/tagsLista de modelos carregados GET /api/versionVersão do servidor POST /api/showMetadados do modelo POST /api/generateGeração de texto POST /api/chatGeração conversacional - Para a integração com OpenClaw, defina a base URL do Ollama como Hypura em
~/.openclaw/openclaw.json - Opções do servidor
hypura serve [OPTIONS] --host padrão 127.0.0.1 --port padrão 8080 --context padrão 4096
Arquitetura
- Estrutura em Cargo workspace, composta por dois crates
hypura: binário principal e bibliotecahypura-sys: bindings FFI do llama.cpp (build com CMake)
- Principais módulos
Módulo Papel scheduler/placement.rsOtimização da alocação de tensores entre GPU/RAM/NVMe compute/inference.rsEngine de inferência e funções de carregamento/geração para o servidor compute/nvme_backend.rsStreaming em NVMe, cache de neurônios e callbacks de avaliação server/routes.rsHandlers HTTP compatíveis com Ollama profiler/Profiling de hardware cli/bench.rsFerramenta de benchmark model/tensor_role.rsClassificação do papel dos tensores
FAQ
-
Sem problema de vida útil do SSD
- O Hypura apenas lê do SSD, sem gravações
- O I/O em NVMe é feito somente em leitura com
pread()+F_NOCACHE - O SSD atua apenas como armazenamento frio, enquanto o processamento ocorre em RAM/GPU
- As escritas se limitam a itens mínimos em escala de KB, como JSON de benchmark e arquivos de estatísticas
Diretrizes de segurança
- Se o modelo exceder o limite de RAM (–4 GB de folga),
bench --baselineé bloqueado - Para modelos ainda não validados, teste com
--max-tokens 10 - Os modelos de teste ficam armazenados no diretório
./test-models/
Licença
- MIT License
Aviso ético
- O código do repositório não foi escrito manualmente pelo autor
- Foi produzido como um experimento de geração de código orientada por instruções com uso de LLM
- É um projeto para explorar as possibilidades práticas de inferência baseada em NVMe
1 comentários
Comentários do Hacker News
Gostaria de sugerir isso ao mantenedor. A tabela comparativa atual inclui modelos antigos como Qwen 2.5 14B, Mixtral 8x7B e Llama 3.3 70B
Recentemente, há muitos relatos de que os modelos Qwen 3.5 MoE apresentam desempenho impressionante em hardware da Apple
Vale a pena consultar o texto de Simon Willison
Se possível, seria bom adicionar também o modelo Kimi K2.5 (1T de parâmetros) à tabela
Tweets relacionados: seikixtc, danpacary
Apareceu uma mensagem de erro relacionada ao Heroku, mas agora voltou ao normal
Entrei para ver este post, e vi que você já tinha escrito também sobre o litellm. Gostei muito de ler
Em trabalho local, mesmo uma velocidade abaixo de 1 token por segundo pode ser perfeitamente utilizável se for uma tarefa em segundo plano
A diferença entre “terminar imediatamente” e “concluir durante a noite” ainda é um salto de desempenho significativo
Na prática, o importante é quão sequencial é o padrão de leitura
O NVMe chega a 5–7GB/s em leitura sequencial, mas cai para algo na faixa de 500MB/s em leitura aleatória
No caso de um modelo 1T, em fp16, seria preciso fazer streaming de 2TB em um único forward pass, então teoricamente levaria mais de 300 segundos por token
Não serve para uso interativo, mas pode ter potencial para inferência em lote (batch inference)
Mas, em modelos MoE pequenos, dá para gerar vários tokens por segundo e isso já é realmente útil
Em vez de ler os 2TB inteiros, só parte das camadas de especialistas é acessada
Como cada camada tem tamanho de alguns MiB, a eficiência de acesso ao NVMe também não é tão ruim
Fiquei me perguntando de onde saiu esse “modelo de 1T de parâmetros”. No repositório só vejo modelos de até 70B
Os modelos realistas são os MoE menores, que ainda conseguem gerar vários tokens por segundo
A questão dos MoE é justamente que, por causa da ativação esparsa, não é preciso ler os 2TB completos
Mas o padrão de acesso fica aleatorizado, o que é a pior condição possível para NVMe
Em tarefas onde a latência é importante, como inferência com agentes, esse ponto é central
Parece o tipo de situação que faria o Intel Optane se revirar no túmulo
Na prática, porém, eles não são mais rápidos que NVMe. Em software que suporta leitura/escrita paralela, a diferença quase desaparece
Mesmo assim, se juntar quatro em RAID 0, talvez dê para saturar toda a largura de banda de PCIe 16x
O hardware Mac para consumidores tem memória unificada e NVMe rápidos, mas a capacidade é limitada
Ao carregar um modelo de 40GB em um M1 Max com 32GB, o swap dispara e no fim o sistema entra em panic
O macOS não tem um OOM killer como o do Linux; ele simplesmente fica sem espaço de swap
Ter “o máximo possível de memória” é importante, mas a variável maior é a largura de banda (bandwidth)
O M4 Pro tem 273GB/s, o M4 Max 546GB/s e o M4 Ultra 819GB/s
Depois que o modelo cabe na memória, a largura de banda passa a determinar a velocidade de tokens
No caso do Hypura, o M4 Max é o sweet spot. Com 64GB, dá para rodar com folga um modelo 70B (Q4) e gerar em 2x a velocidade do Pro
Este projeto na prática funciona como uma espécie de memória swap inteligente
É interessante como ele controla o uso para não sobrecarregar demais o NVMe
Ainda assim, se o NVMe realmente receber muita carga, há preocupação com redução da vida útil
SSDs realmente têm sua vida útil reduzida pelo número de escritas nas células, mas é muito raro que carga de leitura danifique o controlador
Se isso acontecer, então há outro problema no sistema
Seria bom comparar este projeto com experimentos anteriores, outra tentativa
Houve relatos de que esta abordagem, por ser baseada em mmap, traz muito overhead