Como a inference acompanha nossa necessidade insaciável por tokens — Cerebras e Gimlet Labs
Autoria: AI Engineer · Assistir no YouTube
Vídeo de autoria do canal indicado, não da IANIA; todos os direitos pertencem ao criador. Transcrição, resumo e tradução gerados automaticamente; o conteúdo no idioma original é preservado na versão em idioma original.
Idioma original: inglês
Vídeo original: How Inference Keeps Up with Our Insatiable Need for Tokens — Cerebras & Gimlet Labs · Canal: AI Engineer · 22:44 · Assistir no YouTube
Tópicos: Agentes de IA, Inferência e otimização de modelos, Infraestrutura e hardware de IA
Daniel, da Cerebras, e Michelle, da Gimlet Labs, apresentam técnicas que tornam a inference de LLMs mais rápida e eficiente, desde otimizações de memória e batching até a distribuição de cargas entre diferentes máquinas. Eles explicam como as fases de prefill e decode têm necessidades distintas e como disaggregação e speculative decoding podem melhorar velocidade e throughput. A conversa também aborda o uso de hardware especializado e de agentes para otimizar kernels. Os palestrantes concluem que há muitas oportunidades para reduzir custos e acelerar a geração de tokens.
Pontos-chave
Seção intitulada “Pontos-chave”- Na geração autoregressiva, cada token exige a leitura dos pesos do modelo, o que pode deixar o compute ocioso à espera da memória.
- O batching contínuo aproveita períodos ociosos para processar outras solicitações, mas aumenta a demanda por KV cache.
- Paged KV cache reduz o desperdício de memória, enquanto prompt caching reutiliza cálculos de solicitações anteriores.
- Chunked prefill divide prompts longos em partes menores para evitar que eles bloqueiem outras solicitações.
- Prefill tende a ser limitado por compute, enquanto decode tende a ser limitado pela largura de banda da memória.
- A disaggregação permite distribuir fases ou componentes do workload por máquinas mais adequadas a cada tarefa.
- Speculative decoding usa um modelo menor para propor tokens e um modelo completo para verificá-los.
- A Gimlet Labs afirma que seu sistema multi-silicon pode acelerar a inference de três a dez vezes em comparação com sistemas homogêneos com o mesmo orçamento de energia.
- A Gimlet Labs usa o agente KForge para gerar kernels otimizados; os palestrantes relatam uma melhoria de 33% em GPT-OSS-120B em hardware AMD.
- Agentes também podem ajudar a otimizar operações de infraestrutura, adaptar modelos a diferentes hardwares e acelerar o desenvolvimento de software e silício.
Capítulos
Seção intitulada “Capítulos”| Início | Capítulo | Resumo |
|---|---|---|
| 00:01 | A demanda crescente por tokens | Os palestrantes apresentam o crescimento dos gastos com compute e da demanda por tokens, além do objetivo de tornar a inference mais rápida e barata. |
| 02:07 | Uso de compute, batching e KV cache | A apresentação explica o custo de comunicação ao dividir o modelo entre GPUs e descreve continuous batching, paged KV cache e prompt caching. |
| 07:13 | Prefill, decode e chunked prefill | Os palestrantes comparam as fases de prefill e decode e mostram como chunked prefill evita que prompts longos bloqueiem a fila. |
| 09:16 | Disaggregação entre workers e hardwares | A conversa aborda como distribuir fases e workloads entre máquinas com recursos adequados às necessidades de compute e memória. |
| 13:27 | Nuvem multi-silicon e speculative decoding | A Gimlet Labs descreve seu sistema multi-silicon, e os palestrantes explicam como speculative decoding pode aumentar a velocidade da geração. |
| 17:02 | Disaggregação por camada e kernels otimizados | Os palestrantes discutem a separação das camadas de attention e FFN e apresentam o agente KForge para otimizar kernels. |
| 20:07 | Agentes e o futuro da otimização | A conversa explora o uso de agentes para desenvolver silício e software especializados, melhorar operações e acelerar a inference. |
| 22:11 | Encerramento | Os palestrantes agradecem ao público e reforçam o objetivo de oferecer tokens mais rápidos e baratos. |
Citações
Seção intitulada “Citações”Até 90% do tempo, o computador fica esperando a memória carregar. — 02:07
A ideia é dividir um prefill muito longo em partes menores. — 09:16
Não existe uma forma única de disaggregação que seja a melhor. — 18:03
Estamos trabalhando muito para oferecer tokens mais rápidos e baratos. — 22:11
Conceitos e entidades
Seção intitulada “Conceitos e entidades”- Cerebras (empresa): Empresa de IA que desenvolve hardware e sistemas voltados à execução de modelos.
- Gimlet Labs (empresa): Empresa que está desenvolvendo uma nuvem de inference multi-silicon para distribuir workloads entre diferentes hardwares.
- Daniel (pessoa): Profissional de IA e agentes na Cerebras que apresenta as otimizações de inference.
- Michelle (pessoa): Cofundadora da Gimlet Labs que apresenta técnicas de disaggregação e otimização de workloads.
- continuous batching (conceito): Técnica que preenche períodos ociosos de processamento com novas solicitações.
- paged KV cache (conceito): Abordagem que aloca blocos de memória de forma flexível para armazenar o KV cache das solicitações.
- prompt caching (conceito): Reutilização do KV cache de partes do prompt já processadas em solicitações anteriores.
- chunked prefill (conceito): Divisão do prefill de um prompt longo em partes menores que podem ser intercaladas com outras solicitações.
- prefill-decode disaggregation (conceito): Separação das fases de prefill e decode em conjuntos distintos de workers.
- speculative decoding (conceito): Técnica que usa um modelo menor para propor tokens e um modelo completo para verificar as propostas.
- KForge (ferramenta): Agente da Gimlet Labs que gera e otimiza kernels com base em perfis de hardware e de workloads.
- GPT-OSS-120B (modelo): Modelo citado na apresentação como exemplo de otimização de inference em hardware AMD.
- AWS Trainium (ferramenta): Acelerador da AWS mencionado como hardware para executar a fase de prefill.
- NVIDIA (empresa): Empresa citada como fornecedora de hardware que pode integrar uma infraestrutura multi-silicon.
- AMD (empresa): Empresa cujo hardware é citado em um exemplo de otimização do GPT-OSS-120B.
- Anthropic (empresa): Empresa citada em um exemplo de desenvolvimento de um compilador para inference.
Tradução completa (pt-BR)
Seção intitulada “Tradução completa (pt-BR)”00:01 [música] >> Olá a todos. Meu nome é Daniel. Trabalho com IA e agents de IA aqui na Cerebras. Qual é o seu nome? >> Sou Michelle. Sou cofundadora da Gimlet Labs, onde estamos criando uma neocloud multissilício para otimizar a inference em todas as camadas da stack. >> E estamos muito animados para apresentar nossa palestra: todas as coisas que precisamos fazer
00:32 para satisfazer sua insaciável necessidade de tokens. Como vocês sabem, os gastos com IA estão meio fora de controle agora. Neste ano, devemos gastar US$ 765 bilhões em computação e, em 2031, até US$ 1,6 trilhão. Os laboratórios de fronteira estão numa corrida frenética para garantir o máximo possível de capacidade computacional, comprando de fornecedores de hardware para treinar os modelos de fronteira e também atender a todos os seus usuários. E toda
01:03 essa capacidade computacional vai satisfazer a insaciável necessidade de tokens de todo mundo. No IO do ano passado, o Google disse que estava atendendo a 480 trilhões de tokens por mês. E, no mês passado, disse que esse número havia saltado para 3,2 quatrilhões de tokens por mês. Tudo isso está acontecendo ao mesmo tempo que os modelos ficam mais baratos e rápidos. O Llama 3.3 70B, em comparação com quando foi lançado, agora está 25% mais barato
01:34 e, ainda assim, é 3,6 vezes mais rápido. Então, na palestra de hoje, vamos falar sobre duas coisas. Primeiro: o que fizemos até agora para otimizar a inference e torná-la mais barata e rápida? E como é o roteiro para aumentar ainda mais o desempenho e a taxa de processamento? Para isso, vamos dar um salto no tempo até 2022 e conhecer todas as otimizações que nos trouxeram até onde estamos agora e, esperamos, o que o futuro nos reserva. Então, os LLMs produzem tokens um de cada vez
02:07 em algo chamado loop autorregressivo. Então, para gerar mais um token, é preciso ler todos os pesos da memória para a computação. Por isso, na maior parte do tempo, o computador fica ocioso. Ele fica apenas esperando a memória transmitir todos os pesos necessários para realizar a computação. Então, até 90% do tempo, o computador fica parado esperando a memória carregar os dados. Como podemos otimizar isso para reduzir o tempo ocioso, aproveitar ao máximo os recursos e atender mais rápido às solicitações de tokens?
02:37 Uma coisa que você pode fazer é adicionar mais poder computacional ao problema. Então, em vez de transmitir o conjunto inteiro de pesos, e se você pudesse dividir todo o modelo em quatro partes e deixar cada GPU cuidar de um quarto do modelo? Assim, em teoria, você poderia reduzir em quatro vezes o tempo necessário para atender a um único token. No entanto, há um custo para fazer isso. Antes do bloco de atenção e depois o F… Então, depois do bloco de atenção e do bloco FFN, é preciso fazer algo chamado all-reduce, em que você pega cada um dos
03:08 cálculos individuais de cada GPU e combina tudo. Assim, você consegue obter um cálculo, porque cada GPU não tem o quadro completo. Ela só executa um quarto do modelo. Então, é preciso fazer isso em cada camada, duas vezes, o que pode resultar em apenas 2 vezes mais velocidade, mesmo adicionando 4 vezes mais poder computacional. Se eu representasse isso num gráfico bonito, vocês veriam que adicionar mais GPUs ao problema realmente acelera a geração de tokens, mas exige exponencialmente mais energia para atender a um único token à medida que
03:39 se adiciona mais poder computacional ao problema, por causa da sobrecarga de comunicação de que acabamos de falar. Então, se invertermos aqui o eixo Y para mostrar a taxa de processamento, dá para ver que isso se parece com uma fronteira de Pareto, em que é preciso fazer algum tipo de concessão entre taxa de processamento e velocidade quando se é um provedor de inference. Um ótimo exemplo disso é o modo rápido do Claude Code, em que você pode gastar, acho, 6 vezes mais tokens para atender a um único token, em comparação com o Claude normal, para ter o dobro da velocidade. Então, nesse produto, eles estão realmente otimizando
04:10 para o lado direito da fronteira de Pareto, onde conseguem velocidade, mas ao custo de não poder atender a tantos tokens. Então, na palestra de hoje, vamos falar sobre as inovações que fizemos no passado e faremos no futuro para deslocar a fronteira de Pareto para a direita. Como vocês já sabem pelos slides anteriores, para gerar cada token, é preciso ler o modelo inteiro. E se pudéssemos aproveitar uma passagem pela qual já pagamos para atender a várias solicitações? É aí
04:40 que entram as ideias de batching e batching contínuo. A ideia do batching é aproveitar uma leitura de pesos que já foi feita para atender a várias solicitações de usuários. Mas o problema é que algumas dessas solicitações são mais longas do que outras, o que cria todos esses períodos ociosos na computação, em que nada acontece. Como podemos resolver isso e extrair mais desempenho? É aí que entra o batching contínuo. A ideia é que, para cada
05:11 intervalo ocioso, você encaixe uma nova solicitação de usuário para ser atendida durante essa mesma leitura de pesos, a fim de atender ao máximo possível de solicitações. No entanto, isso tem uma pequena desvantagem, porque, na inference, cada token exige que algo seja salvo no KV cache, pois é assim que funciona o bloco de atenção. É preciso saber, para cada token, quais são os vetores K e V. Isso pode aumentar muito rapidamente. Então, se você estiver executando um agent de programação com um
05:41 contexto muito longo — por exemplo, um context de 128k —, vai salvar 42 gigabytes de KV cache necessários para atender àquela solicitação específica. Então, a regra geral para um modelo de 70 bilhões de parâmetros é que, a cada 3.000 tokens, você precisa de 1 GB adicional de KV cache. E isso para uma única solicitação de usuário. Imagine que você esteja fazendo batching com, digamos, oito solicitações diferentes ao mesmo tempo: o KV cache vai explodir, e você não terá memória suficiente para atender a todas as solicitações. Então, quais são algumas das inovações que fizemos para
06:11 otimizar o uso da memória? É aí que entra o paged KV cache. Tradicionalmente, o KV cache funcionava assim: você reservava memória física para garantir que houvesse espaço suficiente para armazenar na memória todas as informações de KV de cada solicitação. Mas isso tinha uma desvantagem e gerava muita ineficiência, porque muitos blocos de memória ficavam reservados sem serem usados de fato. A ideia do paged KV cache é
06:41 usar algo parecido com um sistema operacional ou uma máquina virtual, em que você provisiona um bloco inteiro de memória virtual e pode armazenar o KV cache de cada solicitação onde houver espaço livre. Isso permite atender a três vezes mais solicitações do que sem o paged KV cache, usando apenas o método anterior. E isso reduz bastante o espaço desperdiçado, em que você reserva posições de memória sem usá-las de fato. Logo depois, veio uma inovação chamada prompt caching. Então,
07:13 a ideia é que, se você tem um agent de programação ou um aplicativo de bate-papo com um system prompt muito longo, não precisa recalcular o KV cache necessário toda vez que recebe uma solicitação. Você pode reutilizar o KV cache que já calculou para a solicitação anterior na próxima solicitação. Assim, basta continuar de onde parou. Desse modo, você pode pular a fase de prefill, que consome muito, muito tempo. E talvez você esteja se perguntando: o que é prefill? Na inference, dá para dividir
07:44 o que acontece em duas fases principais: prefill e decode. A fase de prefill inclui tudo o que acontece desde a chegada da solicitação até a geração do primeiro token. Você pode ver isso quando digita algo no ChatGPT: leva alguns segundos até ele começar a retornar o primeiro token e, depois, o processo segue de forma mais ou menos fluida. Então, o que acontece durante esses primeiros segundos, enquanto ele não retorna nada, é que ele calcula os vetores K e V para cada token do prompt que você inseriu e produz os
08:15 primeiro token de saída. Isso exige muito poder computacional, porque dá para otimizar isso demais. É possível paralelizar isso bastante. No entanto, depois que o primeiro token é gerado, o que acontece é que você decodifica um token por vez, reutilizando o KV cache que acabou de criar na fase de prefill. Então, isso depende mais da memória. Estou falando disso porque aconteceu algo recentemente que está atrapalhando muitos pipelines de inference: coding agents que consomem muitos, muitos tokens. Então, vamos
08:46 supor que você tenha um coding agent usando um contexto de 200K, 500K ou um milhão, certo? O que acontece é que ele começa a sobrecarregar o pipeline. Enquanto o prefill está em execução, nenhuma outra solicitação de prefill ou decode consegue passar. Isso é meio catastrófico se você tem várias pessoas enviando solicitações de programação e algumas outras tentando resolver problemas de matemática no modo de chat. Para evitar esse problema de congestionamento, existe uma inovação chamada prefill em blocos, que resolve
09:16 esse problema. E a ideia aqui é bem simples: pegar um trecho muito longo de prefill e dividi-lo em partes menores, para poder intercalar diferentes solicitações de decode e prefill. Assim, uma única tarefa não toma muito tempo nem congestiona todo o pipeline. Então, Michelle, conte-nos mais sobre o que mais podemos otimizar. >> Sim, todas as otimizações de que Daniel acabou de falar são otimizações no nível de execução. Isso explica como exploramos maneiras de tornar a inference mais
09:47 eficiente dentro de um único worker. Mas, para continuarmos avançando nessa fronteira, precisamos começar a analisar otimizações no nível do sistema: como distribuir essas cargas de trabalho entre muitos workers diferentes. A primeira coisa a reconhecer é que cada solicitação é diferente. Por exemplo, considere um caso de uso de sumarização. Você envia vários documentos para o LLM e quer obter a resposta a uma única pergunta. Portanto, essa carga de trabalho terá um prompt longo e uma resposta curta. Assim, ela é dominada pela
10:18 fase de prefill e, portanto, limitada pelo poder computacional. Por outro lado, pode haver um caso oposto. Digamos que você queira escrever uma história longa ou um livro e só queira passar alguns temas para servir de orientação. Nesse caso, você terá um prompt curto e uma resposta longa. A carga de trabalho será dominada pelo decode, porque você terá muitos tokens de saída em comparação com o número de tokens de entrada. E ela será limitada pela memória. Por fim, pode haver um caso intermediário, certo? Tanto o prompt quanto a resposta são longos, e
10:48 vemos aqui que tanto as fases de prefill e decode quanto o poder computacional e a memória são importantes. Ao observar esses exemplos diferentes, fica claro que os requisitos de recursos do hardware são bem diferentes, dependendo da carga de trabalho. Então, como evitar ficar limitado pelo poder computacional ou pela memória? Uma maneira de fazer isso é chamada de desagregação: dividir a carga de trabalho entre diferentes nós worker. E a forma mais comum é chamada de
11:19 desagregação de prefill e decode, em que você de fato divide e desagrega essa carga de trabalho por fase. Isso permite, essencialmente, ter dois grupos. Você tem o grupo de prefill, que executa a parte de prefill da carga de trabalho, e o grupo de decode, que executa a parte de decode. Por exemplo, no caso de uso de sumarização, você vai querer aumentar a escala do grupo de prefill para não ficar limitado pelo poder computacional e reduzir a escala do grupo de decode, porque não quer desperdiçar recursos quando simplesmente não há tanto trabalho de decode a fazer.
11:51 E isso é bom porque agora você pode ajustar a escala de cada um de forma independente, sem que uma parte atrase a outra. E podemos ir um passo além, certo? Dissemos antes que a carga de trabalho de prefill é inerentemente limitada pelo poder computacional, enquanto a de decode é limitada pela memória. Repassando isso rapidamente: durante o decode, você percorre cada um desses tokens, um por um, e em cada etapa de decode relê todo o KV cache, certo? Isso é limitado pela memória. >> Então, sim, o que Michelle acabou de dizer sobre isso ser limitado pela memória pode ser claramente percebido pelo que o hardware realmente consegue fazer. GPUs, certo? A velocidade com que se transferem dados da memória para o processamento é limitada por algo chamado largura de banda da memória. Para uma H100, isso equivale a 3,35 terabytes por segundo. No entanto, a Cerebras tem 7.000 vezes a largura de banda de uma H100, com 21.000 terabytes por segundo. Isso acontece porque temos uma arquitetura de memória baseada em SRAM bastante especializada no nosso chip.
12:24 Como acabamos de dizer, o fato de isso ser limitado pela memória fica muito claro pelo que o hardware consegue fazer de fato. Então, GPUs, certo? A velocidade com que você consegue transferir dados da memória para o processamento é limitada por algo chamado largura de banda da memória. Para uma H100, isso equivale a 3,35 terabytes por segundo. No entanto, a Cerebras tem uma largura de banda 7.000 vezes maior que a de uma H100: 21.000 terabytes por segundo. Isso acontece porque temos uma arquitetura de memória baseada em SRAM muito especializada no nosso chip.
12:56 Isso significa que a Cerebras foi realmente projetada para decode. Assim, podemos processar 3.000 tokens por segundo, enquanto uma H100 processa 600 tokens por segundo em decode. Estamos muito animados para trabalhar com a AWS para levar isso à produção. Vamos trabalhar com a AWS Trainium para que ela execute o prefill usando seus chips AWS Trainium, usar o serviço EFA para transferir o KV cache para os nossos sistemas Cerebras CS-3 e, por fim, processar o token. Isso nos permitirá
13:27 ter uma capacidade de tokens em alta velocidade 5 vezes maior no mesmo espaço. Essa é uma das coisas que estamos fazendo para tornar a inference rápida mais acessível e barata para os desenvolvedores. Estamos muito animados para levar essa parceria adiante. >> Na Gimlet, estamos generalizando essa abordagem para além de apenas Trainium e Cerebras. O que a Gimlet está desenvolvendo é, essencialmente, uma nuvem de inference multissilício, que recebe sua carga de trabalho, divide-a em partes menores, determina as características de recursos de cada uma dessas partes e, então, descobre a melhor maneira de mapeá-las para o hardware subjacente, que
13:58 pode ser praticamente qualquer hardware, certo? Nvidia, AMD, Trainium, Cerebras, D-Matrix, Intel Gaudi. A lista continua. Ao executar essas tarefas na máquina mais eficiente para elas, estamos vendo resultados bem impressionantes. A inference fica de três a dez vezes mais rápida em comparação com sistemas homogêneos com o mesmo orçamento de energia. Isso vai além da desagregação entre prefill e decode mencionada antes. Algumas dessas técnicas, por exemplo, desagregam por modelo em vez de
14:28 por fase. Isso se chama speculative decoding. Para recapitular a fase de decode: normalmente, você faz uma passagem forward para cada token de decode que obtém. Essa é a forma padrão de fazer isso. O speculative decoding funciona assim: você tem um modelo de rascunho. Trata-se de uma versão menor do modelo completo, que geralmente consegue aproximar os resultados que ele produz. Como é menor, ele executa bem mais rápido e também usa menos recursos. Então, no speculative decoding, o que você pode fazer é,
15:00 para obter, digamos, os nove próximos tokens, executar primeiro o decode nesse modelo de rascunho. Ele retornará o que chamamos de tokens candidatos. Você não tem certeza absoluta de que todos esses tokens estão corretos, mas, como muitas vezes eles foram submetidos a fine-tuning ou treinados com base no modelo completo, são aproximadamente corretos. Você quer validar: esses são os tokens que realmente quero emitir? Então, executa a próxima etapa no modelo completo, chamada etapa de verificação, para validar quais desses tokens estão corretos.
15:30 E, essencialmente, você pode continuar fazendo isso até validar todos esses tokens do modelo de rascunho. No fim das contas, como você pode ver aqui em cima, no método padrão seria necessário executar a passagem forward no modelo completo nove vezes para obter aqueles nove tokens. Por outro lado, com speculative decoding, foi necessário executá-la apenas três vezes no modelo completo. E, se você conseguir fazer esse modelo de rascunho executar muito, muito rápido, esse tempo será mínimo e você poderá reduzir bastante o tempo necessário para obter seus tokens. E, observando alguns exemplos mais concretos
16:00 resultados, então essa é essencialmente a fronteira de Pareto que Daniel mostrou antes, em que o eixo x é a velocidade com que você recebe os tokens e o eixo y é a taxa de transferência. E o caso de referência com o qual estamos comparando aqui é a separação entre prefill e decode em GPUs homogêneas. Dá para ver que a taxa de transferência é muito boa, mas, assim que você aumenta a velocidade, ela cai bastante. E se você executar speculative decode nessas mesmas GPUs? Aí você executa aquele modelo rascunho e consegue ver que é possível chegar a
16:31 essa curva mais à direita. Isso acontece porque você executa o decode com o modelo completo menos vezes. Mas podemos ir ainda mais longe, certo? Voltando ao nosso tema de executar essas cargas de trabalho no hardware que consegue executá-las melhor. Em algo como D Matrix ou Cerebrus, em que é possível executar modelos pequenos muito, muito rapidamente, vemos melhorias drásticas de desempenho. Aqui, esses são os números para a mesma taxa de transferência, certo? Você consegue 10 vezes mais interatividade do que se estivesse executando isso apenas em
17:02 máquinas homogêneas. A forma final de separação de que queríamos falar se chama separação entre attention e FFN. E essa fica bem interessante quando pensamos em servir modelos grandes. Estou falando de modelos com 3 trilhões de parâmetros, tão grandes que até executar uma única camada pode exigir muitos recursos. Então, o conceito é essencialmente o mesmo, certo? Para aquela tarefa específica que você precisa realizar, seja a camada de attention ou a camada da rede feedforward FFN, você
17:32 basicamente tenta descobrir quais são as características de recursos e, então, qual é o melhor hardware para mapeá-la. A camada de attention exige mais memória. Ela faz muitos acessos ao cache de KB. A camada FFN faz muitas multiplicações densas de matrizes. Então faz sentido, certo? Você executa a attention na máquina que tem largura de banda de memória e a camada FFN nas máquinas que conseguem executar essas multiplicações de matrizes o mais rápido possível. E, essencialmente, o que acontece aqui é que, mesmo dentro do modelo, você alterna entre várias máquinas diferentes para obter
18:03 a inference desse modelo, separando de fato cada camada. E uma coisa que queríamos destacar é que não existe uma melhor forma de separação. Na verdade, não existe um melhor hardware. Isso depende muito das compensações que você precisa fazer, dependendo do modelo, da carga de trabalho, da latência necessária e das garantias de taxa de transferência de que você precisa. E, olhando para o futuro, vemos que os agents estão cada vez mais incorporados ao nosso cotidiano. Estão incorporados ao nosso trabalho.
18:35 Todo mundo está usando. E isso continua aumentando a necessidade de mais tokens e tokens mais rápidos. >> Sim, está mesmo apontando para a direita. >> Eu [risos] disse ao Daniel para não falar isso. Mas o bom é que, embora isso pareça uma meta maluca, podemos usar agents para nos ajudar a resolver esses problemas e continuar avançando a fronteira. Uma das coisas que estamos fazendo na Gimlet é usar um agent para gerar kernels otimizados. Especialmente no nosso caso de uso, em que queremos dar suporte a uma variedade tão ampla de tipos diferentes de hardware, precisamos
19:06 descobrir como tornar esse problema muito mais tratável. Porque, hoje, a maneira como as pessoas geram e otimizam kernels é passar muito tempo ajustando-os manualmente e tentando descobrir como otimizá-los. E o fato é que essas otimizações podem variar bastante, dependendo do modelo que você está tentando executar, do hardware usado e até mesmo da geração do hardware, além do formato da própria carga de trabalho. Então, o que fazemos na Gimlet é criar o KForge, um agent para gerar esses kernels. Ele
19:37 recebe várias informações, como os perfis do seu hardware, os perfis da sua carga de trabalho e basicamente qualquer coisa que possa ajudar a descobrir como otimizar kernels, e resolvemos isso como um problema de força bruta, certo? Aqui está um exemplo: temos uma passagem forward e o kernel que o KForge otimizou a partir dela. Estamos vendo resultados bem interessantes. Na semana passada, o agent estava em execução havia provavelmente menos de uma semana e, nesse período, conseguiu acelerar o GPT-OSS-120B em hardware AMD em 33% de ponta a ponta. E
20:07 o interessante a observar aqui é que isso se baseia em kernels que já foram otimizados. Podemos levar os agents ainda mais longe e usá-los para nos ajudar a criar e projetar silício personalizado, altamente ajustado para modelos específicos ou para a sua carga de trabalho específica. Isso pode então ser usado para treinar uma IA ainda melhor, mais inteligente e mais rápida, que também pode ser usada para projetar a próxima geração desse silício personalizado. E esse ciclo continua indefinidamente; é um ciclo recursivo. Um salve para o pessoal da
20:39 Recursive. >> E quero encerrar a apresentação dizendo que estamos apenas começando nossa jornada para otimizar a taxa de transferência e a velocidade da inference. Porque, no topo da pilha, você não pensa muito em otimização de inference quando fala, por exemplo, de resposta a incidentes, certo? Mas, quando temos agents que tornam nossos sistemas muito mais confiáveis e aumentam o tempo de atividade, conseguimos mais taxa de transferência e mais tokens. >> Ou você pode aplicar agents ao problema de colocar modelos em funcionamento. Assim que um
21:09 modelo chega ao mercado, colocá-lo para funcionar em todos os diferentes tipos de hardware já no primeiro dia. >> Dá até para ir um pouco além com compiladores. Imagine um mundo em que a inference possa ser criada sob medida para a sua carga de trabalho e para o modelo que você está executando. Isso já está sendo demonstrado pelo pessoal da Anthropic, certo? Eles criaram um compilador em 2 semanas. Então, acho que há muitas otimizações que você pode fazer ao criar software personalizado just-in-time para dar suporte ao modelo que quer executar, à carga de trabalho em que quer executá-lo e ao seu hardware personalizado. >> E, voltando ao slide anterior
21:40 slide, usando agents para continuar nos ajudando a criar mais silício personalizado e a acelerar o processo de tape-out. >> E, por fim, esta é a parte menos técnica, mas trata de tudo o que envolve servir inference: todas as compras, todos os aspectos jurídicos e tudo o que acontece nos bastidores. Todas essas coisas podem ser otimizadas em conjunto com workflows agentic. Então, quando fazemos tudo isso, fico muito otimista em relação ao futuro e a tudo o que podemos realizar para servir tokens com mais rapidez e a um custo menor.
22:11 Então, próximo slide, por favor. Muito obrigado por virem à nossa apresentação. Estamos trabalhando muito, muito duro para oferecer tokens mais rápidos e baratos. E avisem se tiverem alguma pergunta. Estaremos por aqui depois da apresentação. >> Sim, e vão consumir tokens. Estamos criando mais tokens para vocês, assim também podem gerar GIFs como este. >> Sim. >> [risos]
22:44 [música]
Transcrição original
[00:01] [music] >> Hello everyone. My name is Daniel. I work on AI and AI agents here at Cerebras. What’s your name? >> I’m Michelle. I’m a co-founder at Gimlet Labs where we’re building a multi-silicon neo cloud to optimize inference at every layer of the stack. >> And we’re really excited to bring you our talk, all the things we have to do
[00:32] to satisfy your insatiable need for tokens. As you know, AI spend is going kind of bananas right now. With this year we’re slated to spend $765 billion on compute and in 2031 up to $1.6 trillion. The frontier labs are having a mad dash to secure as much compute as possible to buy across hardware vendors to do both training for the frontier models as well as to serve all of their users. And all
[01:03] of their compute is going to satisfy everyone’s insatiable need for tokens. Google at their IO last year said that they were serving 480 trillion tokens per month. And last month they said that it jumped up to 3.2 quadrillion tokens per month. So all of this is happening at the same time as models are getting cheaper and faster. Lama 3.37 B when it was first released compared to now is now 25% cheaper
[01:34] whilst still being 3.6 times faster. So in today’s talk we’re going to talk about two things. One, what have we done so far to optimize inference to make it cheaper and faster. And what does the road map look like to juice perf and throughput even further? So to do this, let’s take a little bit of a time jump to 2022 and learn about all the optimizations that led us to the point we’re at now and hopefully what the future looks like. So, LLMs produce tokens one at a time
[02:07] in something called an auto-regressive loop. So, to generate one additional token, you need to read all of the weights from memory into compute. So, most of the time, the computer is sitting idle. It’s just waiting for memory to be able to stream in all the weights necessary to do the compute itself. So, up to 90% of the time, the computer is just sitting there waiting on memory to load. So, how can we figure out how to optimize this so there’s less idle time and you can make full advantage and serve tokens faster?
[02:37] So, what you can do is throw more compute at the problem. So, instead of streaming in the whole set of weights, what if you could split up the entire model into four and have each GPU take care of a fourth of the model each? Then, you could reduce, in theory, the amount of time it takes to serve a single token by four times. However, you have to pay a tax if you want to do this. Before the attention block and then the F So, after the attention block and then the FFM block, you have to do something called all-reduce, where you take each of the
[03:08] individual calculations from each GPU and you combine it all together. So, you can actually get a calculation because each of the GPUs doesn’t have the whole picture. It only does 1/4 of the model. So, you need to do this across every layer twice, which can lead to only getting 2x speed up for getting 4x the amount of compute that you add on. If I were to graph this in a pretty graph, um you can see that throwing more GPUs at the problem does get you faster tokens, but it requires exponentially more energy to serve a single token as
[03:39] you put in more compute at the problem because of the communication overhead we just talked about. So, if we flip the Y axis here so it’s throughput, you can see that this resembles something like a Pareto frontier, where you can see that you have to make some kind of sacrifice between throughput and speed when you’re an inference provider. A great example of this is Claude code fast mode, where you can spend, I think, 6x the amount of tokens to serve a single token compared to regular Claude for twice the speed. So, for that product, they’re really optimizing
[04:10] towards the right of the Pareto frontier, where they’re getting the speed, but at the cost of not being able to serve as many tokens. So, during today’s talk, we’re going to talk about what are the innovations we have done in the past and in the future to be able to shift the Pareto frontier to the right. So, you all already know from our previous slides that to generate each token, you have to read the whole model. So, what if we could spend one pass that we already paid for to serve multiple requests? So, that is
[04:40] where the idea of batching and continuous batching comes in. The idea of batching is when you take a weight read that you’ve already done and be able to serve multiple user requests. However, the problem, though, is that some of these requests are longer than others, which means that there’s all of these idle periods in the compute where nothing is happening. So, how can we solve this problem and squeeze out more performance? That’s where continuous batching comes in. So, the idea here is that for every
[05:11] single idle slot, you slot in a new user request to be served during that same weight read to be able to serve as many requests as possible. However, this does come with a slight downside because every single token when you do inference requires you to save something into the KV cache because that’s how the attention block works. You need to understand how every single token, like what the K and V vectors are. This can add up very quickly. So, if you are running a coding agent with very
[05:41] long context, for example, 128k context, you’re going to save 42 gigabytes of KV cache that is needed to serve that individual request. So, the rule of thumb here for a 70 billion parameter model is that for every 3,000 tokens, you need 1 GB of additional KV cache. And that’s for one user request. So, imagine you’re doing batching and you’re doing like eight different requests at the same time, then your KV cache is going to explode and you will not have enough memory to be able to serve all of your requests. So, what are some of the innovations we have done to be able to
[06:11] optimize how we use memory? So, that’s where paged KV cache comes into play. So, how traditionally KV cache worked was that you would have physical memory that you would reserve to make sure that you could have enough room to be able to store all of the KV information from each request into memory. However, this came with a downside and a lot of inefficiency because you would just have a lot of memory blocks that would be reserved but wouldn’t actually be used. So, the idea with a paged KV cache is we
[06:41] use something that’s similar to like an OS or a virtual machine where you provision a whole memory block that’s all virtual and you can store wherever there’s free space KV cache for each request. So, this allows you to serve three times more requests than not having a paged KV cache and just doing what was before. And this really reduces the amount of wasted space where you are reserving memory slots without actually using them. This was right after followed by an innovation called prompt caching. So,
[07:13] the idea here is that if you have a coding agent or if you have a chat app that has a very long system prompt, you don’t actually have to recalculate the KV cache needed every single time you have a request. What you can do is you can reuse the KV cache that you calculated already for the previous request for the next request. That way you can just pick up where you left off. Here, you can skip the very, very time-consuming prefill phase. And you might be wondering, what is prefill? So, during inference, you can split up
[07:44] what happens into two major phases, prefill and decode. So, the prefill phase consists of all the things that happen once the request arrives, and then ends when the first tokens gets generated. And here, you can see this when you type something into ChatGPT, and then it takes a couple seconds before it starts returning the first token, and then it goes kind of like smoothly from there. So, what’s happening during the first couple of seconds where it’s not returning anything is that it’s computing K and V vectors for every single prompt token that you’ve inputted and produces the
[08:15] first output token. This is very compute bound because you can optimize the hell out of this. You can parallelize this extremely. However, after the first token is generated, what happens is uh that you decode one token at a time, reusing the KV cache you just built in the prefill phase. So, this is more reliant on memory. The reason I’m talking about this is because something happened lately that’s really messing up a lot of inference pipelines, which is super super token hungry coding agents. So, let’s
[08:46] say you have a coding agent that’s using 200K context or 500K context or a million context, right? What happens is that it starts to clock up the pipeline. While prefill is running, no other prefill or decode request can get through. So, this is kind of catastrophic if you have a bunch of people that are sending in coding requests and a couple people that are just trying to figure out like math problems in chat mode. So, to avoid this clogging problem, there is an innovation called chunked prefill that kind of goes and solves
[09:16] this problem. And the idea is quite simple here. The idea is taking a very long piece of prefill, chopping it up into smaller bits, so you can interleave in different decode and prefill requests. That way, there’s not one thing that’s taking up a bunch of time and clogging the whole pipeline. So, now Michelle, tell us more about what else we can optimize. >> Yeah, so all of the optimizations that Daniel just talked about are run time level optimizations. So, that explains we explore how we make inference more
[09:47] efficient within a single worker. But, in order to to keep pushing that frontier, we really need to start looking at system level optimizations, which is how can we distribute these workloads across many different workers. And so, the first thing to recognize there is that every request is different. So, take for example a summarization use case. You’re throwing the LLM a bunch of different documents, and you just really want a single question answered. And so, this workload is going to have a long prompt and short answer. And so, it’s a dominated by that
[10:18] prefill phase, and so therefore compute bound. On the other hand, you might have a case where it’s the opposite. Let’s say you want to write a long story or book, you just want to pass it a few themes for it to go off of. And so, this is going to have a short prompt and long answer. And this is going to be dominated by decode because you have so many output tokens compared to the number of input tokens coming in. And this is going to be memory bound. And finally, you can have a case that’s somewhere in the middle, right? It’s both a long prompt, long answer, and
[10:48] you’re seeing here that both the prefill and decode phases and therefore compute and memory both matter. And by looking at these different examples, you can really see that the resource requirements that you have for your hardware, it’s pretty different depending on what your workload looks like. And so, how do you prevent yourself from getting, you know, bound by compute, bound by memory? And so, one way to do that is called disaggregation. So, splitting up your workload to different worker nodes. And so, the most common form is called
[11:19] prefill decode disagg, where you’re actually splitting and disaggregating this workload by phase. And what that allows you to do is essentially have two pools. So, you have your prefill pool, that’s going to be running the prefill part of your workload. The decode pool, that’s going to be running the decode part of your workload. And taking the summarization use case for example, you know, you’re going to want to scale up that prefill pool so you’re not blocked by the compute and scale down your decode pool because you don’t want to waste resources when you just really don’t have that much decode work to do.
[11:51] And it’s nice cuz now you can scale all these independently and neither part is stalling the other. And we can take that one step further, right? We said before, prefill, that workload itself is inherently bound by compute. Decode, that is bound by memory. And just walking through that really quickly again, the reason for that is as you’re doing decode, you’re stepping through each of these tokens one by one and for every decode step, you’re re-reading the entire KB cache, right? That’s going to be memory bound. >> So yeah, um the the thing that Michelle
[12:24] just said about this being memory bound, this can be clearly seen by what the hardware can actually do. So GPUs, right? Um the the speed at which you can transfer data from memory into compute is limited by something called memory bandwidth. So for an H100, this looks like 3.35 terabytes per second. However, Cerebras has 7,000 times the bandwidth of a H100 with 21,000 terabytes per second. This is because we have a very specialized SRAM based memory architecture on our chip.
[12:56] So this really means that Cerebras is really built for decode. So we can serve tokens at 3,000 tokens per second versus an H100 serving it at 600 tokens per second for decode. So we’re really excited to partner with AWS to productionize this. So we are going to partner with AWS Trainium so they can serve prefill using their AWS Trainium chips, use their EFA service to transfer the KB cache to our Cerebras CS-3 systems to finally serve the the token. So this will lead us to give us
[13:27] 5x high-speed token capacity in the same footprint. So, this is one of the things that we’re doing to try to make fast inference more accessible and cheaper for developers. So, we’re really excited to really pursue this partnership. >> And at Gimlet, we’re really generalizing that beyond just training them and Cerebras. What Gimlet is building is essentially a multi-silicon inference cloud, which takes your workload, breaks it down into finer-grain pieces, determines the resource characteristics of all of those different pieces, and then figures out the best way to map it to the underlying hardware, where that
[13:58] hardware can be really anything, right? Nvidia, AMD, Trainium, Cerebras, D-Matrix, Intel Gaudi. The list goes on and on. And by running those tasks on the machine that is most efficient for running it, we’re actually seeing pretty crazy results. So, we’re seeing three to 10 times faster inference compared to homogeneous systems that have the same power budget. And this is diving into more than just the pre-full decode disaggregation than before, and some of those techniques are, for example, disaggregating based on model instead of
[14:28] on phase. And so, that’s called speculative decoding. So, just reviewing again the decode phase, typically you do a forward pass for each of the decode tokens that you’re getting out. And that’s the standard way of doing it. What speculative decode is is that you essentially have a draft model. And this is just a smaller form of the full model that um can generally approximate the results that you get out of it. And the nice thing there is because it’s smaller, it runs a lot more quickly and also uses less resources. And so, in speculative decode, what you can do is,
[15:00] in order to get, you know, the nine next tokens, you will essentially run the decode on that draft model first. It’s going to give you back what is called candidate tokens. So, you’re not 100% sure all these tokens are right, but because, you know, often these have been fine-tuned or been trained off of the full model, it’s it’s approximately right. And you want to validate, okay, are these the tokens that I actually want to output? And so you’ll actually run the next phase on that full model that’s called the verify stage to validate, okay, which of these tokens are correct?
[15:30] And essentially you can keep doing this until, you know, you’ve validated all these tokens from the draft model. And at the end of the day you can see here on the top, the standard way of running it, you needed to run that forward pass on your full model nine times to get those nine tokens. On the other hand, with speculative decode, you actually only needed to run it three times on that full model. And if you can get that draft model to run really, really quickly, then that time is minimal and you can really shorten the amount of time it takes to get your tokens. And looking at some more concrete
[16:00] results, so this is essentially that Pareto frontier that Daniel was showing earlier where x-axis is the speed at which you’re getting the tokens and the y-axis is the throughput. And so the baseline case we’re comparing to here is prefill decode disagg across homogeneous GPUs. And you can see that, you know, throughput is pretty good, but as soon as you’re pushing on that speed, that throughput drops pretty drastically. So what if you then run speculative decode across those same GPUs? So now you’re running that draft model and you’re able to see you’re able to get
[16:31] that curve to the right. And the reason for that is because you’re running the decode on that full model less times. But we can push that even further, right? Like going back to our theme of running those workloads on the hardware that can run it best. On something such as, you know, D Matrix or Cerebrus where you’re able to run small models very, very quickly, you see drastic performance improvements. So here this is where you’re seeing those numbers for that same throughput, right? You’re able to get 10x the interactivity compared to if you’re just running it on
[17:02] homogeneous machines. The final form of disagg we wanted to talk about is called attention FFN disagg. And this one gets pretty exciting when you think about serving large models. And I’m saying like 3 trillion parameter models where these models are so large that even just running one layer, it can be pretty resource-intensive. And so the concept is essentially the same thing, right? Like for that particular task that you need to do, whether it’s that attention layer or the feedforward FFN network layer, then you
[17:32] are essentially trying to figure out, okay, what are the resource characteristics, then what is the best hardware to map it to? And so the attention layer, that’s going to be more memory bound. It’s doing a lot of KB cache accesses. The FFN layer, that’s doing a lot of dense matrix multiplications. And so then it makes sense, right? You’re going to run the attention on the machine that has memory bandwidth, the FFN layer on the machines that can run those matrix multiplications as quickly as possible. And essentially what happens here is even within the model, you’re ping-ponging across, you know, many different machines in order to to get
[18:03] the inference from that model and just really disaggregating every single layer. And one thing that we really wanted to note here is that there is no best form of disagg. There is actually no best hardware. It really depends on the tradeoffs that you have for, you know, depending on what your model is, your workload, and what you need for latency, and what you need for throughput guarantees. And as we look towards the future, we see that agents are only becoming more and more incorporated into our everyday life. It’s incorporated into our work.
[18:35] Everyone is using it. And it’s continuing to push that need for more and faster tokens. >> Yeah, it’s really getting geared to the right. >> I [laughter] told Daniel not to say that. But the good thing about this is that even though, you know, this seems like a crazy crazy target, we can actually use agents to help us solve these problems and keep pushing the frontier. And so one of the things that we’re doing at Gimlet is actually using an agent to generate optimized kernels. Especially for our use case where we want to support such a wide range of different kinds of hardware, we need to
[19:06] figure out how do you make that problem a lot more tractable. Cuz right now, how people generate and how people optimize kernels is that there’s a lot of people sitting there hand tuning and figuring out how to optimize these kernels. And the thing is that these optimizations can vary pretty drastically based on you know, the model that you’re trying to run, the hardware that you’re running on, even within generations of the hardware, and you know, the workload shape itself. And so what we do at Gimlet is we built KForge, which is an agent for generating these kernels. It
[19:37] takes in a bunch of information like your hardware profiles, your workload profiles, basically anything that you can use to figure out how to optimize kernels and we solve it as a brute force problem, right? And so here’s an example, right? We have a forward pass and the kernel that um KForge optimized from it. And we’re seeing pretty interesting results. So last week, you know, we were running the agent for probably less than the span of a week and within that time it was able to speed up GPT-OSS-120B on AMD hardware by 33% end-to-end. And
[20:07] the interesting thing to note here is that this is building on top of kernels that have already been optimized. And you can go and take, you know, agents to the next level and use them to help us build and design custom silicon that is hyper tuned for specific models or your specific workload. This can then be used to train even better and smarter and faster AI, which then can also be used then to design the next generation of that custom silicon. And you know, this loop keeps going on and on and it’s a recursive loop. Like shout out to the
[20:39] folks at Recursive. >> And I want to end the talk by saying that we’re just getting started in our journey to optimize throughput and speed on inference. Because at the very top of the stack, you don’t think really about inference optimization when you talk about like incident response, right? But when you have agents that are making our systems much more reliable and increasing uptime, we’re getting more throughput and we can get more tokens. >> Or you can apply agents to the problem of bringing up models. As soon as a
[21:09] model drops on the market, getting it running on all the different kinds of hardware on day one. >> You can even go a little bit crazier with compilers. Imagine a world where an inference that can be custom-built for your workload and the model that you’re running. This is already being demonstrated by folks at Anthropic, right? That built a compiler in 2 weeks. So, I think there’s a lot of optimizations that you can do when you’re building just-in-time custom software to support the model you want to run, on the workload you want to run, on your custom hardware. >> And referring back to the previous
[21:40] slide, using agents to continue to help us to build, you know, more custom silicon and helping speed up the tape-out process. >> And finally, this is the non-very technical part, but all of the things that surround what takes to serve inference. All the procurement, all the legal, all of the things that are in the back office. All of these things combined with agentic workflows are able to be optimized. So, when we do all of this, I’m really optimistic about the future and all the things we can accomplish to serve tokens faster and cheaper.
[22:11] So, next slide, please. Thank you so much for coming to our talk. Uh we are working both very, very hard to give you faster and cheaper tokens. And yeah, let us know if you have any questions. We’ll be around after the talk. >> Yeah, and go eat tokens. We’re making more tokens for you so you can also generate GIFs like this. >> Yeah. >> [laughter]
[22:44] [music]