Elasticsearch:使用硬件加速的 SIMD 指令实现超快 BBQ

news2025/1/19 14:19:21

作者:来自 Elastic Chris Hegarty

我们如何使用硬件加速 SIMD(Single Instruction Multiple Data - 单指令多数据)指令优化 BBQ 中的向量比较。

随着我们继续致力于让 Elasticsearch 和 Apache Lucene 成为存储和搜索向量数据的最佳场所,我们在 BBQ(Better Binary Quantization - 更好的二进制量化)中引入了一种新方法。BBQ 是一个巨大的进步,通过压缩存储的向量带来了显著的(32 倍)效率,同时保持了高排名质量,并同时提供了超快的性能。你可以在 BBQ 博客中阅读有关 BBQ 如何将 float32 量化为单个位向量进行存储、在索引速度(量化时间减少 20-30 倍)和查询速度(查询速度提高 2-5 倍)方面优于乘积量化(Product Quantization)等传统方法的信息,并查看 BBQ 对各种数据集实现的出色准确率和召回率。

由于 BBQ 博客中已经介绍了高级性能,因此我们将在此更深入地了解 BBQ 如何实现如此出色的性能。特别是,我们将研究如何通过硬件加速的 SIMD(单指令多数据)指令优化向量比较。这些 SIMD 指令执行数据级并行,因此一条指令一次可对多个向量组件进行操作。我们将看到 Elasticsearch 和 Lucene 如何针对特定的低级 SIMD 指令(如 x64 上的 AVX 的 VPOPCNTQ 和 ARM 上的 NEON 的向量指令)来加速向量比较。

为什么我们如此关心向量比较?

向量比较决定了向量数据库中的执行时间,通常是成本最高的因素。我们在配置文件跟踪中看到了这一点,无论是使用 float32、int8、int4 还是其他量化级别。这并不奇怪,因为向量数据库必须大量比较向量!无论是在索引过程中,例如构建 HNSW 图,还是在搜索过程中,因为图或分区被导航以找到最近的邻居。向量比较中的低级性能改进对整体高级性能确实有影响。

Elasticsearch 和 Lucene 支持许多向量相似性指标,如点积(dot product)、余弦(cosine)和欧几里得(Euclidean),但是我们将只关注点积,因为其他指标可以从他的值里面得出。尽管我们有能力在 Elasticsearch 中编写自定义的本机(原生)向量比较器,但我们倾向于尽可能留在 Java 领域,以便 Lucene 也能更轻松地获得好处。

比较查询和存储向量

为了使我们的距离比较函数运行速度更快,我们需要尽可能简化它的工作,以便将其转换为一组在 CPU 上高效执行的 SIMD 指令。由于我们已经将向量量化为整数值,因此我们可以将更多组件加载到单个寄存器中,同时避免更昂贵的浮点运算 - 这是一个好的开始,但我们需要更多。

BBQ 进行非对称量化;查询向量(query vector)被量化为 int4,而存储向量被高度压缩为单个位值。由于点积是组件值乘积的总和,我们可以立即看到,唯一可以对结果产生积极影响的查询组件值是存储向量为 1 的值。

进一步的观察是,如果我们以将每个组件值的各个位置位(1、2、3、4)组合在一起的方式转换查询向量,那么我们的点积就会简化为一组基本的按位运算;对每个组件进行 AND + 位数运算,然后进行移位以表示查询部分的相应位置,最后进行求和以得到最终结果。有关更详细的解释,请参阅 BBQ 博客,但下图直观地展示了查询翻译的示例。

从逻辑上讲,点积简化为以下内容,其中 d 是存储的向量,q1、q2、q3、q4 是平移后的查询向量的相应位置部分:

(bitCount(d & q1) << 0) + (bitCount(d & q2) << 1)
+ (bitCount(d & q3) << 2) + (bitCount(d & q4) << 3)

为了执行目的,我们通过增加相应的位位置,在内存中连续布局翻译后的查询部分。因此,我们现在有了翻译后的查询向量 q[],其大小是存储向量 d[] 的四倍。

此点积的标量 Java 实现如下所示:

byte[] d = ... // stored vector bits
byte[] q = ... // query bits

for (int i = 0; i < 4; i++) {
  long subRet = 0;
  for (int j = 0; j < d.length; j++) {
    subRet += Integer.bitCount(q[i*d.length + j] & d[j] & 0xFF);
  }
  ret += subRet << i;
}

虽然语义上正确,但此实现效率不高。让我们继续看看更优化的实现是什么样子,然后我们可以比较每个实现的运行时性能。

性能从何而来?

到目前为止,我们看到的实现是一种简单的标量实现。为了加快速度,我们使用 Panama Vector API 重写了点积,以便明确针对特定的 SIMD 指令。

以下是仅针对查询部分之一的代码的简化片段 - 请记住,我们需要执行四次,每个翻译的 int4 查询部分执行一次。

var sum = LongVector.zero(LongVector.SPECIES_256);
for (int i=0; i < BYTE_SPECIES_256.loopBound(d.length); i += BYTE_SPECIES_256.length()) {
  var vq = ByteVector.fromArray(BYTE_SPECIES_256, q, i).reinterpretAsLongs();
  var vd = ByteVector.fromArray(BYTE_SPECIES_256, d, i).reinterpretAsLongs();
  sum = sum.add(vq.and(vd).lanewise(VectorOperators.BIT_COUNT));
}
long subRet = sum.reduceLanes(VectorOperators.ADD);
// tail processing, if any
ret += subRet << q_part // query part number

这里我们明确针对 AVX,每个循环迭代操作 256 位。首先在 vq 和 vd 之间执行逻辑与,然后对其结果进行位计数,最后将其添加到总和累加器。虽然我们对位数感兴趣,但我们确实将向量中的字节解释为长整型,因为这简化了加法并确保我们不会冒累加器溢出的风险。然后需要最后一步,将累加器向量的通道水平减少为标量结果,然后再按代表性查询部件号进行移位。

在我的 Intel Skylake 上拆解它,我们可以清楚地看到循环的主体。

0x00007cf9bcd57430:   movsxd r14,ecx
0x00007cf9bcd57433:   vmovdqu ymm4,YMMWORD PTR [rsi+r14*1+0x10]
0x00007cf9bcd5743a:   vmovdqu ymm5,YMMWORD PTR [rdx+r14*1+0x10]
0x00007cf9bcd57441:   vpand  ymm4,ymm4,ymm5
0x00007cf9bcd57445:   vpopcntq ymm4,ymm4
0x00007cf9bcd5744b:   vpaddq ymm3,ymm3,ymm4
0x00007cf9bcd5744f:   add    ecx,0x20
0x00007cf9bcd57452:   cmp    ecx,edi
0x00007cf9bcd57454:   jl     0x00007cf9bcd57430

rsirdx 寄存器保存待比较向量的地址,从中分别将下一个 256 位加载到 ymm4ymm5 寄存器中。加载完值后,我们执行按位逻辑与操作(vpand),将结果存储在 ymm4 中。接下来执行的是 vpopcntq 指令,该指令统计设置为 1 的位数。最后,我们将 0x20(32 字节 = 256 位)加到循环计数器中并继续执行。

为了简化,这里没有展示实际操作,但我们实际上展开了 4 个查询部分,并在每次循环迭代中同时执行它们,从而减少了数据向量的加载量。此外,我们为每个部分使用独立的累加器,最后再进行汇总。

当向量维度不足以每次处理 256 位时,采用 128 位的变体;在 ARM 平台上,这些操作会编译成一系列 Neon 向量指令,包括 ANDCNTUADDLP。当然,对于未对齐的数据部分,我们会以标量方式处理。不过,鉴于大多数流行模型的维度大小,这种情况在实际中并不常见。我们还在继续进行 AVX-512 实验,但到目前为止,由于常见的维度大小限制,按 512 位步进处理此数据布局并未显示出明显优势。

SIMD 能改善多少?

当我们比较标量和向量化点积实现时,我们分别看到从 384 到 1536 的一系列流行维度的吞吐量提高了 8 倍到 30 倍。

通过优化点积,我们大大提高了整体性能,使得向量比较不再是使用 BBQ 搜索和索引时最主要的因素。对于感兴趣的人,这里有一些基准和代码的链接。

总结

BBQ 是一种新技术,它带来了令人难以置信的效率和出色的性能。在这篇博客中,我们研究了如何通过硬件加速的 SIMD 指令在 BBQ 中优化向量距离比较。你可以在 BBQ 博客中阅读有关索引和搜索性能以及准确度和召回率的更多信息。BBQ 现已作为技术预览版在 Elasticsearch 8.16 和 Serverless 中发布!

除了 BBQ 等新技术外,我们还在不断改进向量数据库的低级性能。你可以在其他博客中阅读有关我们已经完成的工作的更多信息:FMA、FFM 和 SIMD。此外,随着我​​们不断提高 Elasticsearch 的性能,使其成为存储和搜索向量数据的最佳场所,未来还会看到更多像这样的以低级性能为重点的博客。

Elasticsearch 包含许多新功能,可帮助你为你的用例构建最佳搜索解决方案。深入了解我们的示例笔记本以了解更多信息,开始免费云试用,或立即在你的本地机器上试用 Elastic。

原文:Smokin' fast BBQ with hardware accelerated SIMD instructions - Search Labs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2255975.html

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

相关文章

面经自测——死锁/死锁的必要条件/死锁的预防/进程通信的方式

前言 本文是作者专门用来自测Java后端相关面试题的&#xff0c;所有问题都是在牛客、知识星球或网上找到的最近最新的面试题&#xff0c;全文回答都是作者按自己的真实水平仿照真实环境的回答&#xff0c;所以答案不一定真实&#xff08;但回答一定真诚&#x1f923;&#xff0…

通过电路指纹攻击发现洋葱服务

文章信息 论文题目&#xff1a;Discovering onion services through circuit fingerprinting attacks 期刊&#xff08;会议&#xff09;&#xff1a; High-Confidence Computing 时间&#xff1a;2023 级别&#xff1a;CCF C 文章链接&#xff1a;https://www.sciencedir…

[每周一更]-(第126期):MQ解耦场景

消息队列&#xff08;MQ&#xff09;解耦是一种软件架构设计模式&#xff0c;主要通过中间件将系统中的生产者和消费者模块分离&#xff0c;减少模块之间的直接依赖&#xff0c;使系统具有更高的扩展性和灵活性。这种模式尤其适用于需要处理复杂业务逻辑、频繁请求或异步处理的…

flinkSql 将流和表的互相转换

流——>表 方式一 方式二 方式一&#xff1a;写sql DataStreamSource<String> source env.socketTextStream("localhost", 8881); // 表名&#xff0c;流&#xff0c;字段名称 tableEnv.createTemporaryView("t_1",source&#xff0c;$("…

linuxCNC(五)HAL驱动的指令介绍

HAL驱动的构成 指令举例详解 从终端进入到HAL命令行&#xff0c;执行halrun&#xff0c;即可进入halcmd命令行 # halrun指令描述oadrt加载comoonent&#xff0c;loadrt threads name1 period1创建新线程loadusr halmeter加载万用表UI界面loadusr halscope加载示波器UI界面sho…

SQL SERVER 2016 AlwaysOn 无域集群+负载均衡搭建与简测

之前和很多群友聊天发现对2016的无域和负载均衡满心期待&#xff0c;毕竟可以简单搭建而且可以不适用第三方负载均衡器&#xff0c;SQL自己可以负载了。windows2016已经可以下载使用了&#xff0c;那么这回终于可以揭开令人憧憬向往的AlwaysOn2016 负载均衡集群的神秘面纱了。 …

vue3+elementPlus封装的数据过滤区

目录结构 源码 index.vue <template><el-form class"mb-5" :rules"rules" :model"queryForm" ref"queryDOM" label-width"80"><el-row :gutter"20"><slot></slot><el-col cla…

iOS如何自定义一个类似UITextView的本文编辑View

对于IOS涉及文本输入常用的两个View是UITextView和UITextField&#xff0c;一个用于复杂文本输入&#xff0c;一个用于简单文本输入&#xff0c;在大多数开发中涉及文本输入的场景使用这两个View能够满足需求。但是对于富文本编辑相关的开发&#xff0c;这两个View就无法满足自…

《黑神话:悟空》闪退,提示D3D12崩溃,游戏崩溃无法启动是什么原因?要怎么解决?

《黑神话&#xff1a;悟空》闪退、D3D12崩溃及游戏无法启动&#xff1a;原因、解决方案与预防措施 作为一名软件开发从业者&#xff0c;我深知电脑游戏运行时可能遇到的各种问题&#xff0c;尤其是像《黑神话&#xff1a;悟空》这样的高品质游戏&#xff0c;其对硬件和系统配置…

JUC:Synchronized和锁升级

1. 面试题 谈谈你对Synchronized的理解Sychronized的锁升级你聊聊Synchronized实现原理&#xff0c;monitor对象什么时候生成的&#xff1f;知道monitor的monitorenter和monitorexit这两个是怎么保证同步的嘛&#xff1f;或者说这两个操作计算机底层是如何执行的偏向锁和轻量级…

SAP SD学习笔记19 - 形式发票(Proforma Invoice)

上面几章讲了投诉处理。 SAP SD学习笔记18 - 投诉处理4 - 请求书订正依赖&#xff0c;投诉处理流程的总结-CSDN博客 本章继续学习SD 模块的其他内容。 本章讲了形式发票&#xff08;Proforma Invoice&#xff09;的概要及系统操作。 形式发票是在出库确认之前&#xff0c;有…

M005 PHP+MYSQL+web编程课程网站的设计与实现 源码 配置 文档

web编程课程网站 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 随着互联网的飞速发展&#xff0c;各行各业的信息化进程逐步加快。商业信息化、政务信息化、教育信息、服务信息化等等已遍布全国各地。信息化的服务平台能更加高效的为用户提供各种服务…

【力扣】13.罗马数字转整数

问题描述 思路解析 对于这种限制字符的问题&#xff0c;使用Map来对键值存储 对其进行判断&#xff0c;如果前面的数小于后面的数&#xff0c;那么结果相减 否则&#xff0c;正常相加。 代码 class Solution {Map<Character,Integer> mapnew HashMap<Character,In…

docker安装ddns-go(外网连接局域网)

docker先下载镜像&#xff0c;目前最新版是v6.7.6 也可以csdn资源下载 再导入dockers https://download.csdn.net/download/u014756339/90096748 docker load -i ddns-go.tar 启动 docker run -d --name ddns-go --restartalways --nethost -v /opt/ddns-go:/root jeessy/…

洛谷P4913 【深基16.例3】二叉树深度(c嘎嘎)

题目链接&#xff1a;P4913 【深基16.例3】二叉树深度 - 洛谷 | 计算机科学教育新生态 题目难度&#xff1a;普及 解题思路&#xff1a;本题要求树的深度&#xff0c;即求左右子树高度的最大值&#xff0c;首先我们用结构体存树左右节点&#xff0c;然后分别递归地去左右子树的…

Android -- [SelfView] 自定义多行歌词滚动显示器

Android – [SelfView] 自定义多行歌词滚动显示器 流畅、丝滑的滚动歌词控件* 1. 背景透明&#xff1b;* 2. 外部可控制进度变化&#xff1b;* 3. 支持屏幕拖动调节进度&#xff08;回调给外部&#xff09;&#xff1b;效果 歌词文件&#xff08;.lrc&#xff09; 一. 使用…

DNS/域名

概述 每个应用层协议都是为了解决某一类应用问题&#xff0c;而问题的解决又往往是通过位于不同主机中的多个应用进程之间的通信和协同工作来完成的。应用层的具体内容就是规定应用进程在通信时所遵循的协议。 应用层的许多协议都是基于客户服务器方式。客户(client)和服务器…

淘宝直播间智能化升级:基于LLM的学习与分析

自营直播应用技术团队负责的业务中&#xff0c;淘宝买菜的直播业务起步较晚&#xff0c;业务发展压力较大&#xff0c;业务上也就有了期望能够对一些二方的标杆直播间进行学习&#xff0c;并将其优点应用到自己直播间的需求。 最初 - 人海战术&#xff0c;学习PK 业务侧最直接的…

数学拯救世界(一)———寻“数”记

一、 很久很久以前&#xff0c;在一个只认识整数和小数的国度&#xff0c;有一个很残暴的国王提了一个要求&#xff1a;要是不能表示出把一段1米的绳子三等分后的大小&#xff0c;就要把所有的大臣杀掉。 1➗3 0.333&#xff0c;怎么办呀&#xff1f;怎么办呀&#xff1f; 袁q…

夏普MX-4608N复印机维修模式进入方法及载体初始化方法

夏普MX-4608N复印机载体型号&#xff08;图&#xff09;&#xff1a; 型 号&#xff1a;载体&#xff08;黑色&#xff09;MX-561CV 净含量&#xff1a;395克 下面图片中分别有载体、刮板、鼓芯、上纸盒搓纸轮一套&#xff0c;均原装正品&#xff1b; 保养周期将至的时候建…