<?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/es/search-labs/author/lorenzo-dematte</link>
    </image>
    <link>https://www.elastic.co/es/search-labs/author/lorenzo-dematte</link>
    <atom:link href="https://www.elastic.co/es/search-labs/rss/author/lorenzo-dematte.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[es]]></language>
    <lastBuildDate>Mon, 21 Sep 2026 18:50:35 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Cómo creamos Elasticsearch simdvec para hacer una de las búsquedas vectoriales más rápidas del mundo]]></title>
    <description><![CDATA[Cómo construimos Elasticsearch SIMDvec, la biblioteca del kernel SIMD ajustada a mano detrás de cada consulta de búsqueda vectorial en Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch simdvec es el motor detrás de cada cálculo de distancia vectorial en Elasticsearch. Proporciona kerneles AVX-512 y NEON ajustados manualmente para cada tipo de vector que admite Elasticsearch. Su arquitectura de scoring masivo oculta la latencia de memoria mediante la precarga de datos explícita en x86 y las cargas intercaladas en ARM, por lo que muestra un rendimiento hasta 4 veces mayor que bibliotecas como FAISS y jvector cuando los datos exceden la caché de la CPU. En esta publicación, explicamos por qué lo creamos, qué contiene y cómo hace que la búsqueda vectorial de Elasticsearch sea una de las más rápidas del mundo.</p><h2>Cómo construimos Elasticsearch SIMDvec</h2><p>Cada consulta de búsqueda vectorial en Elasticsearch, ya sea un recorrido de <a href="https://arxiv.org/abs/1603.09320">mundo pequeño jerárquico navegable (HNSW)</a>, un escaneo de archivo invertido (IVF) o una pasada de reclasificación, se reduce al mismo problema: calcular distancias entre vectores, millones de veces por búsqueda. Elasticsearch admite una amplia gama de tipos de datos y estrategias de cuantificación, desde float32 hasta int8, bfloat16, binario y Mejor cuantificación binaria (BBQ). Cada una tiene distintas compensaciones entre memoria, rendimiento y recuperación. Detrás de todo esto hay un único motor: simdvec.</p><p>Creamos simdvec para que cada cálculo de distancia sea tan rápido como el hardware lo permita. En esta publicación, explicamos por qué lo creamos, qué contiene y dónde produce el mayor impacto.</p><h3>Creado como un auto de carreras</h3><p>Como aficionados a la Fórmula 1, y dado que uno de nosotros trabajó anteriormente con el equipo Ferrari de Fórmula 1, vemos un claro paralelismo. Un auto de Fórmula 1 está diseñado con un solo propósito: lograr el mejor tiempo de vuelta. La potencia del motor, la aerodinámica y el diseño del chasis solo importan en la medida en que contribuyen a ese resultado. Lo mismo ocurre con una base de datos vectorial, donde el rendimiento de indexación, la latencia de búsqueda y la recuperación definen el éxito.</p><p>Aunque lo que importa es el resultado final, para alcanzar los máximos niveles de rendimiento es necesario que cada componente funcione a la perfección. No puede ser solo <em>lo suficientemente bueno</em>, tiene que ser <em>el mejor </em>en su categoría. Simdvec está construido con esa mentalidad, que se enfoca en una parte fundamental del sistema: el motor. Es una biblioteca de kernel optimizada para <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">una sola instrucción y múltiples datos</a> (SIMD) diseñada específicamente, que proporciona funciones nativas de distancia en C++ ajustadas a mano, llamadas desde Java a través de la interfaz para funciones externas (FFI) de <a href="https://openjdk.org/projects/panama/">Panamá</a>. Admite evaluación masiva, precarga de líneas de caché y todos los tipos de vectores y diseños utilizados en Elasticsearch.</p><p>Ese es el motor que hay detrás de cada búsqueda.</p><h3>Por qué creamos nuestro propio motor</h3><p>Comenzamos en 2023 con la API Panama Vector en Apache Lucene. Funcionaba bien para productos punto float32, pero las necesidades de Elasticsearch superaron rápidamente lo que podía ofrecer. Elasticsearch admite una amplia gama de tipos de vectores cuantificados: int8, int4, bfloat16, de un solo bit y BBQ asimétrico. Cada uno tiene diferentes estrategias SIMD, diseños de empaquetado y requisitos de acumulador. Más allá de la cobertura de tipos, las rutas de puntuación de Elasticsearch exigen algo más que un rendimiento de un solo par: HNSW necesita puntuar varios vecinos del grafo en una sola pasada, IVF necesita puntuar en masa miles de candidatos con precarga y la puntuación basada en disco debe funcionar directamente en la memoria mapeada con mmap sin necesidad de copiar. Examinamos lo que estaba disponible y nada abarcaba el conjunto completo.</p><p>Así que construimos simdvec: kerneles C++ nativos ajustados a mano llamados desde Java a través de FFI, con puntuación masiva, precarga y soporte para cada tipo de vector que usa Elasticsearch. Al ser propietarios de la biblioteca, controlamos el stack completo. Cuando añadimos un nuevo tipo de cuantificación, como BBQ, se le asigna un kernel SIMD optimizado que se integra en todo el sistema. No esperamos a que una biblioteca upstream le de soporte y no comprometemos el rendimiento para ningún tipo. Cada consulta vectorial en Elasticsearch, ya sea HNSW, IVF, reranking o híbrida, se ejecuta en este motor, construido en torno a las operaciones y los tipos que realmente usamos.</p><p>Simdvec tiene bibliotecas nativas separadas para x86 y ARM, cada una con múltiples niveles de arquitectura de conjunto de instrucciones (ISA) seleccionados al inicio. La sobrecarga de llamadas desde Java vía FFI es muy baja, con <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#ffm-downcall-overhead-measurements">nanosegundos de un solo dígito</a>.</p><h3>El panorama</h3><p>No somos los únicos que construimos kerneles de distancia vectorial optimizados para SIMD. El ecosistema es rico y queríamos comprender cómo se desempeña simdvec. No para clasificar proyectos, sino para proporcionar contexto y explicar dónde se encuentra el motor de Elasticsearch. Seleccionamos tres proyectos como puntos de referencia, cada uno representando un enfoque diferente:</p><ul><li><p><strong>jvector:</strong> Una biblioteca de Java de vecino más cercano aproximado (ANN) que emplea la API Panama Vector para el cálculo vectorizado de distancias, con aceleración nativa en C opcional en x86.</p></li><li><p><strong>FAISS:</strong> Un marco de trabajo de búsqueda vectorial de open source ampliamente desplegado, con kerneles AVX2/AVX-512 ajustados a mano.</p></li><li><p><strong>NumKong</strong> (anteriormente SimSIMD): un conjunto completo de más de 2 000 kerneles SIMD ajustados a mano que abarcan funciones de distancia, operaciones matrices y computación geoespacial.</p></li></ul><p>Cada proyecto cumple un propósito diferente y realiza diferentes concesiones. Incluimos números de referencia de ellos para dar contexto al rendimiento de simdvec en las operaciones específicas que Elasticsearch necesita.</p><h3>Cómo medimos</h3><p>Las evaluaciones de simdvec y <a href="https://github.com/ChrisHegarty/jvector-kernel-benchmarks">jvector</a> están escritos en Java con JMH, la microevaluación estándar de JVM, lo que incluye la sobrecarga de FFI. Para <a href="https://github.com/ldematte/simsimd-benchmarks">las evaluaciones de NumKong</a> y <a href="https://github.com/ChrisHegarty/faiss-kernel-benchmarks">las evaluaciones de FAISS</a>, escribimos pequeños marcos de prueba de C/C++ con Google Benchmark, que es el marco de trabajo estándar para microevaluaciones de C++. Ambos marcos de trabajo reportan nanosegundos por operación con calibración de calentamiento e iteración. Verificamos mediante contadores de rendimiento de hardware que todas las bibliotecas usan SIMD en ambas plataformas. Todo el código de evaluación está disponible públicamente en los repositorios enlazados de GitHub (y, en el caso de simdvec, en el repositorio <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="Tabla en la que se enumeran dos plataformas: x86 con AMD EPYC Turin (Zen 5), AVX2 y AVX-512, AWS c8a.4xlarge; y ARM con Graviton 4 (Neoverse V2), NEON y SVE2, AWS c8g.4xlarge." /><p><strong>Software:</strong> JDK 25.0.2, JMH 1.37, GCC 14, Google Benchmark (última versión).</p><h2>Un vector a la vez</h2><p>La operación más básica en la búsqueda vectorial es calcular la distancia entre dos vectores. Cada evaluación de un vecino de HNSW, cada puntaje de un candidato a IVF, cada comparación de reclasificación se reduce a este bucle interno.</p><p>Medimos el rendimiento de un solo par en 1024 dimensiones en ambas plataformas, empezando por float32, el tipo base y el donde el ecosistema es más competitivo. Comparamos simdvec con FAISS y jvector; hemos excluido NumKong porque utiliza acumuladores float64 para float32, lo que lo hace entre 3,2 y 5,3 veces más lento (dependiendo de la plataforma), ya que prioriza la precisión numérica por encima del rendimiento. Para mantener la comparación de igual a igual, evaluamos NumKong en int8 en su lugar, donde utiliza la misma estrategia de acumulador que simdvec.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte3bc2ecaf3ad2b61/6a1701d2ab7f08039ddb9d0f/352cfa0fc18f123140f746d843404f80127fb1b7-1500x675.png" alt="Gráfico de barras horizontal titulado “Float32 Dot Product — AMD Turin” que compara cinco implementaciones: 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 y jvector a 43,9 ns/op." /><p>En la arquitectura x86, FAISS AVX-512 es el kernel de par único más rápido, con un tiempo de ejecución de 23 ns. A continuación, se ejecuta Simdvec AVX-512 a los 28 ns, un intervalo que refleja la sobrecarga de la llamada FFI. Ambos emplean FMA de 512 bits con desenrollado de múltiples acumuladores. A nivel AVX2, los dos valores son mucho más similares, 36 ns y 39 ns respectivamente, ambos limitados por el ancho de carga de memoria y registro de 256 bits. jvector tarda 44 ns usando la API de Java Panama Vector. Panamá genera buen código SIMD, pero las funciones intrínsecas de C++ ajustadas manualmente siguen teniendo ventaja.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcbbbe442631a575d/6a1701d42b835f81bcf4b083/95e44d9767f21ec4bccaed835e3c99aa180431ee-1500x495.png" alt="Gráfico de barras horizontal llamado “float32 Dot Product — Graviton 4 (ARM)” que muestra ES simdvec en 70.2 ns/op, jvector en 110.0 ns/op y FAISS en 155.6 ns/op." /><p>En ARM, simdvec lidera a 70 ns, muy por delante de jvector a 110 ns y FAISS a 156 ns. Simdvec tiene kernels NEON ajustados a mano para aarch64. Jvector no tiene código ARM nativo y depende de Panama. FAISS se basa en la auto-vectorización del compilador en lugar de en las intrínsecas NEON explícitas, lo que explica la mayor brecha. Esto refleja una ventaja práctica de poseer la biblioteca del kernel: cuando Elasticsearch se expandió a Graviton, agregamos kerneles NEON especialmente diseñados. Ni jvector ni FAISS priorizaron el código nativo de ARM en la misma medida.</p><p>Sin embargo, Elasticsearch no solo puntúa float32. La cuantificación <strong>Int8</strong> reduce la memoria en 4x, bfloat16 en 2x y BBQ en 32x. Cada tipo necesita su propia estrategia SIMD, y simdvec proporciona kernels nativos ajustados a mano para todos ellos.</p><p>De todas las bibliotecas que comparamos, solo NumKong tiene kernels comparables para int8. Medimos el producto escalar int8, la distancia euclidiana al cuadrado y el coseno en 1024 dimensiones.</p><p><strong>Puntuación de par único Int8 (1024 dimensiones, ns/vec op — cuanto más bajo, mejor)</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3ac255d158e93504/6a1701d5a292997e48d00eb1/a0b852fd5f51d57bd2488886600472ee65ab64da-1594x378.png" alt="Tabla que compara el rendimiento de x86 y ARM en el producto punto, distancia euclidiana al cuadrado y similitud del coseno; muestra los valores de ES, NumKong y diff para cada operación en ambas arquitecturas." /><p>En ambas arquitecturas, NumKong es igual o más rápido en dimensiones pequeñas y medias, donde la diferencia se debe en gran parte a una menor sobrecarga de llamadas (llamada C directa vs FFI en Java). En dimensiones mayores, simdvec se pone al día, donde la implementación más eficiente del kernel (que emplea desenrollamiento en cascada) amortiza el costo de llamada: a medida que aumenta la dimensión, <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#single-pair-i8-nsop-2">esta brecha se cierra y finalmente se revierte</a>. El cruce está en dimensiones entre 768 y 1536, dependiendo de la función y la arquitectura.</p><p>A pesar de la sobrecarga ligeramente mayor de Java FFI, simdvec está a la par con las bibliotecas altamente optimizadas de C/C++. No solo es la única librería con kernels optimizados tanto para float32 <em>como para </em> int8, sino que también lidera en ARM y solo está ligeramente por detrás de FAISS en x86 (para float32), y muy cerca de NumKong en ambas arquitecturas (para int8). Y en el caso de bfloat16, int4, binary y BBQ, aunque existen alternativas, simdvec se distingue por su SIMD ajustado manualmente y adaptado a la estructura de datos de cada tipo.</p><p>Pero un motor de búsqueda en producción no califica un vector a la vez; califica miles por consulta. La siguiente pregunta es qué sucede a esa escala.</p><h3>Miles a la vez</h3><p>El rendimiento de un solo par es solo una parte del panorama. Lo que importa en la práctica es cómo se comportan los sistemas bajo carga. Una sola consulta HNSW puede puntuar cientos de vecinos de grafos. Un escaneo de IVF puede puntuar miles de entradas en la lista de publicaciones. Un paso de reclasificación puede puntuar decenas de miles de candidatos. El rendimiento por par individual es importante, pero lo que más importa es la rapidez con la que puedes puntuar muchos vectores, y cómo se degrada el rendimiento de forma gradual a medida que el conjunto de trabajo se desborda de las cachés de la CPU.</p><p>Simdvec proporciona evaluación masiva para todos los tipos de datos. No son solo bucles sobre kernels de un solo par; usan bucles internos de varios acumuladores que cargan el vector de búsqueda una vez por paso de dimensión y lo comparten entre varios vectores de documentos, con precarga explícita de líneas de caché para el siguiente batch. Ni jvector ni FAISS ofrecen un equivalente (en el momento de redacción de esta publicación). Jvector no tiene una API de bulk, así que quien llama puntúa un par a la vez en un bucle. FAISS expone <code>fvec_inner_products_ny</code> que, en el momento de redacción de esta publicación, está implementado como un bucle sobre su función de distancia de un solo par, sin amortización de la búsqueda ni precarga.</p><p><strong>Float32.</strong> Para medir el impacto a nivel del kernel, puntuamos una sola consulta contra un número creciente de vectores de documentos float32 de 1024 dimensiones con patrones de acceso aleatorio que simulan búsquedas de vecinos de grafos dispersos similares a HNSW. Los tres tamaños de sets de datos, 32, 625 y 32 500 vectores, se eligen para que el conjunto de trabajo supere la caché L1, L2 y L3, respectivamente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2df64ec77a1921ae/6a1701d714b270393ae3c4de/1d90267be1c63ac82b8ba588617ebedb0be0d1b6-1334x558.png" alt="Dos gráficos de barras que comparan los tiempos de puntuaciones en producto escalar de Float32 en masa para Elasticsearch simdvec, FAISS y jvector en AMD Turin (x86, AVX-512) y Graviton 4 (ARM, NEON) en tres tamaños: 32 vectores, 625 vectores y 32 500 vectores." /><p>Cuando los datos caben en la caché, simdvec es el más rápido en ambas plataformas, pero las diferencias son modestas, ya que predomina la aritmética del kernel. La separación real se nota cuando el conjunto de trabajo supera el tamaño de L3. En x86, simdvec alcanza los 95 ns por vector, mientras que FAISS necesita 165 ns y jvector 412 ns. En ARM, la tendencia es la misma: simdvec se mantiene en 162 ns, mientras que FAISS sube a 347 ns y jvector a 476 ns. La precarga y la amortización de búsquedas en simdvec mantienen la latencia de memoria oculta de una manera que un bucle simple sobre kerneles de par único no puede coincidir y el beneficio se amplía precisamente donde operan las cargas de búsqueda reales, en lo profundo de la memoria principal.</p><p><strong>Int8.</strong> Lo mismo ocurre con los tipos cuantificados. Medimos el rendimiento del cálculo del producto escalar int8 en 1024 dimensiones con sets de datos de un tamaño tal que superaran los límites de las cachés L1, L2 y L3, en comparación con el cálculo en bloque de simdvec con el cálculo de pares individuales de NumKong en un bucle.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcda85e10007188d0/6a1701d9cf4f25d722b2cff7/9ee97d98b40d13b19370b76b33e67ea66bfb3250-1580x338.png" alt=" Tabla llamada &quot;x86 — puntuación masiva, producto punto int8 (ns/op, menor es mejor)&quot; que compara ES simdvec y NumKong en tres tamaños de vector: 128, 2 500 y 130 000, con los valores correspondientes de ns/op y las proporciones de aceleración." /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt972c311b7d08ba73/6a1701dadc55dec02ee00c87/601f50a03fa3e6263cbac9700281dfe3e511de60-1580x338.png" alt="Tabla llamada “ARM — Puntuación masiva, producto punto int8 (ns/op, menor es mejor)” comparación de ES simdvec y NumKong a través de tres tamaños de vector—128, 2 500 y 130 000—con los valores correspondientes de ns/op y las ratios de aceleración" /><p>En x86, simdvec es entre 1,2 y 1,9 veces más rápido, impulsado por la combinación de precarga explícita y procesamiento por lotes. En ARM, simdvec gana de nuevo (1,7 a 1,9 veces más rápido) en todos los tamaños de sets de datos. La ventaja radica en el procesamiento por lotes de cuatro vectores a la vez, lo que proporciona paralelismo a nivel de memoria mediante un patrón de acceso intercalado. En ambos casos, el resultado más llamativo es lo que ocurre en el mayor tamaño de set de datos, donde más importa.</p><p>Los resultados para la distancia al cuadrado y el coseno muestran un patrón similar, con aceleraciones de 1,4 a 1,8 veces para ARM, y de 1,3 a 3,0 veces para x86 (detalles <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md">aquí</a>).</p><h3>Cuando la memoria importa</h3><p>Los índices de vectores de producción normalmente no caben en la caché de la CPU. Un índice de 10M-vectores int8 a 1024 dimensiones es de 10 GB. La evaluación de candidatos implica el procesamiento en flujo continuo de datos desde la DRAM y ahí es donde la arquitectura de evaluación masiva marca la diferencia.</p><p>Usamos contadores de rendimiento de hardware para medir lo que sucede dentro de la CPU durante la puntuación masiva y descubrimos que ocultar la latencia de la memoria requiere dos estrategias fundamentalmente diferentes, una por arquitectura.</p><p><strong>En x86, la precarga explícita elimina los fallos de caché. </strong>El kernel masivo procesa los vectores secuencialmente, uno completamente calculado antes del siguiente, mientras emite instrucciones de precarga para el siguiente batch. Los datos futuros se cargan en la L1 antes de que la CPU los necesite.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt368f29b5143d0f5a/6a1701dcc1e8a51780f8817b/a39548f8060c2a4a5154521a4047dd92d8cd77be-1580x309.png" alt="Tabla titulada «x86 (AMD Turín) — contadores de hardware por operación int8» comparando modos individuales y masivos para fallos de caché L1, IPC y fallos de dTLB, con los factores de mejora correspondientes." /><p>En ARM, el mismo enfoque secuencial tuvo un rendimiento deficiente, incluso con precarga. En cambio, <strong>el kernel masivo entrelaza las cargas</strong> de cuatro vectores en cada posición de zancada, lo que proporciona al motor fuera de orden cuatro flujos de memoria independientes. La CPU no recoge datos más rápido, sino que espera menos al tener siempre algo más que calcular mientras las solicitudes de memoria están en curso. Puedes encontrar un análisis detallado en <a href="https://github.com/elastic/elasticsearch/issues/145412">este ticket de GitHub</a>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8751ac5b20b75508/6a1701deab7f08db83db9d13/832de3bc0d556a493b7bf3f250196018acfc1585-1580x238.png" alt="Tabla llamada “ARM (Graviton 4): contadores de hardware por operación int8” que compara los modos individual y masivo para los errores de caché L1 y los bloqueos de backend, con las notas de mejora correspondientes" /><p>Los números cuentan dos historias diferentes:</p><ol><li><p>En x86, la precarga convierte 139K fallos de caché en 19K y las instrucciones por ciclo (IPC) se duplican más de dos veces. La ventaja de masa crece con el tamaño de los sets de datos, de 1,2 veces en L2 a 2,8 veces más allá de L3, porque la precarga oculta progresivamente viajes de ida y vuelta de DRAM más costosos.</p></li><li><p>En ARM, los fallos de caché apenas cambian. Lo que cambia es la utilización: las interrupciones del backend disminuyen un 40 % porque el patrón de acceso intercalado mantiene el pipeline alimentado. Esta ventaja se mantiene en un consistente 1,8 veces independientemente del tamaño del sets de datos, porque el paralelismo a nivel de memoria se aplica tanto si los datos provienen de la caché como de la DRAM.</p></li></ol><p>Dos arquitecturas, dos estrategias y un resultado: a escala de producción, simdvec mantiene la pipeline de la CPU ocupada incluso cuando los vectores están dispersos por la memoria principal.</p><h2>Qué significa esto para los usuarios de Elasticsearch</h2><p>Estas capacidades a nivel de kernel se potencian entre sí. Una única consulta de búsqueda vectorial puede calcular millones de operaciones de distancia: recorrido del grafo HNSW, puntuación de candidatos, reclasificación. En miles de búsquedas concurrentes, los nanosegundos por operación se traducen directamente en latencia de búsqueda y rendimiento del cluster. Tanto si usas float32, int8, bfloat16 o BBQ, tanto si tu índice está en la memoria como en el disco, simdvec es el motor subyacente, y cada una de esas operaciones pasa por el mismo motor, lo que optimiza hasta el último nanosegundo.</p><p>La conclusión clave es que, a escala de producción, el rendimiento de la búsqueda vectorial no está determinado principalmente por el rendimiento bruto de SIMD. Lo que marca la diferencia es la eficiencia con la que el sistema oculta la latencia de la memoria mientras mantiene el rendimiento computacional en millones de operaciones pequeñas.</p><p>Los kerneles de simdvec mejoran prácticamente con cada versión de Elasticsearch. Cuando surgen nuevos tipos de cuantización y plataformas de hardware, reciben kerneles ajustados desde el primer día. Y los tipos existentes siguen ganando velocidad a medida que perfeccionamos las implementaciones que ya están disponibles.</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[Base de datos vectorial]]></category>
    <category><![CDATA[Dentro de 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[Indexación vectorial hasta 12 veces más rápida en Elasticsearch con NVIDIA cuVS: aceleración por GPU, capítulo 2]]></title>
    <description><![CDATA[Descubre cómo Elasticsearch logra un rendimiento de indexación casi 12 veces mayor. Esto lo consigue con la indexación vectorial acelerada por GPU y NVIDIA cuVS.]]></description>
    <content:encoded><![CDATA[<p>A principios de este año, Elastic anunció la <a href="https://ir.elastic.co/news/news-details/2025/Elastic-Brings-Enterprise-Data-to-NVIDIA-AI-Factories/default.aspx">colaboración</a> con NVIDIA para llevar la aceleración por GPU a Elasticsearch, integrándola con <a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a>, como se detalló en una <a href="https://www.nvidia.com/en-us/on-demand/session/gtc25-S71286/">sesión en NVIDIA GTC</a> y en varios <a href="https://www.elastic.co/search-labs/blog/gpu-accelerated-vector-search-elasticsearch-nvidia">blogs</a>. Esta publicación es una actualización sobre el esfuerzo de co-ingeniería con el equipo de búsqueda de vectores de NVIDIA.</p><h2>Resumen</h2><p>Primero, pongámonos al día. Elasticsearch se consolidó como una poderosa base de datos vectorial, que ofrece un amplio conjunto de características y un sólido rendimiento para la búsqueda de similitudes a gran escala. Con capacidades como la cuantificación escalar, Better Binary Quantization (<a href="https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch">BBQ</a>), operaciones vectoriales <a href="https://www.elastic.co/blog/accelerating-vector-search-simd-instructions">SIMD</a> y algoritmos más eficientes en disco como <a href="https://www.elastic.co/search-labs/blog/diskbbq-elasticsearch-introduction">DiskBBQ</a>, ya ofrece opciones eficientes y flexibles para gestionar cargas de trabajo vectoriales.</p><p>Al integrar NVIDIA cuVS como un módulo invocable para tareas de búsqueda vectorial, nuestro objetivo es ofrecer beneficios significativos en el rendimiento y la eficiencia de la indexación vectorial para soportar mejor las cargas de trabajo vectoriales a gran escala.</p><h2>El desafío</h2><p>Uno de los mayores desafíos al construir una base de datos vectorial de alto rendimiento es construir el índice vectorial: el grafo <a href="https://arxiv.org/abs/1603.09320">HNSW</a>. La construcción de índices se ve dominada con rapidez por millones o incluso miles de millones de operaciones aritméticas a medida que cada vector se compara con muchos otros. Además, las operaciones del ciclo de vida del índice, como la compactación y las fusiones, pueden aumentar aún más la sobrecarga total de cálculo de la indexación. A medida que los volúmenes de datos y las incrustaciones vectoriales asociadas crecen de manera exponencial, las GPU de cómputo acelerado, diseñadas para el paralelismo masivo y las matemáticas de alto rendimiento, se posicionan idealmente para manejar estas cargas de trabajo.</p><h2>Ingresa al plugin Elasticsearch-GPU</h2><p><a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a> es una biblioteca open source de CUDA-X para la búsqueda vectorial acelerada por GPU y la agrupación de datos, que permite una rápida construcción de índices y recuperación de incrustaciones para cargas de trabajo de AI y de sistemas de recomendación.</p><p>Elasticsearch utiliza cuVS a través de <a href="https://mvnrepository.com/artifact/com.nvidia.cuvs/cuvs-java">cuvs-java</a>, una biblioteca open source desarrollada por la comunidad y que mantiene NVIDIA. La biblioteca cuvs-java es ligera, se basa en la <a href="https://docs.rapids.ai/api/cuvs/nightly/c_api/">API C de cuVS</a> y usa la función externa del <a href="https://openjdk.org/projects/panama/">Proyecto Panamá</a> para exponer las características de cuVS de una manera idiomática en Java, al tiempo que es moderna y presenta un alto rendimiento.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc7fd7361099da05a/6a17e920be608670af00477f/5f6daa1eb07f704a6707d9e6b7ccb81d0abaa8c9-566x419.png" alt="Cómo funciona Elasticsearch con NVIDIA cuVS, CPU e indexación con GPU" /><p>La biblioteca cuvs-java está integrada en un <a href="https://github.com/elastic/elasticsearch/pull/135545">nuevo plugin de Elasticsearch</a>; por lo tanto, la indexación vectorial en la GPU puede ocurrir en el mismo nodo y proceso de Elasticsearch, sin la necesidad de provisionar ningún código o hardware externo. Durante la construcción del índice, si se instala la biblioteca cuVS y hay una GPU presente y configurada, Elasticsearch usará la GPU para acelerar el proceso de indexación vectorial. Los vectores se asignan a la GPU, que construye un grafo <a href="https://arxiv.org/abs/2308.15136">CAGRA</a>. Este grafo se convierte entonces al formato HNSW, y hace que esté disponible de inmediato para la búsqueda vectorial en la CPU. El formato final del grafo construido es el mismo que el que se construiría en la CPU; esto permite a Elasticsearch aprovechar las GPU para indexar vectores de alto rendimiento cuando el hardware subyacente lo admite, al tiempo que libera poder de la CPU para otras tareas (búsqueda simultánea, procesamiento de datos, etc.).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt485f55f29d6df5c4/6a17e922be6086dcf3004785/3ea255bd9bfd7983f78143c5eba999d2149d72be-671x356.png" alt="" /><h2>Aceleración en la generación de índices</h2><p>Como parte de la integración de la aceleración de GPU en Elasticsearch, se realizaron varias mejoras en cuvs-java, centradas en la entrada/salida eficiente de datos y la invocación de funciones. Una mejora clave es el 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 vectores de forma transparente, ya sea que residan en la memoria heap de Java, fuera de la memoria heap o en la memoria de la GPU. Esto permite que los datos se muevan de manera eficiente entre la memoria y la GPU, lo que evita copias innecesarias de potencialmente miles de millones de vectores.</p><p>Gracias a esta abstracción subyacente de copia cero, tanto la transferencia a la memoria de la GPU como la recuperación del grafo se pueden realizar directamente. Durante la indexación, los vectores se almacenan primero en búfer en la memoria heap de Java, y luego se envían a la GPU para construir el grafo CAGRA. Después, el grafo se recupera de la GPU, se convierte al formato HNSW y se mantiene en el disco.</p><p>En el momento de la fusión, los vectores ya están almacenados en disco, sin pasar por la memoria heap de Java. Los archivos de índice se mapean en memoria, y los datos se transfieren directamente a la memoria de la GPU. El diseño también se adapta fácilmente a diferentes anchos de bits, como float32 o int8, y se extiende de forma natural a otros esquemas de cuantificación.</p><h2>Redoble de tambores… entonces, ¿cómo se funciona?</h2><p>Antes de entrar en los números, un poco de contexto es útil. La fusión de segmentos en Elasticsearch suele ejecutarse automáticamente en segundo plano durante la indexación, lo que dificulta hacer benchmarks de forma aislada. Para obtener resultados reproducibles, utilizamos la fusión forzosa para activar explícitamente la combinación de segmentos en un experimento controlado. Dado que la fusión forzosa hace las mismas operaciones de fusión subyacentes que la fusión en segundo plano, su rendimiento sirve como un indicador útil de las mejoras esperadas, aunque las ganancias exactas pueden diferir en las cargas de trabajo de indexación del mundo real.</p><p>Ahora, veamos los números.</p><p>Nuestros resultados iniciales de evaluaciones comparativas son muy prometedores. Ejecutamos la evaluación comparativa en una instancia de AWS <code>g6.4xlarge</code> con almacenamiento NVMe conectado a nivel local. Se configuró un único nodo de Elasticsearch para que use el número predeterminado y óptimo de subprocesos de indexación (8, uno por cada núcleo físico) y deshabilite <a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/merge">la limitación de la fusión</a> (que es menos aplicable con discos NVMe rápidos).</p><p>Para el conjunto de datos, utilizamos 2,6 millones de vectores con 1536 dimensiones del <a href="https://github.com/elastic/rally-tracks/blob/master/openai_vector/README.md">vector de pista de Rally de OpenAI</a>, codificados como <a href="https://github.com/elastic/elasticsearch/pull/137072">cadenas de texto base64</a> e indexados como float32 <em>hnsw</em>. En todos los escenarios, los grafos construidos alcanzan niveles de recuperación de hasta el 95 %. A continuación, presentamos nuestros hallazgos:</p><ul><li><p><strong>Rendimiento de indexación:</strong> al trasladar la construcción de grafos a la GPU durante los vaciados de búferes en memoria, aumentamos el rendimiento en aproximadamente 12 veces.</p></li><li><p><strong>Fusión forzada:</strong> una vez que finaliza la indexación, la GPU continúa acelerando la fusión de segmentos, lo que acelera la fase de fusión forzada en alrededor de 7 veces.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfea4ee13b5a3b10d/6a17e923e9ea879c6aa9c616/f60ea9ee5996e456f393ffd195ee7eada6e5a7c2-948x387.png" alt="" /><ul><li><p><strong>Uso de la CPU:</strong> descargar la construcción de grafos a la GPU reduce de manera significativa el uso promedio y máximo de la CPU. Los grafos a continuación ilustran el uso de la CPU durante la indexación y la fusión, y permiten ver cuánto menor es cuando estas operaciones se ejecutan en la GPU. Un menor uso de la CPU durante la indexación por GPU libera ciclos de CPU que pueden redirigirse para mejorar el rendimiento de la búsqueda.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt80ff9c53f9b6884a/6a17e925445de9ee4b4d0187/5e680a5fc41700a877f3d8b2e5ce18ebd3f37a0b-1600x562.png" alt="" /><ul><li><p><strong>Recuperación:</strong> la precisión se mantiene prácticamente igual entre las ejecuciones de CPU y GPU, y el grafo construido por la GPU alcanza una recuperación un poco mayor.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5cbe084eca27b8e4/6a17e926faa913317093c8b7/48a2b7758606bd321712b7d8378cd2640e652a4e-1384x544.png" alt="" /><h2>Comparación en otra dimensión: el precio</h2><p>La comparación anterior utilizaba intencionalmente hardware idéntico, y la única diferencia era si se usaba la GPU durante la indexación o no. Esa configuración es útil para aislar los efectos de la computación en bruto, pero también podemos analizar la comparación desde una perspectiva de costos.</p><p>A un precio horario similar al de la configuración acelerada por GPU, se puede provisionar una configuración de solo CPU con aproximadamente el doble de recursos comparables de CPU y memoria: 32 vCPUs (AMD EPYC) y 64 GB de RAM, lo que permite duplicar el número de hilos de indexación a 16.</p><p>Para mantener la comparación justa y consistente, ejecutamos este experimento solo de CPU en una instancia AWS g6.8xlarge, con la GPU explícitamente desactivada. Esto nos permitió mantener constantes todas las demás características del hardware mientras evaluábamos la compensación entre costo y rendimiento de la aceleración de GPU frente al indexado solo con CPU.</p><p>Como era de esperar, la instancia de CPU más potente sí muestra un mejor rendimiento en comparación con las evaluaciones comparativas de la sección anterior. Sin embargo, cuando comparamos esta instancia de CPU más potente con los resultados acelerados por GPU originales, la GPU aún ofrece beneficios sustanciales en cuanto al rendimiento: <strong>~ 5 veces</strong> de mejora en el rendimiento de indexación y <strong>~ 6 veces </strong>en la fusión forzada, todo ello mientras se construyen grafos que alcanzan niveles de recuperación de hasta un <strong>95 %.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt94b5eb6f95ba307d/6a17e928abe0f255d4dfea35/8ffa58cae3ad175ef2932a351aeef4c34a1407b9-948x394.png" alt="" /><h2>Conclusión</h2><p>En escenarios completos, la aceleración por GPU con NVIDIA cuVS ofrece una mejora de casi 12 veces en el rendimiento de la indexación y una disminución de 7 veces en la latencia de fusión forzada, con un uso de CPU significativamente menor. Esto demuestra que la indexación vectorial y las cargas de trabajo de fusión se benefician de manera significativa de la aceleración por GPU. En una comparación ajustada por costos, la aceleración por GPU continúa mostrando beneficios sustanciales en cuanto al rendimiento, con alrededor de 5 veces más rendimiento de indexación y 6 veces más rapidez en las operaciones de fusión forzada.</p><p>La indexación vectorial acelerada por GPU tiene planificada hoy en día una vista previa técnica en Elasticsearch 9.3, cuyo lanzamiento está programado para principios de 2026.</p><p>Mantente atento a lo que viene.</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[Base de datos vectorial]]></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>