Transformando um Xeon do AliExpress e uma GPU gamer em um ChatGPT caseiro – Montando um servidor de IA local!
A IA (Inteligência Artificial) está na boca do povo e é um tema que suscita todo tipo de discussão, desde preocupações com a segurança da tecnologia, passando pela parte social e chegando até mesmo no fim da humanidade. Apesar do caráter divisivo da IA, o objetivo aqui não é centrar nas polêmicas e sim no aspecto prático: O que é? Como vive? Como funciona? Dá pra rodar no meu Xeon do AliExpress em casa? As respostas para essas e outras questões estão no artigo a seguir! 🙂
Apesar de parecer algo extremamente recente, as primeiras publicações a respeito datam lá de 1943, com a publicação de A Logical Calculus of the Ideas Immanent in Nervous Activity por McCulloch e Pitts, onde eles estabelecem as fundações usadas pelas IAs modernas, descrevendo o cérebro como um sistema computacional e introduzindo o conceito de redes neurais artificiais. Logo após, em 1950, veio o artigo Computing Machinery and Intelligence, publicado pelo pai da computação, Alan Turing.
Ao longo das décadas seguintes foram publicados vários outros trabalhos e artigos vitais para o desenvolvimento do que hoje se conhece como IA. Cortando para 2020, quando a OpenAI apresentou o modelo GPT-3, que foi uma das primeiras LLM (Large Language Models) e depois para 2022, quando o ChatGPT veio a público usando o modelo GPT-3.5 e teve sucesso estrondoso.
Mas o que está por trás da inteligência artificial, em especial as LLM? Esses são grandes modelos especialmente focados em processar, compreender e gerar texto de forma natural. Por trás desses modelos, existe uma quantidade absurda de dados que são convertidos em parâmetros matemáticos, onde uma arquitetura de rede neural lê um prompt e a partir dai, calcula a probabilidade estatistica pra prever qual será a próxima palavra usada em uma frase, formando um texto que faça sentido aos olhos humanos, parecendo de fato inteligente aos olhos do cidadão comum.
Existem alguns termos que precisamos ter em mente pela sua grande importância nesse mundo do Terminator, o principal deles é o token, que são pequenas unidades de texto, geralmente com até 4 caracteres, que o modelo usa como base para tudo no seu processamento, por exemplo, a palavra ‘gato’ pode ser 1 token, enquanto que ‘maçã’ provavelmente será contabilizada como 2 tokens por conta da acentuação, onde o mesmo vale para palavras mais longas, que são divididas em vários tokens, de forma que um texto de 1000 palavras pode ter de 1500 a 2000 tokens, a depender do idioma. Isso importa porque, em IA generativa, praticamente tudo é medido em tokens. Quando você assina o ChatGPT ou Claude, a cobrança e as limitações geralmente dependem do consumo de tokens.
Já do ponto de vista do modelo, temos os parâmetros, que são milhões, bilhões ou até trilhões de números que durante a fase de treinamento, o modelo aprendeu que seria relevante (ou não) para uma ideia ou outra por meio dos pesos, por exemplo, quando o modelo encontra lá ‘gato’, conexões como ‘mamifero’ ou ‘felino’ tem um peso alto, enquanto ‘jacaré’ (outro animal) teria um peso mais baixo e ‘trator’ teria uma associação ainda menor.
Tem também o contexto, que é o número de tokens máximo que a IA pode usar por conversa, com os modelos atuais geralmente permitindo usar janelas de contexto entre 131k até 1 milhão de tokens! É evidente que quanto maior o contexto selecionado, maior a quantidade de memória alocada, o que requer cautela em sistemas que já estão no limite do uso de memória.
O número de parâmetros costuma ser associado a inteligência do modelo, o que nem sempre é uma realidade, já que diferentes modelos podem com ser treinados com focos em usos diferentes, além da qualidade do material do treinamento e arquitetura podem impactar bastante. A real é que quanto maior o número de parâmetros, maior tende ser a exigência de memória, já que o modelo costuma ser alocado totalmente na RAM ou VRAM.
Visando diminuir esse requerimento, já que um modelo médio como o Qwen3.6 27b tem perto dos seus 55GB em BF16 (BFloat16, formato de precisão que costuma ser padrão no treinamento), inventaram algo chamado quantização, que permite reduzir a precisão do ponto flutuante para um formato inteiro usando um conceito de escala matemática para trazer a tona novamente os decimais, dessa forma, é possível reduzir pela metade o tamanho do modelo indo de BF16 para INT8 ou mesmo em 4x para INT4. Apesar disso parecer mágica, o preço que se paga na quantização é a diminuição da precisão do modelo, o que pode reduzir suas capacidades ou levar a erros, onde o impacto costuma variar entre modelos, com os maiores tendendo a sofrer um pouco menos com isso. Existem modelos que já vem com o treinamento ‘de fábrica’ pensado em quantização, uma técnica chamada QAT (Quantization-Aware Training), mas essa é uma abordagem mais complexa, uma escolha de design dos laboratórios responsáveis pelo modelo, exemplos disso são os GPT-OSS e o Deepseek v4.
Outra coisa que precisa ser levada em consideração é o KV Cache (Key-Value Cache), um rascunho interno do que já foi dito e que vai crescendo conforme se aumenta o contexto. Em um servidor local usado apenas por um usuário, ele tende a ficar um pouco mais contido, entretanto, em um cenário com multiplos usuários, é bem comum que o KV Cache supere até mesmo o tamanho do modelo, se tornando um problema. Ele também pode ser quantizado para ter seu tamanho reduzido, contudo, existe o mesmo trade-off do modelo, onde se perde qualidade, geralmente com consequência do modelo começar a ‘se perder’ durante conversas longas.
A questão que o gargalo não está apenas na quantidade de memória necessária, mas também na banda de memória do dispositivo usado para rodar a IA e isso acontece por conta da natureza token-a-token do processamento, o que exige muita banda de memória pra cuspir tokens com velocidade máxima, portanto, ela acaba normalmente sendo o gargalo nesses casos, o que explica o uso de caras memórias HBM em GPUs de datacenter ou o socket SP7 dos Epyc 9006 vindo com até 16 canais de memória DDR5 e mais de 1 TB/s de banda.
Apesar da dependência de banda continuar, é possível mitigar um pouco isso com a arquitetura do modelo, onde atualmente temos dois caminhos principais: Os modelos densos e os MoE (Mixture of Experts). Os densos simplesmente ativam todos os parâmetros disponíveis para cada token gerado, em um exemplo do mundo real, quando você pergunta alguma coisa pro Qwen3.6 27B, todos os 27 bilhões de parâmetros são usados. Já nos MoE, apenas um pequeno número desses parâmetros, que são meio como se fossem especialistas, são ativados, exemplificando, no Qwen3.6 35B A3B, apenas 3 bilhões de parâmetros são usados por token, o que torna o esforço computacional e exigência de banda menores, criando um modelo que costuma ser mais rápido apesar do número de parâmetros total. Outra vantagem dos MoE é que caso eles não caibam integralmente na VRAM, eles costumam ser muito mais amigáveis ao offload na RAM já que apenas uma pequena parte dos parâmetros é ativada por token, perdendo menos desempenho por usar a CPU para computar parte do modelo.
Outro ponto importante é a diferença entre treinamento e inferência. O treinamento é a parte que o laboratório faz, que envolve submeter o modelo a uma quantidade gigantesca de dados para que ele possa ‘aprender’ as coisas, em um processo de erro e repetição para determinar o valor dos pesos corretamente, onde esse é um processo que leva até semanas e requer uma quantidade extrema de poder de processamento.
Já a inferência se resume a pegar esse modelo novo, que já está preparado, e rodar para ele responder ao usuário, onde a exigência de hardware nessa parte é muito menor, dependendo mais do tamanho do modelo, arquitetura MoE ou densa, número de experts e usuários simultâneos do que de outro fator
Como rodar um modelo localmente?
Para rodar um modelo de IA local, é necessário um software de inferência, que vai carregar o modelo e estabelecer um server para servir ou localmente ou via rede. A boa notícia é que a maioria desses softwares são de código aberto, onde o mais popular é o llama.cpp e seus derivados como o Ollama e o LM Studio, mas existem também o vLLM e SGLang, que tem maior foco em operações maiores servindo múltiplas sessões ao mesmo tempo. Enquanto esses softwares são generalistas e cobrem um vasto número de modelos com arquiteturas distintas, existem outros projetos otimizados para modelos especificos, como o Dwarfstar 4, que é focado no DeepSeek 4 e o colibri, que se propõe a rodar modelos gigantes em máquinas comuns.
É necessário se atentar a alguns detalhes antes de escolher o software de inferência mais adequado, por exemplo, se ele oferece suporte a API mais adequada ao seu hardware, onde CUDA costuma ser a melhor opção para placas NVIDIA, com o ROCm/HIP sendo o equivalente para as AMD e Vulkan como uma alternativa que funciona em qualquer fabricante e que curiosamente, costuma ter melhor desempenho nas GPUs AMD em relação ao ROCm, ao menos no que diz respeito as Radeon de ‘civil’.
Outro ponto é o formato dos modelos, onde o padrão costuma ser o SafeTensors, que tem foco em segurança e velocidade de carregamento e costumam ser distribuidos como multiplos arquivos. Além dele, existe o GGUF, que é o padrão utilizado pelo llama.cpp e também o rei para inferência local, tudo porque ele é distribuido em apenas um arquivo e também permite dividir o modelo entre GPU e CPU.
Existem várias pessoas ou grupos que já oferecem arquivos GGUF prontos para uso em sites como o HuggingFace, onde eles pegam o modelo original em SafeTensors e fazem a quantização (ou não) para o GGUF, onde é comum vermos nomenclaturas como Q4_K_M, Q4_K_S ou Q8_K_XL, o que parece ser uma sopa de letrinhas, mas na real é relativamente simples de entender:
Os dois primeiros digitos se referem a quantização, onde Q4 indica que boa parte dos pesos vem com cerca de 4 bits por parâmetro, já que o formato GGUF admite usar camadas quantizadas em diferentes níveis, ou seja, os pedaços mais sensíveis a perda no modelo podem estar em 8 ou até 16-bit, já o M é de ‘medium precision’ e o S é de ‘small precision’, onde o ‘M’ tende a manter mais camadas criticas com quantização mais alta e o S, nesse exemplo, seria mais próximo de um INT4 puro, mantendo a maior parte em 4-bit para manter o modelo menor.
O Q4_K_M costuma ser considerado o ‘quant’ mais equilibrado no que diz respeito a tamanho vs perdas, mas existe variação entre diferentes modelos, então, idealmente, deve-se pegar o modelo menos quantizado que for possível, já que ele deve ter menos perdas e apresentar melhores resultados, com menos alucinações. Para quem tiver curiosidade, esse vídeo mostra bem o que acontece com a capacidade do modelo nos benchmarks em cada nível de quantização.
Para esse artigo, será utilizado o llama.cpp, pois é a opção mais utilizada para inferência local, com bom suporte a diversos modelos diferentes e também adequado ao nosso hardware, já que será necessário fazer offload para RAM aqui.
Montando um servidor baratinho (ou quase isso):
Hardware barato infelizmente é coisa do passado, mas se procurar bem ainda restam algumas alternativas um pouco mais acessíveis, como é o caso dos Xeon com placas X99 chinesas, os quais aceitam usar memórias DDR4 ECC Reg, que costumam ser um pouco mais baratas que as suas contrapartes UDIMM. Então vamos ver qual vai ser o hardware desse artigo.
Processadores:
Apesar dos Xeon V3/V4 já serem considerados um tanto antigos, com mais de 10 anos do seu lançamento, esses processadores acabaram envelhecendo relativamente bem e por seu status de ‘resto de servidor’, os preços são extremamente amigáveis, por exemplo, é possível adquirir um monstrinho com 18 cores e 36 threads por cerca de 120 reais ou que tal um octa-core todo destravado para overclock por uns 200 reais?
Para descobrir qual é a melhor opção para esse uso, se o monstro multithread ou o singlethread com clocks mais altos, botamos lado a lado o 2699V3 e o 1660V3, assim já descobrimos qual é o preferido do Terminator! Infelizmente não dispomos de nenhum Xeon V4 para testar, o que seria interessante, já que existe um pequeno ganho de IPC por conta da arquitetura Broadwell.
Placa-mãe:
Por se tratar de uma plataforma antiga, placas-mãe novas meio que não existem, exceto no mercado Chinês, lá tem uma infinidade de opções de placas X99 com diferentes focos e recursos, inclusive, temos review de um dos modelos mais populares que é a Qiyida X99-D4, mas para esse teste, iremos usar a Jingsha X99-E Max, que é um modelo mATX com chipset C612, 8 slots de memória, suporte a quad channel, duas M.2 e um slot PCI-E 16x 3.0, a qual foi adquirida faz alguns anos por coisa de R$300.
O detalhe mais notável é que estamos usando a UEFI gráfica do jwagner, que é um modder brasileiro que desenvolveu uma UEFI com interface gráfica para essas placas chinesas, desde que elas usem chipset X99/C612. Ela possui suporte a ReBar, Turbo Unlock pros Xeons e overclock para os modelos destravados, incluindo a possibilidade de ir além dos 2400 MT/s nas memórias, com ajustes de 2666 e 3200 MT/s funcionais, o que talvez nos ajude nos testes com IA.
Memórias:
Com a atual crise das memórias, é aqui que o bicho pega! Normalmente, a recomendação seria pegar a maior quantidade da melhor memória possível, contudo, com os custos atuais, o simples fato de ter algo pra conseguir ligar e usar o PC sem quebrar totalmente a banca já é uma baita vitória.
Dito isso, para esses teste foi usado um ‘catadão’ de kits Samsung B-Die que já viram muito overclock na vida, no caso, um kit 2x16GB Asgard DDR4-3600, um kit 2x16GB G.Skill DDR4-3600, um kit 2x8GB Zadak Spark 4133C19 e um kit 2x8GB Asgard Bragi 4000C16 e apesar da salada mista, todas essas memórias usam PCBs A2 e B2 e os mesmos chips, o que minimiza possiveis incompatibilidades e mesmo com essa plataforma antiga, foi possível rodar DDR4-3200 com facilidade com o 1660V3.
Essa salada acabou totalizando 96GB, o que como veremos nos testes, é meio que overkill para essa plataforma, com 32GB já sendo algo satisfatório para isso. Outra coisa é que não é necessário esses kits Samsung B-Die que nunca foram baratos e hoje além de caros, também são relativamente raros, pode-se usar DDR4 ECC REG sem maiores problemas, ainda que isso pode acabar dando uma limitada no overclocking.
GPU:
Essa é talvez uma das partes mais importantes da build, já que geralmente é a GPU quem entrega desempenho e banda de memória suficientes para fazer a inferência em uma velocidade satisfatória, entretanto, a VRAM (capacidade) costuma ser a maior dificuldade aqui.
Para esse teste, foi escalada a boa e nem tão velha PowerColor RX 6800 XT Red Devil que já foi usada em inúmeros testes aqui no site e apesar de ser um placa ainda competente com 16GB de VRAM, a arquitetura RDNA2 já sente um pouco para esses workloads de IA.
Um detalhe que pega é o backend e enquanto as GPUs NVIDIA tem o CUDA, que é a referência absoluta desse mercado, a AMD usa o ROCm/HIP, que são as bibliotecas equivalentes para as Radeon/Instinct, o problema é que por eles estarem longe de ser lideres de mercado, a opção para o ROCm foi a maior facilidade em portar as aplicações escritas em CUDA, o que claramente é um compromisso em relação ao desempenho, já que são GPUs com arquitetura diferente da NVIDIA.
Também existe a opção de usar um backend em Vulkan, que costuma ser consistentemente mais rápido nas Radeon do que o próprio ROCm, além de ser mais fácil de usar já que o driver Vulkan já vem junto do driver de vídeo, não requerendo uso de mais bibliotecas externas!
Dito isso, quem quer montar um servidor desses pode usar outra GPU, só é necessário observar qual modelo pretende rodar e qual o alvo de tokens por segundo, já que nesse caso aqui do artigo, usar uma GPU com 8GB de VRAM significaria jogar mais layers para a CPU, o que reduzindo assim a velocidade.
Outra possibilidade é usar multiplas GPUs, dividindo o modelo em mais de uma placa, recorrendo a pipeline parallelism ou tensor parallelism, o que seria uma opção melhor do que fazer offload para CPU, contudo, ai passar ser necessário placa–mãe com vários slots PCI-E, fonte mais robusta e por ai vai, portanto, não é o caminho que vamos tomar aqui.
Software – Linux é a solução!
Apesar de existirem softwares de inferência para Windows, a escolha aqui foi por usar Linux e essa escolha tem a ver com desempenho, que costuma ser melhor no sistema do pinguim, facilidade de configuração e instalação, já que não raro será necessário compilar a partir do código-fonte e isso é algo mais trivial no Linux e até mesmo o fato de estarmos lidando com software livre.
Muita gente costuma ter pesadelos com Linux, mas hoje em dia as coisas são bem mais simples e a tarefa de descobrir porque uma coisa ou outra não funcionou agora quase sempre se resume a colar o log ou erro em uma IA e esperar pela resposta, então, não há o que temer! 🙂
Para essa build em especifico, a distro escolhida foi o Xubuntu 26.04 Minimal, por ser bem ‘enxugado’ e a interface gráfica XFCE ser bastante leve com os seguintes passos no terminal para instalar o llama.cpp e suas dependências:
# Atualização do sistema/lista de repositórios
sudo apt update && sudo apt upgrade -y
# Ferramentas básicas de compilação e controle de versão
sudo apt install -y build-essential cmake git wget curl ca-certificates
# Dependências Vulkan (backend gráfico/ACPI)
sudo apt install -y mesa-vulkan-drivers libvulkan-dev vulkan-tools \
glslang-tools spirv-tools spirv-headers libshaderc-dev
# Suporte a requisições HTTP/HTTPS (usado pelo servidor)
sudo apt install -y libcurl4-openssl-dev
# Clonar o repositório do llama.cpp e compilar com suporte a Vulkan
git clone https://github.com/ggml-org/llama.cpp cd llama.cpp
cmake -B build -DGGML_VULKAN=ON
cmake --build build --config Release -j$(nproc)
Com isso, o llama.cpp já deve estar compilado e pronto para uso! Ai o próximo passo é baixar os modelos, no caso desse artigo, vamos testar duas opções:
- Qwen3.6-35B-A3B-MTP com quantização Q4_K_M:
Esse modelo Qwen é a escolha óbvia para o hardware que temos em mãos, já que ele usa arquitetura MoE ativando apenas 3 bilhões de parâmetros por token, o que faz dele uma opção sensata para quem precisa fazer offload para a memória do sistema. Além disso, ele é considerado extremamente capaz pelo tamanho, sendo útil para uso como agente ou código, o que torna ele muito mais do que apenas um ‘brinquedo’.
Apesar de ter utilizado o Q4_K_M, o Q8_0 ou Q8_K_XL, já rodaria tranquilo em uma configuração com 16GB de VRAM e 32GB de RAM principal, apesar que um pouco mais lento que os números que mostrarei adiante.
- GPT-OSS-120B
Essa pode ser uma escolha meio controversa, afinal, esse já é um modelo antigo e já existem coisas mais capazes com tamanho similar, entretanto, nenhuma das alternativas mais modernas ativa apenas 5B de parâmetros por token como é feito no GPT-OSS-120B, sendo essa uma boa opção para mostrar o que acontece quando se faz o offload de uma parte muito grande do modelo para a RAM, mesmo tendo uma GPU razoável com 16GB de VRAM no sistema.
Esse aqui é praticamente uma demonstração da Lei de Amdahl em ação, mostrando que não adianta muita coisa ter uma GPU super rápida, com grande largura de banda se na prática, ela corresponder a uma quantidade muito pequena da memória em uso pelo modelo, nesse contexto, é bom que ao menos metade do modelo caiba na VRAM.
Iniciando o Llama.cpp no terminal – Mas e os parâmetros?
Iniciar o Llama.cpp é uma tarefa simples e complexa ao mesmo tempo. É simples porque é só digitar um comando no terminal e é complexa porque existe uma infinidade de parâmetros que podem fazer uma diferença GIGANTESCA no desempenho! Abaixo temos os comandos com os parâmetros usados e uma breve explicação sobre eles:
Xeon 2699V3:
./llama.cpp/build/bin/llama-cli -m ‘/home/user/IA_Models/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf’ -c 170000 –spec-type draft-mtp –spec-draft-n-max 2 -t 18 -tb 18 -ngl 99 –n-cpu-moe 23 -b 2048 -ub 2048 -fa on -rea on
./llama.cpp/build/bin/llama-cli -m ‘/home/user/IA_Models/GPT-OSS-120B/gpt-oss-120b-Q4_K_M-00001-of-00002.gguf’ -c 131072 -t 18 -tb 18 -ngl 99 –n-cpu-moe 32 -b 2048 -ub 2048 -fa on -rea on
Xeon 1660V3:
./llama.cpp/build/bin/llama-cli -m ‘/home/user/IA_Models/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf’ -c 170000 –spec-type draft-mtp –spec-draft-n-max 2 -t 8 -tb 8 -ngl 99 –n-cpu-moe 23 -b 2048 -ub 2048 -fa on -rea on
./llama.cpp/build/bin/llama-cli -m ‘/home/user/IA_Models/GPT-OSS-120B/gpt-oss-120b-Q4_K_M-00001-of-00002.gguf’ -c 131072 -t 8 -tb 8 -ngl 99 –n-cpu-moe 32 -b 2048 -ub 2048 -fa on -rea on
1. Parâmetros de Modelo e Contexto
- -m … (–model): Define o caminho do arquivo GGUF do modelo que será carregado.
- -c 170000 (–ctx-size): Especifica o tamanho máximo do contexto, onde o limite desse valor varia de modelo para modelo. É bom lembrar que quanto maior o contexto, maior o uso de memória com KV Cache, então é bom ficar atento a isso.
2. Aceleração por GPU e Offloading de Memória (Vital para MoEs)
- -ngl 99 (–n-gpu-layers): Diz para o Llama.cpp fazer offload das camadas do modelo para a GPU. O valor 99 é um atalho para garantir que “todas as camadas possíveis” sejam transferidas para a placa de vídeo.
- –n-cpu-moe 23: Esse é o pulo do gato para modelos MoE que não cabem por completo na VRAM, ai essa flag serve para mantém os pesos dos “experts frios” das primeiras N (número setado ali) camadas na memória RAM do sistema e os envia para GPU pelo PCIe conforme necessário. Isso mantém o núcleo de atenção pesada na GPU, mas impede o erro de falta de VRAM (Out of Memory). Quanto menor esse valor, maior vai ser o uso de VRAM e a velocidade de execução, contudo, é preciso ficar esperto para não cair em OOM (Out of Memory) ou deixar as coisas lentas tentando usar toda a VRAM de uma GPU ligada a um monitor, já que o desktop também usa um pouco de memória de vídeo.
3. Aceleração de Processamento: Lotes e Micro-Lotes
- -b 2048 (–batch-size): Quantos tokens o sistema vai tentar reunir em uma rodada de processamento. É o “plano”, o total de trabalho que ele agenda para avaliar de uma vez.
- -ub 2048 (–ubatch-size): De quanto em quanto esses tokens são realmente enviados ao hardware (GPU/CPU) para calcular. É a “execução física”. Na prática, um ub maior (ou igual a b) pode tornar a execução mais rápida, por outro lado, usa mais memória e pode acabar crashando o sistema caso ela falte.
4. Otimização de Processador (CPU)
- -t 18 (–threads): Define a quantidade de threads do processador dedicadas à fase de geração sequencial dos tokens de resposta. É geralmente configurado para bater com o número de núcleos físicos dá máquina.
- -tb 18 (–threads-batch): Define as threads de CPU usadas especificamente durante o processamento em lote do prompt inicial. HT/SMT não se mostrou útil aqui, na verdade, até piorou as coisas, então use a contagem de núcleos e não threads aqui.
5. Recursos Avançados: Decodificação Especulativa, Memória e Raciocínio
- –spec-type draft-mtp: Ativa a “Decodificação Especulativa” utilizando Multi-Token Prediction (MTP). A mágica por trás desse recurso é que ele tenta prever os próximos tokens, transferindo um pouco do gargalo da banda de memória para compute, onde esse último geralmente está sobrando, acelerando a geração de tokens quando ele consegue acertar a previsão.
- –spec-draft-n-max 2: Em conjunto com o parâmetro anterior, limita as adivinhações do rascunho especulativo a 2 tokens por passo. Esse limite evita desperdício computacional caso o modelo comece a errar os palpites. Geralmente é interessante testar valores entre 1 e 4.
- -fa on (–flash-attn on): Ativa a implementação de Flash Attention, o que ajuda muito com contexto grande, reduzindo não só o uso de memória, como também o tempo computacional de cada token gerado.
- -rea on (–reasoning on): Habilita o recurso de mostrar o ‘thinking’ no chat.
Apesar de não ter usados essas flags aqui, elas também podem ser interessantes de se explorar:
- –cache-type-k/v + –cache-ram: Quantização e offload do KV Cache. Para contextos longos em VRAM limitada, são provavelmente os parâmetros de maior impacto no uso real.
- –jinja: Processamento de template. Necessário para modelos com reasoning estruturado formatarem corretamente o bloco de thinking. Um template errado pode levar a problemas como repetições no thinking ou uso excessivo de tokens nessa fase.
- –no-mmap: Força carregamento completo do modelo na RAM ao iniciar. Útil em servidores que já sabem qual memória vão usar, dispensando a sobrecarga de page faults do mmap.
- –-temp / –top-p / –min-p: Controle de aleatoriedade da geração. Não afeta velocidade, apenas o “tom” das respostas. Geralmente os laboratórios divulgam valores recomendados nesses parâmetros.
Benchmarks
Para testar o desempenho dessa máquina na inferência, foram utilizados os seguintes artifícios:
- A ferramenta de benchmark inclusa no llama.cpp, que permite medir a quantidade de tokens por segundo (t/s) no Prompt Processing (prefill) e no Token Generation de forma bruta, sem recorrer a recursos como MTP, Dspark e afins, até por que isso traria variabilidade ao benchmark, o que é ruim. É bom deixar claro que o gargalo do primeiro é mais limitado no processamento e o segundo pela banda de memória, ou seja, é possível ter uma geração de tokens satisfatória e o prefill lento.
- Uma combinação de 3 prompts seguidos em um servidor aberto com os parâmetros citados logo acima, esse com MTP ligado. O objetivo aqui é ter uma ideia do desempenho do conjunto em uma situação de uso real. Os prompts são os seguintes e foram executados após o fim da execução do prompt anterior, na mesma conversa:
- Faça um jogo pong html js
- Implemente efeitos sonoros no game
- Implemente uma tabela de high-score
Llama-Bench
Comandos:
Qwen3.6 35B A3B:
./llama.cpp/build/bin/llama-bench \
-m ‘/home/terminator-xeon/IA_Models/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf’ \
-t 18 \
-ngl 99 \
–n-cpu-moe 23 \
-b 2048 -ub 2048 \
-fa 1 \
-p 512 -p 8192 -p 65536 -p 128000 \
-n 128 -n 512 -n 1024 \
-r 3
GPT-OSS-120B:
./llama.cpp/build/bin/llama-bench \
-m ‘/home/terminator-xeon/IA_Models/GPT-OSS-120B/gpt-oss-120b-Q4_K_M-00001-of-00002.gguf’ \
-t 18 \
-ngl 99 \
–n-cpu-moe 33 \
-b 2048 -ub 2048 \
-fa 1 \
-p 512 -p 8192 -p 65536 -p 128000 \
-n 128 -n 512 -n 1024 \
-r 3

Nesse primeiro teste, as memórias bem mais rápidas do 1660 v3 acabaram por empurrar ele a frente do 2699 v3 na maioria dos testes, ainda que a diferença tenha sido pequena. Na geração de tokens, ele foi cerca de 5% mais rápido, enquanto no prefill, ele começou com uma vantagem de 7.1% com um prompt curto, com a vantagem caindo para 5.6% com 4096 e o 2699 v3 conseguindo buscar com 8192.
Em relação aos números brutos, eles são bons o suficiente para garantir uma experiência de uso decente, batendo ao menos 40 t/s com ambos processadores e prefill dentro do aceitável.
Teste prático – Qwen3.6 35B


Na prática, os resultados seguiram semelhantes ao benchmark ‘teórico’, com o 2699 v3 se destacando no prefill, ainda que curiosamente, ele tenha perdido por uma margem razoável para o 1660 v3 após o terceiro prompt.
Já na geração de tokens, com ajuda de artificios como MTP, foi possível empurrar dos cerca de 40 t/s brutos para algo próximo dos 60 t/s, o que é bastante rápido e totalmente confortável para uso como agente.
É claro que com longos contextos essa velocidade deve cair, mas o ponto é que mesmo que caia pela metade, o que seria um exagero, ainda sim continuaria decente o suficiente para uso.
Teste prático – GPT-OSS-120B


Já com o GPT-OSS-120B, que é um modelo com muito mais parâmetros que o Qwen que testamos, fica evidente o quanto a CPU/Memórias acabam dominando muito mais do que a GPU, algo que como explicamos anteriormente, se deve a lei de Amdahl, com mais da metade do modelo sendo jogado para a RAM.
Esse cenário se repetiria mesmo usando uma GPU muito mais moderna e rápida, por exemplo, uma RTX 5080, onde talvez os números fossem um pouco melhores, mas ainda deixariam muito a desejar em relação ao potencial da placa de vídeo, ou seja, assim como acontece em um PC Gamer, um servidor de IA também tem seus gargalos e precisa ser bem balanceado para se obter bons resultados!
Consumo
Um detalhe que não poderia faltar é o consumo e visando tornar a máquina mais eficiente possível, foi feito undervolt na GPU com os parâmetros abaixo:
Assim, com o 1660 v3 em 3.9 GHz com 1.025V no vcore, o consumo total da máquina medidos direto da tomada durante a geração de tokens ficou em 310W, enquanto que com o 2699 v3 foi de 285W.
Apesar de parecer contraditório isso pode ser facilmente explicável, já que os 18 cores do 2699 v3 passam longe da plena carga, além do subsistema de memória estar bem mais relaxado, já que ele não permite frequências acima dos 2133 MHz.
Conclusão
Diante do apresentado, fica claro que a plataforma X99 ainda pode ser uma alternativa viável para um servidor local de IA, especialmente quando o objetivo é rodar modelos MoE com offload controlado para RAM. A RX 6800 XT, apesar de ser RDNA2, por ter 16GB de VRAM e boa banda de memória, ainda entrega desempenho confortável em modelos como o Qwen3.6-35B-A3B-MTP na quantização Q4_K_M, especialmente com recursos como MTP habilitados, mas nesse contexto, outra GPU moderna com 16GB de VRAM também daria renderia bons resultados.
Já em modelos maiores, como o GPT-OSS-120B, o gargalo migra fortemente para CPU/RAM/banda de memória. Nesse cenário, a GPU acaba subutilizada, e o usuário precisa aceitar velocidades menores ou investir em mais VRAM/múltiplas GPUs.
Em relação aos processadores, a diferença entre 1660 v3 e 2699 v3 foi pequena, com o primeiro tendo sido um pouco mais rápido na geração de tokens, muito provavelmente por conta das memórias com overclock para 3200 MT/s e algumas centenas de MHz a mais nos núcleos da CPU, algo que não é possível de se fazer no 2699 v3.
O ponto principal é que o 2699 v3 costuma ser mais barato, consome menos e em plena crise das memórias, está confortável em rodar com apenas 2133 MT/s, até porque não existe possibilidade de ir além, o que racionalmente faria dele ou de algum outro Xeon V4 a escolha para um projeto como esse.
Em resumo, IA local é possível sem gastar fortunas com hardware! De tudo, saibam que essa é uma série, onde no próximo artigo, irei abordar um sistema mais moderno com arquitetura UMA, ou seja, memóra unificada e ainda relativamente acessível, feitas as devidas ressalvas pela atual situação do mercado, então fiquem ligados!








