VLDn and VSTn (single n-element structure to one lane)
Vector Load single n-element structure to one lane. It loads one n-element structure from memory into one or more NEON registers. Elements of the register that are not loaded are unaltered.
Vector Store single n-element structure to one lane. It stores one n-element structure into memory from one or more NEON registers.
date: 2020-05-20 top: true
Facebook的ZSTD压缩库从1.0版本发布的那天起,就引起了业界的关注,对比业界常用的压缩库lz4、zilib、xz,ZSTD更注重速度和压缩比的均衡,对比zlib来看,更是在保证压缩比的情况下,较zlib压缩性能提升6倍左右,解压性能提升2倍左右。
我们团队也在2020年年初时,对ZSTD压缩库进行了性能优化,最终优化已推入到Facebook的上游社区中,本文将详细的介绍我们进行的优化。
1. 利用neon指令集对数据复制优化。
完整的Patch链接:facebook/zstd#2041
优化思路:
aarch64提供了一系列的neon指令,本次优化则利用了VLD和VST指令,借助neon寄存器进行读写加速,ARM的官方文档是这样描述这两个指令的:
来自ARM的官方文档Coding for Neon - Part 1: Load and Stores中,写的非常详细,引用一张图来描述neon寄存器和memory加载和存储的方式,核心思想就是:利用neon寄存器作为暂存的中转站,加速数据处理:
我们以u8的复制为例,总结下本次我们在ZSTD具体的优化实现:
核心步骤包含两步:
这样便利用neon完成了对u8的memcpy的优化,对于此类优化,有兴趣的可以阅读What is the fastest way to copy memory on a Cortex-A8?,了解在Cortext-A8的架构下,如何快速的进行memory copy。
性能测试:
完成neon优化后,我们对压缩和解压缩都进行了测试,最终,在压缩场景获得了大概1+%的提升:
2. 使用prefetch机制加速数据读取。
完整的Patch链接:facebook/zstd#2040
优化思路:
Prefetch的中文是预取,原理是通过将数据预取到cache中,加速数据的访问。一个比较常见的场景就是在循环中,我们可以通过显示的调用,充分的预取未来将会访问的数据或指令便能快速从Cache中加载到处理器内部进行运算或者执行。
在Jeff Dean的一次经典的talk--Software Engineering Advice from Building Large-Scale Distributed Systems中,提到了cache和memory的速度差异,大致如下图所示:
可以看到,从cache中拿数据,将比直接从memory拿数据性能提升几十甚至上百倍,因此,我们也在本次的优化中,为aarch64加入的预取指令。
同时,将预取加速加入到了ZSTD_compressBlock_fast_generic和ZSTD_compressBlock_doubleFast_generic的主循环中,在数据访问前,预先先将数据加载到cache中,从而加速后续访问对数据读取。
性能测试:
我们仅对压缩进行了优化,因此,也仅对压缩进行了测试,测试结果可以看出,速度在aarch64架构下获得了1.5-3+%的提升:
3. 总结
在Facebook的ZSTD中,我们使用了neon指令集对memcpy的过程进行了加速,同时,也利用了prefetch机制,加速了循环时数据的访问。
希望本篇文章,能够对大家带来一些性能优化的启发。