<?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/de/search-labs/author/lorenzo-dematte</link>
    </image>
    <link>https://www.elastic.co/de/search-labs/author/lorenzo-dematte</link>
    <atom:link href="https://www.elastic.co/de/search-labs/rss/author/lorenzo-dematte.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[de]]></language>
    <lastBuildDate>Wed, 23 Sep 2026 04:26:30 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Wie wir Elasticsearch simdvec entwickelten, um die Vektorsuche zu einer der schnellsten weltweit zu machen]]></title>
    <description><![CDATA[Wie wir Elasticsearch simdvec entwickelten, die von Hand optimierte SIMD-Kernel-Bibliothek hinter jeder Vektorsuchanfrage in Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch simdvec ist die Engine hinter jeder Vektordistanzberechnung in Elasticsearch. Sie bietet von Hand optimierte AVX-512- und NEON-Kernel für jeden von Elasticsearch unterstützten Vektortyp. Ihre Bulk-Scoring-Architektur verbirgt Speicherlatenz durch explizites Prefetching auf x86 und verschachteltes Laden auf ARM und übertrifft Bibliotheken wie FAISS und jvector um das bis zu Vierfache, wenn Daten den CPU-Cache überschreiten. In diesem Beitrag geht es darum, warum wir sie entwickelt haben, was darin steckt und wie sie die Vektorsuche in Elasticsearch zu einer der schnellsten weltweit macht.</p><h2>Wie wir Elasticsearch simdvec entwickelten</h2><p>Jede Vektorsuchanfrage in Elasticsearch, sei es ein <a href="https://arxiv.org/abs/1603.09320">Hierarchical Navigable Small World (HNSW)</a> Traversal, ein Inverted File (IVF) Scan oder ein Reranking-Pass, reduziert sich auf dasselbe Problem: die Berechnung der Distanzen zwischen Vektoren, und zwar millionenfach pro Anfrage. Elasticsearch unterstützt eine breite Palette von Datentypen und Quantisierungsstrategien, von float32 über int8, bfloat16, binär und Better Binary Quantization (BBQ). Jede Option bringt unterschiedliche Kompromisse zwischen Speicher, Durchsatz und Abruf mit sich. Hinter all dem steht eine einzige Engine: simdvec.</p><p>Wir haben simdvec so entwickelt, dass jede Entfernungsberechnung so schnell erfolgt, wie es die Hardware erlaubt. In diesem Beitrag geht es darum, warum wir sie entwickelt haben, was in ihr steckt und wo sie die größte Wirkung erzielt.</p><h3>Gebaut wie ein Rennwagen</h3><p>Als Formel-1-Enthusiasten, mit einer Person, die bereits mit dem Formel-1-Team von Ferrari gearbeitet hat, sehen wir eine klare Parallele. Ein Formel-1-Wagen wird mit einem einzigen Ziel entwickelt: die beste Rundenzeit zu erzielen. Motorleistung, Aerodynamik und Fahrwerkskonstruktion spielen nur insofern eine Rolle, als dass sie zu diesem Ergebnis beitragen. Das Gleiche gilt für eine Vektordatenbank, in der Indexierungsdurchsatz, Abfragelatenz und Rückruf den Erfolg definieren.</p><p>Das Endergebnis ist zwar wichtig, aber um ein Höchstmaß an Leistung zu erreichen, muss jede Komponente ihr Bestes geben. Es reicht nicht, wenn sie <em>einfach nur gut</em> sind, sie müssen die <em>Besten </em>in ihrer Kategorie sein. Simdvec wurde mit dieser Denkweise entwickelt und konzentriert sich auf einen entscheidenden Teil des Systems: die Engine. Sie ist eine zweckgebundene, <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">Single Instruction Multiple Data</a> (SIMD) optimierte Kernel-Bibliothek, die von Hand optimierte, native C++ Distanzfunktionen bereitstellt, die von Java über die <a href="https://openjdk.org/projects/panama/">Panama</a> Foreign Function Interface (FFI) aufgerufen werden. Sie unterstützt Bulk-Scoring, Prefetching von Cache-Linien sowie alle in Elasticsearch verwendeten Vektortypen und Layouts.</p><p>Das ist der Motor hinter jeder Abfrage.</p><h3>Warum wir unser eigenes System entwickelt haben</h3><p>Wir haben 2023 mit der Panama Vector API in Apache Lucene begonnen. Für float32-Punktprodukte war das zunächst ideal, doch die Anforderungen von Elasticsearch überstiegen schnell die Möglichkeiten des Systems. Elasticsearch unterstützt eine breite Palette quantisierter Vektortypen: int8, int4, bfloat16, Single-Bit und asymmetrisches BBQ. Jedes System verfügt über unterschiedliche SIMD-Strategien, Packungs- und Akkumulatoranforderungen. Über die Typabdeckung hinaus verlangen die Scoring-Pfade von Elasticsearch mehr als einen Durchsatz für einzelne Paare: HNSW muss mehrere Graphnachbarn in einem Durchgang bewerten, IVF benötigt eine Massenbewertung von Tausenden von Kandidaten mit Vorabruf und die auf Festplatten basierte Bewertung muss direkt auf dem mmap-Speicher arbeiten, ohne zu kopieren. Kein Angebot auf dem Markt deckte das gesamte Spektrum ab.</p><p>Also haben wir simdvec entwickelt: Von Hand optimierte, native C++-Kernel, die über FFI aus Java aufgerufen werden, mit Bulk-Scoring, Prefetching und Unterstützung für jeden von Elasticsearch verwendeten Vektortyp. Als Inhaber der Bibliothek kontrollieren wir den gesamten Stack. Wenn wir einen neuen Quantisierungstyp wie BBQ hinzufügen, wird ein optimierter SIMD-Kernel im gesamten System integriert. Wir warten nicht auf die Unterstützung durch eine Upstream-Bibliothek und gehen absolut keine Kompromisse bei der Leistung ein. Jede Vektorabfrage in Elasticsearch, ob HNSW, IVF, Reranking oder Hybrid, läuft auf dieser Engine, die auf den von uns tatsächlich verwendeten Operationen und Typen aufbaut.</p><p>Simdvec verfügt über separate native Bibliotheken für x86 und ARM, wobei jeweils mehrere ISA-Ebenen (Instruction Set Architecture) beim Starten ausgewählt werden. Der Call-Overhead von Java über FFI ist mit <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#ffm-downcall-overhead-measurements">einstelligen Nanosekunden</a> sehr gering.</p><h3>Die Landschaft</h3><p>Wir sind nicht die Einzigen, die SIMD-optimierte Vektordistanz-Kernel erstellen. Das Ökosystem ist vielfältig und wir wollten verstehen, wie simdvec funktioniert. Nicht um Projekte zu bewerten, sondern um Kontext zu liefern und zu erklären, wo die Elasticsearch-Engine angesiedelt ist. Wir haben drei Projekte als Referenzpunkte ausgewählt, die jeweils einen anderen Ansatz repräsentieren:</p><ul><li><p><strong>jvector:</strong> Eine Java-Bibliothek für Approximate Nearest Neighbor (ANN), die die Panama Vector API für vektorisierte Entfernungsberechnungen verwendet, mit optionaler nativer C-Beschleunigung auf x86.</p></li><li><p><strong>FAISS:</strong> Ein weit verbreitetes Open-Source-Framework zur Vektorsuche mit von Hand optimierten AVX2/AVX-512-Kernel.</p></li><li><p><strong>NumKong</strong> (ehemals SimSIMD): Eine umfassende Suite von über 2.000 von Hand optimierten SIMD-Kernel über Distanzfunktionen, Matrixoperationen und georäumliche Berechnungen.</p></li></ul><p>Jedes Projekt verfolgt einen anderen Zweck und geht unterschiedliche Kompromisse ein. Wir fügen daraus Referenznummern hinzu, um Kontext für die Leistung von simdvec bei den spezifischen Abläufen zu erhalten, die Elasticsearch benötigt.</p><h3>Wie wir messen</h3><p>Die simdvec- und <a href="https://github.com/ChrisHegarty/jvector-kernel-benchmarks">jvector-Benchmarks</a> wurden in Java mit JMH, dem Standard JVM-Microbenchmark-Harness, geschrieben, einschließlich FFI-Overhead. Für die <a href="https://github.com/ldematte/simsimd-benchmarks">NumKong-Benchmarks</a> und die <a href="https://github.com/ChrisHegarty/faiss-kernel-benchmarks">FAISS-Benchmarks</a> haben wir mit Google Benchmark, dem Standard-C++-Mikrobenchmark-Framework, kleine C/C++-Harnesses geschrieben. Beide Frameworks melden Nanosekunden pro Operation mit Aufwärmung und Iterationskalibrierung. Wir haben anhand von Hardware-Leistungszählern überprüft, dass alle Bibliotheken auf beiden Plattformen SIMD verwenden. Der gesamte Benchmark-Code ist in den verlinkten GitHub-Repositories (und im Fall von simdvec im <a href="https://github.com/elastic/elasticsearch">Elasticsearch-Repository</a>) öffentlich verfügbar.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt90a7d66553be3c9d/6a1701d166c4f942caf8bea5/aee116772df161cf86b7668f575ac34c733a23c5-1580x238.png" alt="Tabelle mit zwei Plattformen: x86 mit AMD EPYC Turin (Zen 5), AVX2 und AVX-512, AWS c8a.4xlarge und ARM mit Graviton 4 (Neoverse V2), NEON und SVE2, AWS c8g.4xlarge." /><p><strong>Software:</strong> JDK 25.0.2, JMH 1.37, GCC 14, Google Benchmark (neueste Version).</p><h2>Ein Vektor nach dem anderen</h2><p>Die grundlegendste Funktion der Vektorsuche ist die Berechnung des Abstands zwischen zwei Vektoren. Jede HNSW-Nachbarbewertung, jede IVF-Kandidatenbewertung und jeder Reranking-Vergleich dreht sich um diese interne Schleife.</p><p>Wir haben den Durchsatz einzelner Datenpaare in 1024 Dimensionen auf beiden Plattformen gemessen, beginnend mit float32, dem Basistyp, bei dem das Ökosystem am wettbewerbsfähigsten ist. Wir vergleichen simdvec mit FAISS und jvector, wobei wir NumKong ausgeschlossen haben, da es float64-Akkumulatoren für float32 verwendet, was es je nach Plattform 3,2- bis 5,3-mal langsamer macht und numerische Präzision über Durchsatz gestellt wird. Um den Vergleich nicht zu verfälschen, testen wir NumKong stattdessen auf int8, wo es die gleiche Akkumulatorstrategie wie simdvec verwendet.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte3bc2ecaf3ad2b61/6a1701d2ab7f08039ddb9d0f/352cfa0fc18f123140f746d843404f80127fb1b7-1500x675.png" alt="Horizontales Balkendiagramm mit dem Titel „float32 Dot Product — AMD Turin“ vergleicht fünf Implementierungen: FAISS AVX‑512 mit 23,2 ns/op, ES simdvec AVX‑512 mit 28,3 ns/op, FAISS AVX2 mit 36,4 ns/op, ES simdvec AVX2 mit 38,9 ns/op und jvector mit 43,9 ns/op." /><p>Auf x86 ist FAISS AVX-512 der schnellste Einzelpaar-Kernel mit 23 ns. Simdvec AVX-512 folgt mit 28 ns, eine Lücke, die den Overhead des FFI-Aufrufs widerspiegelt. Beide verwenden 512-Bit-FMA mit Multi-Akkumulator-Unrolling. Auf der AVX2-Ebene liegen die beiden sehr viel näher beieinander, nämlich 36 ns bzw. 39 ns, die beide durch die 256-Bit-Register- und Speicherladebreiten eingeschränkt sind. jvector landet bei 44 ns mit der Java Panama Vector API. Panama generiert guten SIMD-Code, aber von Hand optimierte C++-Intrinsics sind hier im Vorteil</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcbbbe442631a575d/6a1701d42b835f81bcf4b083/95e44d9767f21ec4bccaed835e3c99aa180431ee-1500x495.png" alt="Horizontales Balkendiagramm mit dem Titel „float32 Dot Product — Graviton 4 (ARM)“, das ES simdvec bei 70,2 ns/op, jvector bei 110,0 ns/op und FAISS bei 155,6 ns/op zeigt." /><p>Auf ARM liegt simdvec mit 70 ns deutlich vor jvector mit 110 ns und FAISS mit 156 ns. Simdvec verfügt über von Hand optimierte NEON-Kernel für aarch64. Jvector hat keinen nativen ARM-Code und basiert auf Panama. FAISS verlässt sich auf die automatische Vektorisierung des Compilers und nicht auf explizite NEON-Intrinsics, was den größeren Abstand erklärt. Dies spiegelt einen praktischen Vorteil des Besitzes der Kernel-Bibliothek wider: Als Elasticsearch zu Graviton erweitert wurde, fügten wir eigens entwickelte NEON-Kernel hinzu. Weder jvector noch FAISS haben nativem ARM-Code den gleichen Stellenwert eingeräumt.</p><p>Elasticsearch bewertet aber nicht nur float32. <strong>Int8-Quantisierung</strong> reduziert den Speicher um das Vierfache, bfloat16 um das Doppelte und BBQ um das 32-Fache. Jeder Typ benötigt seine eigene SIMD-Strategie und simdvec bietet von Hand optimierte, native Kernel für alle diese Typen.</p><p>Von den Bibliotheken, die wir verglichen haben, hat nur NumKong vergleichbare Kernel für int8. Wir haben das int8-Skalarprodukt, die quadrierte euklidische Distanz und den Kosinus bei 1024 Dimensionen gemessen.</p><p><strong>Int8 Einzelpaar-Wertung (1024 Dimensionen, ns/vec op – je niedriger, desto besser)</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3ac255d158e93504/6a1701d5a292997e48d00eb1/a0b852fd5f51d57bd2488886600472ee65ab64da-1594x378.png" alt="Tabelle, die die Leistung von x86 und ARM für Punktprodukt-, quadratisch-euklidische und Kosinus-Operationen vergleicht und ES-, NumKong- und Diff-Werte für jede Operation auf beiden Architekturen auflistet." /><p>Auf beiden Architekturen ist NumKong bei kleinen bis mittleren Dimensionen gleich schnell oder sogar schneller, wobei der Unterschied hauptsächlich auf den geringeren Call-Overhead zurückzuführen ist (direkter C-Call vs. Java FFI). Bei größeren Dimensionen holt simdvec auf, wobei die effizientere Kernel-Implementierung (die Cascade Unrolling verwendet) die Aufrufkosten amortisiert: Mit zunehmender Dimension <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#single-pair-i8-nsop-2">schließt sich diese Lücke und kehrt sich schließlich um.</a> Die Übergangsdimensionen liegen je nach Funktion und Architektur zwischen 768 und 1536.</p><p>Trotz des etwas höheren Aufwands von Java FFI befindet sich simdvec mit hochoptimierten C/C++-Bibliotheken auf Augenhöhe. Sie ist nicht nur die einzige Bibliothek mit optimierten Kernel für float32 <em>und</em> int8, sondern führt auch beim ARM und liegt auf x86 (für float32) nur leicht hinter FAISS zurück und auf beiden Architekturen sehr nahe an NumKong (für int8). Für bfloat16, int4, binär und BBQ gibt es zwar Alternativen, aber simdvec zeichnet sich durch von Hand optimierte SIMD aus, die auf das Datenlayout jedes Typs zugeschnitten ist.</p><p>Eine Produktionssuchmaschine bewertet jedoch nicht einen Vektor nach dem anderen, sondern Tausende pro Abfrage. Die nächste Frage ist, was in diesem Maßstab passiert.</p><h3>Tausende auf einmal</h3><p>Die Leistung eines einzelnen Paares stellt nur einen Teil des Gesamtbildes dar. In der Praxis ist entscheidend, wie sich Systeme unter Last verhalten. Eine einzelne HNSW-Abfrage kann Hunderte von Nachbarn im Graphen bewerten. Ein IVF-Scan kann Tausende von Einträgen in Posting-Listen bewerten. Ein Reranking-Durchlauf kann Zehntausende von Kandidaten bewerten. Der Durchsatz pro Paar ist wichtig, aber noch wichtiger ist, wie schnell Sie viele Vektoren bewerten können und wie gut die Leistung nachlässt, wenn das Working Set nicht mehr in die CPU-Caches passt.</p><p>Simdvec bietet Bulk-Scoring für jeden Datentyp. Dabei handelt es sich nicht nur um Schleifen über Single-Pair-Kerne, sondern auch um innere Schleifen mit mehreren Akkumulatoren, die den Abfragevektor einmal pro Dimensionsschritt laden und ihn auf mehrere Dokumentvektoren verteilen, mit explizitem Cache-Line-Prefetching für den nächsten Batch. Weder jvector noch FAISS bieten ein Äquivalent (zum jetzigen Zeitpunkt). Jvector hat keine Bulk-API, sodass der Aufrufer ein Paar nach dem anderen in einer Schleife bewertet. FAISS stellt <code>fvec_inner_products_ny</code> zur Verfügung, das zum Zeitpunkt der Erstellung dieses Artikels als Schleife über die Single-Pair-Distanzfunktion ohne Amortisierung der Abfrage oder Vorabruf implementiert ist.</p><p><strong>Float32.</strong> Um die Wirkung auf Kernel-Ebene zu messen, bewerteten wir eine einzelne Abfrage gegen zunehmende Zahlen von 1024-Dimension-float32-Dokumentvektoren mit Random-Access-Mustern, die HNSW-ähnliche verstreute Graph-Nachbarschaftsabfragen simulieren. Die drei Datensatzgrößen von 32, 625 und 32.500 Vektoren werden so gewählt, dass der Arbeitssatz den L1-, L2- und L3-Cache übersteigt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2df64ec77a1921ae/6a1701d714b270393ae3c4de/1d90267be1c63ac82b8ba588617ebedb0be0d1b6-1334x558.png" alt="Zwei Balkendiagramme, die die Bulk-Float32-Punktprodukt-Scoring-Zeiten für Elasticsearch simdvec, FAISS und jvector auf AMD Turin (x86, AVX-512) und Graviton 4 (ARM, NEON) bei drei Größen vergleichen: 32 Vektoren, 625 Vektoren und 32.500 Vektoren." /><p>Wenn die Daten in den Cache passen, ist simdvec auf beiden Plattformen am schnellsten, aber die Margen sind moderat, da die Kernel-Arithmetik dominiert. Die tatsächliche Trennung zeigt sich, wenn der Arbeitssatz über L3 hinauswächst. Auf x86 erzielt simdvec 95 ns pro Vektor, während FAISS 165 ns und jvector 412 ns benötigt. Auf ARM ist das Muster dasselbe: simdvec bleibt bei 162 ns, während FAISS auf 347 ns und jvector auf 476 ns ansteigt. Das Prefetching und die Abfrage-Amortisierung in simdvec verbergen die Speicherlatenz auf eine Weise, die eine einfache Schleife über Einzelpaar-Kernel nicht erreichen kann, und der Vorteil erweitert sich genau dort, wo reale Suchworkloads tief im Hauptspeicher arbeiten.</p><p><strong>Int8.</strong> Das gleiche Muster gilt für quantisierte Datentypen. Wir haben die Bulk-Bewertung von int8-Punktprodukten in 1024 Dimensionen mit Datensatzgrößen gemessen, die so gewählt wurden, dass sie die gleichen L1-, L2- und L3-Cache-Grenzen überschritten, und die Bulk-Bewertung von simdvec mit der Single-Pair-Bewertung von NumKong in einer Schleife verglichen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcda85e10007188d0/6a1701d9cf4f25d722b2cff7/9ee97d98b40d13b19370b76b33e67ea66bfb3250-1580x338.png" alt=" Tabelle mit dem Titel „x86 – Bulk-Scoring, int8-Punktprodukt (ns/op, je niedriger, desto besser)“, in der ES simdvec und NumKong über drei Vektorgrößen – 128, 2.500 und 130.000 – mit entsprechenden ns/op-Werten und Beschleunigungsverhältnissen verglichen werden." /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt972c311b7d08ba73/6a1701dadc55dec02ee00c87/601f50a03fa3e6263cbac9700281dfe3e511de60-1580x338.png" alt="Tabelle mit dem Titel „ARM — Bulk Scoring, int8-Punktprodukt (ns/op, je niedriger, desto besser)“, die ES simdvec und NumKong über drei Vektorgrößen – 128, 2.500 und 130.000 – mit entsprechenden ns/op-Werten und Beschleunigungsverhältnissen vergleicht." /><p>Auf x86 ist simdvec zwischen 1,2-mal und 1,9-mal schneller, was auf die Kombination aus explizitem Prefetching und Batch-Verarbeitung zurückzuführen ist. Auf ARM ist simdvec bei allen Datensätzen erneut im Vorteil (1,7- bis 1,9-mal schneller). Der Vorteil liegt in der Batch-Verarbeitung von vier Vektoren auf einmal, die über ein verschachteltes Zugriffsmuster Parallelisierung auf Speicherebene bietet. In beiden Fällen ist das auffälligste Ergebnis, was bei der größten Datensatzgröße passiert, wo es am wichtigsten ist.</p><p>Die Ergebnisse für quadrierten Abstand und Kosinus zeigen ein ähnliches Muster, mit Beschleunigungen von 1,4x bis 1,8x für ARM und von 1,3x bis 3,0x für x86 (mehr dazu <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md">hier</a>).</p><h3>Wo Speicher eine Rolle spielt</h3><p>Vektorindizes in der Produktion passen normalerweise nicht in den CPU-Cache. Ein 10M-Vektor-Int8-Index bei 1024 Dimensionen entspricht 10 GB. Die Bewertung von Kandidaten bedeutet das Streamen von Daten aus dem DRAM, und genau hier macht die Architektur für die Massenbewertung den Unterschied.</p><p>Wir verwendeten Hardware-Leistungszähler, um zu messen, was während der Massenbewertung innerhalb der CPU passiert, und stellten fest, dass das Verbergen der Speicherlatenz zwei grundlegend verschiedene Strategien erfordert: eine pro Architektur.</p><p><strong>Auf x86 eliminiert explizites Prefetching Cache-Fehler. </strong>Der Bulk-Kernel verarbeitet Vektoren sequenziell – einen nach dem anderen vollständig berechnet – während er gleichzeitig Prefetch-Anweisungen für den nächsten Batch ausgibt. Künftige Daten werden in den L1-Cache geladen, bevor die CPU sie benötigt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt368f29b5143d0f5a/6a1701dcc1e8a51780f8817b/a39548f8060c2a4a5154521a4047dd92d8cd77be-1580x309.png" alt="Tabelle mit dem Titel „x86 (AMD Turin) — Hardware-Zähler pro int8-Operation“ vergleicht Einzel- und Bulk-Modi für L1-Cache-Fehler, IPC und dTLB-Fehler, mit entsprechenden Verbesserungsfaktoren." /><p>Auf ARM funktionierte derselbe sequentielle Ansatz nicht so gut, selbst mit Prefetching. Stattdessen <strong>verschachtelt der Bulk-Kernel Ladungen</strong> von vier Vektoren an jeder Schrittposition, wodurch die Out-of-Order-Engine vier unabhängige Speicherstreams erhält. Die CPU holt Daten nicht schneller, sondern wartet vielmehr weniger, weil sie während der Bearbeitung von Speicheranfragen immer etwas anderes zu berechnen hat. Eine detaillierte Analyse finden Sie in <a href="https://github.com/elastic/elasticsearch/issues/145412">diesem GitHub-Issue</a>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8751ac5b20b75508/6a1701deab7f08db83db9d13/832de3bc0d556a493b7bf3f250196018acfc1585-1580x238.png" alt="Tabelle mit dem Titel „ARM (Graviton 4) — Hardware-Zähler pro int8-Operation“ vergleicht Einzel- und Bulk-Modi für L1-Cache-Fehler und Backend-Stalls, mit entsprechenden Verbesserungshinweisen" /><p>Die Zahlen erzählen zwei unterschiedliche Geschichten:</p><ol><li><p>Auf x86 verwandelt Prefetching 139K Cache-Fehler in 19K und die Anweisungen pro Zyklus (IPC) werden mehr als verdoppelt. Der Massenvorteil wächst mit der Größe der Datensätze, von 1,2-mal in L2 bis 2,8-mal jenseits von L3, weil das Prefetching zunehmend teurere DRAM-Roundtrips verbirgt.</p></li><li><p>Bei ARM ändern sich Cache-Fehler kaum. Was sich ändert, ist die Auslastung: Backend-Verzögerungen sinken um 40 %, da das verschachtelte Zugriffsmuster die Pipeline füttert. Dieser Vorteil bleibt konstant bei 1,8-mal, unabhängig von der Größe der Datensätze, da die Parallelität auf Speicherebene gilt, unabhängig davon, ob Daten aus dem Cache oder dem DRAM stammen.</p></li></ol><p>Zwei Architekturen, zwei Strategien, ein Ergebnis: Im Produktionsmaßstab beschäftigt simdvec die CPU-Pipeline durchgehend, selbst wenn die Vektoren über den Hauptspeicher verteilt sind.</p><h2>Was das für Elasticsearch-Nutzer bedeutet</h2><p>Diese Fähigkeiten auf Kernel-Ebene verstärken sich gegenseitig. Eine einzelne Vektorsuchabfrage kann Millionen von Distanzoperationen berechnen: HNSW-Graph-Durchläufe, Kandidatenbewertung, Neusortierung. Bei Tausenden gleichzeitiger Abfragen lassen sich Nanosekunden pro Operation direkt in Abfragelatenz und Cluster-Durchsatz umrechnen. Egal ob Sie float32, int8, bfloat16 oder BBQ verwenden, egal ob sich Ihr Index im Arbeitsspeicher oder auf der Festplatte befindet, simdvec ist die zugrunde liegende Engine, wobei jede dieser Operationen über dieselbe Engine läuft, die bis auf die letzte Nanosekunde genau abgestimmt ist.</p><p>Die wichtigste Erkenntnis ist, dass die Leistung der Vektorsuche im Produktionsmaßstab nicht primär durch den reinen SIMD-Durchsatz bestimmt wird. Entscheidend ist, wie effizient das System die Speicherlatenz verbirgt und gleichzeitig die Rechenleistung über Millionen kleiner Operationen hinweg aufrechterhält.</p><p>Die simdvec-Kernel werden mit fast jeder Elasticsearch-Version verbessert. Wenn neue Quantisierungstypen und Hardwareplattformen entstehen, erhalten sie von Anfang an optimierte Kernel. Und die bestehenden Typen werden immer schneller, während wir die bereits ausgelieferten Implementierungen optimieren.</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[Vektordatenbank]]></category>
    <category><![CDATA[Inside 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[Bis zu 12 Mal schnellere Vektorindizierung in Elasticsearch mit NVIDIA cuVS: GPU-Beschleunigung Kapitel 2]]></title>
    <description><![CDATA[Entdecken Sie, wie Elasticsearch mit GPU-beschleunigter Vektorindizierung und NVIDIA cuVS einen fast 12-mal höheren Indizierungsdurchsatz erzielt.]]></description>
    <content:encoded><![CDATA[<p>Anfang dieses Jahres kündigte Elastic die <a href="https://ir.elastic.co/news/news-details/2025/Elastic-Brings-Enterprise-Data-to-NVIDIA-AI-Factories/default.aspx">Zusammenarbeit</a> mit NVIDIA an, um die GPU-Beschleunigung für Elasticsearch zu realisieren und sie in <a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a> zu integrieren – wie in einer <a href="https://www.nvidia.com/en-us/on-demand/session/gtc25-S71286/">Session auf der NVIDIA GTC</a> und in verschiedenen <a href="https://www.elastic.co/search-labs/blog/gpu-accelerated-vector-search-elasticsearch-nvidia">Blogs</a> detailliert beschrieben. Dieser Beitrag ist ein Update zum gemeinsamen Entwicklungsprojekt mit dem NVIDIA-Vektorsuchteam.</p><h2>Zusammenfassung</h2><p>Zunächst einmal ein kurzer Überblick. Elasticsearch hat sich als leistungsstarke Vektordatenbank etabliert und bietet eine Vielzahl von Funktionen sowie eine hohe Leistungsfähigkeit für die Ähnlichkeitssuche im großen Maßstab. Mit Funktionen wie Skalarquantisierung, Better Binary Quantization (<a href="https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch">BBQ</a>), <a href="https://www.elastic.co/blog/accelerating-vector-search-simd-instructions">SIMD-</a> Vektoroperationen und speichereffizienteren Algorithmen wie <a href="https://www.elastic.co/search-labs/blog/diskbbq-elasticsearch-introduction">DiskBBQ</a> bietet es bereits effiziente und flexible Optionen für die Verwaltung von Vektor-Workloads.</p><p>Durch die Integration von NVIDIA cuVS als aufrufbares Modul für Vektorsuchaufgaben wollen wir signifikante Verbesserungen bei der Vektorindizierungsleistung und -effizienz erzielen, um große Vektor-Workloads besser zu unterstützen.</p><h2>Die Herausforderung</h2><p>Eine der größten Herausforderungen beim Aufbau einer leistungsstarken Vektordatenbank ist die Konstruktion des Vektorindexes – des <a href="https://arxiv.org/abs/1603.09320">HNSW-Graphen</a>. Die Indexbildung wird schnell von Millionen oder sogar Milliarden arithmetischer Operationen dominiert, da jeder Vektor mit vielen anderen verglichen wird. Darüber hinaus können Index-Lebenszyklusoperationen wie Komprimierung und Zusammenführungen den gesamten Rechenaufwand für die Indizierung weiter erhöhen. Da Datenmengen und die damit verbundenen Vektoreinbettungen exponentiell wachsen, sind beschleunigte Rechen-GPUs, die für massive Parallelität und mathematische Berechnungen mit hohem Durchsatz ausgelegt sind, ideal für die Bewältigung dieser Arbeitslasten geeignet.</p><h2>Öffnen Sie das Elasticsearch-GPU-Plugin.</h2><p><a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a> ist eine Open-Source-CUDA-X-Bibliothek für GPU-beschleunigte Vektorsuche und Datenclustering, die schnelles Indexieren und Einbetten für KI- und Empfehlungs-Workloads ermöglicht.</p><p>Elasticsearch nutzt cuVS über <a href="https://mvnrepository.com/artifact/com.nvidia.cuvs/cuvs-java">cuvs-java</a>, eine Open-Source-Bibliothek, die von der Community entwickelt und von NVIDIA gepflegt wird. Die cuvs-java Bibliothek ist leichtgewichtig und baut auf der <a href="https://docs.rapids.ai/api/cuvs/nightly/c_api/">cuVS C API</a> auf, indem sie <a href="https://openjdk.org/projects/panama/">Panama</a> Foreign Function verwendet, um cuVS-Funktionen auf idiomatische Java-Art bereitzustellen und dabei modern und leistungsstark zu bleiben.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc7fd7361099da05a/6a17e920be608670af00477f/5f6daa1eb07f704a6707d9e6b7ccb81d0abaa8c9-566x419.png" alt="So funktioniert Elasticsearch mit NVIDIA cuVS, CPU- und GPU-Indizierung" /><p>Die cuvs-java-Bibliothek ist in ein <a href="https://github.com/elastic/elasticsearch/pull/135545">neues Elasticsearch-Plugin</a> integriert; daher kann die Vektorindizierung auf der GPU auf demselben Elasticsearch-Knoten und -Prozess erfolgen, ohne dass externer Code oder Hardware bereitgestellt werden muss. Während des Indexaufbaus nutzt Elasticsearch die GPU, um den Vektorindexierungsprozess zu beschleunigen, sofern die cuVS-Bibliothek installiert und eine GPU vorhanden und konfiguriert ist. Die Vektoren werden der GPU übergeben, die daraus einen <a href="https://arxiv.org/abs/2308.15136">CAGRA-Graphen</a> erstellt. Dieser Graph wird dann in das HNSW-Format umgewandelt, wodurch er sofort für die Vektorsuche auf der CPU verfügbar ist. Das endgültige Format des erstellten Graphen ist identisch mit dem, das auf der CPU erstellt würde; dadurch kann Elasticsearch GPUs für die Vektorindizierung mit hohem Durchsatz nutzen, wenn die zugrunde liegende Hardware dies unterstützt, während gleichzeitig CPU-Leistung für andere Aufgaben (gleichzeitige Suche, Datenverarbeitung usw.) frei bleibt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt485f55f29d6df5c4/6a17e922be6086dcf3004785/3ea255bd9bfd7983f78143c5eba999d2149d72be-671x356.png" alt="" /><h2>Beschleunigung des Indexaufbaus</h2><p>Im Rahmen der Integration der GPU-Beschleunigung in Elasticsearch wurden mehrere Verbesserungen an cuvs-java vorgenommen, die sich auf einen effizienten Dateneingang/-ausgang und Funktionsaufruf konzentrieren. Eine wichtige Verbesserung ist die Verwendung von <a href="https://github.com/rapidsai/cuvs/blob/2cf5fa7666d703dccbe655f8214656b0952bb69b/java/cuvs-java/src/main/java/com/nvidia/cuvs/CuVSMatrix.java">cuVSMatrix</a> zur transparenten Modellierung von Vektoren, unabhängig davon, ob sie sich auf dem Java-Heap, außerhalb des Heaps oder im GPU-Speicher befinden. Dadurch können Daten effizient zwischen Arbeitsspeicher und GPU übertragen werden, wodurch unnötige Kopien von potenziell Milliarden von Vektoren vermieden werden.</p><p>Dank dieser zugrundeliegenden Zero-Copy-Abstraktion können sowohl die Übertragung in den GPU-Speicher als auch der Abruf des Graphen direkt erfolgen. Beim Indizieren werden die Vektoren zunächst im Speicher auf dem Java-Heap zwischengespeichert und dann an die GPU gesendet, um den CAGRA-Graphen zu erstellen. Der Graph wird anschließend von der GPU abgerufen, in das HNSW-Format konvertiert und auf der Festplatte gespeichert.</p><p>Beim Zusammenführen sind die Vektoren bereits auf der Festplatte gespeichert, wodurch der Java-Heap vollständig umgangen wird. Indexdateien sind speicherabgebildet und die Daten werden direkt in den GPU-Speicher übertragen. Das Design unterstützt zudem problemlos unterschiedliche Bitbreiten, z. B. float32 oder int8, und lässt sich natürlich auf andere Quantisierungsschemata erweitern.</p><h2>Trommelwirbel ... wie gut funktioniert es?</h2><p>Bevor wir zu den Zahlen kommen, ist ein bisschen Kontext hilfreich. Die Segmentzusammenführung in Elasticsearch läuft in der Regel automatisch im Hintergrund während der Indizierung, was ein isoliertes Benchmarking schwierig macht. Um reproduzierbare Ergebnisse zu erzielen, haben wir in einem kontrollierten Experiment die Segmentzusammenführung explizit mit der Funktion Force-Merge ausgelöst. Da Force-Merge die gleichen zugrunde liegenden Zusammenführungsoperationen wie das Zusammenführen im Hintergrund durchführt, dient seine Leistung als nützlicher Indikator für erwartete Verbesserungen, auch wenn die genauen Gewinne in realen Indexierungs-Workloads abweichen können.</p><p>Schauen wir uns nun die Zahlen an.</p><p>Unsere ersten Benchmark-Ergebnisse sind sehr vielversprechend. Wir haben den Benchmark auf einer AWS <code>g6.4xlarge</code> Instanz mit lokal angeschlossenem NVMe-Speicher ausgeführt. Ein einzelner Knoten von Elasticsearch wurde so konfiguriert, dass er die standardmäßige, optimale Anzahl von Indizierungs-Threads (8 – einer für jeden physischen Kern) verwendet und <a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/merge">Merge Throttling</a> deaktiviert (was bei schnellen NVMe-Festplatten weniger relevant ist).</p><p>Für den Datensatz verwendeten wir 2,6 Millionen Vektoren mit 1.536 Dimensionen aus der <a href="https://github.com/elastic/rally-tracks/blob/master/openai_vector/README.md">OpenAI Rally-Vektorstrecke</a>, kodiert als <a href="https://github.com/elastic/elasticsearch/pull/137072">Base64-Zeichenfolgen</a> und indexiert als float32 <em>hnsw</em>. In allen Szenarien erreichen die konstruierten Graphen Recall-Werte von bis zu 95 %. Hier sind unsere Ergebnisse:</p><ul><li><p><strong>Indizierungsdurchsatz:</strong> Durch die Verlagerung der Graphenkonstruktion auf die GPU während des Speicherpuffer-Flushs steigern wir den Durchsatz um das 12-fache.</p></li><li><p><strong>Force-Merge:</strong> Nach Abschluss der Indizierung beschleunigt die GPU weiterhin die Segmentzusammenführung und beschleunigt die Force-Merge-Phase um das ~7-fache.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfea4ee13b5a3b10d/6a17e923e9ea879c6aa9c616/f60ea9ee5996e456f393ffd195ee7eada6e5a7c2-948x387.png" alt="" /><ul><li><p><strong>CPU-Auslastung:</strong> Durch die Auslagerung der Graph-Konstruktion auf die GPU werden sowohl die durchschnittliche als auch die maximale CPU-Auslastung deutlich reduziert. Die folgenden Graphen veranschaulichen die CPU-Auslastung während der Indizierung und Zusammenführung und zeigen, wie viel geringer sie ist, wenn diese Vorgänge auf der GPU ausgeführt werden. Eine geringere CPU-Auslastung während der GPU-Indexierung setzt CPU-Zyklen frei, die zur Verbesserung der Suchleistung umgeleitet werden können.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt80ff9c53f9b6884a/6a17e925445de9ee4b4d0187/5e680a5fc41700a877f3d8b2e5ce18ebd3f37a0b-1600x562.png" alt="" /><ul><li><p><strong>Recall:</strong> Die Genauigkeit bleibt zwischen CPU- und GPU-Läufen praktisch gleich, wobei der mit der GPU erstellte Graph einen geringfügig höheren Recall erreicht.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5cbe084eca27b8e4/6a17e926faa913317093c8b7/48a2b7758606bd321712b7d8378cd2640e652a4e-1384x544.png" alt="" /><h2>Vergleich anhand einer weiteren Dimension: Preis</h2><p>Beim vorherigen Vergleich wurde absichtlich identische Hardware verwendet; der einzige Unterschied bestand darin, ob die GPU während der Indizierung verwendet wurde. Diese Konfiguration ist nützlich, um die Auswirkungen der reinen Rechenleistung zu isolieren, aber wir können den Vergleich auch aus einer Kostenperspektive betrachten.</p><p>Bei etwa demselben Stundenpreis wie die GPU-beschleunigte Konfiguration kann man ein CPU-reines Setup mit etwa doppelt so vielen vergleichbaren CPU- und Speicherressourcen bereitstellen: 32 vCPUs (AMD EPYC) und 64 GB RAM, wodurch die Anzahl der Indexierungs-Threads auf 16 verdoppelt werden kann.</p><p>Um den Vergleich fair und konsistent zu halten, haben wir dieses reine CPU Experiment auf einer AWS g6.8xlarge Instanz ausgeführt, wobei die GPU explizit deaktiviert war. Dadurch konnten wir alle anderen Hardwareeigenschaften konstant halten und gleichzeitig den Kosten-Leistungs-Kompromiss zwischen GPU-Beschleunigung und reiner CPU-Indexierung evaluieren.</p><p>Die leistungsstärkere CPU-Instanz zeigt erwartungsgemäß eine verbesserte Performance im Vergleich zu den Benchmarks im obigen Abschnitt. Wenn wir jedoch diese leistungsstärkere CPU-Instanz mit den ursprünglichen GPU-beschleunigten Ergebnissen vergleichen, liefert die GPU immer noch erhebliche Leistungssteigerungen: <strong>~5-fache</strong> Verbesserung des Indizierungsdurchsatzes und <strong>~6-fache</strong> Verbesserung beim Force Merge, während gleichzeitig Graphen erstellt werden, die Recall-Werte von bis zu <strong>95 %</strong> erreichen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt94b5eb6f95ba307d/6a17e928abe0f255d4dfea35/8ffa58cae3ad175ef2932a351aeef4c34a1407b9-948x394.png" alt="" /><h2>Fazit</h2><p>In End-to-End-Szenarien bietet die GPU-Beschleunigung mit NVIDIA cuVS eine nahezu 12-fache Verbesserung des Indexierungsdurchsatzes und eine 7-fache Verringerung der Force-Merge-Latenz bei deutlich geringerer CPU-Auslastung. Dies zeigt, dass Vektorindizierungs- und Merge-Workloads erheblich von der GPU-Beschleunigung profitieren. Im Kostenvergleich bietet die GPU-Beschleunigung weiterhin deutliche Leistungssteigerungen, mit einem etwa 5-fach höheren Indexierungsdurchsatz und 6-fach schnelleren Force-Merge-Operationen.</p><p>Die GPU-beschleunigte Vektorindizierung ist derzeit für die Tech Preview in Elasticsearch 9.3 geplant, deren Veröffentlichung für Anfang 2026 vorgesehen ist.</p><p>Mehr dazu in Kürze.</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[Vektordatenbank]]></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>