<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Lorenzo Dematte - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Lorenzo Dematte - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/pt/search-labs/author/lorenzo-dematte</link>
    </image>
    <link>https://www.elastic.co/pt/search-labs/author/lorenzo-dematte</link>
    <atom:link href="https://www.elastic.co/pt/search-labs/rss/author/lorenzo-dematte.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[pt]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 17:12:11 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Como criamos o Elasticsearch simdvec para que a busca vetorial seja uma das mais rápidas do mundo]]></title>
    <description><![CDATA[Como criamos o Elasticsearch simdvec, a biblioteca do kernel SIMD ajustada manualmente por trás de cada consulta de busca vetorial no Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch simdvec é o motor por trás de cada cálculo de distância vetorial no Elasticsearch. Ele fornece kernels AVX-512 e NEON ajustados manualmente para cada tipo de vetor que o Elasticsearch aceita. A arquitetura de pontuação em lote oculta a latência de memória por meio de pré-busca explícita em x86 e carregamento intercalado no ARM, superando bibliotecas como FAISS e jvector por até 4x quando os dados excedem o cache da CPU. Neste post, explicamos por que o construímos, o que ele contém e como ele deixa a busca vetorial do Elasticsearch uma das mais rápidas do mundo.</p><h2>Como construímos o Elasticsearch com simdvec</h2><p>Toda consulta de busca vetorial no Elasticsearch, seja por meio de percurso <a href="https://arxiv.org/abs/1603.09320">Hierarchical Navigable Small World (HNSW)</a>, varredura de arquivo invertido (IVF) ou reclassificação, se resume ao mesmo problema: calcular as distâncias entre vetores, milhões de vezes por consulta. O Elasticsearch é compatível com uma ampla variedade de tipos de dados e estratégias de quantização, desde float32 até int8, bfloat16, binário e Quantização Binária Aprimorada (BBQ). Cada uma traz diferentes contrapartidas entre memória, taxa de transferência e recuperação. Por trás de tudo isso há um único mecanismo: simdvec.</p><p>Criamos o simdvec para tornar cada cálculo de distância o mais rápido que o hardware permite. Neste post, explicamos por que o criamos, o que está dentro e onde ele entrega o maior impacto.</p><h3>Construído como um carro de corrida</h3><p>Como entusiastas da Fórmula 1, e um de nós tendo trabalhado anteriormente com a equipe Ferrari de Fórmula 1, vemos um paralelo claro. Um carro de Fórmula 1 é projetado com um único propósito: alcançar o melhor tempo de volta. Potência do motor, aerodinâmica e design do chassi só importam na medida em que contribuem para esse resultado. O mesmo vale para um banco de dados vetorial, onde a taxa de transferência de indexação, a latência de consulta e o recall definem o sucesso.</p><p>Embora o resultado final seja o que importa, alcançar os mais altos níveis de desempenho exige que cada componente esteja no estado ideal. Não pode ser só <em>bom o suficiente</em>, tem que ser o <em>melhor </em>na categoria. O Simdvec foi construído com essa mentalidade, focando uma parte crítica do sistema: o mecanismo. Trata-se de uma biblioteca de kernel otimizada para SIMD (<a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">Single Instruction Multiple Data</a>), criada especificamente para fornecer funções de distância nativas em C++ ajustadas manualmente, chamadas a partir do Java via interface de função estrangeira (FFI) <a href="https://openjdk.org/projects/panama/">Panama</a>. Ele trabalha com pontuação em lote, pré-busca de linhas de cache e todos os tipos e layouts vetoriais usados no Elasticsearch.</p><p>Esse é o mecanismo por trás de cada consulta.</p><h3>Por que criamos nosso</h3><p>Começamos em 2023 com a Panama Vector API no Apache Lucene. Funcionou bem para produtos dot float32, mas as necessidades do Elasticsearch logo superaram o que ele podia oferecer. O Elasticsearch é compatível com uma ampla variedade de tipos de vetores quantizados: int8, int4, bfloat16, bit único e BBQ assimétrico. Cada um possui estratégias SIMD diferentes, layouts de empacotamento e requisitos de acumuladores. Além da cobertura de tipos, os caminhos de pontuação do Elasticsearch exigem mais do que a taxa de transferência de pares únicos: o HNSW precisa pontuar vários vizinhos do gráfico em uma única passagem, o IVF precisa da pontuação em lote de milhares de candidatos com pré-busca e a pontuação baseada em disco precisa funcionar diretamente na memória mapeada em memória (mmap) sem cópia. Vimos o que estava disponível e nada abrangia o conjunto completo.</p><p>Então, criamos o simdvec: kernels C++ nativos ajustados manualmente, chamados de Java via FFI, com pontuação em massa, pré-busca e suporte para cada tipo de vetor que o Elasticsearch usa. Ao possuir a biblioteca, controlamos toda a stack. Quando adicionamos um novo tipo de quantização como BBQ, ele recebe um kernel SIMD ajustado ligado por todo o sistema. Não esperamos uma biblioteca upstream para suportá-lo e não comprometemos o desempenho de nenhum tipo. Toda consulta vetorial no Elasticsearch, seja HNSW, IVF, de reclassificação ou híbrida, pode ser executada nesse mecanismo, construído em torno das operações e tipos que realmente usamos.</p><p>O Simdvec possui bibliotecas nativas separadas para x86 e ARM, cada uma com múltiplos níveis de arquitetura de conjunto de instruções (ISA) selecionados no início. A sobrecarga de chamadas do Java via FFI é muito baixa, com <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#ffm-downcall-overhead-measurements">nanossegundos de um dígito</a>.</p><h3>O cenário</h3><p>Não somos os únicos a construir kernels de distância vetorial otimizados para SIMD. O ecossistema é rico, e queríamos entender como o simdvec funciona. Não para classificar projetos, mas para fornecer contexto e explicar onde o mecanismo do Elasticsearch está localizado. Selecionamos três projetos como pontos de referência, cada um representando uma abordagem diferente:</p><ul><li><p><strong>jvector:</strong> uma biblioteca Java de busca aproximada de vizinhos mais próximos (ANN) que usa a Panama Vector API para cálculo vetorizado de distância, com aceleração nativa em C opcional no x86.</p></li><li><p><strong>FAISS:</strong> um framework de busca vetorial open source amplamente utilizada, com kernels AVX2/AVX-512 otimizados manualmente.</p></li><li><p><strong>NumKong</strong> (anteriormente SimSIMD): um conjunto abrangente de mais de 2.000 kernels SIMD ajustados manualmente, abrangendo funções de distância, operações matriciais e computação geoespacial.</p></li></ul><p>Cada projeto tem um propósito diferente e realiza diferentes compensações. Incluímos números de referência deles para dar contexto sobre o desempenho do simdvec nas operações específicas que o Elasticsearch precisa.</p><h3>Como medimos</h3><p>Os <a href="https://github.com/ChrisHegarty/jvector-kernel-benchmarks">benchmarks simdvec</a> e jvector são escritos em Java com o JMH, o conjunto padrão de microbenchmark da JVM, com a sobrecarga de FFI incluída. Para os <a href="https://github.com/ldematte/simsimd-benchmarks">benchmarks NumKong</a> e <a href="https://github.com/ChrisHegarty/faiss-kernel-benchmarks">FAISS</a>, criamos programas em C/C++ reduzidos usando o Google Benchmark, que é a estrutura padrão de microbenchmarks em C++. Ambos os frameworks reportam nanossegundos por operação com calibração de aquecimento e iteração. Verificamos por meio de contadores de desempenho de hardware que todas as bibliotecas estão usando SIMD em ambas as plataformas. Todo o código do benchmark está disponível publicamente nos repositórios vinculados do GitHub (e, no caso do simdvec, no repositório <a href="https://github.com/elastic/elasticsearch">elasticsearch</a>).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt90a7d66553be3c9d/6a1701d166c4f942caf8bea5/aee116772df161cf86b7668f575ac34c733a23c5-1580x238.png" alt="Tabela listando duas plataformas: x86 com AMD EPYC Turin (Zen 5), AVX2 e AVX‑512, AWS c8a.4xlarge; e ARM com Graviton 4 (Neoverse V2), NEON e SVE2, AWS c8g.4xlarge." /><p><strong>Software:</strong> JDK 25.0.2, JMH 1.37, GCC 14, Google Benchmark (a versão mais recente).</p><h2>Um vetor de cada vez</h2><p>A operação mais fundamental na busca vetorial é calcular a distância entre dois vetores. Cada avaliação de vizinho HNSW, cada pontuação de candidata a IVF, cada comparação de reclassificação se reduz a esse ciclo interno.</p><p>Medimos a taxa de transferência de pares individuais em 1024 dimensões em ambas as plataformas, começando com float32, o tipo de referência e aquele em que o ecossistema é mais competitivo. Comparamos simdvec com FAISS e jvector; excluímos o NumKong porque ele usa acumuladores float64 para float32, tornando-o 3,2x-5,3x mais lento (dependendo da plataforma), priorizando precisão numérica em vez de throughput. Para manter a comparação comparável, comparamos o NumKong no int8, onde ele usa a mesma estratégia de acumulador do simdvec.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte3bc2ecaf3ad2b61/6a1701d2ab7f08039ddb9d0f/352cfa0fc18f123140f746d843404f80127fb1b7-1500x675.png" alt="Gráfico de barras horizontais intitulado &quot;float32 Dot Product — AMD Turin&quot; comparando cinco implementações: FAISS AVX-512 a 23,2 ns/op, ES simdvec AVX-512 a 28,3 ns/op, FAISS AVX2 a 36,4 ns/op, ES simdvec AVX2 a 38,9 ns/op e jvector a 43,9 ns/op." /><p>No x86, o FAISS AVX-512 é o kernel de par único mais rápido, com 23 ns. O Simdvec AVX-512 segue a 28 ns, uma lacuna que reflete a sobrecarga de chamadas FFI. Ambos usam FMA de 512 bits com desenrolamento de multi-acumuladores. No nível AVX2, os dois são muito mais próximos, 36 ns e 39 ns respectivamente, ambos limitados pela largura de carga de registrador e memória de 256 bits. O jvector é executado em 44 ns usando a API Java Panama Vector. O Panama gera um bom código SIMD, mas os intrínsecos do C++ ajustados manualmente mantêm uma vantagem.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcbbbe442631a575d/6a1701d42b835f81bcf4b083/95e44d9767f21ec4bccaed835e3c99aa180431ee-1500x495.png" alt="Gráfico de barras horizontais intitulado &quot;float32 Dot Product - Graviton 4 (ARM)&quot; mostrando ES simdvec a 70.2 ns/op, jvector a 110.0 ns/op e FAISS a 155.6 ns/op." /><p>No ARM, o simdvec lidera com 70 ns, bem à frente do jvector com 110 ns e do FAISS com 156 ns. O Simdvec tem kernels NEON ajustados manualmente para aarch64. O Jvector não tem código ARM nativo e depende do Panama. O FAISS depende da autovetorização do compilador em vez de intrínsecos explícitos do NEON, o que explica a lacuna maior. Isso reflete uma vantagem prática de ter a biblioteca do kernel: quando o Elasticsearch expandiu para o Graviton, adicionamos kernels NEON construídos especificamente para isso. Nem o jvector, nem o FAISS priorizaram código nativo ARM na mesma medida.</p><p>Mas o Elasticsearch não pontua apenas em float32. A quantização <strong>Int8</strong> reduz a memória em 4x, bfloat16 em 2x e BBQ em 32x. Cada tipo precisa de sua própria estratégia SIMD, e o simdvec fornece kernels nativos ajustados manualmente para todos eles.</p><p>Das bibliotecas que comparamos, apenas a NumKong tem kernels comparáveis para int8. Medimos o produto escalar int8, euclidiano ao quadrado e cosseno em 1.024 dimensões.</p><p><strong>Pontuação Int8 par único (1024 dimensões, ns/vec op – quanto menor, melhor)</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3ac255d158e93504/6a1701d5a292997e48d00eb1/a0b852fd5f51d57bd2488886600472ee65ab64da-1594x378.png" alt="Tabela comparando o desempenho de x86 e ARM para operações de produto escalar, euclidiano quadrado e cosseno, listando os valores ES, NumKong e diff para cada operação em ambas as arquiteturas." /><p>Em ambas as arquiteturas, o NumKong é igual ou mais rápido em dimensões pequenas a médias, onde a diferença se deve em grande parte à menor sobrecarga de chamadas (chamada direta em C vs Java FFI). Em dimensões maiores, o simdvec alcança o desempenho do kernel, onde a implementação mais eficiente (que usa desenrolamento em cascata) amortiza o custo da chamada: conforme a dimensão aumenta, <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#single-pair-i8-nsop-2">essa diferença diminui e eventualmente se inverte</a>. O crossover está em dimensões entre 768 e 1.536, dependendo da função e arquitetura.</p><p>Apesar da sobrecarga ligeiramente maior do Java FFI, o simdvec está no mesmo nível das bibliotecas altamente otimizadas em C/C++. Além de ser a única biblioteca com kernels otimizados tanto para float32 <em>quanto</em> para int8, também lidera em ARM e fica apenas um pouco atrás de FAISS em x86 (para float32), e muito próxima de NumKong em ambas as arquiteturas (para int8). E, para bfloat16, int4, binário e BBQ, embora existam alternativas, o simdvec se destaca graças ao SIMD ajustado manualmente, adaptado ao layout de dados de cada tipo.</p><p>Mas um mecanismo de busca de produção não pontua um vetor de cada vez; ele marca milhares por consulta. A próxima pergunta é o que acontece nessa escala.</p><h3>Milhares de uma só vez</h3><p>O desempenho de um único par é apenas parte do panorama. O que importa na prática é como os sistemas se comportam sob carga. Uma única consulta HNSW pode pontuar centenas de vizinhos do gráfico. Uma varredura de IVF pode pontuar milhares de entradas da lista de postagens. Uma passagem de reclassificação pode pontuar dezenas de milhares de candidatos. A taxa de transferência de pares individuais é importante, mas o que importa ainda mais é a rapidez com que você consegue pontuar vários vetores e a suavidade com que o desempenho se degrada à medida que o conjunto de trabalho transborda dos caches da CPU.</p><p>O Simdvec fornece pontuação em lote para todos os tipos de dados. Esses não são apenas loops sobre kernels de par único; eles usam loops internos multiacumuladores que carregam o vetor de consulta uma vez por passo dimensional e o compartilham entre múltiplos vetores de documentos, com pré-busca explícita de linha de cache para o lote seguinte. Nem jvector, nem FAISS oferecem algo equivalente (no momento em que escrevo). O Jvector não tem bulk API, então os chamadores marcam um par por vez em um loop. O FAISS expõe <code>fvec_inner_products_ny</code>, que, no momento da escrita, é implementado como um ciclo sobre a função de distância de par único, sem amortização de consulta ou pré-busca.</p><p><strong>Float32.</strong> Para medir o impacto no nível do kernel, avaliamos uma única consulta contra números crescentes de vetores de documento float32 de 1.024 dimensões, usando padrões de acesso aleatório que simulam buscas de vizinhos de gráficos dispersos semelhantes ao HNSW. Os três tamanhos de conjunto de dados, 32, 625 e 32.500 vetores, são escolhidos para que o conjunto de trabalho exceda o cache L1, L2 e L3, respectivamente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2df64ec77a1921ae/6a1701d714b270393ae3c4de/1d90267be1c63ac82b8ba588617ebedb0be0d1b6-1334x558.png" alt="Dois gráficos de barras comparando tempos de pontuação em lote do Float32 para Elasticsearch simdvec, FAISS e jvector no AMD Turin (x86, AVX-512) e Graviton 4 (ARM, NEON) em três tamanhos: 32 vetores, 625 vetores e 32.500 vetores." /><p>Quando os dados cabem no cache, o simdvec é o mais rápido em ambas as plataformas, mas as margens são modestas, já que a aritmética do kernel predomina. A verdadeira separação surge à medida que o conjunto de trabalho cresce além do nível L3. Em x86, o simdvec atinge 95 ns por vetor, enquanto o FAISS precisa de 165 ns e o jvector, de 412 ns. Em ARM, o padrão é o mesmo: o simdvec se mantém em 162 ns, enquanto o FAISS sobe para 347 ns e o jvector para 476 ns. A pré-busca e a amortização de consultas no simdvec mantêm a latência de memória oculta de uma forma que um simples loop sobre kernels de par único não consegue igualar, e a vantagem se amplia precisamente onde as cargas de trabalho de busca reais operam, nas profundezas da memória principal.</p><p><strong>Int8.</strong> O mesmo padrão se aplica aos tipos quantizados. Medimos a pontuação em lote do produto escalar int8 em 1.024 dimensões, com tamanhos de conjuntos de dados escolhidos para exceder os mesmos limites do cache L1, L2 e L3, comparando a pontuação em lote do simdvec com a pontuação de par único do NumKong em um ciclo.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcda85e10007188d0/6a1701d9cf4f25d722b2cff7/9ee97d98b40d13b19370b76b33e67ea66bfb3250-1580x338.png" alt=" Tabela intitulada &quot;x86 — Pontuação em lote, produto escalar int8 (ns/op, quanto menor, melhor)&quot; comparando ES simdvec e NumKong em três tamanhos de vetor — 128, 2.500 e 130.000 — com valores correspondentes de ns/op e fatores de aceleração." /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt972c311b7d08ba73/6a1701dadc55dec02ee00c87/601f50a03fa3e6263cbac9700281dfe3e511de60-1580x338.png" alt="Tabela intitulada &quot;ARM — Pontuação em lote, produto escalar int8 (ns/op, quanto menor, melhor)&quot; comparando ES simdvec e NumKong em três tamanhos de vetor — 128, 2.500 e 130.000 — com valores correspondentes de ns/op e fatores de aceleração" /><p>No x86, o simdvec é de 1,2x a 1,9x mais rápido, impulsionado pela combinação de pré-busca explícita e processamento em lote. No ARM, o simdvec vence novamente (1,7x a 1,9x mais rápido) em todos os tamanhos de conjuntos de dados. A vantagem vem do processamento em lote de quatro vetores por vez, oferecendo paralelismo em nível de memória por meio de um padrão de acesso intercalado. Em ambos os casos, o resultado mais impressionante é o que ocorre no maior tamanho de conjunto de dados, onde mais importa.</p><p>Os resultados para distância ao quadrado e cosseno mostram um padrão semelhante, com acelerações de 1,4x a 1,8x para ARM e de 1,3x a 3,0x para x86 (detalhes <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md">aqui</a>).</p><h3>Quando a memória é o mais importante</h3><p>Índices vetoriais de produção normalmente não cabem no cache da CPU. Um índice int8 de 10 milhões de vetores, com 1.024 dimensões, tem 10 GB. Pontuar candidatos significa fazer streaming de dados a partir da DRAM e é aí que a arquitetura de pontuação em lote faz a diferença.</p><p>Usamos contadores de desempenho de hardware para medir o que acontece dentro da CPU durante a pontuação em lote e descobrimos que ocultar a latência de memória exige duas estratégias fundamentalmente diferentes, uma por arquitetura.</p><p><strong>No x86, a pré-busca explícita elimina os erros de cache. </strong>O kernel em massa processa os vetores sequencialmente, um totalmente computado antes do próximo, enquanto emite instruções de pré-busca para o próximo lote. Os dados futuros são puxados para L1 antes que a CPU precise deles.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt368f29b5143d0f5a/6a1701dcc1e8a51780f8817b/a39548f8060c2a4a5154521a4047dd92d8cd77be-1580x309.png" alt="Tabela intitulada “x86 (AMD Turin) — Contadores de hardware por operação int8” comparando os modos único e em massa para falhas de cache L1, falhas de IPC e dTLB, com os fatores de melhoria correspondentes." /><p>Em ARM, a mesma abordagem sequencial teve desempenho ruim, mesmo com prefetching. Em vez disso, o <strong>kernel bulk intercala leituras</strong> de quatro vetores em cada posição do stride, dando ao mecanismo de execução fora de ordem quatro fluxos de memória independentes. A CPU não está buscando dados mais rápido, mas sim esperando menos, porque sempre há outra coisa para calcular enquanto as requisições de memória estão em voo. Você pode encontrar uma análise detalhada <a href="https://github.com/elastic/elasticsearch/issues/145412">nesta edição do GitHub</a>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8751ac5b20b75508/6a1701deab7f08db83db9d13/832de3bc0d556a493b7bf3f250196018acfc1585-1580x238.png" alt="Tabela Intitulada &quot;ARM (Graviton 4) — Contadores de hardware por operação Int8&quot; comparando os modos único e em lote para falhas de cache L1 e paradas do backend, com notas de melhoria correspondentes" /><p>Os números contam duas histórias diferentes:</p><ol><li><p>Em x86, a pré-busca transforma 139K erros de cache em 19K, e as instruções por ciclo (IPC) mais que dobram. A grande vantagem aumenta com o tamanho do conjunto de dados, de 1,2x em L2 para 2,8x além de L3, porque a pré-busca oculta viagens de ida e volta de DRAM cada vez mais caras.</p></li><li><p>No ARM, as falhas de cache mal mudam. O que muda é o uso: as estagnações de backend caem 40% porque o padrão de acesso intercalado mantém o pipeline alimentado. Essa vantagem se mantém consistente em 1,8x, independentemente do tamanho do conjunto de dados, porque o paralelismo no nível da memória se aplica independentemente de os dados virem do cache ou da DRAM.</p></li></ol><p>Duas arquiteturas, duas estratégias, um resultado: em escala de produção, o simdvec mantém o pipeline da CPU ocupado mesmo quando os vetores estão espalhados pela memória principal.</p><h2>O que isso significa para os usuários do Elasticsearch</h2><p>Essas capacidades em nível de kernel se acumulam. Uma única consulta vetorial pode calcular milhões de operações de distância: percurso de gráficos HNSW, pontuação de candidatos, reclassificação. Ao longo de milhares de consultas concorrentes, nanossegundos por operação se traduzem diretamente em latência de consulta e transferência do cluster. Seja usando float32, int8, bfloat16 ou BBQ, seja seu índice na memória ou no disco, simdvec é o motor por baixo, e cada uma dessas operações executa pelo mesmo motor, ajustado até o último nanosegundo.</p><p>A principal conclusão é que, em escala de produção, o desempenho da busca vetorial não é determinado principalmente pela taxa de transferência SIMD bruta. Ele é dominado pela eficiência com que o sistema oculta a latência da memória e, ao mesmo tempo, mantém a computação em milhões de pequenas operações.</p><p>Os kernels simdvec são aprimorados em quase todas as versões do Elasticsearch. Quando surgem novos tipos de quantização e plataformas de hardware, eles recebem kernels ajustados desde o primeiro dia. E os tipos existentes continuam a ficar mais rápidos à medida que refinamos as implementações que já estão sendo lançadas.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-vector-search-simdvec-engine</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-vector-search-simdvec-engine</guid>
    <category><![CDATA[Banco de dados vetorial]]></category>
    <category><![CDATA[Na Elastic]]></category>
    <dc:creator><![CDATA[Chris Hegarty,Lorenzo Dematte,Simon Cooper]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta18088409621369b/6a1701dfdc55de7297e00c8b/df9646091bafbbf0a6dfd212ff8a6bd1e8589708-1280x720.png" length="0" type="image/png"/>
    <pubDate>Thu, 23 Apr 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Indexação Vetorial Até 12x Mais Rápida no Elasticsearch com NVIDIA cuVS: Aceleração por GPU - Capítulo 2]]></title>
    <description><![CDATA[Descubra como o Elasticsearch alcança uma taxa de indexação quase 12x maior com indexação vetorial acelerada por GPU e NVIDIA cuVS.]]></description>
    <content:encoded><![CDATA[<p>No início deste ano, a Elastic anunciou a <a href="https://ir.elastic.co/news/news-details/2025/Elastic-Brings-Enterprise-Data-to-NVIDIA-AI-Factories/default.aspx">colaboração</a> com a NVIDIA para trazer aceleração de GPU ao Elasticsearch, integrando-se com a <a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a>—conforme detalhado em uma <a href="https://www.nvidia.com/en-us/on-demand/session/gtc25-S71286/">sessão na NVIDIA GTC</a> e em vários <a href="https://www.elastic.co/search-labs/blog/gpu-accelerated-vector-search-elasticsearch-nvidia">blogs</a>. Esta postagem é uma atualização sobre o esforço de coengenharia com a equipe de busca vetorial da NVIDIA.</p><h2>Resumo</h2><p>Primeiro, vamos atualizá-lo. O Elasticsearch se estabeleceu como um poderoso banco de dados vetorial, oferecendo um rico conjunto de recursos e um forte desempenho para buscas por similaridade em larga escala. Com recursos como quantização escalar, Better Binary Quantization (<a href="https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch">BBQ</a>), operações vetoriais <a href="https://www.elastic.co/blog/accelerating-vector-search-simd-instructions">SIMD</a> e algoritmos mais eficientes em termos de disco, como <a href="https://www.elastic.co/search-labs/blog/diskbbq-elasticsearch-introduction">DiskBBQ</a>, ele já oferece opções eficientes e flexíveis para o gerenciamento de cargas de trabalho vetoriais.</p><p>Ao integrar o NVIDIA cuVS como um módulo chamável para tarefas de busca vetorial, buscamos entregar ganhos significativos no desempenho e eficiência da indexação vetorial para melhor suportar cargas de trabalho vetoriais em grande escala.</p><h2>O desafio</h2><p>Um dos maiores desafios na construção de um banco de dados vetorial de alto desempenho é a construção do índice vetorial - o gráfico <a href="https://arxiv.org/abs/1603.09320">HNSW</a>. Rapidamente, a construção de índices se torna dominada por milhões ou até bilhões de operações aritméticas, à medida que cada vetor é comparado com muitos outros. Além disso, operações do ciclo de vida do índice, como compactação e fusões, podem aumentar ainda mais a sobrecarga total de processamento da indexação. À medida que os volumes de dados e os embeddings vetoriais associados crescem exponencialmente, GPUs de computação acelerada, construídas para paralelismo massivo e matemática de alto rendimento, estão idealmente posicionadas para lidar com essas cargas de trabalho.</p><h2>Apresentando o plugin Elasticsearch-GPU</h2><p><a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a> é uma biblioteca open source CUDA-X para busca vetorial acelerada por GPU e clustering de dados que permite a construção rápida de índices e recuperação de embeddings para cargas de trabalho de IA e recomendação.</p><p>O Elasticsearch utiliza o cuVS através do <a href="https://mvnrepository.com/artifact/com.nvidia.cuvs/cuvs-java">cuvs-java</a>, uma biblioteca de open source desenvolvida pela comunidade e mantida pela NVIDIA. A biblioteca cuvs-java é leve e se baseia na <a href="https://docs.rapids.ai/api/cuvs/nightly/c_api/">API C do cuVS</a>, utilizando a função estrangeira <a href="https://openjdk.org/projects/panama/">Panama</a> para expor os recursos do cuVS de uma maneira idiomática em Java, mantendo-se moderna e eficiente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc7fd7361099da05a/6a17e920be608670af00477f/5f6daa1eb07f704a6707d9e6b7ccb81d0abaa8c9-566x419.png" alt="Como o Elasticsearch funciona com NVIDIA cuVS, indexação por CPU e GPU" /><p>A biblioteca cuvs-java está integrada a um <a href="https://github.com/elastic/elasticsearch/pull/135545">novo plugin do Elasticsearch</a>; portanto, a indexação na GPU pode ocorrer no mesmo node e processo do Elasticsearch, sem a necessidade de provisionar qualquer código ou hardware externo. Durante a criação do índice, se a biblioteca cuVS estiver instalada e uma GPU estiver presente e configurada, o Elasticsearch usará a GPU para acelerar o processo de indexação vetorial. Os vetores são fornecidos à GPU, que constrói um gráfico <a href="https://arxiv.org/abs/2308.15136">CAGRA</a>. Esse gráfico é então convertido para o formato HNSW, tornando-o imediatamente disponível para busca vetorial na CPU. O formato final do gráfico construído é o mesmo que seria construído na CPU; isso permite que o Elasticsearch utilize GPUs para indexação de alto desempenho quando o hardware subjacente a suporta, liberando poder de processamento da CPU para outras tarefas (buscar, processamento de dados, etc.).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt485f55f29d6df5c4/6a17e922be6086dcf3004785/3ea255bd9bfd7983f78143c5eba999d2149d72be-671x356.png" alt="" /><h2>Aceleração de construção de índice</h2><p>Como parte da integração da aceleração de GPU no Elasticsearch, várias melhorias foram feitas no cuvs-java, focando na entrada/saída eficiente de dados e na invocação de funções. Uma melhoria importante é o uso de <a href="https://github.com/rapidsai/cuvs/blob/2cf5fa7666d703dccbe655f8214656b0952bb69b/java/cuvs-java/src/main/java/com/nvidia/cuvs/CuVSMatrix.java">cuVSMatrix</a> para modelar vetores de forma transparente, independentemente de estarem na heap do Java, fora da heap ou na memória da GPU. Isso permite que os dados se movam eficientemente entre a memória e a GPU, evitando cópias desnecessárias de potencialmente bilhões de vetores.</p><p>Graças a essa abstração subjacente de cópia zero, tanto a transferência para a memória da GPU quanto a recuperação do gráfico podem ocorrer diretamente. Durante a indexação, os vetores são primeiro armazenados em buffer na memória do heap Java e depois enviados para a GPU para construir o gráfico CAGRA. O gráfico é posteriormente recuperado da GPU, convertido para o formato HNSW e persistido no disco.</p><p>No momento da fusão, os vetores já estão armazenar no disco, ignorando completamente o heap Java. Os arquivos de índice são mapeados em memória, e os dados são transferidos diretamente para a memória da GPU. O projeto também acomoda facilmente diferentes larguras de bits, como float32 ou int8, e se estende naturalmente a outros esquemas de quantização.</p><h2>Drumroll... então, como funciona?</h2><p>Antes de entrarmos nos números, um pouco de contexto é útil. A fusão de segmentos no Elasticsearch normalmente é executada de forma automática em segundo plano durante a indexação, o que dificulta a realização de testes de desempenho isoladamente. Para obter resultados reprodutíveis, usamos a fusão forçada para desencadear explicitamente a fusão de segmentos em um experimento controlado. Como a fusão forçada realiza as mesmas operações subjacentes de fusão que a fusão em segundo plano, seu desempenho serve como um indicador útil das melhorias esperadas, mesmo que os ganhos exatos possam diferir nas cargas de trabalho de indexação do mundo real.</p><p>Agora, vamos ver os números.</p><p>Nossos resultados iniciais de benchmark são muito promissores. Executamos o benchmark em uma instância AWS <code>g6.4xlarge</code> com armazenamento NVMe conectado localmente. Um único node do Elasticsearch foi configurado para usar o número padrão e ideal de threads de indexação (8 - uma para cada núcleo físico) e para desativar <a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/merge">a limitação de mesclagem</a> (o que é menos aplicável com discos NVMe rápidos).</p><p>Para o conjunto de dados, usamos 2,6 milhões de vetores com 1.536 dimensões da <a href="https://github.com/elastic/rally-tracks/blob/master/openai_vector/README.md">trilha vetorial do OpenAI Rally</a>, codificados como <a href="https://github.com/elastic/elasticsearch/pull/137072">strings base64</a> e indexados como float32 <em>hnsw</em>. Em todos os cenários, os gráficos construídos atingem níveis de recall de até 95%. Veja o que descobrimos:</p><ul><li><p><strong>Taxa de transferência de indexação:</strong> ao transferir a construção de gráficos para a GPU durante as descargas de buffer na memória, aumentamos a taxa de transferência em cerca de 12 vezes.</p></li><li><p><strong>Fusão forçada:</strong> após a conclusão da indexação, a GPU continua acelerando a fusão de segmentos, acelerando a fase de mesclagem forçada em aproximadamente 7x.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfea4ee13b5a3b10d/6a17e923e9ea879c6aa9c616/f60ea9ee5996e456f393ffd195ee7eada6e5a7c2-948x387.png" alt="" /><ul><li><p><strong>Uso da CPU:</strong> o descarregamento da construção de gráficos para a GPU reduz significativamente a utilização média e de pico da CPU. Os gráficos abaixo ilustram o uso da CPU durante a indexação e a fusão, destacando o quanto é menor quando essas operações são executadas na GPU. Menor utilização da CPU durante a indexação da GPU libera ciclos de CPU que podem ser redirecionados para melhorar o desempenho da busca.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt80ff9c53f9b6884a/6a17e925445de9ee4b4d0187/5e680a5fc41700a877f3d8b2e5ce18ebd3f37a0b-1600x562.png" alt="" /><ul><li><p><strong>Lembrete:</strong> a precisão permanece efetivamente a mesma entre as execuções de CPU e GPU, com o gráfico construído por GPU alcançando um recall marginalmente mais alto.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5cbe084eca27b8e4/6a17e926faa913317093c8b7/48a2b7758606bd321712b7d8378cd2640e652a4e-1384x544.png" alt="" /><h2>Comparando em outra dimensão: Preço</h2><p>A comparação anterior usava intencionalmente hardware idêntico, com a única diferença sendo se a GPU era usada durante a indexação. Essa configuração é útil para isolar efeitos brutos de computação, mas também podemos olhar para a comparação dos custos.</p><p>Por aproximadamente o mesmo preço por hora da configuração acelerada por GPU, é possível provisionar uma configuração apenas CPU com aproximadamente o dobro dos recursos comparáveis de CPU e memória: 32 vCPUs (AMD EPYC) e 64 GB de RAM, permitindo dobrar o número de threads de indexação para 16.</p><p>Para manter a comparação justa e consistente, executamos esse experimento apenas com CPU em uma instância AWS g6.8xlarge, com a GPU explicitamente desativada. Isso nos permitiu manter todas as outras características de hardware constantes ao avaliar a relação custo-desempenho da aceleração da GPU em comparação  com a indexação somente da CPU.</p><p>A instância mais potente da CPU mostra desempenho melhor em comparação com os benchmarks da seção acima, como era de se esperar. No entanto, ao compararmos essa instância de CPU mais potente com os resultados originais acelerados por GPU, a GPU ainda oferece ganhos de desempenho substanciais: <strong>melhoria de aproximadamente 5 vezes</strong> na taxa de transferência de indexação e <strong>aproximadamente 6 vezes </strong>na fusão forçada, tudo isso enquanto constrói gráficos que atingem níveis de recall de até <strong>95%</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt94b5eb6f95ba307d/6a17e928abe0f255d4dfea35/8ffa58cae3ad175ef2932a351aeef4c34a1407b9-948x394.png" alt="" /><h2>Conclusão</h2><p>Em cenários de ponta a ponta, a aceleração de GPU com NVIDIA cuVS proporciona quase 12x de melhoria na taxa de indexação e uma redução de 7x na latência de fusão forçada, com uma utilização significativamente menor da CPU. Isso mostra que a indexação vetorial e as cargas de trabalho de fusão se beneficiam significativamente da aceleração da GPU. Em uma comparação ajustada ao custo, a aceleração da GPU continua a gerar ganhos substanciais de desempenho, com taxa de transferência de indexação aproximadamente 5 vezes maior e operações de fusão forçada 6 vezes mais rápidas.</p><p>A indexação de vetores acelerada por GPU está atualmente planejada para Prévia Técnica no Elasticsearch 9.3, que está programada para ser lançada no início de 2026.</p><p>Fique ligado para mais.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-gpu-accelerated-vector-indexing-nvidia</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-gpu-accelerated-vector-indexing-nvidia</guid>
    <category><![CDATA[Banco de dados vetorial]]></category>
    <dc:creator><![CDATA[Chris Hegarty,Hemant Malik,Corey Nolet,Manas Singh,Mithun Radhakrishnan,Mayya Sharipova,Lorenzo Dematte,Ben Frederickson]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1248d51633bd75d9/6a17e92ae9ea8714b3a9c61a/08f7469a4daaf67b7c5999585aae179b6680c78d-896x746.png" length="0" type="image/png"/>
    <pubDate>Wed, 03 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>