<?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[Chris Hegarty - 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[Chris Hegarty - 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/chris-hegarty</link>
    </image>
    <link>https://www.elastic.co/pt/search-labs/author/chris-hegarty</link>
    <atom:link href="https://www.elastic.co/pt/search-labs/rss/author/chris-hegarty.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[pt]]></language>
    <lastBuildDate>Wed, 23 Sep 2026 06:46:07 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[Estatísticas ES|QL mais rápidas com tabelas hash no estilo Swiss Tables]]></title>
    <description><![CDATA[Como o hashing inspirado em Swiss Tables e o design compatível com SIMD entregam acelerações consistentes e mensuráveis na linguagem de consulta do Elasticsearch (ES|QL).]]></description>
    <content:encoded><![CDATA[<p>Recentemente, substituímos partes importantes da implementação de tabelas hash do Elasticsearch por um design no estilo de Swiss Tables e observamos tempos de construção e iteração de 2 a 3 vezes mais rápidos em cargas de trabalho uniformes e de alta cardinalidade. O resultado é menor latência, melhor taxa de transferência e desempenho mais previsível para a linguagem de consulta do Elasticsearch (ES|QL) em estatísticas e operações de análise.</p><h2>Por que isso é importante</h2><p>A maioria dos fluxos de trabalho analíticos típicos acaba se resumindo ao agrupamento de dados. Seja calculando a média de bytes por host, contando eventos por usuário ou agregando métricas entre dimensões, a operação principal é a mesma: mapear chaves para grupos e atualizar agregados em execução.</p><p>Em pequena escala, praticamente qualquer tabela hash razoável funciona bem. Em grande escala (centenas de milhões de documentos e milhões de grupos distintos), os detalhes começam a importar. Fatores de carregamento, estratégia de sondagem, layout da memória e comportamento do cache podem fazer a diferença entre um desempenho linear e uma série de falhas de cache.</p><p>O Elasticsearch oferece suporte a essas cargas de trabalho há anos, mas estamos sempre buscando oportunidades para modernizar os algoritmos principais. Assim, avaliamos uma abordagem mais recente inspirada nas Swiss Tables e a aplicamos à maneira como o ES|QL calcula as estatísticas.</p><h2>Afinal, o que são Swiss Tables?</h2><p>As Swiss Tables são uma família de tabelas de hash modernas popularizadas pelo SwissTable do Google e posteriormente adotadas na Abseil e em outras bibliotecas.</p><p>Tabelas hash tradicionais gastam muito tempo atrás de ponteiros ou carregando chaves apenas para descobrir que não correspondem. O principal recurso das Swiss Tables é a capacidade de rejeitar a maioria das sondagens usando uma pequena estrutura de matriz residente em cache, armazenada separadamente das chaves e valores, chamada de <em>bytes de controle</em>, para reduzir drasticamente o tráfego de memória.</p><p>Cada byte de controle representa um único slot e, em nosso caso, codifica duas coisas: se o slot está vazio e uma pequena impressão digital derivada do hash. Esses bytes de controle são dispostos de maneira contígua na memória, geralmente em grupos de 16, tornando-os ideais para processamento de <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">instrução única e dados múltiplos</a> (SIMD).</p><p>Em vez de sondar um slot de cada vez, as Swiss Tables analisam um bloco inteiro de controle de bytes usando instruções vetoriais. Em uma única operação, a CPU compara a impressão digital da chave de entrada com 16 slots e retira as entradas vazias. Somente os poucos candidatos que sobrevivem a esse processo rápido precisam ser carregados e comparados às chaves reais.</p><p>Esse design troca uma pequena quantidade extra de metadados por uma melhor localidade de cache e muito menos carregamentos aleatórios. À medida que a tabela cresce e as cadeias de sondagem se alongam, essas propriedades tornam-se cada vez mais valiosas.</p><h2>SIMD no centro</h2><p>A verdadeira estrela do espetáculo é o SIMD.</p><p>Bytes de controle não são apenas compactos, eles também são explicitamente projetados para serem processados com instruções vetoriais. Uma única comparação SIMD pode verificar 16 impressões digitais de uma vez, transformando o que normalmente seria um loop em algumas operações amplas. Por exemplo:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1f710e87dd749ab3/6a170cc46234e052dadb1a49/bd418778f0c6144f8f5f18419f6220ac0c935c7a-903x407.png" alt="SIMD no centro do Elasticsearch" /><p>Na prática, isso significa:</p><ul><li><p>Menos ramificações.</p></li><li><p>Cadeias de sondagem mais curtas.</p></li><li><p>Menos carregamentos da memória de chave e valor.</p></li><li><p>Utilização muito melhor das unidades de execução da CPU.</p></li></ul><p>A maioria das pesquisas nunca passa da verificação do byte de controle. Quando isso acontece, o restante do trabalho é focado e previsível. Esse é exatamente o tipo de carga de trabalho que CPUs modernas fazem bem.</p><h2>SIMD nos bastidores</h2><p>Para os leitores que gostam de espiar os bastidores, aqui está o que acontece ao inserir uma nova chave na tabela. Usamos a Panama Vector API com vetores de 128 bits, operando assim em 16 bytes de controle em paralelo.</p><p>O trecho a seguir mostra o código gerado em um Intel Rocket Lake com AVX-512. Embora as instruções reflitam esse ambiente, o design não depende do AVX-512. As mesmas operações vetoriais de alto nível são emitidas em outras plataformas usando instruções equivalentes (por exemplo, AVX2, SSE ou NEON).</p>; Load 16 control bytes from the control block
vmovdqu xmm0, XMMWORD PTR [r9+r10*1+0x10]

; Broadcast the 7-bit fingerprint of the new key across the vector
vpbroadcastb xmm1, r11d

; Compare all 16 control bytes to the new fingerprint
vpcmpeqb k7, xmm0, xmm1
kmovq rbx, k7

; Check if any matches were found
test rbx, rbx
jne &lt;handle_match&gt;<p>Cada instrução tem um papel claro no processo de inserção:</p><ul><li><p><code>vmovdqu</code>: Carrega 16 bytes de controle consecutivos no registrador <code>xmm0</code> de 128 bits.</p></li><li><p><code>vpbroadcastb</code>: Replica a impressão digital de 7 bits da nova chave em todas as faixas do registrador <code>xmm1</code>.</p></li><li><p><code>vpcmpeqb</code>: Compara cada byte de controle com a impressão digital transmitida, produzindo uma máscara de possíveis correspondências.</p></li><li><p><code>kmovq</code> + <code>test</code>: Move a máscara para um registrador de uso geral e verifica rapidamente se existe uma correspondência.</p></li></ul><p>Finalmente, decidimos sondar grupos de 16 bytes de controle por vez, pois o benchmarking mostrou que a expansão para 32 ou 64 bytes com registros mais amplos não oferecia nenhum benefício mensurável de desempenho.</p><h2>Integração em ES|QL</h2><p>Adotar o hashing com a técnica de Swiss Tables no Elasticsearch não foi uma simples substituição. O ES|QL tem requisitos rigorosos em relação à contabilidade de memória, segurança e integração com o restante do motor de computação.</p><p>Integramos a nova tabela hash de maneira precisa com o gerenciamento de memória do Elasticsearch, incluindo o reciclador de páginas e a contabilização de mecanismos de interrupção, garantindo que as alocações permaneçam visíveis e limitadas. As agregações do Elasticsearch são armazenadas densamente e indexadas por uma ID de grupo, mantendo o layout da memória compacto e rápido para iterações, além de possibilitar certas otimizações de desempenho ao permitir acesso aleatório.</p><p>Para chaves de bytes de comprimento variável, armazenamos em cache o hash completo junto com a ID do grupo. Isso evita o recálculo de códigos hash caros durante a sondagem e melhora a localidade do cache ao manter os metadados relacionados próximos uns dos outros. Durante o rehashing, podemos confiar no hash e bytes de controle em cache sem inspecionar os próprios valores, mantendo os custos de redimensionamento baixos.</p><p>Uma simplificação importante em nossa implementação é que as entradas nunca são excluídas. Isso elimina a necessidade de <em>lápides</em> (marcadores para identificar slots ocupados anteriormente) e permite que os slots vazios permaneçam realmente vazios, o que melhora ainda mais o comportamento da sondagem e mantém a eficiência das varreduras dos bytes de controle.</p><p>O resultado é um design que se encaixa naturalmente no modelo de execução do Elasticsearch, preservando as características de desempenho que tornam as Swiss Tables interessantes.</p><h2>Qual é o desempenho?</h2><p>Em pequenas cardinalidades, as Swiss Tables apresentam desempenho aproximadamente equivalente à implementação existente. Isso é esperado: quando as tabelas são pequenas, os efeitos de cache dominam menos e há pouca sondagem para otimizar.</p><p>À medida que a cardinalidade aumenta, o cenário logo muda.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt09b13af2fe162f59/6a170cc66f7f04485c9148b8/24900afc47ab07b0e9933f6117b99d0f4613f794-962x599.png" alt="Estatísticas ES|QL com tabelas hash no estilo Swiss Tables" /><p>O heatmap acima mostra fatores de melhoria de tempo para diferentes tamanhos de chave (8, 32, 64 e 128 bytes) entre cardinalidades de 1.000 a 10.000.000 de grupos. À medida que a cardinalidade aumenta, o fator de melhoria aumenta constantemente, chegando a 2 a 3 vezes para distribuições uniformes.</p><p>Essa tendência é exatamente o que o design prevê. Uma maior cardinalidade leva a cadeias de sondagem mais longas em tabelas hash tradicionais, enquanto a sondagem com a técnica Swiss Tables continua resolvendo a maioria das pesquisas em blocos de bytes de controle compatíveis com SIMD.</p><h2>O comportamento do cache conta a história</h2><p>Para entender melhor as acelerações, executamos os mesmos <a href="https://github.com/elastic/elasticsearch/pull/139343/files#diff-d0e0cc91a7495bf36b2d44eacce95f5185d01879e5f6c38089ac7a89aad17da7"><code>benchmarks</code></a> JMH sob o Linux <code>perf</code> e capturamos cache e estatísticas do TLB.</p><p>Em comparação com a implementação original, a versão Swiss Tables realiza cerca de 60% menos referências de cache no geral. Os carregamentos de cache no último nível caem mais de 4 vezes, e as falhas de carregamento da LLC caem mais de 6 vezes. Como as falhas de LLC costumam se traduzir diretamente em acessos à memória principal, essa redução sozinha explica grande parte da melhoria de ponta a ponta.</p><p>Mais próximo da CPU, observamos menos falhas de cache de dados L1 e quase 6 vezes menos falhas de dados TLB, indicando uma localidade espacial mais precisa e padrões de acesso à memória mais previsíveis.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb987a5bd98c0d7eb/6a170cc8a929cf9655ae0a25/6e49b7609fba83e33692cb9834552b6ca7e42a83-998x499.png" alt="Comportamento do cache: estatísticas originais x ES|QL com tabelas hash no estilo Swiss Tables" /><p>Esse é o benefício prático dos bytes de controle compatíveis com SIMD. Em vez de carregar repetidamente chaves e valores de locais de memória dispersos, a maioria das sondagens é resolvida analisando uma estrutura compacta residente no cache. Menos memória acessada significa menos falhas, e menos falhas significam consultas mais rápidas.</p><h2>Conclusão</h2><p>Ao adotar um design de tabela hash com a técnica Swiss Tables e apostar fortemente na sondagem compatível com SIMD, alcançamos uma aceleração de 2 a 3 vezes para cargas de trabalho de estatísticas ES|QL de alta cardinalidade, além de um desempenho mais estável e previsível.</p><p>Este trabalho destaca como estruturas de dados modernas conscientes da CPU podem desbloquear ganhos substanciais, mesmo para problemas já conhecidos, como tabelas hash. Há mais espaço para explorar aqui, como especializações adicionais de tipos primitivos e uso em outros caminhos de alta cardinalidade, como joins, todos eles apenas parte do esforço mais amplo e contínuo para modernizar continuamente os internos do Elasticsearch.</p><p>Se você tiver interesse nos detalhes ou quiser acompanhar o trabalho, confira o rastreamento de progresso de <a href="https://github.com/elastic/elasticsearch/pull/139343">pull request</a> e <a href="https://github.com/elastic/elasticsearch/issues/138799">meta issue</a> no Github.</p><p>Boa sorte com o hashing!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/esql-swiss-hash-stats</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/esql-swiss-hash-stats</guid>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Chris Hegarty,Matthew Alp,Nik Everett]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf76dd688c5b737e6/6a170cc9839dfa7fc7dcff40/21036e031070f14faccb2b53b22723de2750c391-1280x720.png" length="0" type="image/png"/>
    <pubDate>Mon, 19 Jan 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>
  <item>
    <title><![CDATA[Explorando a busca vetorial acelerada por GPU no Elasticsearch com NVIDIA: Capítulo I]]></title>
    <description><![CDATA[Com tecnologia NVIDIA cuVS, a colaboração busca fornecer aos desenvolvedores aceleração de GPU para pesquisa vetorial no Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Nós da organização Elastic Engineering estamos ocupados otimizando o desempenho do banco de dados vetorial há algum tempo. Nossa missão: tornar o Lucene e o Elasticsearch o melhor banco de dados vetorial. Por meio de <a href="https://www.elastic.co/pt/blog/accelerating-vector-search-simd-instructions">instruções SIMD de CPU</a> aceleradas por hardware, introduzindo novas inovações em compressão de dados vetoriais (<a href="https://www.elastic.co/pt/search-labs/blog/better-binary-quantization-lucene-elasticsearch">melhor quantização binária, também conhecida como BBQ</a>) e, em seguida, superando as expectativas ao atualizar a abordagem algorítmica do BBQ para obter ainda mais benefícios, além <a href="https://www.elastic.co/pt/search-labs/blog/filtered-hnsw-knn-search">de tornar o HNSW filtrado mais rápido</a>. Você entendeu a essência: estamos construindo um sistema mais rápido, melhor e mais eficiente. banco de dados vetorial para os desenvolvedores resolverem aqueles problemas RAG-gedy!</p><p>Como parte da nossa missão de não deixar nada para trás em termos de eficiência, estamos explorando oportunidades de aceleração com esses curiosos chips de computador, dos quais você provavelmente já ouviu falar: GPUs NVIDIA! (Sério, não é mesmo?).</p><p>Quando nos preocupamos com desempenho, temos vários espaços problemáticos a explorar: como indexar exponencialmente mais dados, como recuperar insights deles e como fazer isso quando seus modelos de ML estão envolvidos. Você deve conseguir aproveitar todos os benefícios disponíveis quando tiver GPUs.</p><p>Nesta postagem, mergulhamos em nossa colaboração com a equipe de pesquisa de vetores da NVIDIA enquanto exploramos a pesquisa de vetores acelerada por GPU no Elasticsearch. Este trabalho abre caminho para casos de uso em que os desenvolvedores podem usar uma combinação de GPUs e CPUs para aplicativos reais baseados no Elasticsearch. Tempos emocionantes!</p><h2>GPUs Elasticsearch</h2><p>Estamos felizes em compartilhar que a equipe de engenharia do Elasticsearch está ajudando a criar a experiência da API Java cuVS de código aberto para desenvolvedores, que expõe vinculações para algoritmos de pesquisa vetorial. Este trabalho aproveita nossa experiência anterior com a Panama FFI. O Elasticsearch e o Apache Lucene usam a API NVIDIA cuVS para criar o gráfico durante a indexação. Certo, vamos avançar; vamos voltar um pouco.</p><p><a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a>, uma biblioteca C++ de código aberto, está no centro desta colaboração. O objetivo é levar a aceleração da GPU para a pesquisa vetorial, fornecendo maior rendimento, menor latência e tempos de construção de índice mais rápidos. Mas o Elasticsearch e o Apache Lucene são escritos em Java; como isso funcionará?</p><p>Entre em contato com <a href="https://github.com/SearchScale/lucene-cuvs">o lucene-cuvs</a> e a colaboração Elastic-NVIDIA-SearchScale para trazê-lo ao ecossistema Lucene para explorar a pesquisa vetorial acelerada por GPU no Elasticsearch. Na versão recente do NVIDIA cuVS 25.02, adicionamos uma API Java para cuVS. A nova API é experimental e continuará evoluindo, mas atualmente está disponível para uso. Pode surgir a pergunta: as chamadas de funções nativas do Java não são lentas? Não mais! Estamos usando a nova <a href="https://openjdk.org/projects/panama/">Panama FFI</a> (Foreign Function Interface) para as vinculações, que tem sobrecarga mínima para downcalls Java para nativos.</p><p>Já faz algum tempo que usamos <a href="https://www.elastic.co/pt/search-labs/blog/lucene-and-java-moving-forward-together">o Panama FFI no Elasticsearch e no Lucene</a> . É incrível! Mas... sempre tem um “mas”, não é mesmo? O FFI tem desafios de disponibilidade nas versões do Java. Superamos isso compilando a API do cuVS para o Java 21 e encapsulando a implementação em um jar de várias versões voltado para o Java 22. Isso permite o uso do cuVS Java diretamente no Lucene e no Elasticsearch.</p><p>Ok, agora que temos a API Java do cuVS, o que mais precisaríamos?</p><h2>Um conto de dois algoritmos para CPU</h2><p>O Elasticsearch oferece suporte ao <a href="https://arxiv.org/abs/1603.09320">algoritmo HNSW</a> para pesquisa KNN aproximada e escalável. No entanto, para obter o máximo da GPU, usamos um algoritmo diferente, <a href="https://arxiv.org/pdf/2308.15136">CAGRA [</a><a href="https://arxiv.org/pdf/2308.15136"><strong>C</strong></a><a href="https://arxiv.org/pdf/2308.15136"><em>UDA</em></a> <a href="https://arxiv.org/pdf/2308.15136"><strong>A</strong></a><a href="https://arxiv.org/pdf/2308.15136"><em>NN</em></a> <a href="https://arxiv.org/pdf/2308.15136"><strong>GRA</strong></a><a href="https://arxiv.org/pdf/2308.15136"><em>ph</em></a><a href="https://arxiv.org/pdf/2308.15136">]</a>, que foi projetado especificamente para os altos níveis de paralelismo oferecidos pela GPU.</p><p>Antes de entrarmos em como pretendemos adicionar suporte ao CAGRA, vamos ver como o Elasticsearch e o Lucene acessam dados de índice por meio de um “formato de codec”. Isso consiste em</p><ol><li><p>a representação no disco,</p></li><li><p>as interfaces para leitura e escrita de dados,</p></li><li><p>e a maquinaria para lidar com a arquitetura baseada em segmentos do Lucene.</p></li></ol><p>Estamos implementando um novo <a href="https://lucene.apache.org/core/10_1_0/core/org/apache/lucene/codecs/KnnVectorsFormat.html">formato de vetor</a> KNN (k-vizinhos mais próximos) que usa internamente a API Java do cuVS para indexar e pesquisar na GPU. A partir daqui, “analisamos” esse tipo de codec por meio dos mapeamentos do Elasticsearch para um tipo de campo no índice. Como resultado, suas consultas KNN existentes continuam funcionando independentemente de o índice de apoio estar usando um gráfico CAGRA ou HNSW. É claro que isso encobre muitos detalhes, que planejamos abordar em um blog futuro. A seguir está a arquitetura de alto nível para um Elasticsearch acelerado por GPU.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb6197b631a34f8b6/6a170b0da6c2b9e60ce7970b/be6b7356c03df4dee7230625c2c9af3b019f93be-756x510.png" alt="" /><p>Este novo formato de codec tem como padrão o CAGRA. No entanto, ele também suporta a conversão de um gráfico CAGRA em um gráfico HNSW para pesquisa na CPU.</p><h2>Indexação e pesquisa na GPU: tomando algumas decisões “essenciais”</h2><p>Com a <a href="https://www.elastic.co/pt/search-labs/blog/stateless-your-new-state-of-find-with-elasticsearch">arquitetura</a> sem estado do Elasticsearch Serverless, que separa indexação e pesquisa, agora há uma delimitação clara de responsabilidades. Selecionamos o melhor perfil de hardware para cumprir cada uma dessas responsabilidades independentes.</p><p>Esperamos que os usuários considerem duas estratégias principais de implantação:</p><ol><li><p>Indexação e pesquisa na GPU: durante a indexação, crie um gráfico CAGRA e use-o durante a pesquisa — ideal quando uma pesquisa com latência extremamente baixa é necessária.</p></li><li><p>Indexar na GPU e pesquisar na CPU: durante a indexação, crie um gráfico CAGRA e converta-o em um gráfico HNSW. O gráfico HNSW é armazenado no índice, que pode ser usado posteriormente na CPU para pesquisa.</p></li></ol><p>Essa flexibilidade oferece diferentes modelos de implantação, oferecendo compensações entre custo e desempenho. Por exemplo, um serviço de indexação pode usar GPU para criar e mesclar gráficos de forma eficiente e oportuna, enquanto usa uma CPU de menor potência para pesquisa.</p><h2>Então aqui está o plano para pesquisa vetorial acelerada por GPU no Elasticsearch</h2><p>Estamos ansiosos para oferecer ganhos de desempenho e flexibilidade com estratégias de implantação aos usuários, oferecendo vários botões para equilibrar custo e desempenho. <a href="https://www.nvidia.com/gtc/session-catalog/?tab.catalogallsessionstab=16566177511100015Kus&amp;search=Lucene#/">Aqui está a sessão do NVIDIA GTC 2025</a> onde este trabalho foi apresentado em detalhes.</p><p>Gostaríamos de agradecer às equipes de engenharia da NVIDIA e da SearchScale pela fantástica colaboração. Em um próximo blog, exploraremos os detalhes da implementação e a análise de desempenho com mais profundidade. Segurem seus chapéus de curiosidade 🎩!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/gpu-accelerated-vector-search-elasticsearch-nvidia</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/gpu-accelerated-vector-search-elasticsearch-nvidia</guid>
    <category><![CDATA[Banco de dados vetorial]]></category>
    <dc:creator><![CDATA[Chris Hegarty,Hemant Malik]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt298e839e708ca11c/6a170b0fb339d560c2769fc2/38bc0377a6adce7eae0099f61902fdbbe644eb4a-1440x960.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 19 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Lucene Wrapped 2024]]></title>
    <description><![CDATA[2024 foi mais um ano importante para o Apache Lucene. Neste blog, vamos explorar os principais destaques.]]></description>
    <content:encoded><![CDATA[<p>O Apache Lucene teve um ano de 2024 bastante movimentado, com vários lançamentos, incluindo a primeira grande atualização em três anos, repleta de melhorias interessantes e novos recursos. Vamos explorar alguns dos principais destaques.</p><h2>Lucene e a comunidade</h2><p>Um projeto só é tão forte quanto a comunidade que o apoia. Apesar de mais de 20 anos de desenvolvimento, o projeto Lucene permanece vibrante e próspero graças aos seus colaboradores apaixonados e ativos.</p><p>Em 2024, o projeto Lucene registrou mais de 2.000 commits de 98 colaboradores únicos e quase 800 pull requests. O número de colaboradores continua a crescer, com novos committers e membros do PMC juntando-se ao projeto e ajudando a impulsionar seu sucesso.</p><h2>Lucene 10</h2><p>Em 2024, houve o primeiro grande lançamento em quase 3 anos - o Lucene 10, com mais de 2.000 commits de 185 colaboradores únicos. Embora o modelo de desenvolvimento seguido pelo Lucene permita a implementação de muitas melhorias e recursos em versões secundárias, uma versão principal oferece a oportunidade de trazer recursos e modernizações mais abrangentes. Por exemplo, o Lucene 10 requer no mínimo o Java 21. Aumentar a versão mínima do Java garante que o Lucene possa continuar a aproveitar as melhorias que o Java moderno oferece.</p><p>O principal objetivo do Lucene 10 é aproveitar melhor o hardware em que é executado. Vamos dar uma olhada rápida em alguns dos principais destaques:</p><ul><li><p><strong>Mais paralelismo na busca</strong> - embora a execução da busca já seja paralelizada entre os segmentos, agora vamos além, paralelizando dentro dos próprios segmentos. Isso desacopla a representação em disco do desempenho de execução, permitindo que até mesmo segmentos individuais se beneficiem do número de núcleos em sistemas modernos.</p></li><li><p><strong>Melhor paralelismo de E/S</strong> - o modelo de E/S síncrono direto usado pelo Lucene foi aprimorado com um estágio de pré-busca. Isso informa ao sistema operacional que uma região de um arquivo de índice será necessária em um futuro muito próximo, sem bloquear a thread de chamada.</p></li><li><p><strong>Melhoria na eficiência de CPU e armazenamento com indexação esparsa</strong> - O Lucene 10 introduz suporte para indexação esparsa, também chamada de indexação por chave primária ou indexação por zona em outros sistemas de armazenamento de dados.</p></li></ul><p>Para obter mais informações sobre o Lucene 10, consulte o <a href="https://www.elastic.co/search-labs/blog/apache-lucene-10-release-highlights">artigo</a> dedicado ao Lucene 10.</p><h2>Pesquisa e inovação em Lucene</h2><p>Em 2024, o Lucene testemunhou um aumento significativo em pesquisa e inovação, particularmente nas áreas de integração de aprendizado de máquina, busca vetorial e otimização para conjuntos de dados em larga escala, com referência em 10 <a href="https://scholar.google.com/scholar?as_ylo=2024&amp;q=lucene&amp;hl=en&amp;as_sdt=0,5">artigos e publicações de pesquisa</a> distintos. Algumas das principais áreas de pesquisa e desenvolvimentos incluem:</p><ul><li><p><strong>Suporte para Busca Vetorial e Incorporação</strong> - O Lucene oferece uma solução poderosa e escalável para busca baseada em vetores, permitindo a recuperação semântica em grande escala. Ao aproveitar a robusta infraestrutura de indexação e busca do Lucene, os usuários podem combinar o melhor da busca textual tradicional com os recursos avançados da busca vetorial moderna, tornando o Lucene uma solução abrangente para uma ampla gama de tarefas de busca e recuperação de informações.</p></li><li><p><strong>Modelos de Busca Híbrida</strong> - A pesquisa também explorou técnicas de busca híbrida, onde o Lucene combina a busca tradicional baseada em palavras-chave com a recuperação moderna baseada em vetores. Ao combinar índices baseados em termos com representações vetoriais densas, o Lucene consegue fornecer resultados de pesquisa mais precisos e contextualmente relevantes, preenchendo a lacuna entre a precisão dos mecanismos de busca tradicionais e a flexibilidade da busca semântica.</p></li></ul><p>Os esforços de pesquisa em andamento em 2024 demonstram a adaptabilidade do Lucene às necessidades em constante evolução das tecnologias de busca modernas, particularmente no contexto de IA, busca semântica e aplicações de big data. O projeto continua a crescer como uma plataforma poderosa, flexível e eficiente para casos de uso de busca tanto tradicionais quanto de ponta.</p><h2>Lançamentos do Lucene em 2024</h2><p>Embora não seja um reflexo exato, o grande volume de lançamentos destaca a dedicação e a energia contínuas da comunidade. Essas atualizações incluem melhorias significativas no desempenho e na eficiência da busca vetorial, suporte para madvise, otimizações para decodificação de listas de postagens, melhorias adicionais de velocidade por meio de SIMD e muito mais.</p><p>Segue a lista completa de lançamentos:</p><ul><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-1010-available">10.1.0</a> (2024-12-20)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9121-available">9.12.1</a> (2024-12-13)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-1000-available">10.0.0</a> (2024-10-14)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9120-available">9.12.0</a> (28/09/2024)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-8114-available">8.11.4</a> (2024-09-24)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9111-available">9.11.1</a> (2024-06-27)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9110-available">9.11.0</a> (2024-06-06)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9100-available">9.10.0</a> (2024-02-20)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-8113-available">8.11.3</a> (2024-02-08)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-992-available">9.9.2</a> (2024-01-29)</p></li></ul><p>Você pode encontrar mais informações e notas de lançamento na página <a href="https://projects.apache.org/project.html?lucene-core">do Lucene Core</a> . Além disso, existem versões equivalentes <a href="https://projects.apache.org/project.html?lucene-pylucene">do PyLucene</a> .</p><h2>Concluindo</h2><p>À medida que Lucene amadurece, continua a prosperar graças à sua comunidade dedicada e vibrante. Como vimos, 2024 foi um ano incrivelmente produtivo e agora aguardamos com expectativa os desenvolvimentos empolgantes que 2025 trará.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/apache-lucene-wrapped-2024</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/apache-lucene-wrapped-2024</guid>
    <category><![CDATA[Lucene]]></category>
    <dc:creator><![CDATA[Chris Hegarty]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt901211870015335c/6a17ddf6a292998b08d02b93/29a02c89b3c5adb37a5f900de634ff09cb63fdd9-1792x1024.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 03 Jan 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>