Elasticsearch:使用向量化和 FFI/madvise 加速 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.mzph.cn/news/825599.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Springboot+Vue线上教学平台赠送配套文档1w字

SpringbootVue线上教学平台赠送配套文档1w字 项目描述 线上教学平台是一个功能丰富的在线教育工具,它为学生、教师和管理员提供了一个集成的学习、交流和管理环境。以下是关于该平台各项功能的简要介绍: 前台门户:前台门户是平台的门面&#…

实战|哈尔滨等保2.0 Linux主机测评过程之身份鉴别

一、身份鉴别 a)应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换。 输入 more /etc/shadow,得知系统所有用户,此语句字段格式有九段。 第一字段:用户名(也被称为登录名…

jmeter-while控制器用法

condition中添加while结束循环的条件,以下语句的意思是,当percent等于100时,就跳出while循环继续执行 ${__javaScript("${percent}" ! 100)} 举例,以下方法是getPercent为一个引出的异步接口,该接口的返回包…

java如何实现rabbitmq的消息确认机制和消息持久化机制配置和示例

在Java中,使用RabbitMQ的客户端库(通常是AMQP客户端库,如RabbitMQ的Java客户端)可以方便地实现消息确认机制和消息持久化机制。以下是如何实现这两个机制的示例。 1、消息确认机制 RabbitMQ支持两种类型的确认:生产者…

Python编程小例子—石头、剪子、布游戏

random库的应用—石头、剪子、布游戏 Random标准库的用法 在Python中,random是一个标准库,提供了生成随机数的功能。以下是一些常见用法: 生成随机整数: import random# 生成指定范围内的随机整数 random_int random.randint(1, 100)生成…

HiveSql中的函数家族(二)

一、窗口函数 1、什么是窗口函数 在 SQL 中,窗口函数(Window Functions)是一种特殊的函数,它允许在查询结果集的特定窗口(通常是一组行)上执行聚合、分析和计算操作,而无需聚合整个结果集。窗口…

FTP客户端Transmit 5 for Mac中文激活版

Transmit 5是一款功能强大的Mac FTP客户端软件,它由Panic公司开发,为用户提供简单、高效的文件传输体验。 Transmit 5 for Mac中文激活版下载 Transmit 5支持多种传输协议,如FTP、SFTP、WebDAV和Amazon S3等,满足用户不同的文件传…

【公司UI自动化学习】

公司课程链接:https://l.jd.com/student/project/project.du?project_id697509403 公司的课程,是给一个学习方向。 一、 PC自动化 1)什么项目适合 2)PC自动化介入时间点 3)自动化率: 频繁改动的&…

不需要GPU就可以玩转模型,同时支持本地化部署

简单一款不需要GPU就可以在Win 机器跑的模型:Ollama;用于本地运行和部署大型语言模型(LLMs)的开源工具 关于Ollama的简要介绍 平台兼容性:Ollama支持多种操作系统,包括macOS、Linux和Windows,…

华为手机无法弹出wifi上网认证页面处理

华为手机无法弹出wifi上网认证页面 连wifi后跳到上图界面卡住,不跳转到单位的上网认证界面。 打开手机的设置应用,点击上面的WLAN选项。 点击上面的更多WLAN设置选项。 关闭WLAN安全检测就可以正常弹出上网认证界面, 正常弹出上网认证界面&a…

C++类和对象 中(六大默认成员函数)

前言 紧接着上一篇文章,接下来我们来认识下类的六大默认成员函数,如下图。之所以叫他默认成员函数,是因为即使我们不写,编译器会默认帮我们写,但只要我们自己显示的写了,编译器就不会帮我们生成对应的成员函…

H3C交换机FTP与TFTP

一、设备作为服务器端 服务器端配置:首先保证服务器和客户端网络联通,开启 FTP 服务,配置访问 FTP 服务器的账号密码权限。 system-view # 登录系统界面 intg1/0/1 …

windows平台编译OpenCV以支持CUDA

一、环境要求 VS 2022社区版点击这里CMake(个人是GUI版本)点击这里OpenCV源码点击这里Opencv-contrib源码点击这里CUDA CUDNN参考这篇文章 个人的工具使用版本工具版本说明vs2019 社区版

第十五届蓝桥杯复盘python大学A组——试题C 数字诗意

思路 数字可以分为 有诗意的数字可以写成 (ij)(j-i1)/2 ( i、j都是正整数 ) ij 、j-i1 的奇偶性不同(因为i、j都是正整数) 因此, 如果一个数是奇数就一定有诗意 eg.312 ,523,734,945… 原因:根据上述分…

114 接口中幂等性的保证

前言 同样是 面试问题 如何确保接口的 幂等性 幂等是一个 较为抽象的概念, 多次重复访问, 不会导致业务逻辑的异常 这里从增删改查, 几个方面列一下 一般来说, 我们核心需要关注的就是 新增 和 更新 对于 增加元素, 首先针对唯一约束进行校验, 然后再处理新增的相关业…

Day09 React———— 第九天

ReactRoter 一个路径 path 对应一个组件 component 当我们在浏览器中访问一个 path 的时候,path 对应的组件会在页面中进行渲染 基础用法 import { createBrowserRouter, RouterProvider } from "react-router-dom"; const router createBrowserRoute…

基于windowns下的TCP网络通信编程

Tcp通信的三次握手和四次挥手 TCP的三次握手和四次挥手是TCP连接的建立和断开过程,确保了可靠的数据传输和连接状态的正确管理。 TCP的三次握手(TCP 链接建立): 1. 客户端发送 SYN : 客户端向服务器发送一个 SYN 报文…

AI讲师人工智能讲师大模型培训讲师叶梓:突破大型语言模型推理效率的创新方法

大型语言模型(LLM)在自然语言处理(NLP)任务中展现出了前所未有的能力,但它们对计算资源的巨大需求限制了其在资源受限环境中的应用。SparQ Attention算法提出了一种创新的方法,通过减少注意力机制中的内存带…

TCP为什么需要3次握手?

一、3次握手过程 客户端向服务端发送一个表示建立连接的SYN报文段,服务端从IP数据报中提取出TCP SYN报文段,为该TCP连接分配需要的缓存和变量,并向客户端发送表示允许连接的报文段ACK。客户端在收到ACK报文段之后,也要给该连接分配…

探索Java世界中的七大排序算法(上)

文章目录 排序的概念直接插入排序希尔排序( 缩小增量排序)选择排序堆排序冒泡排序 在计算机科学中,排序算法是一类重要的算法,它们用于将一组元素按照一定的顺序进行排列。在Java编程中,我们经常需要对数组或集合进行排序操作。本文将介绍Jav…