GaussDB的向量化处理技术

本文将深入探讨GaussDB中的向量化处理技术,涵盖其常见特性和实际应用。先详细介绍存储数据和即时数据(正在处理的数据)的按列组织格式,并阐述其优势。后通过分析SIMD(单指令多数据流)处理技术的一般原理,探讨在GaussDB中的巧妙运用。

一、列处理和即时数据

关系数据库管理系统(DBMS)将数据组织在表中,表包含列和行。表通常按行存储,同一行的数据存放在一起。表也可以按列存储,此时表的行被划分为行组,同一行组中同一列的数据存放在一起。

图1展示了一个员工表。在左侧,表按行组织;在右侧,表按列组织,每个行组包含两行。

图片

图1:按行组织和按列组织的员工表

磁盘上存储的持久化数据和内存中正在处理的即时数据都可以按列组织。持久化数据的行组通常较大,旨在实现更好的压缩率和更高的IO效率。而即时数据的行组相对较小,通常只有几千行,旨在减少内存消耗并实现更好的CPU缓存效率。

GaussDB向量SQL引擎就是为即时数据的列式处理而设计的。即时数据在GaussDB向量SQL引擎中的处理单元为 VectorBatch。Vector代表单列的行组,VectorBatch 代表多个单列的行组,参见图2。

图片

GaussDB向量SQL引擎算子接收一个VectorBatch输出一个VectorBatch。GaussDB向量SQL 引擎算子以批处理模式处理一个 SQL 查询:一次处理一批行,而不是一次处理一行。每个 VectorBatch 包含最多1000行。GaussDB 向量 SQL 引擎算子使用面向列的处理和优化来高效处理 VectorBatch。

例如,当一个算子需要计算多个列的哈希值时,它首先完成对 VectorBatch 中所有行的第一列的哈希值计算,然后是第二列,以此类推。最后,它累加所有列的哈希值。

按列存储和处理数据有几个好处:

1. 按列存储的数据可以更好地压缩

按列存储的数据可以更好地压缩。同一列的数据通常具有较高的重复率或相似的值。这些是压缩算法实现高压缩率的良好数据特征。例如,在员工表中,DeptID(部门ID)列的数据具有高重复率,可以很好地压缩。

2. 处理按列存储的数据显著减少IO

不仅因为更好的压缩率减少了IO的数量,还因为列存可以实现“延迟物化”技术。SQL 处理通常从 SCAN 算子开始,列存的SCAN 算子负责将磁盘上存储的行组转换为内存中的行组,这个过程中谓词评估可以被推入SCAN算子中以实现“延迟物化”。

例如,要处理查询“select * from employees where salary > 20”,向量SQL引擎首先读取salary列的行组,并判断行组中每一行是否满足谓词条件“salary > 20”,那些不满足谓词条件的行所对应的其他列将不会被读取。

3.批处理可以减少函数调用的次数,减少CPU开销

GaussDB 向量 SQL 引擎算子的处理单元是一个 VectorBatch,包含一千行。基于行的 SQL 引擎算子通常一次处理一行。因此,处理相同数量的数据,向量 SQL 引擎需要的函数调用次数要少得多。

4.列化数据处理可以实现更好的CPU缓存效率

列式数据可以避免CPU缓存被无关数据污染。图3展示了 GaussDB 向量 SQL 引擎在计算员工表的ID列的哈希值时的CPU缓存状态。当数据按列组织时,只有ID列数据被加载到CPU缓存中。name等列稍后才需要,所以它们必须包含在 VectorBatch 中。但在哈希值计算期间不需要它们,因此它们尚未加载到CPU缓存中。当数据按行组织时,所有列可能都必须加载到CPU缓存中,因为它们与 ID 列相邻存储。

图片

图3:按行组织与按列组织的 CPU 缓存状态

5.列式处理方式有利于单指令多数据(SIMD)操作

在下一章节中有详细解释。

二、什么是SIMD

单指令多数据 (SIMD) 是60/70年代由Michael Flynn提出的计算分类之一。SIMD 描述了一种数据并行处理技术。其中单一指令可以同时应用于一组输入数据。例如,在大量使用矩阵/向量运算的计算机图形学中,专门的GPU协处理器被用来高效地执行这些计算密集型运算。

图片

图4: 一个简单的向量加法示例图解,该操作可应用SIMD

除了GPU,SIMD处理也在CPU中得到实现。X86和ARM架构分别有支持不同程度数据并行和操作的指令集。SIMD寄存器的宽度决定了一次可以容纳的操作数数量;同时也决定了一条SIMD指令可以执行的操作数量。

例如,在X86架构中,AVX2将大多数指令扩展到256位寄存器(即:最多4个64位操作数),而AVX-512提供了使用高达512位的寄存器(即:每条指令最多8个64位操作数)。相应地,NEON指令集在ARM架构上实现了SIMD。

图片

图5: SIMD 示例图解,一条指令内完成4个元素的加法

三、向量化处理

向量化处理用于描述列式内存布局(通常被称为向量)以及在可能的情况下对其进行的SIMD操作。让我们以一个计算示例来说明:salary + bonus èpayout。

图片

图6:向量化处理的计算示例图

虽然在行式内存布局上执行SIMD操作是可能的,但效率较低。因为 “salary” 和 “bonus”的内存位置都不连续。步骤1和3中将数据移入/移出SIMD寄存器的操作会变得更加昂贵,有时这种开销可能会抵消SIMD操作带来的所有潜在速度提升。这就是向量内存布局和SIMD常常密不可分的原因。

四、GaussDB中的向量化处理

自动向量化

GaussDB是用C/C++实现的,C/C++可以支持多种方法在目标硬件上使用SIMD指令。其中两个方法是使用内联汇编和内部函数,尽管它们给程序员提供了精细的控制,但编程更加困难(尤其是汇编)。

此外,这两个方法都是平台相关的。还有一个方法是利用编译器的自动向量化,这个方法让现代编译器在为目标硬件平台编译时能够自动优化某些代码。

只要有可能,程序员就可以编写代码来帮助/建议编译器使其可向量化/SIMD化。以下是几个例子:

图片

图7:代码帮助编译器使GaussDB自动向量化/SIMD化

关于GCC和CLANG中的自动向量化,另见参考文献1和2。

GaussDB 旨在尽可能利用自动向量化,以充分发挥编译器生成目标硬件可执行文件的能力,同时保持代码的平台独立性。在特殊情况下,如果编译器无法生成我们想要的代码,内部函数将作为一种后备方法。

启用快速路径

在某些情况下,SIMD无法应用于给定的输入数据/向量。例如,编译器自动向量化通常要求循环必须是无分支的。然而,分支在输入向量中进行空值/空检查时很常见。

为了最大化SIMD向量化的机会,我们首先对输入数据/向量执行条件检查,如果满足可以应用SIMD的条件,就会调用专门的"快速路径",否则就回退到常规路径。在空值/空检查的情况下,由于空值标志也是以列/向量格式存在,检查本身也是向量化的。

图片

图8:最大化SIMD向量化启用快速路径示意图

此外,这种方法是按每个VectorBatch应用的,这意味着如果空值 (empty) 或 null 值很稀疏,大多数计算将利用快速路径,只有少数会回退到常规代码路径。

处理不同的数据类型

为了处理不同的数据类型,模板类可以为不同的操作数类型组合生成代码。编译器将尽可能自动向量化。

五、向量适配器

GaussDB实现了 '向量适配器'  (Vector Adapter),原本按行组织的数据也可以利用GaussDB向量SQL引擎的优势。例如,以下查询计划显示,在扫描完按行组织的表(lineitem表)后,这些行被 '向量适配器' 转换成 VectorBatch,然后GaussDB向量SQL引擎接管并继续处理查询。在这个查询中使用向量引擎是有益的,因为进入 ' Hash Aggregate' 算子的数据量很大。

Row Adapter
   ->  Vector Sort
         Sort Key: l_returnflag, l_linestatus
         ->  Vector Hash Aggregate
               Group By Key: l_returnflag, l_linestatus
               ->  Vector Adapter(type: BATCH MODE)

图9:GaussDB'向量适配器' 代码实现

六、性能结果

作为GaussDB最新版本的一部分,使用SIMD向量化的优化被添加到过滤器 (filter) 和表达式 (expression) 计算中。相比之前的实现显示出良好的性能提升。下面是与基线版本的性能对比,测试使用TPC-H SF=100数据库进行,下图显示Q1、Q6、Q9和Q15有显著改进;最高达到3倍的提升。

图片

图10:GaussDB最近版本添加SIMD向量化前后的性能对比。

基准测试在X86机器上运行,并行度(query_dop)为 48;

使用TPC-H SF=100,浮点数值类型为双精度 (double)

引用

文献1:GCC 中的自动向量化

https://gcc.gnu.org/projects/tree-ssa/vectorization.html

文献2:LLVM 中的自动向量化

https://llvm.org/docs/Vectorizers.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript猜数游戏小游戏

1.由系统生成一个1-100的随机整数。 2.提示用户输入一个1-100的整数,并将用户输入的数转换为整数。 3.将用户输入的数与随机生成的数进行比较,如果相等提示猜对了;否则给出提示,帮询问用户是否继续游戏。 4.如果用户在提示框中…

鸿蒙多线程开发——并发模型对比(Actor与内存共享)

1、概 述 并发是指在同一时间段内,能够处理多个任务的能力。为了提升应用的响应速度与帧率,以及防止耗时任务对主线程的干扰,HarmonyOS系统提供了异步并发和多线程并发两种处理策略。 异步并发:指异步代码在执行到一定程度后会被…

C++builder中的人工智能(12):了解ELU(Exponential Linear Unit)——人工神经网络中的激活函数

在这篇文章中,我们将解释什么是指数线性单元(ELU),以及如何利用ELU激活函数。通过学习这些知识,你将能够使用C软件创建C应用程序。 我们需要了解哪些关于激活函数的知识? 激活函数(phi()&#…

Spark中的宽窄依赖-宽窄巷子

1、什么是依赖关系? 2、什么是宽窄依赖? 窄依赖:Narrow Dependencies 定义:父RDD的一个分区的数据只给了子RDD的一个分区 【不用经过Shuffle】 特点:一对一或者多对一,不经过Shuffle,性能相对…

Scrapy入门

Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架。 安装scrapy pip install scrapy2.5.0 1.新建 Scrapy项目 scrapy startproject mySpider # 项目名为mySpider 2.进入到spiders目录 cd mySpider/mySpider/spiders 3.创建爬虫 scrapy gensp…

C++ 继承:代码传承的魔法棒,开启奇幻编程之旅

文章目录 一.继承的概念及定义1.1继承的概念1.2继承类1.2.1继承方法 1.3继承模板 二.基类和派生类的转换三.继承中的作用域四.派生类的默认成员函数4.1默认成员函数的行为4.2实现一个无法被继承的类 五.继承与友元六.继承与静态成员七.多继承和菱形继承7.1多继承和菱形继承7.2虚…

Liunx:文件fd、重定向、管道

文件fd: 操作系统运行中一定存在着许多被打开的文件,这些文件需要被管理。一个进程会打开若干个文件。一个文件如果在操作系统中被打开,那么必须给该文件创建一个文件对象,包含被打开文件的各种属性。那么进程与文件的关系就变成…

【AIGC】ChatGPT提示词Prompt高效编写技巧:逆向拆解OpenAI官方提示词

博客主页: [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 💯前言💯OpenAI官方提示词的介绍OpenAI官方提示词的结构与组成如何通过分析提示词找到其核心组件 💯OpenAI官方提示词分析案例一:制定教学计划案例二&…

干部谈话考察系统:革新传统,精准高效

在干部选拔任用和考核评价的过程中,谈话考察一直是关键环节之一。然而,传统的谈话考察方式却面临着诸多痛点,严重影响了干部考察工作的质量和效率。干部谈话考察系统的出现,为解决这些问题提供了有力的武器。 一、传统谈话考察的…

细说STM32单片机USART中断收发RTC实时时间并改善其鲁棒性的另一种方法

目录 一、工程目的 1、目标 2、通讯协议及应对错误指令的处理目标 二、工程设置 三、程序改进 四、下载与调试 1、合规的指令 2、不以#开头,但以;结束,长度不限 3、以#开头,不以;结束,也不包含;,长…

轨迹规划中优化预测:学习多个初始解的优化器

Abstract 在许多应用中,如机器人控制、自动驾驶和投资组合管理,需要在严格的运行时间限制下连续地解决相似的优化问题。在这种情况下,局部优化方法的性能对初始解的质量非常敏感:不良的初始化可能会导致收敛缓慢或得到次优解。为…

Xserver v1.4.2发布,支持自动重载 nginx 配置

Xserver——优雅、强大的 php 集成开发环境 本次更新为大家带来了更好的用户体验。 🎉 下载依赖组件时,显示进度条,展示下载进度。 🎉 保存站点信息和手动修改 vhost 配置文件之后,自动重载 nginx 配置 &#x1f41e…

idea 基础简单应用(java)

Java IDE(集成开发环境)的使用方法因不同的IDE而异,但通常都包含一些基本的操作和功能。以下以IntelliJ IDEA这一流行的Java IDE为例,介绍Java IDE的基本使用方法与指南: 一、下载与安装 请点击观看 idea免费安装步…

Notepad++ 更改字体大小和颜色

前言 在长时间编程或文本编辑过程中,合适的字体大小和颜色可以显著提高工作效率和减少眼睛疲劳。Notepad 提供了丰富的自定义选项,让你可以根据个人喜好调整编辑器的外观。 步骤详解 1. 更改字体大小 打开 Notepad 启动 Notepad 编辑器。 进入设置菜…

五个高质量伤感视频素材资源站,帮你快速找到完美创作素材

在制作短视频、MV或者广告时,伤感主题的视频素材往往能触动观众的情感,让作品更具共鸣。无论是表达分手、离别,还是展现孤独与失落,合适的伤感素材对情感类创作至关重要。为帮助创作者找到优质的视频素材,以下推荐5个高…

理解Web登录机制:会话管理与跟踪技术解析(一)

在这篇博客中,我们将深入探讨登录校验、会话技术和会话跟踪技术的基本概念、实现原理及其在Web应用中的应用。我们将介绍常见的会话跟踪技术,如Cookies、Session,并讨论它们的优缺点。同时,我们也会涉及如何使用现有的技术栈来实现…

ffmpeg:视频字幕嵌入(GPU加速)

实现方案 参考指令 ffmpeg -i input_video.mp4 -vf "subtitlessubtitles.srt" output_video.mp4 解决因文件名称复杂导致的指令执行失败问题(引号给文件框起来) ffmpeg -i "A.mp4" -vf "subtitlesB.srt" "c.mp4&qu…

qt QListWidget详解

1、概述 QListWidget 是 Qt 框架中的一个类,它提供了一个基于模型的视图,用于显示项目的列表。QListWidget 继承自 QAbstractItemView 并为项目列表提供了一个直观的接口。与 QTreeView 和 QTableView 不同,QListWidget 是专门为单行或多行项…

UE5 材质篇 0 创建一个材质

首先在starter里的shape里拖入一个几何到场景里 我选了个sphere 然后开始制作一个材质,直接右键点击 进入材质的蓝图界面 先来个纹理采样 左侧detail里选个图给他 type这里可以指定他是其他图片,例如normal map 采样一个之前给UV加个动态offset

AOSP沙盒android 11

这里介绍一下aosp装系统 什么是aosp AOSP(Android Open Source Project)是Android操作系统的开源版本。 它由Google主导,提供了Android的源代码和相关工具,供开发者使用和修改。 AOSP包含了Android的核心组件和API,使…