Elasticsearch:使用向量化和 FFI/madvise 加速 Lucene

ops/2024/9/20 1:25:20/ 标签: elasticsearch, lucene, 大数据, 全文检索, 搜索引擎

作者:来自 Elastic Chris Hegarty

在 Lucene 领域,我们一直热切地采用新版本 Java 的功能。这些功能使 Lucene 更接近 JVM 和底层硬件,从而提高了性能和稳定性。这使得 Lucene 保持现代化和具有竞争力。

Lucene 的下一个主要版本,Lucene 10,将需要至少 Java 21。让我们看看我们为什么要这样做以及它将如何惠及 Lucene。

外部内存

出于效率考虑,索引及其各种支持结构被存储在 Java 堆之外 - 它们被存储在磁盘上,并映射到进程的虚拟地址空间中。直到最近,在 Java 中执行此操作的方法是使用直接字节缓冲区,这正是 Lucene 一直在做的。

直接字节缓冲区具有一些固有的限制。例如,它们最多只能寻址 2GB,需要更多的结构和代码来跨越更大的尺寸。然而,最重要的是缺乏确定性关闭,我们通过调用 Unsafe::invokeCleaner 来绕过此问题,有效地关闭缓冲区并释放内存。正如其名称所暗示的那样,这是一种不安全的操作。Lucene 在此周围添加了保障,但根据定义,在释放内存后仍然存在微小的失败风险。

更近些时候,Java 添加了 MemorySegment,它克服了我们在直接字节缓冲区中遇到的限制。我们现在拥有了安全的确定性关闭,并且可以处理远远超过以前限制的内存。虽然 Lucene 9.x 已经可选地支持由内存段支持的映射目录实现,但即将推出的 Lucene 10 放弃了对字节缓冲区的支持。所有这些意味着,Lucene 10 只能使用内存段,因此最终在一个安全的模型中运行。

外部函数

不同的工作负载,如搜索或索引,或者不同类型的数据,比如文档值或向量嵌入,具有不同的访问模式。正如我们所见,由于 Lucene 映射其索引数据的方式,与操作系统页面缓存的交互对性能至关重要。

多年来,人们在围绕内存使用和页面缓存进行优化方面付出了大量的努力和考虑。首先是通过调用 madvise 的本地 JNI 代码,然后是使用直接 I/O 的目录实现。然而,尽管在当时表现良好,但这两种解决方案都略显不理想。前者需要特定于平台的构建和构件,后者则利用了可选的 JDK 特定 API。因此,出于这些原因,这两种解决方案都不是 Lucene 核心的一部分,而是存在于更远的 misc 模块中。Mike McCandless 在 2010 年写了一篇很好的博客!

在现代 Java 中,我们现在可以使用 Panama Foreign Function Interface (FFI) 来调用系统上的本地库函数。我们在 Lucene 核心中直接使用它来从 Java 中调用标准 C 库中的 posix_madvise - 而无需任何 JNI 代码或非标准功能。通过这个,我们现在可以告诉系统我们打算使用的内存访问模式。

向量化

并行性和并发性,虽然是不同的概念,但通常都可以转化为 “将任务拆分以便更快地执行”,或者 “同时执行更多任务”。Lucene 不断研究新的算法,并努力以更高效和有效的方式实现现有算法。现在在 Java 中对我们来说更加简单的一个领域是数据级并行性 - 即使用 SIMD(单指令多数据)向量指令来提高性能。

Lucene 使用最新的 JDK Vector API 来实现向量距离计算,从而产生高效的硬件特定的 SIMD 指令。这些指令在支持的硬件上运行时,可以比等效的标量代码快 8 倍执行浮点点积计算。这篇博客包含了关于这个特定优化的更具体信息。

随着向 Java 21 最低版本的转变,我们可以更加直接地看到在更多地方使用 JDK Vector API 的可能性。我们甚至正在尝试使用 FFI 调用定制的 SIMD 实现,因为现在本地调用的开销已经非常小了。

结论

尽管最新的 Lucene 9.x 版本能够受益于许多最近的 Java 功能,但需要在 Java 11 之类的早期版本上运行的要求意味着我们在 9.x 中已经达到了一定的复杂性水平,虽然今天可能还可以,但这并不是我们未来想要的状态。

即将推出的 Lucene 10 将比以往任何时候都更接近 JVM 和硬件。通过要求至少使用 Java 21,我们能够放弃旧的直接字节缓冲区目录实现,通过 posix_madvise 可靠地向系统建议关于内存访问模式的信息,并继续努力利用硬件加速的指令。

准备将 RAG 构建到你的应用中吗?想要尝试使用向量数据库的不同 LLM 吗? 在 Github 上查看我们的 LangChain、Cohere 等示例笔记本,即将开始的 Elasticsearch 工程师培训!

原文:Lucene Speed: How Vectorization and FFI/madvise Make Lucene Faster — Elastic Search Labs


http://www.ppmy.cn/ops/7744.html

相关文章

RIME-SVM,基于RIME寒冰优化算法优化SVM支持向量机回归预测 (多输入单输出)-附代码

支持向量机(SVM) 支持向量机(SVM)是一种广泛用于分类和回归的强大监督学习算法。在回归任务中,特别是在SVM被用作支持向量回归(SVR)时,目标是找到一个函数,这个函数在给…

Apache Hadoop 输入格式示例

目录 TextInputFormat 示例 SequenceFileInputFormat 示例 总结 TextInputFormat 示例 描述: TextInputFormat 是 Hadoop 中使用最广泛的输入格式之一,适用于纯文本文件。它将文件按行划分,把每一行的起始偏移量作为键(key)&am…

JDBC学习

DriverManager(驱动管理类) Drivermanager的作用有: 1.注册驱动; 2.获取数据库连接 Class.forName("com.mysql.cj.jdbc.Driver"); 这一行的作用就是注册Mysql驱动(把我们下载的jar包加载到内存里去&…

实现 Android 设备屏幕录制的批处理脚本

在本文中,我们将介绍如何使用批处理脚本来实现在 Android 设备上进行屏幕录制,并将录制的视频文件传输到计算机上。这个脚本利用了 Windows 的批处理脚本和 Android 的 adb 工具。 背景 在进行 Android 应用开发、教学演示或问题排查时,我们…

毕业设计——基于ESP32的智能家居系统(语音识别、APP控制)

ESP32嵌入式单片机实战项目 一、功能演示二、项目介绍1、功能演示2、外设介绍 三、资料获取 一、功能演示 多种控制方式 ① 语音控制 ②APP控制 ③本地按键控制 ESP32嵌入式单片机实战项目演示 二、项目介绍 1、功能演示 这一个基于esp32c3的智能家居控制系统,能实…

使用51单片机控制T0和T1分别间隔1秒2秒亮灭逻辑

#include <reg51.h>sbit LED1 P1^0; // 设置LED1灯的接口 sbit LED2 P1^1; // 设置LED2灯的接口unsigned int cnt1 0; // 设置LED1灯的定时器溢出次数 unsigned int cnt2 0; // 设置LED2灯的定时器溢出次数// 定时器T0 void Init_Timer0() {TMOD | 0x01;; // 定时器…

三、Flask模型基础

ORM 创建模型 # exts.py&#xff1a;插件管理 # 扩展的第三方插件 # 1.导入第三方插件 from flask_sqlalchemy import SQLAlchemy # ORM插件 from flask_migrate import Migrate # 2. 初始化 db SQLAlchemy() # ORM migrate Migrate() # 数据迁移 # 3. 和app对象绑定 def…

Flink的安装、项目创建、任务打包和部署完整实现,任务实现使用JAVA语言

Flink资源下载地址 Flink安装包下载地址 一、本地模式安装Flink 1、在Linux服务上&#xff0c;创建flink文件夹 mkdir flink 2、上传文件并解压 tar -zxvf flink-1.14.6-bin-scala_2.11.tgz 解压完成后&#xff0c;如图&#xff1a; 3、启动Flink 进入到解压目录下&#x…

Css切换不同窗口

代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>Title</title></head><style>/*label {*//* display: block;*//*}*/* {padding: 0;margin: 0;}body {height: 100vh;backgroun…

设计模式之原型模式

1、简单介绍 原型模式&#xff08;Prototype Pattern&#xff09;是一种创建型设计模式&#xff0c;它通过复制现有的实例来创建新对象&#xff0c;而不是通过调用类的构造函数来创建新实例。这种模式适用于需要快速复制大量相同或相似对象&#xff0c;或者创建对象需要消耗大量…

【图论 单源最短路】100276. 最短路径中的边

本文时间知识点 单源最短路 图论知识汇总 LeetCode100276. 最短路径中的边 给你一个 n 个节点的无向带权图&#xff0c;节点编号为 0 到 n - 1 。图中总共有 m 条边&#xff0c;用二维数组 edges 表示&#xff0c;其中 edges[i] [ai, bi, wi] 表示节点 ai 和 bi 之间有一条…

前端nodead面试题

1.CSR和SSR分别是什么&#xff1f; CSR是客户端渲染&#xff0c;客户端访问网站时&#xff0c;服务器向客户端发送Html文档&#xff0c;让浏览器去渲染。其中像js,图片等还需要再次发请求。就是要啥给啥绝不多给。 缺点&#xff1a;不利于SEO&#xff0c;首次加载速度慢&…

Vue-router的动态路由:获取传递的值

Vue.js是一款流行的JavaScript框架&#xff0c;用于构建单页面应用程序。它提供了许多有用的功能&#xff0c;其中之一是Vue-router&#xff0c;它允许您轻松地管理应用程序的路由。Vue-router支持动态路由&#xff0c;这意味着您可以在路由中使用变量&#xff0c;并在组件中访…

Redis入门

1.初始Redis Redis是一种键值型的NoSql数据库&#xff0c;这里有两个关键字&#xff1a; 键值型 NoSql 其中键值型&#xff0c;是指Redis中存储的数据都是以key、value对的形式存储&#xff0c;而value的形式多种多样&#xff0c;可以是字符串、数值、甚至json&#xff1a;…

Excel数据处理:动态数据分析报表、单元格数字格式、使用排序工具

1、在生成数据透视表之后选中一个单元格&#xff0c;点击插入&#xff0c;在图表中选择一个自己想要的图表。&#xff08;生成可视化的图表&#xff09; 2、在分析中找到切片器&#xff0c;通过点击切片器可以即时变换生成不同的可视化图&#xff0c;可以右键切片器选择关联两个…

初始化Git仓库时应该运行哪个命令?

文章目录 初始化Git仓库时&#xff0c;你应该运行git init这个命令。这个命令的作用是在你当前所在的目录里创建一个新的Git仓库。这样&#xff0c;你就可以在这个目录里开始使用Git来管理你的文件了。 下面我给你举个详细的例子来说明一下&#xff1a; 首先&#xff0c;你需要…

【从浅学到熟知Linux】基础IO第一弹=>C语言文件操作接口、文件系统调用、文件描述符概念及分配规则

&#x1f3e0;关于专栏&#xff1a;Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 C语言文件接口回顾系统文件概念与接口文件基本概念系统接口openreadwritecloselseek 什么是当前路径 文件描…

Simba:Mamba 增强了 U-ShiftGCN,用于视频中的骨骼动作识别

Simba&#xff1a;Mamba 增强了 U-ShiftGCN&#xff0c;用于视频中的骨骼动作识别 摘要IntroductionRelated WorksMethodologyDown-sampling ShiftGCN Encoder Experiments & ResultsDatasets Simba: Mamba augmented U-ShiftGCN for Skeletal Action Recognition in Video…

大创项目推荐 深度学习+opencv+python实现车道线检测 - 自动驾驶

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &am…

搜索引擎中的倒排索引是什么

在搜索引擎领域&#xff0c;倒排索引是一种核心数据结构&#xff0c;它让搜索引擎能够以极高的效率找到包含用户查询关键词的所有网页。为了理解倒排索引的工作原理&#xff0c;我们可以将其与一种更直观、生活化的例子相比较&#xff1a;书店里的索引卡片系统。 假设你是一位…