PostgreSQL 利用编译器extension 支持int128,提升聚合性能

简介:

标签

PostgreSQL , int128 , clang , gcc , icc


背景

PostgreSQL 9.4以及以前的版本,在INT,INT2,INT8的聚合计算中,为了保证数据不会溢出,中间结果使用numeric来存储。

numeric是PostgreSQL自己实现的一种数值类型,可以存储非常大的数值(估计是做科学计算的需求),但是牺牲了一定的性能。

为了提高聚合,特别是大数据量的聚合时的性能,社区借用了编译器支持的int128类型,作为数据库int, int2, int8的中间计算结果,从而提升计算性能。

编译器相关的解释

gcc,clang,icc都支持int128

1. gcc

6.8 128-bit Integers

As an extension the integer scalar type __int128 is supported for targets which have an integer mode wide enough to hold 128 bits. 

Simply write __int128 for a signed 128-bit integer, or unsigned __int128 for an unsigned 128-bit integer. 

There is no support in GCC for expressing an integer constant of type __int128 for targets with long long integer less than 128 bits wide.

2. icc

From what I can tell, at least icc 13.0.1+ support __int128_t and __uint128_t. Courtesy of Matt Godbolt's Compiler Explorer:

__int128_t ai (__int128_t x, __int128_t y) {
  return x + y;
}

__int128_t mi (__int128_t x, __int128_t y) {
  return x * y;
}

__int128_t di (__int128_t x, __int128_t y) {
  return x / y;
}

__int128_t ri (__int128_t x, __int128_t y) {
  return x % y;
}
compiles to:

L__routine_start_ai_0:
ai:
        add       rdi, rdx                                      #2.14
        mov       rax, rdi                                      #2.14
        adc       rsi, rcx                                      #2.14
        mov       rdx, rsi                                      #2.14
        ret                                                     #2.14
L__routine_start_mi_1:
mi:
        mov       rax, rdi                                      #6.14
        imul      rsi, rdx                                      #6.14
        imul      rcx, rdi                                      #6.14
        mul       rdx                                           #6.14
        add       rsi, rcx                                      #6.14
        add       rdx, rsi                                      #6.14
        ret                                                     #6.14
L__routine_start_di_2:
di:
        push      rsi                                           #9.44
        call      __divti3                                      #10.14
        pop       rcx                                           #10.14
        ret                                                     #10.14
L__routine_start_ri_3:
ri:
        push      rsi                                           #13.44
        call      __modti3                                      #14.14
        pop       rcx                                           #14.14
        ret                                                     #14.14
with icc 13.0.1 (http://goo.gl/UnxEFt).

PostgreSQL int128支持

编译时根据编译器的特性自动判断是否使用int128特性.

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=8122e1437e332e156d971a0274879b0ee76e488a

Add, optional, support for 128bit integers.

We will, for the foreseeable future, not expose 128 bit datatypes to
SQL. But being able to use 128bit math will allow us, in a later patch,
to use 128bit accumulators for some aggregates; leading to noticeable
speedups over using numeric.

So far we only detect a gcc/clang extension that supports 128bit math,
but no 128bit literals, and no *printf support. We might want to expand
this in the future to further compilers; if there are any that that
provide similar support.


config/c-compiler.m4        diff | blob | blame | history
configure       diff | blob | blame | history
configure.in        diff | blob | blame | history
src/include/c.h     diff | blob | blame | history
src/include/pg_config.h.in      diff | blob | blame | history
src/include/pg_config.h.win32       diff | blob | blame | history

性能提升测试

There was recently talk about if we should start using 128-bit integers
(where available) to speed up the aggregate functions over integers
which uses numeric for their internal state. So I hacked together a
patch for this to see what the performance gain would be.

Previous thread:
http://www.postgresql.org/message-id/20141017182500.GF2075@alap3.anarazel.de

What the patch does is switching from using numerics in the aggregate
state to int128 and then convert the type from the 128-bit integer in
the final function.

The functions where we can make use of int128 states are:

- sum(int8)
- avg(int8)
- var_*(int2)
- var_*(int4)
- stdev_*(int2)
- stdev_*(int4)

The initial benchmark results look very promising. When summing 10
million int8 I get a speedup of ~2.5x and similarly for var_samp() on 10
million int4 I see a speed up of ~3.7x. To me this indicates that it is
worth the extra code. What do you say? Is this worth implementing?

The current patch still requires work. I have not written the detection
of int128 support yet, and the patch needs code cleanup (for example: I
used an int16_ prefix on the added functions, suggestions for better
names are welcome). I also need to decide on what estimate to use for
the size of that state.

The patch should work and pass make check on platforms where __int128_t
is supported.

The simple benchmarks:

CREATE TABLE test_int8 AS SELECT x::int8 FROM generate_series(1, 
10000000) x;

Before:

# SELECT sum(x) FROM test_int8;
       sum
----------------
  50000005000000
(1 row)

Time: 2521.217 ms

After:

# SELECT sum(x) FROM test_int8;
       sum
----------------
  50000005000000
(1 row)

Time: 1022.811 ms

CREATE TABLE test_int4 AS SELECT x::int4 FROM generate_series(1, 
10000000) x;

Before:

# SELECT var_samp(x) FROM test_int4;
       var_samp
--------------------
  8333334166666.6667
(1 row)

Time: 3808.546 ms

After:

# SELECT var_samp(x) FROM test_int4;
       var_samp
--------------------
  8333334166666.6667
(1 row)

Time: 1033.243 ms

参考

1. https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=8122e1437e332e156d971a0274879b0ee76e488a

2. https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=959277a4f579da5243968c750069570a58e92b38

3. https://www.postgresql.org/message-id/flat/544BB5F1.50709%40proxel.se#544BB5F1.50709@proxel.se

4. http://stackoverflow.com/questions/16365840/128-bit-integers-supporting-and-in-the-intel-c-compiler

5. https://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
存储 关系型数据库 PostgreSQL
深入浅出PostgreSQL B-Tree索引结构
PostgreSQL 的B-Tree索引页分为几种类别 meta page root page # btpo_flags=2 branch page # btpo_flags=0 leaf page # btpo_flags=1 如果即
15002 0
|
3月前
|
机器学习/深度学习 传感器 数据采集
【故障识别】基于CNN-SVM卷积神经网络结合支持向量机的数据分类预测研究(Matlab代码实现)
【故障识别】基于CNN-SVM卷积神经网络结合支持向量机的数据分类预测研究(Matlab代码实现)
271 0
|
11月前
|
人工智能 数据处理 C#
AI Dev Gallery:微软开源 Windows AI 模型本地运行工具包和示例库,助理开发者快速集成 AI 功能
微软推出的AI Dev Gallery,为Windows开发者提供开源AI工具包和示例库,支持本地运行AI模型,提升开发效率。
732 13
|
Unix Linux 开发者
Perl 语言入门学习
Perl 语言入门学习
|
存储 并行计算 数据处理
跨语言集成:Dask 与其他编程环境的交互
【8月更文第29天】Dask 是一个开源的并行计算库,旨在为 Python 社区提供高性能的并行计算能力。尽管 Dask 主要在 Python 生态系统中使用,但它也可以与其他编程语言环境(如 R 和 Julia)进行交互,实现跨语言的数据处理。本文将探讨如何利用 Dask 与 R 和 Julia 等其他语言集成,以便在不同编程环境中共享数据和计算资源。
318 4
|
弹性计算 缓存 安全
阿里云服务器ECS实例2核4G有哪些?性能如何?
阿里云2核4G配置的云服务器提供多样化的ECS实例规格,如突发性能t6、经济型e、计算型c7/c6/c8i/c8a等,不同规格性能各异,参考价格从68元/月至203元/月不等。其中,经济型e和通用算力型u1实例为主推产品。2核4G配置理论上支持约20人同时在线访问,实际并发数受应用架构、带宽、用户行为等多种因素影响。详情参见阿里云官方页面。
|
应用服务中间件 Linux nginx
在Linux中,如何统计ip访问情况?分析 nginx 访问日志?如何找出访问页面数量在前十位的ip?
在Linux中,如何统计ip访问情况?分析 nginx 访问日志?如何找出访问页面数量在前十位的ip?
|
搜索推荐 程序员 开发工具
Emacs Verilog mode 简单使用指南
【6月更文挑战第17天】Emacs Verilog mode 提升Verilog编程体验,提供语法高亮、代码补全、自动缩进等功能。安装可通过`M-x package-install RET verilog-mode`。常见问题包括补全不生效、高亮不准确,可通过调整配置解决。支持模板插入、代码折叠、错误高亮、代码跳转。通过个性化配置、整合Git、集成其他工具和社区资源,实现高效Verilog开发。Emacs学习曲线虽陡,但效能提升显著。
530 4
|
Android开发 C++
so兼容32位和64位
在Android开发中遇到32位`xxx.so`动态库在64位设备上运行失败的问题,导致应用崩溃。错误提示因缺少64位版本的库。尝试创建`arm64-v8a`目录并复制库文件后,依然崩溃,因为库本身是32位。解决方案是在`build.gradle`中添加配置,指定支持的ABI滤镜,并在`gradle.properties`中设置`android.useDeprecatedNdk=true`,以解决兼容性问题。
547 7
|
前端开发 JavaScript Java
基于springboot+vue的医院预约系统(前后端分离)
本系统采用springboot+vue整合开发,前端主要使用了Vue框架、Element UI和AJAX技术。项目后端主要使用了springboot等一系列框架和MyBatis以及Maven。这一套技术易于学习、操作和管理。数据库方面则是使用了MySQL数据库以及Navicat数据库管理工具,轻量,易于管理。
基于springboot+vue的医院预约系统(前后端分离)

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版