聊聊Doris向量化执行引擎-过滤操作

news/2024/11/8 0:29:52/

聊聊Doris向量化执行引擎-过滤操作

Doris是开源的新一代极速MPP数据库,和StarRocks同源,采用全面向量化技术,充分利用CPU单核资源,将单核执行性能做到极致。本文,我们聊聊过滤操作是如何利用SIMD指令进行向量化操作。

过滤操作的SIMD向量化函数是_evaluate_vectorization_predicate:和StarRocks实现大致类似,但稍有不同:

  SegmentIterator::_evaluate_vectorization_predicate

执行过程如下图所示:

f5421203f20354d8b5f70df070bfd624.png

1、通过1个字节bool类型的ret_flags数组来表示是否满足过滤条件,1表示满足条件,0表示不满足

2、AVX2指令集环境下:通过_mm256_loadu_si256封装的指令函数加载256位长度值到寄存器,也就是32字节值f

3、_mm256_setzero_si256生成256位的0值all0

4、_mm256_cmpgt_epi8函数将f和all0每个字节进行并行比较,也就是32个字节并行比较,f中字节>all0中字节值时,对应结果位为1,否则为0

5、将第4步的值通过_mm256_movemask_epi8转换成int整数mask。比如10001111111111111,转换后为36863,其中ret_flags[0]为1,ret_flags[1]为0...

6、mask等于0,表示没有一个满足条件。

7、mask等于0xffffffff,表示全部满足条件,需要将32个数据的行号保存到数组sel_rowid_idx[]中

8、mask等于其他值时,表示有一部分值满足条件。这个时候需要特殊处理:

1)通过__builtin_ctzll(mask)计算mask中末尾0的个数bit_pos。比如:

11100000:有5个0

2)sel_rowid_idx[new_size++] = sel_pos + bit_pos;后导第一个满足条件的行号保存到sel_rowid_idx数组中

3)mask = mask & (mask - 1)跳过不满足的行,StarRocks实现方式:mask右移6位,即11,值3。

4)当然还需要处理尾数据,也就是SIMD对其后剩余的部分:按照标量处理方式处理

for (; sel_pos < sel_end; sel_pos++) {if (ret_flags[sel_pos]) {sel_rowid_idx[new_size++] = sel_pos;}
}

5)返回1)步继续计算。

9、当然,上述涉及mask的计算,仅说明了AVX指令集下实现方式,同时还实现了SSE2指令集

inline uint32_t bytes32_mask_to_bits32_mask(const uint8_t* data) {
#ifdef __AVX2__auto zero32 = _mm256_setzero_si256();uint32_t mask = static_cast<uint32_t>(_mm256_movemask_epi8(_mm256_cmpgt_epi8(_mm256_loadu_si256(reinterpret_cast<const __m256i*>(data)), zero32)));
#elif defined(__SSE2__) || defined(__aarch64__)auto zero16 = _mm_setzero_si128();uint32_t mask =(static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpgt_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(data)), zero16)))) |((static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpgt_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i*>(data + 16)), zero16)))<< 16) &0xffff0000);
#elseuint32_t mask = 0;for (std::size_t i = 0; i < 32; ++i) {mask |= static_cast<uint32_t>(1 == *(data + i)) << i;}
#endifreturn mask;
}

关键原理同样是将32字节的select数组,转变成32bit位的无符号整数来操作


http://www.ppmy.cn/news/64112.html

相关文章

Unity开发——如何在协程中进行回调

在Unity开发中&#xff0c;协程是一种实用的异步编程方法&#xff0c;要在协程中进行回调&#xff0c;可以使用委托&#xff08;delegate&#xff09;、Action或UnityAction 一、委托&#xff08;delegate&#xff09; 下面是一个使用协程和回调的简单示例&#xff1a; // 声明…

Window下载Android源码

Android 10源码下载 想要研究Android 源码的同学可以用此方法进行下载。源码从清华大学开源软件镜像站&#xff08;https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/&#xff09;下载。 使用Linux的同学直接参照清华镜像站提供的使用帮助(https://mirrors.tuna.tsinghua.edu…

修改lib64/l.ibc.so6导致系统命令都不能用

问题&#xff1a;想升级libc-2.12.so到libc2.17&#xff0c;拷贝了一个libc2.17到lib64下&#xff0c;然后建立软连接到l.ibc.so6&#xff0c;导致系统除了cd之类的命令&#xff0c;其他都不能使用 报错&#xff1a;relocation error: /usr/lib64/libc.so.6: symbol _dl_start…

肝一肝设计模式【七】-- 代理模式

系列文章目录 肝一肝设计模式【一】-- 单例模式 传送门 肝一肝设计模式【二】-- 工厂模式 传送门 肝一肝设计模式【三】-- 原型模式 传送门 肝一肝设计模式【四】-- 建造者模式 传送门 肝一肝设计模式【五】-- 适配器模式 传送门 肝一肝设计模式【六】-- 装饰器模式 传送门 文…

【shell脚本里的数组】

目录 一、数组的定义方法1、定义数组1.1、使用shell脚本来写出怎么查看这个数组有没有缺少元素1.2、使用shell脚本&#xff0c;来生成数组1.3、元素的切片 二、数组追加元素三、传输和传出1、向函数传入数组的值2、从函数返回数组 一、数组的定义方法 &#xff08; 20 10 60…

企业布局新媒体矩阵,如何走得更远?

企业搭建新媒体矩阵有很多好处——扩大品牌声量、丰富内容形式、提高宣传效率、降低运营风险、节省广告成本...... 即便如此&#xff0c;能真正让新媒体矩阵产生如此效果的企业&#xff0c;却是凤毛麟角。 更多的企业&#xff0c;往往冒然入场&#xff0c;也黯然离场&#xff0…

【iOS】---pthread,NSThread

在iOS中多线程开发有四种方式&#xff0c;在之前我们浅浅了解了一下GCD&#xff0c;这期来看看pthread和NSThread pehread pthread简介 pthread 是一套通用的多线程的 API&#xff0c;可以在Unix / Linux / Windows 等系统跨平台使用&#xff0c;使用 C 语言编写&#xff0c;…

头歌机器学习---决策树

第1关&#xff1a;什么是决策树&#xff1a; 如何构造出一棵好的决策树呢&#xff1f;其实构造决策树时会遵循一个指标&#xff0c;有的是按照信息增益来构建&#xff0c;如ID3算法&#xff1b;有的是信息增益率来构建&#xff0c;如C4.5算法&#xff1b;有的是按照基尼系数来构…