Os benchmarks de desempenho de LLM são confiáveis? — Ashok Chandrasekar e Jason Kramberger, Google
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: Are LLM Performance Benchmarks Reliable? — Ashok Chandrasekar & Jason Kramberger, Google · Canal: AI Engineer · 16:04 · Assistir no YouTube
Tópicos: Avaliação e benchmarks de IA, Engenharia de software com IA, Inferência e otimização de modelos, Infraestrutura e hardware de IA
Ashok Chandrasekar e Jason Kramberger discutem por que benchmarks de desempenho de LLM podem produzir resultados imprecisos ou difíceis de reproduzir, sobretudo em cenários de inference em escala de produção. Eles mostram como limitações do cliente de benchmark, como o GIL do Python, podem impedir que a carga solicitada seja gerada e até inflar a latência medida. Em seguida, apresentam o inference-perf, uma ferramenta com geração de carga distribuída, métricas do cliente e do servidor e configurações declarativas para melhorar a reprodutibilidade. A palestra também destaca a importância de cargas de trabalho e conjuntos de dados que representem o uso real.
Pontos-chave
Seção intitulada “Pontos-chave”- Benchmarks simples podem não representar a complexidade de uma stack de inference em produção, que pode incluir várias réplicas, workloads online e em lote, autoscaling e prefill-decode disaggregation.
- Um cliente de benchmark limitado pode não gerar a QPS configurada, mesmo que reporte resultados como se tivesse cumprido a carga.
- O processamento do cliente pode inflar a latência observada e levar a atribuir ao servidor um gargalo que, na verdade, está no harness.
- Configurações como a temperatura do modelo e a forma de amostrar ou truncar dados afetam os resultados e sua comparabilidade.
- Benchmarks de produção precisam de métricas confiáveis, observabilidade do cliente e verificação de que a carga configurada foi realmente executada.
- O inference-perf distribui a geração de carga entre processos para lidar com limitações do GIL do Python e reporta métricas do cliente junto às do servidor.
- Configurações declarativas e workloads padronizados ajudam a reproduzir e compartilhar cenários de benchmark entre ferramentas.
- Os conjuntos de dados e as workloads devem se aproximar do uso real, incluindo padrões como geração multi-turn, geração agentic e sumarização em lote.
Capítulos
Seção intitulada “Capítulos”| Início | Capítulo | Resumo |
|---|---|---|
| 00:12 | Apresentação e panorama dos benchmarks | Os palestrantes se apresentam e situam o inference-perf entre ferramentas de benchmark para servidores, análise competitiva, tráfego web e inference em produção. |
| 02:18 | Desafios de medir workloads em produção | A palestra descreve a complexidade de medir stacks de inference em produção e as características necessárias para avaliar carga, métricas e SLOs. |
| 04:24 | Fontes de resultados imprecisos | Os palestrantes mostram como limitações do cliente, latência inflada, temperatura e diferenças no tratamento dos dados podem comprometer os resultados. |
| 08:33 | Como o inference-perf gera carga e métricas | Jason apresenta o inference-perf, sua configuração declarativa e seu gerador de carga distribuído entre processos. |
| 10:42 | Configurações e catálogo de workloads | A apresentação aborda configurações detalhadas e workloads padronizados, incluindo geração multi-turn, agentic e sumarização em lote. |
| 12:50 | Resultados e princípios de validade | Os palestrantes mostram resultados em produção com o Prism e resumem os princípios para garantir benchmarks representativos e confiáveis. |
Citações
Seção intitulada “Citações”Que utilidade há em uma workload sintética que não representa com precisão o que seus clientes vão executar? — 03:21
Você pode achar que o servidor está no limite, mas, na verdade, é o cliente de benchmark que está inflando a latência. — 06:30
Você executa o benchmark e confia nos números que ele produz, mas eles podem ser muito diferentes. — 08:01
Os conjuntos de dados realmente importam. — 14:27
Conceitos e entidades
Seção intitulada “Conceitos e entidades”- Ashok Chandrasekar (pessoa): Engenheiro de software da Google que trabalha com avaliação e otimização de desempenho de inference.
- Jason Kramberger (pessoa): Engenheiro de software da Google e co-maintainer do inference-perf.
- Google (empresa): Empresa onde trabalham os dois palestrantes.
- inference-perf (ferramenta): Ferramenta de benchmark voltada a medir desempenho de inference de forma confiável, inclusive em escala de produção.
- llm-d (ferramenta): Framework distribuído de inference apresentado como capaz de viabilizar inference em escala de produção.
- Prism (ferramenta): Interface do projeto llm-d para compartilhar workloads e resultados de benchmark.
- Global Interpreter Lock (GIL) (conceito): Mecanismo do Python que pode limitar a execução paralela de threads e restringir a geração de carga em benchmarks.
- workload catalog (conceito): Catálogo de workloads de inference com cenários e configurações compartilháveis para padronizar benchmarks.
Tradução completa (pt-BR)
Seção intitulada “Tradução completa (pt-BR)”00:12 Olá a todos, sejam bem-vindos à nossa palestra sobre se os benchmarks de desempenho de LLM são confiáveis. Um pouco sobre nós. Sou Ashok Chandrasekar. Sou engenheiro de software sênior no Google. Trabalho com avaliação e otimização do desempenho de inference. Também lidero alguns projetos open source. Um deles se chama inference-perf, uma ferramenta de benchmarking para realizar benchmarks de desempenho confiáveis. Também sou o líder do SIG de benchmarking do llm-d. O llm-d é um framework de inference distribuída que torna possível a inference em escala de produção.
00:44 Olá a todos, sou Jason Kramberger. Sou engenheiro de software no Google. Também sou um dos mantenedores de inference-perf e de alguns dos subprojetos que Ashok mencionou. Trabalho com desempenho de inference e benchmarking. Vamos começar. Vamos dar uma olhada em como é o ecossistema de benchmarks. Certo? Temos os frameworks de servidores de modelos. São o vLLM, o SGLang e outros servidores de modelos, e todos eles têm algum recurso de benchmark integrado. Certo? Em geral, são scripts em Python e benchmarks voltados para desenvolvedores, para que possam medir o desempenho do próprio servidor de modelos. Depois, temos as ferramentas de análise competitiva. São o MLPerf, o SemiAnalysis, o Artificial Analysis e assim por diante. Certo? Elas têm como principal objetivo realizar benchmarks de desempenho competitivos para comparar o desempenho de chips e aceleradores. E também temos os benchmarks web tradicionais. São ferramentas como Locust, Grafana, k6 e assim por diante. Esses
01:14 se concentram principalmente em benchmarks HTTP de alta escala, certo? E, por fim, temos o último segmento: os benchmarks de LLM em escala de produção. Eles servem para fazer o benchmark da sua stack de serving de inference em produção, e esse é o nosso foco hoje. Vamos nos concentrar principalmente em inference-perf e em como resolvemos esse problema de benchmarking em escala de produção. Se você já executou um benchmark, ele normalmente se parece com isto, certo? Você tem algum tipo de harness de benchmark
01:46 e especifica qual modelo está usando no benchmark, o número de prompts que quer executar, o tamanho da sequência de entrada e de saída e a taxa de solicitações ou carga que quer enviar, certo? E a saída se parece com o que está à direita. Basicamente, ela mostra a taxa de processamento de tokens de entrada, a taxa de processamento de tokens de saída, algumas métricas de latência, o tempo até o primeiro token, o tempo por token de saída e assim por diante. Quais são alguns dos problemas de um benchmark simples como esse? Certo? Se você quiser, de fato, fazer o benchmark de cargas de trabalho
02:18 em escala de produção, aqui temos como exemplo a stack de inference do llm-d. Você pode ter serving online e cargas de trabalho em lote. Se observar o pool de inference abaixo, há muitos servidores em execução. Além disso, há configurações complexas, como a desagregação entre prefill e decode, o escalonamento automático da carga de trabalho e outras coisas que acontecem nos bastidores. E, em geral, a escala é muito maior. Então, os harnesses de benchmark normais enfrentam problemas quando você tenta fazer o benchmark de uma configuração
02:49 como essa. Se analisarmos as principais características que queremos em um benchmark em escala de produção, precisamos conseguir gerar uma carga alta, algo que muitas ferramentas disponíveis não conseguem fazer. Precisamos simular cargas de trabalho do mundo real, certo? De que adianta usar apenas uma carga de trabalho sintética que não representa com precisão o que seus clientes vão executar? A fidelidade das métricas também é muito importante, certo? As métricas são precisas? E com que eficácia funcionam? Este é o conjunto de métricas que
03:21 o llm-d mede por padrão. Acabei de pegar isso do site. Como podem ver, não se trata apenas de executar um único QPS, certo? Você percorre uma lista de diferentes cargas e tenta medir qual é o desempenho de referência, quais otimizações está fazendo e qual é a diferença. É preciso encontrar o ponto certo em que o servidor fica saturado, para saber qual é o ponto ideal de operação dos servidores e, assim, maximizar o desempenho e reduzir os custos. E coisas como
03:52 os SLOs estão se tornando mais importantes, certo? Qual é o seu SLO de P90 para o tempo até o primeiro token? E você está em conformidade com esse SLO? Quando executamos um benchmark normal, como o que vimos antes, quais são algumas das armadilhas que encontramos? Temos executado benchmarks há alguns anos. Então, nos deparamos com todo tipo de resultado diferente compartilhado por outras pessoas e, muitas vezes, não conseguimos reproduzir os resultados que elas compartilham. Certo? Foi isso que motivou esta palestra. Essas quatro
04:24 coisas comuns são problemas que observamos, certo? A primeira é a precisão das métricas; a segunda, a observabilidade da própria ferramenta de benchmark. Você sabe se o seu harness de benchmark está falhando? Ele não está conseguindo manter a carga? A terceira é a reprodutibilidade. Há uma aleatoriedade inerente nos conjuntos de dados que você usa. Então, como garantir que o resultado seja reproduzível? E a quarta é a qualidade do próprio conjunto de dados. Este é um experimento que realizamos. Nós
04:56 pedimos a diferentes harnesses de benchmark que gerassem 200 QPS, e este foi o resultado. Quero destacar algumas coisas. O Python tem esse bloqueio global do interpretador, o GIL. Se você trabalha com Python, sabe que isso faz com que tudo seja, de certa forma, executado em uma única thread. Então, mesmo quando você tem uma máquina com várias CPUs, muitas vezes fica limitado pelo desempenho de uma única CPU, especialmente quando o gargalo está na CPU. Isso mostra um harness de benchmark de processo único e um harness de vários processos, e como o QPS que você consegue atingir varia de acordo com isso. Quando você executa o teste em uma máquina pequena com poucos núcleos, pode ver que, mesmo solicitando 200 QPS, você só obtém 38 QPS. Depois, você dá a ele uma máquina maior, e alguns desses harnesses de processo único chegam a um limite de cerca de 170 QPS. Esta é uma máquina muito mais potente. Mas isso é um problema, porque você pede 200 QPS e não sabe se a ferramenta realmente entregou esse valor. Ela simplesmente diz: “Executei o teste; estes são os números”. Então, você pensa: “Certo, executei a 200 QPS”, mas, na verdade,
05:27 não executou. O outro problema que surge é a inflação da latência. Se o seu servidor diz: “Esta é a quantidade de QPS que consegui processar, e estes são os números precisos”, isso é uma coisa. Mas, se o seu harness de benchmark está inflando a latência porque está sobrecarregado ao tentar coletar todas as solicitações de tokens em streaming, isso é outra. Em um dos testes, percebemos que o atraso chegou a 58 segundos. Então, você pode olhar para isso e pensar: “Ah, meu servidor é o gargalo; não consegue lidar com todas as solicitações”. Mas, na verdade, é
05:58 o seu cliente de benchmark que está inflando a latência. Executamos um teste de 1.000 QPS. Quando o seu harness de benchmark consegue escalar horizontalmente, você pode ver que a latência é mínima. Este servidor foi simulado, então não deveria haver latência alguma. Como eu disse, há outras variáveis envolvidas. Em um dos benchmarks que alguém compartilhou, a pessoa disse: “Ei, estamos obtendo 20% mais throughput”. Então, investigamos e descobrimos que o harness de benchmark
06:30 estava definindo a temperatura do modelo como zero, certo? Isso significa que as saídas do modelo são muito mais determinísticas, e ele conseguiu atingir um throughput maior do que o que normalmente se observaria em uma carga de trabalho real, certo? Nela, a temperatura do modelo fica em torno de 0,7. Outra coisa: usamos o mesmo conjunto de dados do ShareGPT em dois harnesses de benchmark diferentes, e eles produziram tokens de entrada diferentes. Isso acontece porque eles fazem a amostragem de formas diferentes e truncam os dados de formas diferentes. Então, como usuário, você não
07:00 Na verdade, é o cliente do benchmark que está aumentando a latência, certo? Fizemos um teste de cerca de mil QPS. Quando o seu harness de benchmark consegue escalar, dá para ver que há muito pouca latência, certo? Este é um servidor simulado, então não deveria haver latência alguma. E, como eu disse, há outras variáveis envolvidas. Em um dos benchmarks, alguém compartilhou os resultados e disse: “Estamos conseguindo 20% mais throughput.” Então investigamos e descobrimos que o harness de benchmark
07:31 estava definindo a temperatura do modelo como zero, certo? Isso significa que as saídas do modelo são muito mais determinísticas e que ele conseguia gerar um throughput maior do que o que você normalmente veria em uma carga de trabalho real, certo? Em que a temperatura do modelo fica em torno de 0,7. Outra coisa é que usamos um conjunto de dados do ShareGPT, o mesmo conjunto de dados, em dois harnesses de benchmark diferentes, e eles produziram quantidades diferentes de tokens de entrada, certo? Isso acontece porque eles os amostram de maneiras diferentes e os truncam de maneiras diferentes. Então, como usuário, você não tem
08:01 ter uma visão disso: você executa, confia nos números que ele produz, mas eles são muito diferentes. E há muito mais: você realmente força a geração até o fim da sequência? Você observa as taxas de prefix cache? Como faz o replay de várias conversas em benchmarks? E como consegue alta fidelidade na carga de trabalho real, que deveria se parecer com a sua carga de trabalho de produção? Então, o principal que eu queria transmitir aqui é que, muitas vezes, você diagnostica isso como um problema do seu servidor ou da sua pilha de inference.
08:33 Mas, em muitos casos, o problema pode estar no seu harness de benchmark. Então, qual é a solução para isso? Como fazemos benchmarks reproduzíveis? Jason vai explicar. Obrigado, Ashok. Então, como resolvemos esses problemas? Nós nos juntamos em torno do inference-perf, um projeto da CNCF que surgiu do grupo de trabalho de serving do Kubernetes, para oferecer um espaço padronizado onde a comunidade possa trabalhar e resolver alguns desses problemas em conjunto.
09:07 Ele permite usar uma configuração declarativa definida pelo usuário, que possibilita uma reprodução clara entre as execuções. Também adicionamos um gerador de carga que resolve o problema do GIL em Python entre vários processos e informa as métricas do cliente,
09:39 junto com as métricas do servidor, para garantir a maior fidelidade possível das métricas e permitir que você observe quando há um problema na sua ferramenta, em vez de no sistema sob teste. Primeiro, falando do gerador de carga: o processo principal enfileira as requisições com base no horário planejado para a execução, que depende da sua configuração. Isso pode ser um processo de Poisson,
10:11 uma taxa constante ou a manutenção de um número constante de requisições simultâneas. Esse canal de fila de requisições é então distribuído entre vários processos, que as retiram da fila e garantem que sejam executadas com o mínimo de sobrecarga, além de permitir observar quando são executadas em comparação com o horário planejado. E você pode ver isso funcionando em grande escala. Esta é uma comparação com outras ferramentas, algumas delas ferramentas de escala HTTP,
10:42 como o K6. Mas você pode ver que, mesmo a 5.000 QPS, o inference-perf conseguiu acompanhar devido a essa arquitetura e, o mais importante, conseguiu informar que estava acompanhando. A outra parte é a configuração. Antes, mostrei um exemplo rápido de como você poderia simplesmente executar uma ferramenta de benchmarking. Aqui à esquerda, você pode ver um exemplo simples executando um conjunto de dados aleatório contra um endpoint.
11:13 Mas a configuração disponível no inference-perf é bastante detalhada e tem muitos parâmetros que permitem testar sua configuração com precisão de acordo com suas cargas de trabalho. À direita, você pode ver uma configuração para replay de conversas, na qual é possível configurar não só os comprimentos de entrada e saída, mas também as distribuições e assim por diante.
11:44 Além da possibilidade de configurar uma única execução, também trabalhamos em conjunto para publicar um conjunto de algumas dessas cargas de trabalho e configurações do inference-perf, vinculadas a cargas de trabalho de inference de ponta. Por exemplo, no catálogo de cargas de trabalho que publicamos, você pode acessar geração padrão de várias conversas, tree of thought, geração agentic,
12:15 além de sumarização em lote e outras. Cada uma delas tem uma definição simples, em linguagem natural, que ajuda a entender qual é o cenário. Além disso, há configurações e métricas bastante detalhadas, não só na configuração do inference-perf, mas também em termos genéricos, para que possam ser compartilhadas entre ferramentas e sirvam de base para a padronização dessas cargas de trabalho.
12:50 A combinação dessas coisas nos leva a resultados que podemos apresentar com clareza. Aqui está uma captura de tela do Prism, uma interface que temos para compartilhar não só as cargas de trabalho que mostrei antes, mas também alguns resultados de benchmarking. O Prism faz parte do projeto LLMD. Aqui você pode ver um resultado de benchmark para a carga de trabalho de geração de código agentic que mostramos antes, em TPUs. Estas três
13:23 linhas mostram a diferença entre as otimizações combinadas, representadas pela linha verde, e uma linha de base que consiste apenas em um serviço simples do Kubernetes, sem estar à frente de várias réplicas do servidor de modelos. É importante observar que isso foi feito em escala de produção, com oito réplicas. E você pode ver que as otimizações combinadas foram medidas como muito superiores à linha de base, escalando para
13:55 quase centenas de milhares de tokens por segundo. Então, estas são as conclusões, os princípios para a validade de benchmarks, com base nas armadilhas que Ashok mencionou antes. Em escala de produção, você precisa de concorrência do cliente e de observabilidade do comportamento do cliente e da capacidade dele de atender à sua configuração. A fidelidade das métricas permite observar o comportamento do cliente
14:27 e também o do sistema sob teste, além de entender se o cenário foi executado com precisão e se os resultados de desempenho são válidos. As variáveis estocásticas e o não determinismo ou determinismo que você define na execução precisam refletir as demandas do mundo real da sua carga de trabalho. E, o mais importante, seus conjuntos de dados realmente importam. Suas cargas de trabalho precisam ser o mais próximas possível daquilo que você
14:58 pretende testar. E temos exemplos no catálogo de cargas de trabalho. Aqui estão três links para algumas das coisas que apresentamos. O Inferencepf é nossa ferramenta de benchmarking, e este é o repo dela. O LLMD é um projeto no qual trabalhamos, e o inferencepf está nele, no LLMD benchmark. O LLMD é voltado para inference em escala de produção. E o LLMD Prism é
15:30 aquela interface que mostramos para os resultados de benchmarking e para o catálogo de cargas de trabalho que define algumas dessas cargas. Vamos responder às perguntas depois, mas agradecemos o seu tempo. [aplausos]
16:04 [música]
Transcrição original
[00:12] Hi everyone, welcome to our talk on um our LLM performance benchmarks reliable. A little bit about us. I am Ashok Chandra Seeker. I’m a staff software engineer at Google. I work on inference performance evaluation and optimization. Um and I lead a couple of open source projects. One is called inference perf uh which is a benchmarking tool to do reliable performance benchmarks and uh I’m also the sig lead for LLMD benchmarking. LLMD is a distributed inference framework um that makes
[00:44] production scale inference possible. >> Hi everyone, I’m Jason Kroger. I’m a software engineer at Google. Uh I’m also a co-maintainer of inference Perf and a few of the sub projects that Ashok brought up. uh and I work on inference performance and benchmarking. >> Okay, let’s get started. Um let’s look a little bit about the how the benchmark ecosystem looks like. Right? You have your model server frameworks. Uh these are VLM, SGLAN, um and other model
[01:14] servers and all of these have some benchmark capability within them. Right? These are primarily Python scripts and are developer focused benchmarks to see how you can measure the performance of your model server itself. And then you have your competitive analysis tools. Uh these are MLPF, semi analysis, artificial analysis and so on. Right? They mainly aim for competitive performance benchmarks to compare like chip and accelerator performance. Uh and then you have your typical web benchmarks. Uh these are like locus, graphfana, ksix um and so on. These
[01:46] mainly focus on highcale http benchmarks, right? uh and then you have your um last segment which is the production scale LLM benchmarks right these are to actually benchmark uh your production inference serving stack and that is our focus today right we’ll be focusing mainly on inference perf and how we solve this uh production scale benchmark problem so if you have run a benchmark before uh it typically looks like this right um you have some sort of benchmark hardness
[02:18] uh and then you specify what model you are bench benchmarking the number of prompts you want to run, what is the input output sequence length uh and the request rate or the load you want to send, right? Uh and your output looks something uh like what is on the right. Uh this is basically your uh input token throughput, output token throughput, some latency metrics, time to first token, time per output token and so on. Um so what are some issues with a simple benchmark like this? Right? So if you want to actually benchmark production
[02:49] scale workloads um here I have LLMD inference stack as an example right uh you can have uh online serving you can have batch workloads and if you see the inference pool below uh there are like lot of servers that are running right and then you have like complex configurations like pre-fill decode disagregation um and workload autoscaling and other things that are going on under the hood and usually the scale is much larger right so your um normal benchmark harnesses runs into issues when you try to benchmark a setup
[03:21] like this. And if you look at like the key characteristics of what we want out of a production scale benchmark, we need to be able to do high load uh which is limited in a lot of tools out there. We need to be able to simulate real world workloads, right? Um what use it is if it is just some synthetic workload that is not accurately representing uh what your customers are going to run. Uh and then metrics fidelity is very important, right? Are the metrics accurate and how well they work? Uh this is like the set of metrics that
[03:52] LLMD measures uh by default. Uh I just pulled it from the website there. Uh as you can see it’s not just like a single QPS that you are running, right? You are sweeping a a list of various loads and uh you try to measure what the baseline is and what optimizations you are making and what the difference there is. um you need to find the right point where the server gets saturated so you know the right optimal uh point to run your servers on uh to maximize performance and to save costs um and things like uh
[04:24] SLOs’s become more important right what is your um time to first token P90 SLO and are you conformant to that SLO so when you run like um normal benchmark like we saw before what are some of the pitfalls that you run into right uh we have been uh running benchmarks for a couple of years. So we run into all sort of uh different results that people share and a lot of times we aren’t able to reproduce the results that are shared by other people. Right? So that is what motivated this talk. Um so these four
[04:56] common uh things that we see as an issue, right? One is accurate uh metrics and two observability into your benchmark tool itself. Um do you know if your benchmark harness is actually failing? Is it not able to maintain the load? Um and three reproducibility. Uh there is some inherent uh randomness uh in like the data sets that you use. So how do you make sure it is reproducible and four the data set quality itself. So this is an experiment we ran. Um we
[05:27] asked like different benchmark harness to generate 200 QPS and this was the result right. Um so a couple of things I want to point out. Um, Python has this global interpreter lock GIL if you have been working with Python, you know that which makes everything uh sort of single threaded. So even when you have like a multiCPU mission, a lot of times you are limited by the performance of a single CPU uh when you’re CPU bound especially, right? Uh so this kind of shows a single process um benchmark harness and a
[05:58] multiprocess harness and how the QPS you are able to achieve differs based on it, right? when you run with a really uh small shad core mission, you can see that even when you request 200 QPS, you are only getting 38 QPS and then you give it a bigger mission and then some of these uh single process harness they cap out at like 170 QPS, right? This is a much more powerful machine. Um but it is a problem because you ask for 200 QPS and then you don’t know whether it actually delivered it. It will just say I ran it these are the numbers. So you think okay you ran 200 QPS but in fact
[06:30] you you have not. Uh the other issue that comes out of it is the latency inflation right if your server is saying okay this is how much QPS I was able to run and this was the accurate numbers that is one thing but if your uh benchmark harness is actually inflating latency right because it’s thrashing trying to collect all the streaming token requests um in one of the tests we noticed like u the delay was up to 58 seconds. So you might look at this and go oh my server is bottlenecked right it’s not able to handle all the requests but in fact it’s
[07:00] actually your benchmark client that is inflating the latency right uh we ran like a th000 QPS test uh when your when your benchmark harness is actually able to scale out you can see there is very minimal latency right this simulated server so there shouldn’t be any latency at all um and like I said there are like other variables that go into it right in one of the benchmarks um someone shared and they said, “Hey, we are getting 20% better throughput.” Then we looked into it and we found out the benchmark
[07:31] harness were setting the model temperature to zero, right? Which means your model outputs are a lot more deterministic and it was able to turn out a higher throughput than what you would normally see in like a real workload, right? Where your model temperature is somewhere around 0.7. Um another thing is like we used a a shar GPD data set the same data set across two different benchmark harness and they produce different input tokens right this is because they sample them differently they truncate them uh differently so as a user you don’t have
[08:01] insight into this right you run it you trust the numbers it produces but they are wildly different uh and there is much more right do you actually force it to generate till the end of sequence are you looking at prefix cache rates how do you do mult multi-turn uh replay via benchmarks and uh how how do you actually get high fidelity uh on the actual workload that would resemble your production workload right so the main thing I wanted to convey here is like a lot of times you diagnose it as a your server or inference stack
[08:33] problem but in a lot of cases it could be your benchmark harness so what is the solution to this how do we actually do reproducible benchmarks Jason here will take you over Thanks Ashook. Uh so yeah, how do you how do you solve these problems? Uh we al together inferencepf uh the CNCF project spanned out of Kubernetes working group serving uh to provide like a standardized place for us to work with
[09:07] the community and solve some of these issues together. uh it enables the ability to have like a userdefined declarative configuration uh that allows you to have clear reproducibility across runs. We also added a load generator uh that solves the GIL problem in Python uh across multiple processes and reports those client metrics back
[09:39] along with server metrics to ensure that you have the highest metric fidelity and you’re able to actually observe when your tool is having an issue versus your system under test. So, first going over the load generator, uh you see that the main process actually cues requests based off of the planned time that they need to execute, which is based off of your configuration. This may be in some
[10:11] poison process or constant rate or maintaining a constant number of concurrent requests. This request Q channel is then spread across multiple processes which pull and ensure that they execute with minimum overhead but then also observability about when they execute versus their plan time. And you can see this working at scale. So this is a comparison across other tools uh some being the HTTP scaled
[10:42] tools like K6. uh but you see that even at 5,000 QPS inference perf was able to keep up due to this architecture and most importantly actually report that it was able to keep up. Other portion is configuration. So earlier I show showed a brief example of how you might simply run a benchmarking tool. And here on the left you can see a simple example running a random data set
[11:13] against an endpoint. But the actual configuration that we have in front of inference perf is very detailed with a lot of knobs that allow you to accurately uh test your configuration off of your workloads. You can see here on the right that this is uh configuration for conversation replay where you’re able to configure not only like the input output length but their distributions etc.
[11:44] And further beyond just the ability to configure a single run, we’ve actually worked together to have a published set of some of these workloads and configuration of inference perf that are tied to state-of-the-art inference workloads. For example, here in the workload catalog that we’ve put out, you’re able to access standard multi-turn uh generation, tree of thought, agentic generation uh
[12:15] as well as batch summarization and others. Each one of these has a simple definition uh kind of in natural language that allows you to understand what the scenario is. But beyond that there’s also pretty detailed configuration metrics not only in inference perf configuration but in generic terms so that this can actually be shared across tools and have a place for standardization of these workloads.
[12:50] So kind of the culmination of these things uh leads us to actual results that we can clearly display. Uh and here’s a screenshot from Prism which is a UI we have for sharing not only those workloads that I showed before but also some benchmarking results. Uh and Prism is a part of the LLMD project. Here you can see a benchmark result for the agentic code generation workload that we showed before on TPUs. Uh these three
[13:23] lines you see here show you The difference between combined optimizations is the green line and a baseline that is just a simple Kubernetes service instead of in front of multiple model server replicas. It’s important to note here is that this is at production scale with eight replicas. And you can see that the combined optimizations were measured to be much higher than the baseline scaling into
[13:55] almost hundreds of thousands of tokens per second. So the takeaways kind of the principles for benchmarking validity based off of the pitfalls that Ashok brought up earlier. At production scale, you need client concurrency and you need observability into your client’s behavior and its ability to meet your configuration. The metric fidelity allows you to actually observe your client’s behavior
[14:27] as well as your system under test and understand that your scenario was accurately executed and your performance results were valid. The stochcastic variables uh and non-determinism or determin determinism that you set amongst your run needs to reflect your real world demands uh for your workload. And most importantly, your data sets do truly matter. Your workloads uh need to be as close to what you are
[14:58] intending to test as possible. And uh we have examples in the workload catalog. So here we have three links to some of the things that we’ve presented on here before. Inferencepf is our benchmarking tool and there’s the git repo for it. Llmd is a project that we work under and inferencepf under it in LLMD benchmark. uh LLMD is for production scale inference and then LLMD Prism which was
[15:30] that UI we showed for the benchmarking results uh and the workload catalog that defines some of these workloads. So that will answer questions after but we appreciate your time. [applause]
[16:04] >> [music]