<?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[Mayya Sharipova - 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[Mayya Sharipova - 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/mayya-sharipova</link>
    </image>
    <link>https://www.elastic.co/es/search-labs/author/mayya-sharipova</link>
    <atom:link href="https://www.elastic.co/es/search-labs/rss/author/mayya-sharipova.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[es]]></language>
    <lastBuildDate>Wed, 23 Sep 2026 02:34:48 GMT</lastBuildDate>
  <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>
  <item>
    <title><![CDATA[Acelerar la fusión de gráficos HNSW]]></title>
    <description><![CDATA[Explore el trabajo que estuvimos haciendo para reducir la sobrecarga de crear varios gráficos HNSW, en individuo reducir el costo de fusionar gráficos.]]></description>
    <content:encoded><![CDATA[<p>En el pasado, <a href="https://www.elastic.co/es/search-labs/blog/multi-graph-vector-search">hablamos</a> de algunos de los retos de tener que buscar <a href="https://www.elastic.co/es/search-labs/blog/hnsw-graph">en varios gráficos HNSW</a> y cómo pudimos mitigarlos. En ese momento insinuamos algunas mejoras adicionales que planeamos. Esta publicación es la culminación de ese trabajo.</p><p>Podrías preguntarte, ¿por qué usar varios gráficos? Este es un efecto secundario de una elección arquitectónica en Lucene: segmentos inmutables. Como ocurre con la mayoría de las opciones arquitectónicas, hay pros y contras. Por ejemplo, recientemente lanzamos Elasticsearch sin servidor con GA. En este contexto, obtuvimos beneficios muy significativos de los segmentos inmutables, incluida la replicación eficiente de índices y la capacidad de desacoplar el índice y el proceso de consulta y escalarlos automáticamente de forma independiente. Para la cuantificación vectorial, las fusiones de segmentos nos dan la oportunidad de actualizar los parámetros para adaptarlos a las características de los datos. En este sentido, creemos que hay otros beneficios que ofrece tener oportunidades para medir las características de los datos y revisar las opciones de indexación.</p><p>En esta publicación, discutiremos el trabajo que estuvimos haciendo para reducir significativamente la sobrecarga de crear múltiples gráficos HNSW y, en individuo, para reducir el costo de fusionar gráficos.</p><h3>Fondo</h3><p>Para mantener un número manejable de segmentos, Lucene verifica periódicamente si debe fusionar segmentos. Esto equivale a comprobar si el recuento de segmentos actual supera un recuento de segmentos de destino, que está determinado por el tamaño del segmento base y la política de combinación. Si se supera el recuento, Lucene combina grupos de segmentos mientras se infringe la restricción. Este proceso se describió en detalle <a href="https://blog.mikemccandless.com/2011/02/visualizing-lucenes-segment-merges.html">en otra parte</a>.</p><p>Lucene elige fusionar segmentos de tamaño similar porque esto logra un crecimiento logarítmico en la amplificación de escritura. En el caso de un índice vectorial, la amplificación de escritura es el número de veces que se insertará un vector en un gráfico. Lucene intentará fusionar segmentos en grupos de aproximadamente 10. En consecuencia, los vectores se insertan en un gráfico aproximadamente veces, donde  es el recuento de vectores índice y  es el recuento de vectores de segmento base esperado. Debido al crecimiento logarítmico, la amplificación de escritura es de un solo dígito incluso para índices enormes. Sin embargo, el tiempo total dedicado a fusionar gráficos es linealmente proporcional a la amplificación de escritura.</p><p>Al fusionar gráficos HNSW ya hacemos una pequeña optimización: retener el gráfico para el segmento más grande e insertar vectores de los otros segmentos en él. Esta es la razón del factor 9/10 anterior. A continuación, mostramos cómo podemos hacerlo significativamente mejor empleando información de todos los gráficos que estamos fusionando.</p><h3>Fusión de grafos HNSW</h3><p>Antes conservábamos el grafo más grande e insertábamos vectores de los otros ignorando los gráficos que los contenían. La idea clave que aprovechamos a continuación es que cada grafo HNSW que descartamos contiene información importante de proximidad sobre los vectores que contiene. Nos gustaría usar esta información para acelerar la inserción, al menos algunos, de los vectores.</p><p>Nos enfocamos en el problema de insertar un gráfico más pequeño  en un gráfico más grande , ya que esta es una operación atómica que podemos usar para construir cualquier política de combinación.</p><p>La estrategia consiste en encontrar un subconjunto de vértices de  insertarlos en el gráfico grande. Luego usamos la conectividad de estos vértices en el gráfico pequeño para acelerar la inserción de los vértices restantes . A continuación, usamos  y  para denotar los vecinos de un vértice  en el grafo pequeño y grande, respectivamente. Esquemáticamente, el proceso es el siguiente.</p><p><code>MERGE-HNSW</code></p><p><code>Inputs </code><code> and </code></p><p><code>1</code><code>Find </code><code> to insert into </code><code> using COMPUTE-JOIN-SET</code>
<code>2</code><code>Insert each vertex </code><code> into </code>
<code>3</code><code>for </code><code> do</code>
<code>4</code>
<code>5</code>
<code>6</code><code>FAST-SEARCH-LAYER</code>
<code>7</code><code>SELECT-NEIGHBORS-HEURISTIC</code>
<code>8</code></p><p>Calculamos el conjunto  empleando un procedimiento que discutimos a continuación (línea 1). Luego insertamos cada vértice en  en el gráfico grande usando el procedimiento de inserción HNSW estándar (línea 2). Para cada vértice que no insertamos encontramos sus vecinos que insertamos y sus vecinos en el gráfico grande (líneas 4 y 5). Usamos un procedimiento <code>FAST-SEARCH-LAYER</code> sembrado con este conjunto (línea 6) para encontrar los candidatos para el <code>SELECT-NEIGHBORS-HEURISTIC</code> del <a href="https://arxiv.org/pdf/1603.09320">artículo</a> HNSW (línea 7). En efecto, estamos reemplazando <code>SEARCH-LAYER</code> para encontrar el conjunto candidato en el método <code>INSERT</code> (Algoritmo 1 del artículo), que de lo contrario no cambia. Finalmente, agregamos el vértice que acabamos de insertar en  (línea 8).</p><p>Está claro que para que esto funcione, cada vértice en  debe tener al menos un vecino en . De hecho, requerimos que para cada vértice en  que  para algunos , la máxima conectividad de capa. Observamos que en los gráficos reales de HNSW vemos una gran dispersión de grados de vértice. La siguiente figura muestra una función de densidad acumulativa típica del grado de vértice para la capa inferior de un gráfico HNSW de Lucene.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc815e1a9c3bb0d06/6a17e178ec0f89308a5a6564/44f001b3a1bc6627e172fed5c52a02cfdcb4cd66-1324x898.png" alt="Grafo HNSW: Ejemplo de distribución de grados de vértices" /><p>Exploramos el uso de un valor fijo para  así como convertirlo en una función del grado del vértice. Esta segunda opción conduce a mayores aceleramientos con un impacto mínimo en la calidad del gráfico, por lo que optó por lo siguiente</p><p>Tenga en cuenta que | es igual al grado del vértice  en el gráfico pequeño por definición. Tener un límite inferior de dos significa que insertaremos cada vértice cuyo grado sea menor que dos.</p><p>Un argumento de conteo simple sugiere que si elegimos  con cuidado, solo necesitamos insertar alrededor  en  directamente. Específicamente, coloreamos una arista del grafo si insertamos exactamente uno de sus vértices finales en . Entonces sabemos que para que cada vértice en  tenga al menos  vecinos en  , necesitamos colorear al menos  aristas. Además, esperamos que</p><p>Aquí,  es el grado medio del vértice en la gráfica pequeña. Para cada vértice  coloreamos como máximo  Bordes. Por lo tanto, el número total de bordes que esperamos colorear es como máximo . Esperamos que al elegir  con cuidado coloreemos cerca de este número de aristas y así cubrir todos los vértices  necesidades para satisfacer</p><p>Esto implica que .</p><p>Siempre que <code>SEARCH-LAYER</code> domine el tiempo de ejecución, esto sugiere que podríamos lograr un aceleramiento de hasta  en el tiempo de fusión. Dado el crecimiento logarítmico de la amplificación de escritura, esto significa que incluso para índices muy grandes, normalmente solo duplicaríamos el tiempo de construcción en comparación con la construcción de un gráfico.</p><p>El riesgo en esta estrategia es que dañamos la calidad del gráfico. Inicialmente lo intentamos con un <code>FAST-SEARCH-LAYER</code>sin operación. Descubrimos que esto degrada la calidad del gráfico en la medida en que la recuperación en función de la latencia se vio afectada, particularmente cuando se fusiona en un solo segmento. Luego exploramos varias alternativas empleando una búsqueda limitada del gráfico. Al final, la elección más efectiva fue la más simple. Usar <code>SEARCH-LAYER</code> pero con un <code>ef_construction</code>bajo. Con esta parametrización pudimos lograr gráficos de excelente calidad y aún así disminuir el tiempo de fusión en un poco más del 30% en promedio.</p><h3>Cálculo del conjunto de unión</h3><p>Encontrar un buen conjunto de unión puede formular como un problema de cobertura de grafos HNSW. Una heurística codiciosa es una heurística simple y efectiva para aproximar cubiertas óptimas de grafos. El enfoque que tomamos elige vértices uno a uno para sumar a  en orden decreciente de ganancia. La ganancia se define de la siguiente manera:</p><p>Aquí,  denota el recuento de vecinos de un vector  en  y  es la función indicadora. La ganancia incluye el cambio en el recuento del vértice que agregamos a , es decir,  ya que nos acercamos a nuestro objetivo al agregar un vértice menos cubierto. El cálculo de la ganancia se ilustra en la siguiente figura para el vértice naranja central.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7a353d56fa09af5f/6a17e17a2f4a5c33f7fa8825/fe11cd55a7d94d9e0b0f4d47ea309a99075c355d-540x474.png" alt="Ganancia de vértices para agregar al conjunto de unión J en el grafo HNSW" /><p>Mantenemos el siguiente estado para cada vértice :</p><ol><li><p>Ya sea rancio,</p></li><li><p>Su ganancia </p></li><li><p>El recuento de vértices adyacentes en  denotado </p></li><li><p>Un número aleatorio en el rango [0,1] que se usa para el desempate.</p></li></ol><p>El pseudocódigo para calcular el conjunto de combinaciones es el siguiente.</p><p><code>COMPUTE-JOIN-SET</code></p><p><code>Inputs </code></p><p><code>1</code>
<code>2</code>
<code>3</code><code>for </code><code> do</code>
<code>4</code>
<code>5</code>
<code>6</code>
<code>7</code><code>while </code><code> do
8</code><code> maximum gain vertex in </code>
<code>9</code><code>Remove the state for </code><code> from </code>
<code>10</code><code>if </code><code> is not stale then</code>
<code>11</code>
<code>12</code>
<code>13</code><code>for </code><code> do</code>
<code>14</code><code>mark </code><code> as stale if </code>
<code>15</code><code>mark neighbors of </code><code> stale if </code><code>
16</code><code>
17</code><code>else
18</code><code>
19</code><code>if </code><code> then
20</code><code>
21</code><code>return </code></p><p>Primero inicializamos el estado en las líneas 1-5.</p><p>En cada iteración del bucle principal extraemos inicialmente el vértice de ganancia máxima (línea 8), rompiendo los empates al azar. Antes de realizar cualquier cambio, debemos verificar si la ganancia del vértice está obsoleta. En individuo, cada vez que agregamos un vértice a  afectamos la ganancia de otros vértices:</p><ol><li><p>Dado que todos sus vecinos tienen un vecino adicional en  , sus ganancias pueden cambiar (línea 14)</p></li><li><p>Si alguno de sus vecinos ahora está completamente cubierto, todas las ganancias de sus vecinos pueden cambiar (líneas 14-16)</p></li></ol><p>Recalculamos las ganancias de manera perezosa, por lo que solo recalculamos la ganancia de un vértice si queremos insertarlo en  (líneas 18-20). Dado que las ganancias solo disminuyen, nunca podemos perder un vértice que debamos insertar.</p><p>Tenga en cuenta que simplemente necesitamos realizar un seguimiento de la ganancia total de vértices que agregamos a  para determinar cuándo salir. Además,  al menos un vértice tendrá una ganancia distinta de cero, por lo que siempre progresamos.</p><h3>Resultados</h3><p>Realizamos experimentos en cuatro conjuntos de datos que juntos cubren nuestras tres métricas de distancia admitidas (euclidiana, coseno y producto interno):</p><ol><li><p>quora-E5-small: 522931 documentos, 384 dimensiones y emplea la similitud del coseno,</p></li><li><p>cohe-wikipedia-v2: 1M de documentos, 768 dimensiones y emplea similitud de coseno,</p></li><li><p>gist: 1M documentos, 960 dimensiones y emplea la distancia euclidiana, y</p></li><li><p>cohe-wikipedia-v3: 1M de documentos, 1024 dimensiones y emplea el máximo producto interno.</p></li></ol><p>Para cada conjunto de datos evaluamos dos niveles de cuantificación:</p><ol><li><p>int8: que emplea un entero de 1 byte por dimensión y</p></li><li><p>BBQ: que emplea un solo bit por dimensión.</p></li></ol><p>Finalmente, para cada experimento evaluamos la calidad de la búsqueda a dos profundidades de recuperación y examinamos luego de construir el índice y luego luego de forzar la fusión en un solo segmento.</p><p>En resumen, logramos aceleramientos sustanciales consistentes en la indexación y la fusión mientras mantenemos la calidad del gráfico y, por lo tanto, el rendimiento de búsqueda en todos los casos.</p><h4>Experimento 1: cuantización int8</h4><p>Los aceleramientos promedio desde la línea de base hasta el candidato, los cambios propuestos, son:</p><p>Aceleramiento del tiempo del índice: <strong>1.28</strong></p><p>Forzar la velocidad de combinación: <strong>1.72</strong></p><p>Esto corresponde al siguiente desglose en tiempos de ejecución</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8422be122ef1a9c9/6a17e17bbe6086522e00467d/5f9f6d487b4c74c4998aa47465912c1a9743e928-734x479.png" alt="Indexar y fusionar tiempos para las estrategias de fusión de línea base y candidatas" /><p>Para completar, los tiempos exactos son</p><p></p><p>Índice</p><p></p><p>Fusionar</p><p></p><p>Conjunto de datos</p><p>referencia</p><p>candidato</p><p>Desarrolla</p><p>candidato</p><p>quora-E5-pequeño</p><p>112.41s</p><p>81.55s</p><p>113.81s</p><p>70.87s</p><p>wiki-cohesión-v2</p><p>158.1s</p><p>122,95 segundos</p><p>425.20s</p><p>239.28s</p><p>quid</p><p>141.82s</p><p>119.26s</p><p>536.07s</p><p>279.05s</p><p>wiki-cohesión-v3</p><p>211.86s</p><p>168.22s</p><p>654,97 segundos</p><p>414.12s</p><p>A continuación, mostramos los gráficos de recuperación frente a latencia que comparan el candidato (líneas discontinuas) con la línea de base en dos profundidades de recuperación: recall@10 y recall@100 para índices con múltiples segmentos (el resultado final de nuestra estrategia de fusión predeterminada luego de indexar todos los vectores) y luego de forzar la fusión en un solo segmento. Una curva más alta y más a la izquierda es mejor, lo que significa una mayor recuperación con una latencia más baja.</p><p>Como puede ver, para índices de múltiples segmentos, el candidato es mejor para el conjunto de datos Cohere v3 y un poco peor, pero casi comparable, para todos los demás conjuntos de datos. Luego de fusionar en un solo segmento, las curvas de recuperación son casi idénticas para todos los casos.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf674622469bf6a90/6a17e17dfbc5f874a84919c9/9195297f19f90b172d832ba56bdada7b0d8a768b-985x392.png" alt="Recuperar @10 y @100 frente a la latencia luego de crear el índice" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltde89f7e94ac823f4/6a17e17fe9ea876429a9c507/c866f32d579ae2b841e92ca733dd29c0e214ac6b-986x386.png" alt="Recuperar @10 y @100 frente a la latencia luego de fusionar en un solo segmento" /><h4>Experimento 2: Cuantización de asado</h4><p>Los aceleramientos promedio desde la línea de base hasta el candidato son:</p><p>Aceleramiento del tiempo de índice: <strong>1.33</strong></p><p>Forzar la velocidad de combinación: <strong>1.34</strong></p><p>Esto corresponde al siguiente desglose en tiempos de ejecución</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5b0eb305222fa5c2/6a17e18125daab514f08a18c/11be0cf6b63480dc703409329357ea4847b55051-740x415.png" alt="Indexar y fusionar el tiempo para las estrategias de fusión de línea base y candidatas" /><p>Para completar, los tiempos exactos son</p><p></p><p>Índice</p><p></p><p>Fusionar</p><p></p><p>Conjunto de datos</p><p>referencia</p><p>candidato</p><p>Desarrolla</p><p>candidato</p><p>quora-E5-pequeño</p><p>70.71s</p><p>58.25s</p><p>59.38s</p><p>40.15s</p><p>wiki-cohesión-v2</p><p>203.08s</p><p>142.27s</p><p>107.27s</p><p>85.68s</p><p>quid</p><p>110.35s</p><p>105,52 segundos</p><p>323,66 segundos</p><p>202.2s</p><p>wiki-cohesión-v3</p><p>313.43s</p><p>190.63s</p><p>165,98 segundos</p><p>159,95 segundos</p><p>Para índices de segmentos múltiples, el candidato es mejor para casi todos los conjuntos de datos, excepto cohere v2, donde la línea de base es ligeramente mejor. Para los índices de un solo segmento, las curvas de recuperación son casi idénticas para todos los casos.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb12174abeadbcdd1/6a17e1822f4a5c4cc2fa8829/7da1be27bab5a7f5f9c9a1882ea35761a4a0ba5c-973x383.png" alt="Recuperar @10 y @100 frente a la latencia luego de crear el índice" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf1b88d4f7fec9905/6a17e184414c64a8de9450b4/a26af30a56c55a12addee7e4fb7e8f606f366668-979x386.png" alt="Recordar @10 y @100 frente a la latencia que se fusionó en un solo segmento" /><h3>Conclusión</h3><p>El algoritmo discutido en este blog estará disponible en el próximo Lucene 10.2 y en la versión de Elasticsearch que se basa en él. Los usuarios podrán aprovechar el rendimiento mejorado de la combinación y el tiempo de compilación de índices reducido en estas nuevas versiones. Este cambio es parte de nuestro esfuerzo continuo para hacer que Lucene y Elasticsearch sean rápidos y eficientes para la búsqueda vectorial e híbrida.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/hnsw-graphs-speed-up-merging</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/hnsw-graphs-speed-up-merging</guid>
    <category><![CDATA[Base de datos vectorial]]></category>
    <category><![CDATA[Lucene]]></category>
    <dc:creator><![CDATA[Thomas Veasey,Mayya Sharipova]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9fca6a01d0541cfb/6a17e187033c8d46486bb0e1/49a6c880f5dedd0fa502ece5be124824ee218cc0-1792x1024.png" length="0" type="image/png"/>
    <pubDate>Mon, 07 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>