mpp文件用什么打开(project文件用什么软件打开)

1.背景

SIMD(Single instruction multiple data)是缩写,表示一条指令可以操作一批数据,一组指令可以并行操作多组数据。这项技术首先应用于视频的加速解码。早在英特尔奔腾系列中就引入了MMX(多媒体扩展)技术。不过这种技术是用来支持MPEG视频解码的。图像数据常用的数据类型有RGB565、RGBA8888、YUV422等格式。这些格式的数据的特征在于,像素的一个分量总是由小于或等于8比特的数据来表示。如果用传统的处理器进行计算,虽然处理器的寄存器是32位或者64位的,但是处理这些数据只能用到它们的低8位,似乎有点浪费。如果将64位寄存器拆分成8个8 8位寄存器,可以同时完成8次运算,计算效率会提高8倍。后来,英特尔进一步实现了SSE、SSE2~SSE4和AVX指令集。下面两张图分别展示了各个指令集的功能差异,以及不同CPU支持的指令集的丰富程度。

指令集名称

功能

多媒体增强指令集(Multi Media Extension)

64位整数

同SOUTH-SOUTH-EAST

28位浮点运算,整数运算还是需要MMX寄存器,只支持单精度浮点运算。

SSE2

支持整数数据,双精度浮点运算,CPU缓存控制指令。

SSE3

扩展指令包含寄存器的局部位之间的运算,例如高位和低位之间的加法和减法;浮点数到整数的转换,并支持超线程技术。

SSE4

添加了更多指令,支持数据移动中的错位数据移动,并添加了超级洗牌引擎。

AVX

26位浮点运算

AVX2

支持256位整数数据、3操作数指令

AVX512

52位操作

表1:不同指令集支持的函数迭代

图2:不同CPU家族支持的SIMD指令集示意图

随着移动互联网和IOT技术的发展和普及,系统中可用的数据呈指数级增长。如何应对这些海量数据的快速处理和查询,大数据软件厂商迫切需要使用SIMD向量来加速海量数据的处理。SIMD指令可以在一个控制器上同时控制多个并行处理单元,一个指令操作可以执行多个数据流。这样,CPU在同一个时钟周期内处理数据的能力大大提高。本质上,SIMD非常类似于向量处理器,可以在控制器上同时对一组数据(也叫“数据向量”)进行相同的操作,从而实现空之间的并行性。通过单指令多数据技术,在单个时钟周期内并行处理多个浮点,可以有效提高浮点运算速度。

通过乘法计算说明SIMD计算与传统CPU计算的区别和优势;

图3:传统的CPU乘法计算方法

图3是一个简单的乘法计算:所有四个数都需要乘以3。总共需要执行12条指令:

◇4加载存储器指令

◇ 4个乘法指令

◇ 4存储器回写指令

图4: SIMD计算模式

从图4可以看出,128位寄存器的CPU可以保存4个32位数字,执行一次计算,比一次执行一条指令快4倍。SIMD指令可以更快地批量处理数据,从原来的12条指令减少到3条指令。当代的X86处理器通常支持MMX、SSE、AVX等SIMD指令。,从而加快CPU的运算速度。当然,SIMD的指示也有一定的条件,这从上图可以看出。

◇处理的数据需要连续,对齐的内存可以获得更好的性能。

◇寄存器占用的空间比传统的SISD CPU多。

一般来说,有两种方法生成SIMD指令:

自动矢量化

自动矢量化,即编译器自动分析for循环是否可以矢量化。如果可能,将自动生成矢量化代码。通常,我们开始的-O3优化将打开自动矢量化。

手写SIMD说明书

SIMD可以得到图书馆的支持。您也可以通过英特尔提供的库直接对矢量化进行编程。比如SSE的API头文件是xmmintrin.h,AVX的API头文件是immintrin.h,这种实现效率最高,但是需要程序员熟悉SIMD编码,不具有通用性。比如AVX的矢量化算法,不能在不支持AVX指令集的机器上运行,也不能被SSE指令集替代。

2.2的常见应用场景分析。MPP数据库中的SIMD

SIMD指令为分析数据库引擎性能改进的设计和实现提供了新的机会。我们研究了开源OLAP数据库(如starrocks和clickhouse)的SIMD应用程序,以了解它们如何使用SIMD指令来加速各种SQL执行过程中的查询。

◆ 2.1排序计算加速

在数据分析的场景中,大多数SQL都有对一列数据进行排序的需求。如何利用SIMD指令加速数据排序是MPP数据库的一个非常重要的研究方向。

而SIMD技术排序的规模受限于向量寄存器的长度,所以SIMD实现的排序网络只能作为一个积木块,生成若干个有序的小向量,然后外层合并这些有序向量。快速排序不适合用SIMD优化,因为快速排序划分的子块不均匀。对于归并排序算法,基本上所有子块大小相等,所以当子块大小划分达到向量长度阈值时,可以使用SIMD来加快子块的排序。

双音排序是一种特别适合并行计算的排序算法。在介绍双音排序之前,先介绍一下双音序列和Batcher定理。

双音序列:先单调递增后单调递减(或先单调递减后单调递增)的序列,如1,5,8,6,3。

Er定理:将任意一个2n长的双音序列a分成两个等长的两半x和y,将x中的元素和y中的元素按原顺序逐一比较,即a[i]和a [I+n] (I < N)比较,将较大的放入MAX序列,较小的放入MIN序列。那么得到的MAX和MIN序列仍然是双音序列,并且MAX序列中的任意元素不小于MIN序列中的任意元素。

双音排序:假设我们有一个双音序列,我们将根据Batcher定理把它分成两个双音序列,然后继续递归划分每个双音序列,得到一个更短的双音序列,直到得到的子序列长度为1。此时,输出序列以单调递增的顺序排列。

见下图:升序排序。具体方法是把一个序列(1…n)分成两半,假设n = 2 K,然后把1和n/2+1比较,把较小的放上,然后把2和n/2+2比较,把较小的放上,以此类推;然后考虑为两个(n/2)长度的序列,因为都是双音序列,可以重复上面的过程;一共重复k轮,也就是最后一轮已经是长度为2的序列比较,可以得到最终的排序结果。

双音排序示意图

上面介绍了对已删除序列进行排序的过程,但并不是所有的序列都是已删除序列。首先,我们需要生成丢弃的序列。

双音序列的生成过程叫做双音合并,其实就是分而治之的思想。与前面排序的思路相反,它是一个自下而上的过程——将两个相邻的单调性相反的单调序列视为一个双音序列,每次都将这两个相邻的单调性相反的单调序列合并生成一个新的双音序列,然后进行排序(与3和2-tone排序相同)。这样只要相邻的两个长度为n的序列每次单调性相反,就可以通过连接得到一个长度为2n的双音序列,然后将相邻的两个长度为2n的序列排序一次,然后合并(先升后降)。n从1开始,每次加倍,直到等于数组的长度。最后,只需要再次进行单向(单调)排序。

以16个元素的数组为例:

1.两个相邻元素合并形成八个单调性相反的单调序列。

2.两两序列合并形成四个双音序列,按相反单调性排序。

3.4长度为4的相反单调单调序列,两个相邻序列合并生成两个长度为8的单调序列,分别排序。

4.2长度为8的相反单调单调序列,两个相邻序列合并生成长度为16的双音序列,排序。

如下图所示:

最后,放一个完整的8元素排序图:

谈完双音排序算法后,让我们看看如何使用SIMD指令来加速双音排序。

G++-o test test.cc-mavx2用于编译和。/测试此排序算法的排序结果。与std::sort相比,排序速度快4-5倍。实测数据如下:

如果想对一个更大的数组进行排序,可以使用merge_sort递归调用这个基本的排序算法。

◆ 2.2数值条件比较的加速

从tbl1中选择a,其中a & gt1.像这样的SQL语句非常常见。如何通过SIMD指令来加速SQL语句中过滤运算符的执行过程是非常有益的。

以表达式a >:为例,让我们看看常见的数据过滤是如何实现的。

图5:内存谓词计算

遍历a列,将a中的数据与1进行比较,并将比较结果写入筛选结果数组。过滤结果数组由UInt8 (1字节)组成,其中1代表过滤条件,0代表过滤条件。

遍历过滤结果数组,得到元素为1的偏移量,将数据库对应位置存储的数据复制到结果列中。

下面展示了如何根据starrocks2.3中的过滤结果获取目标数据:

以上代码片段基于starrocks2.3版本2.3。BinaryColumnBase & ltT & gt::filter_range周期开始后,使用AVX2命令加速计算。26位,每次计算32字节(SIMD字节),即32个元素。每次循环中8位与0比较,当大于0时,1位将被写入目的地。假设所有32个比较都是1,那么目的有32位1。

If(mask==0)如果全是0,就意味着这个循环中的32个元素都不满足条件,那么什么都不会做。

Else if(mask==0xffffffff)如果全部为yes,则表示该周期的32个元素全部满足条件,那么这32个元素将被一次性复制到结果列中。因为starrocks中的列是一个数组表示,所以这里是连续内存的副本。在循环展开中,减少了对寄存器的依赖,连续内存复制对CPU缓存友好。

如果不是全0或者全1,就需要继续单独判断32个元素。首先,将掩码转换为32位整数,然后将元素值1复制到结果列中。

从上面可以看出,在过滤int值的时候,这个函数的每一个循环都是将8个连续过滤的数据(即int类型)压缩成一个__m256i一起做比特计数。每次调用上述指令都会被32个8位整数处理,其中8位不能溢出,正好是256位。基于SIMD,CPU可以一次计算一个值到一组值,这样计算效率和速度会提高数倍。

AVX2指令中涉及的代码,简介:

#ifdef__AVX2__表示当前环境支持AVX2指令集。

__m256i包含几个整数数据的向量,比如char,short,int,unsigned long long等。例如,一个256位向量可以有32个char、16个short和8个int,这些整数可以是有符号的,也可以是无符号的;

_mm256_setzero_si256()初始化一个256位(32字节)全零位图,即XMM寄存器;

_mm256_loadu_si256()从内存地址读入一个256位整数数据(32字节地址不需要对齐;

_mm256_cmpgt_epi8(f,all0)由8位整形,比较两个256位整形数f和all0。如果f对应的8位大于all0对应的8位,则对应位全1填充,否则全0填充。

_mm256_movemask_epi8()根据一个256位整数的每个八位字节的最高位创建一个掩码;

◆2.3 Join计算的加速

连接计算通常是最常见的耗时操作,有两种方法可以优化连接操作的延迟。第一个想法是改进Join的计算算法。比如对于HashJoin,可以优化HashTable的实现(包括降低hash函数的计算复杂度和冲突列的查询复杂度),也可以通过在表中做适当数量的分区来增加并行度,在网络传输和计算并行度之间做一些平衡。

另一个思路是在具体的计算过程中尽可能的切割数据,减少算子计算涉及的数据。运行时过滤器在某些场景下有很好的效果,尤其是在事实表连接维度表的星型模型场景下。在这样的场景中,事实表的规模通常非常大,大部分过滤条件都在维度表上。

运行时过滤器(以下简称RF)在运行时过滤数据,过滤通常发生在Join阶段。当多个表被连接时,数据过滤往往伴随着谓词下推等优化手段,以减少对连接表数据的扫描和shuffle等阶段产生的IO,从而提高查询性能。RF的优化方法也对数据进行过滤,但是执行引擎会自动对查询进行过滤和优化,无需用户设置。

在StarRocks中,为了充分利用AVX2指令的并行处理能力,实现了基于SIMD的运行时过滤器,进一步加速多表连接。

以下方案使用运行时筛选器来加速starrocks的联接:

如图所示,事实表和维度表通过id字段连接。左图显示,未优化时,左表需要扫描10亿行数据,而优化后只需要扫描100万行,减少了大量数据扫描,查询效率大大提高。这里的实现是运行时过滤,即在sql运行的过程中,通过一个RF将右表的查询结果下推到左表,可以达到提前过滤的效果。目前支持广播和shuffle运行时过滤,整个过程自动优化。

以下代码使用SIMD来加速在运行时过滤器中构建布隆过滤器的过程:

◆ 2.4加速字符串的大小写转换。

大小写转换也是SQL中的常见操作。以ASCII拉丁字符大小写转换函数(即toLower()和toUpper())为例,我们来看看string case在ClickHouse中的实现。

原理很简单,就是用flip_case_mask来翻转字符的大小写(大小写字母的ASCII码值相差32)。Not_case_lower_bound和not_case_lower_bound用于校准转换后的字符范围,如a~z或A ~ Z,但在SSE2的加持下,可以一次加载16个字符进行转换。

◆ 2.5加速字符串的子串搜索。

相似子串匹配也是SQL查询中非常常见的场景。对于前缀和后缀,可以使用字典树索引+倒排组织进行快速搜索。但是对于像%abc%这样的子串匹配,使用index并不容易,通常采用逐行匹配。所以如何加快单行数据中子串的查找是很有意义的。让我们来看看常规的子串匹配算法:

其原理是逐字符匹配,但它有以下缺点:

◇逐字节比较还需要连续访问内存,浪费CPU周期;

◇错误的分支预测会浪费更多的CPU周期;

◇这种代码很难无序并行执行。

那么如何在MPP数据库中使用SMID来优化子串搜索的性能呢?

假设我们有一些8字节的寄存器,我们想在字符串“a_cat_tries”中搜索子字符串“cat”。

首先,我们将“cat”的第一个字节和最后一个字节分别填充到两个寄存器中,尽可能重复,直到寄存器填满。

然后我们将字符串“a_cat_tries”加载到另外两个寄存器中,其中一个从子字符串length -1字符开始。

然后比较两组寄存器的内容,对应位置的内容相同为1,否则为0。

最后,我们将两个寄存器的内容合并,即按位AND运算。

这时我们发现只有第二位(从零开始)是1,也就是说只有从这里开始才有可能搜索子串。这减少了我们的搜索次数。

下面提供基于SIMD指令中AVX2指令集的实现:

◆ 2.6场景总结

从上面的场景来看,随着现代CPU架构提供的指令集越来越丰富,可以使用不同的指令对多个数据进行不同的并行操作。目前,MPP数据库中的许多基本操作符都是基于SIMD指令集重写的,从而获得相应的性能提升。以上算符只是列举,还有更多算符可以用SIMD指令集加速。基于SIMD指令集的加速算子是MPP性能改进的一个非常重要的方向。

3.摘要

提高OLAP引擎在大数据场景下的分析性能是一个永无止境的话题。近年来,该领域出现了一些新的技术方向,包括存储格式、数据裁剪、CodeGen、矢量化计算等。向量化计算是充分利用CPU硬件的SIMD指令对连续内存的数据进行并行计算,从而达到加快执行的目的。SIMD采用独立于并发的数据级并行,SIMD指令允许多个数据在同一时钟周期内执行同一条指令。今天的英特尔编译器配置了AVX-512(高级向量扩展)指令集,将SIMD寄存器的宽度增加到512位。换句话说,可以并行操作16个4字节整数列值。为了使用SIMD指令集进行矢量化处理,正确组织数据以实现收益最大化非常重要。如何正确合理地组织数据,充分利用SIMD指令,是提高OLAP发动机性能的一个非常重要的研究方向。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

作者:美站资讯,如若转载,请注明出处:https://www.meizw.com/n/237494.html

发表回复

登录后才能评论