<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Chris Hegarty - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Chris Hegarty - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/cn/search-labs/author/chris-hegarty</link>
    </image>
    <link>https://www.elastic.co/cn/search-labs/author/chris-hegarty</link>
    <atom:link href="https://www.elastic.co/cn/search-labs/rss/author/chris-hegarty.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[cn]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 03:58:46 GMT</lastBuildDate>
  <item>
    <title><![CDATA[我们如何构建 Elasticsearch simdvec，使其成为世界上速度最快的向量搜索之一]]></title>
    <description><![CDATA[我们如何打造 Elasticsearch simdvec——这是 Elasticsearch 中每一次向量搜索查询背后的手动调优 SIMD 内核库。]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch simdvec 是 Elasticsearch 中每一次向量距离计算的核心引擎。它为 Elasticsearch 支持的每一种向量类型提供手动调优的 AVX-512 和 NEON 内核。其批量评分架构通过 x86 上的显式预取和 ARM 上的交错加载来隐藏内存延迟；当数据规模超出 CPU 缓存容量时，性能最高可比 FAISS 和 jvector 等库快 4 倍。在本文中，我们将介绍为何要打造它、其内部构成，以及它如何让 Elasticsearch 向量搜索跻身全球最快之列。</p><h2>我们如何构建 Elasticsearch simdvec</h2><p>Elasticsearch 中的每一次向量搜索查询，无论是<a href="https://arxiv.org/abs/1603.09320">分层导航小世界 (HNSW)</a> 遍历、倒排文件 (IVF) 扫描，还是重排序阶段，最终都会归结为同一个问题：在一次查询中，数百万次计算向量之间的距离。Elasticsearch 支持广泛的数据类型和量化策略，从 float32 到 int8、bfloat16、binary 以及 Better Binary Quantization (BBQ)。每种类型都在内存、吞吐量和召回率之间形成不同取舍。而这一切背后都有一个统一的引擎：simdvec。</p><p>我们打造 simdvec，是为了让每一次距离计算都尽可能逼近硬件允许的性能上限。在本文中，我们将介绍为何要打造它、它的内部构成，以及它在哪些场景中影响最大。</p><h3>设计得如同一辆赛车</h3><p>作为一级方程式赛车 (F1) 爱好者（我们其中一人曾效力于法拉利 F1 车队），我们看到了一个清晰的相似之处。F1 赛车的设计只有一个目标：取得最佳单圈成绩。发动机功率、空气动力学和底盘设计之所以重要，是因为它们都服务于这一结果。向量数据库也是如此：索引吞吐量、查询延迟和召回率决定了成功与否。</p><p>最终结果固然重要，但要达到最高性能水平，就需要每个组件都做到极致。它不能只是<em>“足够好”</em>，而必须是同类中的<em>“最佳”</em>。simdvec 正是以这种思路打造的，聚焦于系统中的一个关键部分：引擎。它是一个专门构建、针对<a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">单指令多数据</a> (SIMD) 优化的内核库，提供手动调优的原生 C++ 距离函数，并通过 <a href="https://openjdk.org/projects/panama/">Panama</a> 外部函数接口 (FFI) 从 Java 调用这些函数。它支持批量评分、缓存行预取，以及 Elasticsearch 中使用的所有向量类型和布局。</p><p>这就是每个查询背后的引擎。</p><h3>为什么我们要自研</h3><p>我们在 2023 年从 Apache Lucene 中的 Panama Vector API 起步。它在处理 float32 点积时表现良好，但 Elasticsearch 的需求很快就超出了它的能力范围。Elasticsearch 需要支持一系列量化向量类型：int8、int4、bfloat16、单比特以及非对称 BBQ。每种类型都有不同的 SIMD 策略、打包布局和累加器要求。除了类型覆盖范围之外，Elasticsearch 的评分路径还需要的不只是单对向量吞吐量：HNSW 需要在一次过程中为多个图邻居评分，IVF 需要对数千个候选项进行带预取的批量评分，而基于磁盘的评分需要直接在 mmap 映射内存上工作，实现零拷贝。我们考察了现有方案，发现没有一个能完全满足这些要求。</p><p>于是，我们打造了 simdvec：通过 FFI 从 Java 调用手动调优的原生 C++ 内核，具备批量评分和预取能力，并支持 Elasticsearch 使用的每一种向量类型。通过自有这个库，我们可以控制完整技术栈。当我们添加 BBQ 这样的新量化类型时，它会获得经过调优的 SIMD 内核，并完整接入整个系统。我们无需等待上游库支持它，也无需在任何类型的性能上做出妥协。Elasticsearch 中的每一次向量查询——无论是 HNSW、IVF、重排序还是混合检索——都运行在这个引擎之上。这个引擎正是围绕我们实际使用的操作和类型量身打造的。</p><p>simdvec 针对 x86 和 ARM 分别提供原生库，每种库都有多个指令集架构 (ISA) 层级，并在启动时选择。通过 FFI 从 Java 调用的开销非常低，仅为<a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#ffm-downcall-overhead-measurements">个位数纳秒级</a>。</p><h3>技术格局</h3><p>我们并不是唯一在打造 SIMD 优化向量距离内核的团队。这个生态系统非常丰富，我们希望了解 simdvec 的表现。这并非为了给项目排名，而是为了提供上下文，说明 Elasticsearch 的引擎处在什么位置。我们选择了三个项目作为参考点，每个代表一种不同的技术路径：</p><ul><li><p><strong>jvector：</strong>一个 Java 近似最近邻 (ANN) 库，使用 Panama Vector API 进行向量化距离计算，并在 x86 上提供可选的原生 C 加速。</p></li><li><p><strong>FAISS：</strong>一个广泛部署的开源矢量搜索框架，带有手动调整的 AVX2/AVX-512 内核。</p></li><li><p><strong>NumKong</strong>（原 SimSIMD）：一个包含 2,000 多个手动调优 SIMD 内核的综合库，覆盖距离函数、矩阵运算和地理空间计算。</p></li></ul><p>每个项目服务于不同的目标，有着不同的取舍。我们引用它们的参考数据，是为了给 simdvec 在 Elasticsearch 所需特定操作上的性能提供参照。</p><h3>我们如何衡量</h3><p>simdvec 和 <a href="https://github.com/ChrisHegarty/jvector-kernel-benchmarks">jvector 基准测试</a>使用 Java 编写，并采用 JMH（标准 JVM 微基准测试框架），测试中包含 FFI 开销。对于 <a href="https://github.com/ldematte/simsimd-benchmarks">NumKong 基准测试</a>和 <a href="https://github.com/ChrisHegarty/faiss-kernel-benchmarks">FAISS 基准测试</a>，我们使用 Google Benchmark（标准 C++ 微基准测试框架）编写了小型 C/C++ 测试程序。两个框架都会在预热和迭代校准后报告每次操作所需的纳秒数。我们通过硬件性能计数器验证了所有库在两个平台上都确实使用了 SIMD。所有基准测试代码均已公开在链接的 GitHub 存储库中；对于 simdvec，代码位于 <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="表格列出两个平台：x86（AMD EPYC Turin Zen 5，AVX2 和 AVX-512，AWS c8a.4xlarge）；ARM（Graviton 4 Neoverse V2，NEON 和 SVE2，AWS c8g.4xlarge）。" /><p><strong>软件：</strong>JDK 25.0.2、JMH 1.37、GCC 14、Google Benchmark（最新版）。</p><h2>一次处理一个向量</h2><p>向量搜索中最基础的操作是计算两个向量之间的距离。每一次 HNSW 邻居评估、每一次 IVF 候选项评分、每一次重排序比较，都会归结为这个内层循环。</p><p>我们在两个平台上测量了 1024 维下的单对向量吞吐量，首先从 float32 开始。这是基准类型，也是生态系统中竞争最激烈的类型。我们将 simdvec 与 FAISS 和 jvector 进行了对比；我们排除了 NumKong，因为它在 float32 上使用 float64 累加器，速度慢 3.2 到 5.3 倍（取决于平台），这是以吞吐量换取数值精度。为了保持同类对比，我们改为在 int8 上测试 NumKong，因为此时它采用的累加器策略与 simdvec 相同。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte3bc2ecaf3ad2b61/6a1701d2ab7f08039ddb9d0f/352cfa0fc18f123140f746d843404f80127fb1b7-1500x675.png" alt="横向条形图，标题为“float32 点积 — AMD Turin”，比较了五个实现：FAISS AVX-512，23.2 ns/op；ES simdvec AVX-512，28.3 ns/op；FAISS AVX2，36.4 ns/op；ES simdvec AVX2，38.9 ns/op；以及 jvector，43.9 ns/op。" /><p>在 x86 上，FAISS AVX-512 是最快的单对内核，耗时 23 ns。simdvec AVX-512 紧随其后，为 28 ns，这一差距反映了 FFI 调用开销。两者都使用 512 位 FMA，并采用多累加器展开。在 AVX2 层级，两者更接近，分别为 36 ns 和 39 ns，都受限于 256 位寄存器和内存加载宽度。jvector 使用 Java Panama Vector API，耗时 44 ns。Panama 能生成良好的 SIMD 代码，但手动调优的 C++ 内部函数仍然具有优势。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcbbbe442631a575d/6a1701d42b835f81bcf4b083/95e44d9767f21ec4bccaed835e3c99aa180431ee-1500x495.png" alt="题为“float32 点积－Graviton 4 (ARM)”的横条形图显示 ES simdvec 为 70.2 ns/op，jvector 为 110.0 ns/op，FAISS 为 155.6 ns/op。" /><p>在 ARM 上，simdvec 以 70 ns 领先，明显快于 110 ns 的 jvector 和 156 ns 的 FAISS。simdvec 针对 aarch64 提供手动调优的 NEON 内核。jvector 没有 ARM 原生代码，依赖 Panama。FAISS 依赖编译器自动向量化，而非显式的 NEON 内部函数，这也解释了更大的性能差距。这体现了拥有自有内核库的一个实际优势：当 Elasticsearch 扩展到 Graviton 时，我们添加了专门构建的 NEON 内核。而 jvector 和 FAISS 尚未以同等程度优先投入 ARM 原生代码。</p><p>但 Elasticsearch 评分的远不止 float32。<strong>int8</strong> 量化可将内存占用降至原来的四分之一，bfloat16 降至原来的一半，BBQ 降至原来的三十二分之一。每种类型都需要自己的 SIMD 策略，而 simdvec 为所有这些类型都提供手动调优的原生内核。</p><p>在我们比较的库中，只有 NumKong 拥有可用于 int8 对比的内核。我们测量了 1024 维度下的 int8 点积、平方欧几里得距离和余弦计算。</p><p><strong>Int8 单对评分（1024 维，ns/vec op – 越低越好）</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3ac255d158e93504/6a1701d5a292997e48d00eb1/a0b852fd5f51d57bd2488886600472ee65ab64da-1594x378.png" alt="表格对比了 x86 和 ARM 上点积、平方欧几里得距离和余弦运算的性能，并列出两种架构下每项操作对应的 ES、NumKong 和 diff 值。" /><p>在两种架构上，NumKong 在中小维度下持平或更快，差异主要来自更低的调用开销（直接 C 调用 vs Java FFI）。在更高维度下，simdvec 迎头赶上，因为更高效的内核实现（使用级联展开）摊薄了调用成本：随着维度增加，<a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#single-pair-i8-nsop-2">这一差距会缩小并最终反转</a>。交叉点出现在 768 到 1536 维之间，具体取决于函数和架构。</p><p>尽管 Java FFI 存在略高的开销，simdvec 的表现仍足以媲美高度优化的 C/C++ 库。它不仅是唯一一个同时为 float32 <em>和</em> int8 提供优化内核的库，而且在 ARM 上保持领先，在 x86 上的 float32 方面也仅略逊于 FAISS，在 int8 上与 NumKong 在两个架构上都非常接近。对于 bfloat16、int4、binary 和 BBQ，虽然存在其他替代方案，但 simdvec 的优势在于，它能够针对每种类型的数据布局进行手动 SIMD 调优。</p><p>然而，生产环境下的搜索引擎不会一次只为一个向量评分，而是会在每次查询中为数千个向量评分。接下来的问题是：在如此规模下性能表现如何？</p><h3>一次处理数千个向量</h3><p>单对向量性能只是整体图景的一部分。在实践中，真正重要的是系统在负载下的行为。一次 HNSW 查询可能会为数百个图邻居评分。一次 IVF 扫描可能会为数千个倒排列表条目评分。一次重排序阶段可能会为数万个候选项评分。单对吞吐量固然重要，但更关键的是评分大量向量时的速度，以及当工作集超出 CPU 缓存时性能下降是否平缓。</p><p>simdvec 为每一种数据类型都提供了批量评分功能。这绝非简单的单对内核循环，而是使用了多累加器内层循环：在每个维度步长 (stride) 中仅加载一次查询向量，并让多个文档向量共享该向量，同时针对下一批次执行显式的缓存行预取。在本文撰写之时，jvector 和 FAISS 都没有提供等效功能。jvector 没有批量 API，调用者只能在循环中逐对评分。FAISS 暴露了 <code>fvec_inner_products_ny</code>，但在撰写本文时，其实现方式仍是循环调用单对向量距离函数，没有查询向量摊销，也没有预取。</p><p><strong>Float32。</strong>为了在内核层面衡量影响，我们使用随机访问模式来模拟类似 HNSW 的分散式图邻居查找，并让单个查询对数量不断增加的 1024 维 float32 文档向量进行评分。我们选择了 32、625 和 32,500 个向量这三种数据集规模，使工作集分别超出 L1、L2 和 L3 缓存。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2df64ec77a1921ae/6a1701d714b270393ae3c4de/1d90267be1c63ac82b8ba588617ebedb0be0d1b6-1334x558.png" alt="两张条形图对比了 Elasticsearch simdvec、FAISS 和 jvector 在 AMD Turin（x86，AVX-512）和 Graviton 4（ARM，NEON）上，针对 32 个、625 个和 32,500 个向量的批量 float32 点积评分耗时。" /><p>当数据能放入缓存时，simdvec 在两个平台上都是最快的，但优势不大，因为此时内核算术运算占主导。真正的差距出现在工作集超出 L3 缓存之后。在 x86 上，simdvec 每个向量 95 ns，而 FAISS 需要 165 ns，jvector 需要 412 ns。在 ARM 上，模式相同：simdvec 保持在 162 ns，而 FAISS 攀升到 347 ns，jvector 到 476 ns。simdvec 中的预取和查询向量摊销能够以简单循环调用单对向量内核无法匹敌的方式掩盖内存延迟；而在真实搜索工作负载所处的大量访问主内存的场景中，这种优势会进一步扩大。</p><p><strong>Int8。</strong>同样的模式在量化类型上也成立。我们测量了 1024 维 int8 点积的批量评分，数据集大小同样选择为超出 L1、L2、L3 缓存边界，将 simdvec 的批量评分与 NumKong 循环调用的单对评分进行了对比。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcda85e10007188d0/6a1701d9cf4f25d722b2cff7/9ee97d98b40d13b19370b76b33e67ea66bfb3250-1580x338.png" alt=" 标题为“x86 — 批量评分，int8 点积（ns/op，越低越好）”的表格，对比了 ES simdvec 和 NumKong 在三种向量规模（128、2,500 和 130,000）下的表现，并列出了相应的 ns/op 数值和加速比。" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt972c311b7d08ba73/6a1701dadc55dec02ee00c87/601f50a03fa3e6263cbac9700281dfe3e511de60-1580x338.png" alt="标题为“ARM — 批量评分，int8 点积（ns/op，越低越好）”的表格，对比了 ES simdvec 和 NumKong 在三种向量规模（128、2,500 和 130,000）下的表现，并列出了相应的 ns/op 数值和加速比" /><p>在 x86 上，simdvec 快 1.2 倍到 1.9 倍，这得益于显式预取和批处理的结合。在 ARM 上，simdvec 再次胜出，在所有数据集大小下快 1.7 倍到 1.9 倍。优势来自每次批处理四个向量，通过交错访问模式提供内存级并行性。在这两种情况下，最引人注目的结果都出现在最大数据集规模上，而这也正是最关键的场景。</p><p>平方距离和余弦计算的结果也呈现类似模式：ARM 上加速 1.4 倍到 1.8 倍，x86 上加速 1.3 倍到 3.0 倍（详见<a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md">此处</a>）。</p><h3>当内存成为瓶颈</h3><p>生产环境中的向量索引通常无法放入 CPU 缓存。一个包含 1,000 万个 1024 维 int8 向量的索引大小为 10 GB。为候选项评分意味着需要从 DRAM 流式读取数据，而这正是批量评分架构发挥作用的地方。</p><p>我们使用硬件性能计数器来测量批量评分过程中 CPU 内部的实际运行情况，结果发现，隐藏内存延迟需要两种截然不同的策略，每种架构各对应一种。</p><p><strong>在 x86 上，显式预取大幅减少了缓存未命中。</strong>批量内核会按顺序处理向量，先完整计算一个向量，再处理下一个，同时为下一批数据发出预取指令。未来所需的数据在 CPU 需要之前就被拉入 L1 缓存。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt368f29b5143d0f5a/6a1701dcc1e8a51780f8817b/a39548f8060c2a4a5154521a4047dd92d8cd77be-1580x309.png" alt="标题为“x86 (AMD Turin) — 每次 int8 操作的硬件计数器”的表格，对比了单对模式与批量模式下的 L1 缓存未命中、IPC 和 dTLB 未命中，并列出相应的改进倍数。" /><p>在 ARM 上，即使使用预取，顺序处理方法也表现不佳。取而代之的是，<strong>批量内核采用交错加载策略</strong>：在每个步幅位置交错加载四个向量的数据，为乱序执行引擎提供四个独立的内存流。CPU 并没有加快取数速度，而是在内存请求在途时，通过始终保持有计算任务可做来减少等待时间。详细分析可参阅<a href="https://github.com/elastic/elasticsearch/issues/145412">此 GitHub issue</a>。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8751ac5b20b75508/6a1701deab7f08db83db9d13/832de3bc0d556a493b7bf3f250196018acfc1585-1580x238.png" alt="标题为“ARM (Graviton 4) — 每次 int8 操作的硬件计数器”的表格，对比了单对模式与批量模式下的 L1 缓存未命中和后端停顿，并列出相应的改进说明" /><p>这些数字讲述了两个不同的故事：</p><ol><li><p>在 x86 上，预取将缓存未命中从 13.9 万次降低到 1.9 万次，每周期指令数 (IPC) 提升了一倍以上。批量处理的优势会随着数据集规模增长而扩大：当工作集位于 L2 时为 1.2 倍，超出 L3 后则达到 2.8 倍，因为预取能够掩盖越来越高的 DRAM 往返访问开销。</p></li><li><p>在 ARM 上，缓存未命中几乎没有变化。真正变化的是利用率：后端停顿减少 40%，因为交错访问模式让流水线持续有任务可执行。这一优势在不同数据集规模下稳定保持在 1.8 倍，因为内存级并行性无论数据来自缓存还是 DRAM 都同样适用。</p></li></ol><p>两种架构，两种策略，一个结果：在生产规模下，即使向量散落在主内存各处，simdvec 也能让 CPU 流水线保持忙碌。</p><h2>这对 Elasticsearch 用户意味着什么</h2><p>这些内核层面的能力会不断叠加。一次向量搜索查询可能会执行数百万次距离操作：HNSW 图遍历、候选项评分、重排序。在数千个并发查询下，每次操作的纳秒级差异都会直接影响查询延迟和集群吞吐量。无论您使用 float32、int8、bfloat16 还是 BBQ，无论您的索引在内存中还是磁盘上，simdvec 都是底层的引擎，而每一次操作都运行在这个引擎上，并经过了哪怕一纳秒都不放过的极致精细调优。</p><p>关键结论是，在生产规模下，向量搜索性能并不主要由原始 SIMD 吞吐量决定，而是取决于系统能否在持续处理数百万次小型操作的同时，高效掩盖内存延迟。</p><p>simdvec 内核几乎会随每个 Elasticsearch 版本持续改进。当新的量化类型和硬件平台出现时，它们从第一天起就能获得经过调优的内核。而现有类型也会随着我们不断优化已发布的实现而持续变快。</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[向量数据库]]></category>
    <category><![CDATA[在 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[基于 Swiss 式哈希表实现更快的 ES|QL 统计数据]]></title>
    <description><![CDATA[受 Swiss 启发的哈希和 SIMD 友好型设计如何为 Elasticsearch 查询语言 (ES|QL) 中提供稳定、可衡量的速度提升。]]></description>
    <content:encoded><![CDATA[<p>我们近期将 Elasticsearch 哈希表实现的核心组件替换为 Swiss 式设计，在均匀高基数工作负载下观察到构建与迭代速度提升 2-3 倍。最终使 Elasticsearch 查询语言 (ES|QL) 的统计数据与分析操作实现更低延迟、更高吞吐量，且性能表现更可预测。</p><h2>为什么这很重要</h2><p>绝大多数典型分析流程最终都归结为数据分组操作。无论是计算每台主机的平均字节数、统计每个用户的事件数量，还是跨维度聚合指标，其核心操作始终如一，那就是将键映射到分组并更新累计聚合值。</p><p>在小规模场景下，几乎任何合理的哈希表都能良好运行。但在大规模场景（数亿文档、数百万独立分组）中，细节决定成败。负载因素、探测策略、内存布局和缓存行为，这些因素可能让性能呈现线性增长，也可能导致严重的缓存未命中问题。</p><p>Elasticsearch 多年来一直支持这些工作负载，但我们一直在寻找机会来更新核心算法。因此，我们评估了一种受 Swiss 表启发的新方法，并将其应用于 ES|QL 如何计算统计数据。</p><h2>到底什么是 Swiss 表？</h2><p>Swiss 表是一类由 Google SwissTable 推广的现代哈希表系列，后被 Abseil 等资料库采纳。</p><p>传统哈希表在探测过程中需频繁追踪指针或加载键值，却发现大量不匹配情况。Swiss 哈希表的核心创新在于通过独立于键值存储的微型缓存驻留数组结构（称为<em>控制字节</em>），可拒绝大多数探测，从而显著降低内存流量。</p><p>每个控制字节对应一个哈希槽，在我们的应用中编码两类信息：槽是否为空，以及从哈希值派生的短指纹。这些控制字节在内存中连续存储（通常以 16 字节为一组），使其非常适合<a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">单指令多数据</a> (SIMD) 并行处理。</p><p>Swiss 表摒弃逐槽探测的传统方式，转而通过向量指令一次性扫描整个控制字节块。CPU 在单次操作中，将待插入键的指纹与 16 个槽位的指纹进行批量比对，并过滤掉空条目。仅当少数候选键通过这一快速通道后，才需要加载并比对实际键值。</p><p>该设计通过引入少量额外元数据，换取了更高的缓存命中率和大幅减少的随机内存访问。随着哈希表规模扩大及探测链长度增加，这些特性将愈发凸显其价值。</p><h2>以SIMD为中心</h2><p>真正的主角是 SIMD。</p><p>控制字节不仅结构紧凑，更专门针对向量指令处理进行优化设计。单条 SIMD 比对指令可同时校验 16 个指纹，将传统循环操作转化为数条高效宽指令处理。例如：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1f710e87dd749ab3/6a170cc46234e052dadb1a49/bd418778f0c6144f8f5f18419f6220ac0c935c7a-903x407.png" alt="SIMD 是 Elasticsearch 的核心" /><p>实际上，这意味着：</p><ul><li><p>更少的分支。</p></li><li><p>更短的探针链。</p></li><li><p>减少键值存储的内存加载次数。</p></li><li><p>更好地利用了CPU的执行单元。</p></li></ul><p>绝大多数查询在控制字节扫描阶段即可完成过滤。当需要进一步处理时，剩余操作高度集中且可预测，而这正是现代 CPU 所擅长的负载类型。</p><h2>深入了解 SIMD</h2><p>对于喜欢探究底层实现细节的读者，以下是向表中插入新键时的具体流程：我们使用 Panama Vector API 配合 128 位向量，因此可并行处理 16 个控制字节。</p><p>以下代码片段展示了在配备 AVX-512 的 Intel Rocket Lake 处理器上生成的代码。虽然这些指令反映了当前硬件环境，但该设计并不依赖 AVX-512。在其他平台上会生成等效指令（如 AVX2、SSE 或 NEON）来实现相同的高层向量操作。</p>; Load 16 control bytes from the control block
vmovdqu xmm0, XMMWORD PTR [r9+r10*1+0x10]

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

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

; Check if any matches were found
test rbx, rbx
jne &lt;handle_match&gt;<p>每条指令在插入过程中都起着明确的作用：</p><ul><li><p><code>vmovdqu</code>：将 16 个连续的控制字节加载到 128 位 <code>xmm0</code> 寄存器中。</p></li><li><p><code>vpbroadcastb</code>：将新键的 7 位指纹复制到<code>xmm1</code>寄存器的所有向量通道中。</p></li><li><p><code>vpcmpeqb</code>：将每个控制字节与广播后的指纹进行并行比较，生成潜在匹配的掩码。</p></li><li><p><code>kmovq</code> + <code>test</code>：将掩码移动到通用寄存器，并快速检查是否存在匹配。</p></li></ul><p>最终，我们决定一次探测 16 个控制字节组，因为基准测试表明，扩展到 32 或 64 个字节并使用更宽的寄存器并没有带来明显的性能提升。</p><h2>ES|QL 中的集成</h2><p>在 Elasticsearch 中采用 Swiss 式哈希算法并非简单的替换操作。ES|QL 对内存核算、安全性以及与计算引擎其他部分的集成有着严苛要求。</p><p>我们将新型哈希表与 Elasticsearch 的内存管理机制深度集成，包括分页回收器和熔断器核算模块，确保内存分配始终透明且受控。Elasticsearch 的聚合数据采用密集存储方式并通过组 ID 索引，在保持内存布局紧凑、迭代高效的同时，通过支持随机访问实现了特定性能优化。</p><p>对于可变长度字节键，我们在存储组 ID 的同时缓存完整哈希值。此设计避免了探测过程中重复计算高开销的哈希码，并通过将关联元数据集中存储提升了缓存命中率。在重新哈希时，系统可直接利用缓存的哈希值和控制字节，无需检查键值本身，从而将容量调整成本降至最低。</p><p>我们实施中的一个重要简化策略是永不删除条目。这一设计消除了对<em>“墓碑”标记</em>（用于标识已释放槽位的占位符）的需求，使空槽保持真正空闲状态。这种优化进一步改善了探测行为，并确保控制字节扫描始终保持高效。</p><p>这样的设计在完美契合 Elasticsearch 执行模型的同时，保留了使 Swiss 表具吸引力的高性能特性。</p><h2>它的表现如何？</h2><p>在小规模数据量下，Swiss 表的性能与现有实现基本持平。这符合预期，当哈希表较小时，缓存效应的影响减弱，且待优化的探测操作本就较少。</p><p>随着数据规模扩大，性能特征迅速发生质变。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt09b13af2fe162f59/6a170cc66f7f04485c9148b8/24900afc47ab07b0e9933f6117b99d0f4613f794-962x599.png" alt="ES|QL 统计数据使用瑞士风格哈希表" /><p>上方热图展示了不同键大小（8、32、64 和 128 字节）在数据规模从 1,000 至 10,000,000 组变化时的时间优化倍数。随着数据规模扩大，优化倍数呈稳定上升趋势，在均匀分布场景下最高可达 2-3 倍。</p><p>这一趋势完全符合设计预期。传统哈希表在数据规模扩大时会导致探测链长度增加，而 Swiss 式探测仍能在支持 SIMD 指令的控制字节块内完成绝大多数查询操作。</p><h2>缓存行为说明了一切</h2><p>为深入分析加速效果，我们在 Linux <code>perf</code>环境下运行相同的 JMH <a href="https://github.com/elastic/elasticsearch/pull/139343/files#diff-d0e0cc91a7495bf36b2d44eacce95f5185d01879e5f6c38089ac7a89aad17da7"><code>benchmarks</code></a>基准测试，并采集缓存与 TLB 统计数据。</p><p>与原始实施相比，Swiss 版实现的总缓存引用量减少约 60%，末级缓存（LLC）加载次数下降超 4 倍，LLC 加载未命中次数更是降低超 6 倍。由于 LLC 未命中通常直接导致主存访问，仅此一项优化就解释了端到端性能提升的绝大部分原因。</p><p>在更靠近 CPU 的层级，我们观察到 L1 数据缓存未命中次数显著减少，数据 TLB 未命中次数更降低近 6 倍，这表明数据空间局部性增强且内存访问模式更具可预测性。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb987a5bd98c0d7eb/6a170cc8a929cf9655ae0a25/6e49b7609fba83e33692cb9834552b6ca7e42a83-998x499.png" alt="缓存执行：原始实施与采用 Swiss 式哈希表的 ES|QL 统计数据" /><p>这正是 SIMD 友好型控制字节带来的实际效益。无需反复从分散的内存位置加载键和值，大多数探测操作仅需扫描紧凑、驻留缓存的结构体即可完成。内存访问量减少意味着缓存未命中率降低，而未命中率降低则直接提升查询速度。</p><h2>总结</h2><p>通过采用 Swiss 式哈希表设计并深度融合 SIMD 友好型探测机制，我们在高基数 ES|QL 统计工作负载中实现了 2-3 倍的速度提升，同时获得了更稳定且可预测的系统表现。</p><p>本研究揭示了现代 CPU 感知型数据结构如何为哈希表等老问题带来显著性能提升。该领域仍有广阔探索空间，例如扩展至更多基础数据类型的特化实现，以及在连接等高基数操作路径中的应用。这些工作均属于 Elasticsearch 内核持续现代化这一长期工程的重要组成部分。</p><p>如需了解详细信息或跟进项目进展，可查看 GitHub 上的该<a href="https://github.com/elastic/elasticsearch/pull/139343">拉取请求</a>及追踪进度的<a href="https://github.com/elastic/elasticsearch/issues/138799">元议题</a>。</p><p>祝您哈希愉快！</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/esql-swiss-hash-stats</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/esql-swiss-hash-stats</guid>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Chris Hegarty,Matthew Alp,Nik Everett]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf76dd688c5b737e6/6a170cc9839dfa7fc7dcff40/21036e031070f14faccb2b53b22723de2750c391-1280x720.png" length="0" type="image/png"/>
    <pubDate>Mon, 19 Jan 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[使用 NVIDIA cuVS 将 Elasticsearch 中的向量索引速度提升高达 12 倍：GPU 加速（第二章）]]></title>
    <description><![CDATA[了解 Elasticsearch 如何借助 GPU 加速的向量索引和 NVIDIA cuVS，实现近 12 倍的索引吞吐量提升。]]></description>
    <content:encoded><![CDATA[<p>今年早些时候，Elastic 宣布与 NVIDIA <a href="https://ir.elastic.co/news/news-details/2025/Elastic-Brings-Enterprise-Data-to-NVIDIA-AI-Factories/default.aspx">合作</a>，为 Elasticsearch 引入 GPU 加速功能，并与 <a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a> 集成 — 相关详情可参阅 <a href="https://www.nvidia.com/en-us/on-demand/session/gtc25-S71286/">NVIDIA GTC 大会</a>的相关会议以及多篇<a href="https://www.elastic.co/search-labs/blog/gpu-accelerated-vector-search-elasticsearch-nvidia">博文</a>。本文主要介绍我们与 NVIDIA 向量搜索团队在联合工程方面的最新进展。</p><h2>回顾</h2><p>先简单回顾一下最新动态。Elasticsearch 现已确立其作为强大向量数据库的地位，在大规模相似性搜索方面提供了丰富的功能和强劲的性能。凭借标量量化、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> 向量运算以及 <a href="https://www.elastic.co/search-labs/blog/diskbbq-elasticsearch-introduction">DiskBBQ</a> 等在磁盘利用方面更高效的算法，Elasticsearch 已经为管理向量工作负载提供了高效而灵活的多种选项。</p><p>通过将 NVIDIA cuVS 集成为可调用的向量搜索模块，我们希望大幅提升向量索引的性能和效率，从而更好地支撑大规模向量工作负载。</p><h2>挑战</h2><p>构建高性能向量数据库的最大挑战之一，就是构建向量索引，即 <a href="https://arxiv.org/abs/1603.09320">HNSW</a> 图。随着每个向量都要与大量其他向量进行比对，索引构建很快就会被数以百万乃至数十亿次的算术运算所主导。此外，压缩、合并等索引生命周期操作还会进一步增加索引的整体计算开销。随着数据量和相关向量嵌入呈指数级增长，专为大规模并行和高吞吐量数值运算而设计的加速计算 GPU 非常适合处理这些工作负载。</p><h2>进入 Elasticsearch-GPU 插件</h2><p><a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a>是一个开源的 CUDA-X 库，用于 GPU 加速的向量搜索和数据集群，能够为 AI 和推荐工作负载快速构建索引和嵌入检索。</p><p>Elasticsearch 通过 <a href="https://mvnrepository.com/artifact/com.nvidia.cuvs/cuvs-java">cuvs-java</a> 使用 cuVS，这是一个由社区开发并由 NVIDIA 维护的开源库。cuvs-java 库十分轻量，基于 <a href="https://docs.rapids.ai/api/cuvs/nightly/c_api/">cuVS C API</a> 构建，并借助 <a href="https://openjdk.org/projects/panama/">Panama</a> 外部函数接口，以符合 Java 习惯用法的方式暴露 cuVS 功能，同时兼具现代性和高性能。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc7fd7361099da05a/6a17e920be608670af00477f/5f6daa1eb07f704a6707d9e6b7ccb81d0abaa8c9-566x419.png" alt="Elasticsearch 如何与 NVIDIA cuVS 协同工作，并支持 CPU 与 GPU 两种索引方式" /><p>cuvs-java 库被集成到<a href="https://github.com/elastic/elasticsearch/pull/135545">一个新的 Elasticsearch 插件</a>中；因此，GPU 上的向量索引可在同一 Elasticsearch 节点和同一进程内完成，无需部署任何外部组件或额外硬件。在索引构建过程中，如果已安装 cuVS 库且存在已正确配置的 GPU，Elasticsearch 会利用 GPU 加速向量索引过程。向量会被传递给 GPU，由 GPU 构建 <a href="https://arxiv.org/abs/2308.15136">CAGRA</a> 图。随后将该图转换为 HNSW 格式，使其能够立即在 CPU 上用于向量搜索。构建完成的图，其最终格式与在 CPU 上构建的图完全一致；这使得在底层硬件支持的情况下，Elasticsearch 可以利用 GPU 实现高吞吐量的向量索引，同时释放 CPU 算力，用于并发搜索、数据处理等其他任务。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt485f55f29d6df5c4/6a17e922be6086dcf3004785/3ea255bd9bfd7983f78143c5eba999d2149d72be-671x356.png" alt="" /><h2>索引构建加速</h2><p>作为将 GPU 加速集成到 Elasticsearch 的一部分，对 cuvs-java 进行了多项增强，重点是高效的数据输入/输出和函数调用。一项关键增强是使用 <a href="https://github.com/rapidsai/cuvs/blob/2cf5fa7666d703dccbe655f8214656b0952bb69b/java/cuvs-java/src/main/java/com/nvidia/cuvs/CuVSMatrix.java">cuVSMatrix</a> 对向量进行透明建模，无论它们位于 Java 堆中、堆外还是 GPU 内存中。这使数据可以在内存与 GPU 之间高效传输，避免对可能多达数十亿个向量进行不必要的复制。</p><p>由于这种底层的零拷贝抽象，数据传输到 GPU 内存以及从中检索图时都可以直接完成。在索引过程中，向量首先缓存在 Java 堆内存中，然后发送到 GPU，以构建 CAGRA 图。随后，从 GPU 中取回该图，将其转换为 HNSW 格式，并持久化到磁盘。</p><p>在合并时，向量已经存储在磁盘上，完全绕过了 Java 堆。索引文件采用内存映射，数据直接传输到 GPU 内存中。该设计还能轻松适应不同的位宽，如 float32 或 int8，并自然扩展到其他量化方案。</p><h2>话不多说，那它的实际表现如何呢？</h2><p>在我们探讨数字之前，了解一些背景信息会有所帮助。在索引期间，Elasticsearch 中的分段合并通常在后台自动运行，这会导致在隔离环境中进行基准测试变得十分困难。为了获得可重复的结果，我们使用了强制合并来在受控实验中明确触发分段合并。由于强制合并与后台合并执行相同的底层合并操作，因此其性能可作为预期改进的有用指标，尽管在实际索引工作负载中，具体收获可能会有所不同。</p><p>现在让我们来探讨数字。</p><p>我们的初步基准测试结果非常令人鼓舞。我们在 AWS <code>g6.4xlarge</code> 实例上运行了基准测试，该实例具有本地连接的 NVMe 存储。我们将单个 Elasticsearch 节点配置为使用默认的最佳索引线程数（8 个，每个物理核心一个），并关闭<a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/merge">合并限速功能</a>（在使用快速 NVMe 磁盘时，这一功能的适用性较低）。</p><p>对于数据集，我们使用了 <a href="https://github.com/elastic/rally-tracks/blob/master/openai_vector/README.md">OpenAI Rally 向量赛道</a>中的 260 万个、每个具有 1,536 维的向量，将其编码为 <a href="https://github.com/elastic/elasticsearch/pull/137072">base64 字符串</a>，并以 float32 <em>hnsw</em> 结构进行索引。在所有场景中，构建的图都能达到最高约 95% 的召回率。以下是我们的发现：</p><ul><li><p><strong>索引吞吐量：</strong>通过在内存缓冲区刷新期间将图构建移交给 GPU 处理，我们将吞吐量提高了约 12 倍。</p></li><li><p><strong>强制合并：</strong>索引完成后，GPU 继续加速分段合并，将强制合并阶段加快约 7 倍。</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfea4ee13b5a3b10d/6a17e923e9ea879c6aa9c616/f60ea9ee5996e456f393ffd195ee7eada6e5a7c2-948x387.png" alt="" /><ul><li><p><strong>CPU 使用率：</strong>将图构建任务分流到 GPU，可显著降低 CPU 的平均和峰值利用率。以下图表展示了索引和合并期间的 CPU 使用情况，凸显了在 GPU 上运行这些操作时 CPU 使用率的显著降低。GPU 索引期间降低 CPU 使用率，可释放 CPU 周期并重新分配，从而提升搜索性能。</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt80ff9c53f9b6884a/6a17e925445de9ee4b4d0187/5e680a5fc41700a877f3d8b2e5ce18ebd3f37a0b-1600x562.png" alt="" /><ul><li><p><strong>召回率：</strong>在 CPU 与 GPU 的运行结果中，准确性几乎一致，而 GPU 所构建的图在召回率方面略胜一筹。</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5cbe084eca27b8e4/6a17e926faa913317093c8b7/48a2b7758606bd321712b7d8378cd2640e652a4e-1384x544.png" alt="" /><h2>再从价格这个维度来进行比较</h2><p>前面的对比特意选用了相同的硬件配置，唯一的区别只是索引时是否启用 GPU。这种设置有助于单独考察计算性能的影响，不过也可以从成本角度来进行对比。</p><p>在与 GPU 加速配置大致相同的按小时费用下，可以搭建一套仅使用 CPU 的环境，其 CPU 和内存资源大约是前者的两倍：32 个 vCPU（AMD EPYC）和 64 GB RAM，因而可将索引线程数量增加到 16</p><p>为了保持比较的公平和一致性，我们在 AWS g6.8xlarge 实例上运行了这个仅 CPU 的实验，并且明确禁用了 GPU。这使我们能够在评估 GPU 加速与仅 CPU 索引的成本-性能权衡时，保持所有其他硬件特性不变。</p><p>正如您所预期的那样，更强大的 CPU 实例与上述部分的基准测试相比，性能确实有所提高。然而，将这一性能更强的 CPU 实例与最初的 GPU 加速结果进行对比后可以看到，GPU 依然带来显著性能提升：索引吞吐量提高<strong>约 5 倍</strong>，强制合并阶段加速<strong>约 6 倍</strong>，同时构建的图其召回率最高可达 <strong>95%</strong>。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt94b5eb6f95ba307d/6a17e928abe0f255d4dfea35/8ffa58cae3ad175ef2932a351aeef4c34a1407b9-948x394.png" alt="" /><h2>结论</h2><p>在端到端场景中，使用 NVIDIA cuVS 进行的 GPU 加速使索引吞吐量提高了近 12 倍，将强制合并延迟降低到原来的 1/7，同时显著降低了 CPU 利用率。这表明向量索引和合并工作负载从 GPU 加速中受益显著。在成本调整后的对比中，GPU 加速依然带来显著的性能提升：索引吞吐量约提升 5 倍，强制合并操作的速度提升约 6 倍。</p><p>GPU 加速的向量索引目前计划在 Elasticsearch 9.3 的技术预览版中推出，该版本计划于 2026 年初发布。</p><p>敬请关注更多内容。</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[向量数据库]]></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[利用英伟达™（NVIDIA®）探索 Elasticsearch 中的 GPU 加速矢量搜索：第一章]]></title>
    <description><![CDATA[这项合作由英伟达™（NVIDIA®）cuVS 提供支持，旨在为开发人员在 Elasticsearch 中进行矢量搜索提供 GPU 加速。]]></description>
    <content:encoded><![CDATA[<p>我们 Elastic Engineering 组织一直在忙于优化矢量数据库的性能。我们的使命：让 Lucene 和 Elasticsearch 成为最好的矢量数据库。通过硬件加速<a href="https://www.elastic.co/cn/blog/accelerating-vector-search-simd-instructions">CPU SIMD 指令</a>，引入新的矢量数据压缩创新技术<a href="https://www.elastic.co/cn/search-labs/blog/better-binary-quantization-lucene-elasticsearch">（更好的二进制量化，又称 BBQ</a>），然后通过更新 BBQ 算法方法以获得更多优势，并<a href="https://www.elastic.co/cn/search-labs/blog/filtered-hnsw-knn-search">使过滤 HNSW 更快</a>，从而超越了预期。我们正在打造一个更快、更好、更高效（呃？）在开发人员解决这些 RAG-gedy 问题时，为他们提供矢量数据库！</p><p>作为 "不遗余力地提高效率 "这一使命的一部分，我们正在利用这些奇特的计算机芯片探索加速机会，你可能听说过英伟达™（NVIDIA®）GPU！(说真的，你没听说过吗？）</p><p>在执着于性能时，我们有几个问题空间需要探索--如何索引指数级增长的数据，如何从中获取洞察力，以及如何在涉及 ML 模型时做到这一点。有了 GPU，你就能把所有的优势都发挥出来。</p><p>在本篇文章中，我们将深入探讨与英伟达™（NVIDIA®）矢量搜索团队的合作，探索 Elasticsearch 中的 GPU 加速矢量搜索。这项工作为开发人员在实际的 Elasticsearch 应用程序中混合使用 GPU 和 CPU 的用例铺平了道路。激动人心的时刻</p><h2>Elasticsearch GPU</h2><p>我们很高兴地与大家分享，Elasticsearch 工程团队正在帮助开发人员构建开源的 cuVS Java API 体验，该体验为矢量搜索算法提供了绑定。这项工作利用了我们以前在巴拿马 FFI 方面的经验。Elasticsearch 和 Apache Lucene 在索引过程中使用英伟达 cuVS API 构建图形。好吧，我们跳到前面，让我们倒退一下。</p><p><a href="https://developer.nvidia.com/cuvs">NVIDIA cuVS</a> 是一个开源 C++ 库，是此次合作的核心。它旨在通过提供更高的吞吐量、更低的延迟和更快的索引构建时间，为矢量搜索提供 GPU 加速。但 Elasticsearch 和 Apache Lucene 都是用 Java 编写的，这怎么行呢？</p><p>进入<a href="https://github.com/SearchScale/lucene-cuvs">lucene-cuvs</a>和 Elastic-NVIDIA-SearchScale 合作，将其引入 Lucene 生态系统，在 Elasticsearch 中探索 GPU 加速的矢量搜索。在最近发布的英伟达 cuVS 25.02 中，我们为 cuVS 添加了 Java API。新的应用程序接口是试验性的，将继续发展，但目前已经可以使用。也许有人会问：Java 对本地函数的调用不是很慢吗？现在不一样了！我们正在使用新的<a href="https://openjdk.org/projects/panama/">巴拿马 FFI</a>（外来函数接口）进行绑定，它将 Java 与本地向下调用的开销降至最低。</p><p>我们<a href="https://www.elastic.co/cn/search-labs/blog/lucene-and-java-moving-forward-together"> 在 Elasticsearch 和 Lucene 中 使用 巴拿马 FFI</a> 已经有一段时间了。太棒了但是......总是有 "但是 "的，不是吗？FFI 在跨 Java 版本的可用性方面存在挑战。我们将 cuVS 应用程序接口编译到 Java 21，并将实现封装在一个针对 Java 22 的多版本 jar 中，从而克服了这一问题。这样就可以直接在 Lucene 和 Elasticsearch 中使用 cuVS Java。</p><p>好了，既然我们已经有了 cuVS Java API，还需要什么呢？</p><h2>两种 CPU 算法的故事</h2><p>Elasticsearch 支持用于可扩展近似 KNN 搜索的<a href="https://arxiv.org/abs/1603.09320">HNSW 算法</a>。不过，为了最大限度地利用 GPU，我们使用了另一种算法<a href="https://arxiv.org/pdf/2308.15136"> CAGRA [</a><a href="https://arxiv.org/pdf/2308.15136"><strong> CUDA</strong></a><a href="https://arxiv.org/pdf/2308.15136"></a><a href="https://arxiv.org/pdf/2308.15136"></a><a href="https://arxiv.org/pdf/2308.15136"><em>ANN</em></a><a href="https://arxiv.org/pdf/2308.15136"></a><a href="https://arxiv.org/pdf/2308.15136"></a><a href="https://arxiv.org/pdf/2308.15136">GRAph]</a> ，它是专门为 GPU 提供的高并行性而设计的。</p><p>在了解如何添加对 CAGRA 的支持之前，我们先来看看 Elasticsearch 和 Lucene 是如何通过 "编解码器格式 "访问索引数据的。这包括</p><ol><li><p>磁盘表示法、</p></li><li><p>读写数据的接口、</p></li><li><p>以及处理 Lucene 基于段的架构的机制。</p></li></ol><p>我们正在实施一种新的 KNN（k-近邻）<a href="https://lucene.apache.org/core/10_1_0/core/org/apache/lucene/codecs/KnnVectorsFormat.html">向量格式</a>，该格式内部使用 cuVS Java API 在 GPU 上进行索引和搜索。从这里开始，我们通过 Elasticsearch 的映射将此编解码器类型 "剽窃 "到索引中的字段类型。因此，无论后备索引使用的是 CAGRA 还是 HNSW 图形，现有的 KNN 查询都能继续工作。当然，这忽略了许多细节，我们计划在今后的博客中加以介绍。以下是 GPU 加速 Elasticsearch 的高级架构。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb6197b631a34f8b6/6a170b0da6c2b9e60ce7970b/be6b7356c03df4dee7230625c2c9af3b019f93be-756x510.png" alt="" /><p>这种新的编解码器格式默认为 CAGRA。不过，它也支持将 CAGRA 图形转换为 HNSW 图形，以便在 CPU 上进行搜索。</p><h2>在 GPU 上进行索引和搜索：做出一些 "核心 "决定</h2><p>Elasticsearch Serverless 的无状态<a href="https://www.elastic.co/cn/search-labs/blog/stateless-your-new-state-of-find-with-elasticsearch">架构</a>将索引和搜索分离开来，因此现在有了明确的职责划分。我们选择最佳的硬件配置文件来履行这些独立的职责。</p><p>我们预计用户会考虑两种主要的部署策略：</p><ol><li><p>在 GPU 上进行索引和搜索：在索引过程中，建立一个 CAGRA 图，并在搜索过程中使用它--这在需要极低延迟的搜索时非常理想。</p></li><li><p>在 GPU 上索引，在 CPU 上搜索：在索引过程中，构建 CAGRA 图并将其转换为 HNSW 图。HNSW 图形存储在索引中，随后可用于 CPU 的搜索。</p></li></ol><p>这种灵活性提供了不同的部署模式，在成本和性能之间进行了权衡。例如，索引服务可以使用 GPU 及时高效地构建和合并图形，同时使用性能较低的 CPU 进行搜索。</p><h2>以下是在 Elasticsearch 中使用 GPU 加速矢量搜索的计划</h2><p>我们期待为用户带来性能提升和部署策略的灵活性，提供各种旋钮来平衡成本和性能。<a href="https://www.nvidia.com/gtc/session-catalog/?tab.catalogallsessionstab=16566177511100015Kus&amp;search=Lucene#/">下面是 NVIDIA GTC 2025 会议</a>对这项工作的详细介绍。</p><p>我们要感谢 NVIDIA 和 SearchScale 工程团队的出色合作。在下一篇博客中，我们将更深入地探讨实施细节和性能分析。戴上好奇帽🎩 ！</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/gpu-accelerated-vector-search-elasticsearch-nvidia</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/gpu-accelerated-vector-search-elasticsearch-nvidia</guid>
    <category><![CDATA[向量数据库]]></category>
    <dc:creator><![CDATA[Chris Hegarty,Hemant Malik]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt298e839e708ca11c/6a170b0fb339d560c2769fc2/38bc0377a6adce7eae0099f61902fdbbe644eb4a-1440x960.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 19 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Lucene 包裹 2024]]></title>
    <description><![CDATA[2024 年是 Apache Lucene 的又一个重要年份。在本博客中，我们将探讨其中的主要亮点。]]></description>
    <content:encoded><![CDATA[<p>2024 年，Apache Lucene 活动频繁，发布了许多版本，包括三年来的首次重大更新，其中包含了令人兴奋的改进和新功能。让我们来探讨其中的一些主要亮点。</p><h2>Lucene&amp; 社区</h2><p>只有得到社区的支持，项目才会强大。尽管经过 20 多年的发展，Lucene 项目仍然充满活力，并在热情和积极的贡献者的帮助下蓬勃发展。</p><p>2024 年，Lucene 项目已收到来自 98 位贡献者的 2000 多条提交和近 800 条拉取请求。贡献者的数量持续增长，新的提交者和项目管理委员会成员不断加入，帮助推动项目取得成功。</p><h2>Lucene 10</h2><p>2024 年，Lucene 10 发布了近 3 年来的首个重要版本，共有 185 位贡献者提交了 2000 多条信息。Lucene 遵循的开发模式允许在次要版本中提供许多改进和功能，而主要版本则提供了带来更多功能和现代化的机会。例如，Lucene 10 至少需要 Java 21。提高最低 Java 版本可确保 Lucene 能够继续利用现代 Java 所提供的改进。</p><p>Lucene 10 的主要重点是更好地利用运行它的硬件。让我们快速浏览一下其中的主要亮点：</p><ul><li><p><strong>更多搜索并行</strong>化--虽然搜索执行已经实现了跨网段并行化，但我们现在更进一步，实现了网段内的并行化。这就将磁盘上的表示与执行性能分离开来，即使是单个片段也能从现代系统的内核数量中获益。</p></li><li><p><strong>更好的 I/O 并行性</strong>--Lucene 使用的直接同步 I/O 模型通过预取阶段得到了增强。这将通知操作系统在不久的将来需要索引文件的一个区域，同时不会阻塞调用线程。</p></li><li><p><strong>利用稀疏索引提高 CPU 和存储效率</strong>--Lucene 10 引入了对稀疏索引的支持，在其他数据存储中，稀疏索引有时被称为主键索引或区域索引。</p></li></ul><p>有关 Lucene 10 的更多信息，请查看 Lucene 10<a href="https://www.elastic.co/search-labs/blog/apache-lucene-10-release-highlights">专文</a>。</p><h2>Lucene 研究与创新</h2><p>2024 年，Lucene 的研究和创新突飞猛进，尤其是在机器学习集成、矢量搜索和大规模数据集优化等领域，共<a href="https://scholar.google.com/scholar?as_ylo=2024&amp;q=lucene&amp;hl=en&amp;as_sdt=0,5"> 发表</a> 了 10 篇独立的 研究论文和出版物 。一些重要的研究领域和发展包括</p><ul><li><p><strong>矢量搜索和嵌入支持</strong>- Lucene 为基于矢量的搜索提供了功能强大且可扩展的解决方案，可实现大规模语义检索。通过利用 Lucene 强大的索引和搜索基础架构，用户可以将传统文本搜索的优点与现代矢量搜索的高级功能相结合，使 Lucene 成为适用于各种搜索和信息检索任务的全面解决方案。</p></li><li><p><strong>混合搜索模型</strong>- 研究还深入到混合搜索技术，Lucene 将传统的基于关键字的搜索与现代的基于向量的检索相结合。通过将基于术语的索引与密集的矢量表示合并，Lucene 可以提供更准确、与上下文更相关的搜索结果，缩小了传统搜索引擎的精确性与语义搜索的灵活性之间的差距。</p></li></ul><p>2024 年正在进行的研究工作表明，Lucene 能够适应现代搜索技术不断发展的需求，特别是在人工智能、语义搜索和大数据应用方面。该项目作为一个功能强大、灵活高效的平台，在传统和前沿搜索应用案例中不断发展壮大。</p><h2>2024 年发布 Lucene</h2><p>尽管这并不能完全反映情况，但发行量之大彰显了社区的持续奉献精神和活力。这些更新包括对向量搜索性能和效率的重大增强、对 madvise 的支持、对张贴列表解码的优化、通过 SIMD 进一步提高速度等等。</p><p>以下是完整的发布清单：</p><ul><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-1010-available">10.1.0</a>(2024-12-20)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9121-available">9.12.1</a>(2024-12-13)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-1000-available">10.0.0</a>(2024-10-14)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9120-available">9.12.0</a>(2024-09-28)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-8114-available">8.11.4</a>(2024-09-24)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9111-available">9.11.1</a>(2024-06-27)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9110-available">9.11.0</a>(2024-06-06)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-9100-available">9.10.0</a>(2024-02-20)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-8113-available">8.11.3</a>(2024-02-08)</p></li><li><p><a href="https://lucene.apache.org/core/corenews.html#apache-lucenetm-992-available">9.9.2</a>(2024-01-29)</p></li></ul><p>您可以在<a href="https://projects.apache.org/project.html?lucene-core">Lucene Core</a>页面找到更多信息和发布说明。此外，还有相应的<a href="https://projects.apache.org/project.html?lucene-pylucene">PyLucene</a>版本。</p><h2>总结</h2><p>随着 Lucene 日渐成熟，它也因其敬业而充满活力的社区而继续蓬勃发展。正如我们所看到的，2024 年是极其富有成效的一年，现在我们展望 2025 年将带来的激动人心的发展。</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/apache-lucene-wrapped-2024</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/apache-lucene-wrapped-2024</guid>
    <category><![CDATA[Lucene]]></category>
    <dc:creator><![CDATA[Chris Hegarty]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt901211870015335c/6a17ddf6a292998b08d02b93/29a02c89b3c5adb37a5f900de634ff09cb63fdd9-1792x1024.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 03 Jan 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>