写点什么

【ELT.ZIP】OpenHarmony 啃论文成长计划——多维探秘通用无损压缩

作者:ELT.ZIP
  • 2022 年 3 月 11 日
  • 本文字数:21032 字

    阅读完需:约 69 分钟

【ELT.ZIP】OpenHarmony啃论文成长计划——多维探秘通用无损压缩
  • 本文出自 ELT.ZIP 团队,ELT<=>Elite(精英),.ZIP 为压缩格式,ELT.ZIP 即压缩精英。

  • 成员:

  • 上海工程技术大学大二在校生

  • 合肥师范学院大二在校生

  • 清华大学大二在校生

  • 成都信息工程大学大一在校生

  • 我们是来自 4 个地方的同学,我们在OpenHarmony成长计划啃论文俱乐部里,通过啃论文方式学习操作系统技术...


@[toc]

引言

压缩的标准方法是定义产生不同类型数据源的类别,假设数据是由某一类源产生的,并应用为其特殊设计的压缩算法,若可以在近似为输出的数据上良好运行,便可被称为通用压缩算法

熵编码器

  • 熵编码器(entropy coder)是一种根据字符出现的概率为字母表中的每个字符分配编码的方法。更有可能出现的字符被分配的编码比不太可能出现的更短,这种方式可以使压缩序列的预期长度最小。目前流行的熵编码器是 Huffman 编码器算术编码器,这两种方法都做到了相对最优,所以不能分配比预期长度更小的压缩序列编码。其中,Huffman 在分配整数长度编码的方法类中是最优的,算术编码则不受这种限制,因此,它通常可产生更短的期望编码长度。

  • 图 1:序列 abracadabra 的 Huffman 树 



图 2:算术编码过程 

BWT 算法

  • 块排序压缩算法(block-sorting compression algorithm),通常被称为 Burrows-Wheeler 变换算法*(Burrows–Wheeler compression algorithm)***,是一个被应用在数据压缩技术(如 bzip2)中的算法,于 1994 年被 Michael Burrows 和 David Wheeler 在位于加利福尼亚州帕洛阿尔托的 DEC 系统研究中心发明。

  • 原理思想:


  1. 构造矩阵,其行存储压缩序列的所有单字符循环移位

  2. 按字典顺序对行进行排序

  3. 使用矩阵最后一列进行后续处理


BWT 算法与以往的压缩算法有所不同,比较著名的压缩算法如Lempel-Ziv(LZ77,LZ78)、PPM、DMC针对的是通用的数据流模型,比如无记忆源(Memoryless sources),马尔可夫源(Markov sources),有限阶 FSM 源(finite-order FSM sources),一次读取一个或多个字节,而BWT可以处理成块的数据。BWT 算法的核心思想是对一个字符串中的字符进行位置变换,使相同的字符相邻的概率增大。上述过程被称为 Burrows-Wheeler 变换*(BWT)*。随后,变换的输出由一个前移变换处理,最后阶段,由熵编码器压缩,可以是Huffman编码算术编码。结果是,获得了一个序列,其中出现在相似上下文中的所有字符被分组。字符串经过 BWT 算法转换后并没有被压缩,而是因其极有规律性的字母内聚的特点使其他文本压缩算法大大简化,提高压缩速率和压缩比。


基于 BWT 算法的重要特点是运行速度快、压缩比合理,比 LZ 算法好得多,只比现有最佳部分匹配*(PPM, prediction by partial matching)*算法稍差;是 Ziv-Lempel 快速压缩算法和 PPM 算法的有趣替代品,前者压缩比较差,后者压缩比较好,但工作速度较慢


  • 对于一个长度为 n 的序列 x,可以将序列轮转形成一个的矩阵:

  • 然后将矩阵以行为单位按照字母表顺序重新排列成矩阵,得到,并用 R(x)记录在新矩阵中原序列 x 所在的行数。取矩阵的最后一列记为即得到 BWT 的最终结果。


下面我们用字符序列 x=“abracadabra”,且为了获得更好的关系类型的序列,我们在 x 前加上哨兵字符“drcraaaabba,R(x) = 1。可以看出通过 BWT 算法,一些字符连续出现的概率增大


BWT 算法的逆过程则比较复杂,但在编程实现上也比较简单。其主要思想是以 x^bwt^为基础,对字符序列进行转移、排序和组合构建 BWT 转换后得到的矩阵 M~(x)。还是以 $drcraaaabba 为例:







按照这样的规律一直操作下去,最终可以得到:



最后一次操作的得到的组合即为 x 对应的矩阵 M~(x),矩阵的第一行去掉最后的“$“就得到原字符序列 x=”abracadabra”。



BWT 就是一个加标记,循环转移,算出数组,输出结果的过程。


① 这里我们输入字符串ababc,并给其加上标记得到ababc$这个标记$要比所有字符都要小。



② 之后我们对处理后的字符串进行循环转移,此时你可以把ababc$当作一个圆,然后让其旋转,使得 F 列(第一列)的字符按照 ASCII 码从小到大排列。




③ 得到的 M 数组最后一列便是输出的 L 列


BWT 编码及解码的 C++实现:


#include <iostream>#include <string>#include <algorithm>#include <string.h>using namespace std;
///编码,生成last数组int getLastArray(char *lastArray,const string &str){ ///子串排序 int len=str.size(); string array[len];
for(int i=0;i<len;i++){ array[i] = str.substr(i); } sort(array,array+len); for(int i=0;i<len;i++){ lastArray[i] = str.at((2*len-array[i].size()-1)%len); } return 0;}
int getCountPreSum(int *preSum,const string &str){ memset(preSum,0,27*sizeof(int)); for(int i=0;i<str.size();i++){ if(str.at(i) == &#039;#&#039;) preSum[0]++; else preSum[str.at(i)-&#039;a&#039;+1]++; }
for(int i=1;i<27;i++) preSum[i] += preSum[i-1]; return 0;}
///解码,使用last数组,恢复原来的文本块int regainTextFromLastArray(char *lastArray,char *reGainStr,int *preSum){ int len=strlen(lastArray); int pos=0; char c; for(int i=len-1;i>=0;){ reGainStr[i] = lastArray[pos]; c = lastArray[pos]; pos = preSum[c-&#039;a&#039;]+count(lastArray,lastArray+pos,c); i--; } return 0;}
int main (){ string str("sdfsfdfdsdfgdfgfgfggfgdgfgd#"); int preSum[27]; int len=str.size();
char *lastArray = new char[len+1]; char *reGainStr = new char[len+1]; lastArray[len]=&#039;&#039;; reGainStr[len]=&#039;&#039;;
getCountPreSum(preSum,str); getLastArray(lastArray,str); regainTextFromLastArray(lastArray,reGainStr,preSum);
cout<<" str: "<<str<<endl; cout<<"lastArray : "<<lastArray<<endl; cout<<"reGainStr : "<<reGainStr<<endl;
delete lastArray; delete reGainStr; return 0;}
复制代码


研究者提出一种基于 Burrows-Wheeler 变换的改进算法,该算法在获得最佳压缩比的同时,其运算速度可以与该类算法中最快的算法媲美。

基于 BWT 的改进算法

一般结构

算法的第一阶段是Burrows-Wheeler变换。BWT 输出序列在第二阶段经历一个加权频率计数变换,第三阶段是零运行长度编码,它减少了 0 次运行的长度。在最后阶段,序列 x^(rle-0)^由二进制算术编码器编码。算术编码是一种行之有效的熵编码方法,其中最重要的部分是概率估计方法。BWT只是对序列x的转换,并不起到压缩的作用,经过 BWT 算法编码后的序列还需要通过其他压缩算法才可以完成整个压缩任务:



图 3:基于 BWT 的改进算法


  • MTF*(Move-To-Front)*是一种数据编码方式,作为一个额外的步骤,用于提高数据压缩技术效果。MTF 主要使用的是数据“空间局部性”,也就是最近出现过的字符很可能在接下来的文本附近再次出现。MTF 的主要思想是:


  1. 首先维护一个序列字符集大小的栈表,其中每个不同的字符在其中占一个位置,位置从 0 开始编号

  2. 扫描需要重新编码的序列数据,对于每个扫描到的字符,使用该字符在栈表中的索引替换,并将该字符提到栈表的栈顶的位置(索引为 0 的位置)

  3. 重复上一步骤,直到序列扫描结束


以经过 BWT 算法得到的 x^bwt^ = drcraaaabba 为例:



最终的得到的 x^mtf^为 34413000401.相比于 BWT 算法,MTF 算法的解码过程更为简单,其实就是上述过程的逆过程



根据上表所示过程即可解码 x^mtf^.


  • RLE-0(Zero run length encoding)叫做零游程编码,不同于一般的 RLE 算法,它只对序列中的 0 进行替换。在这里使用 RLE-0 处理序列是由于经过 BWT 和 MTF 两个过程,一般在序列中会存在大量的连续的零,因此用 RLE-0 对 x^mtf^进行编码会起到一定的压缩效果。


RLE-0 的原理是:


  1. 统计序列中由 0 组成的子序列含 0 的个数

  2. 用 0~a~和 0~b~符号表示数字 m


第 2 步的具体做法是,先将(m+1)转换成二进制数,然后用 0~a~代替 0,0~b~代替 1,最后舍弃最高位:



所以,x^mtf^ = 34413000401 经过 RLE-0 算法得到的序列为 x^rle-0^ = 344130~a~0~a~40~a~1,由于这里的序列 x 过短,所以零游程编码的压缩效果并未很好的体现出来;RLE-0 的解码过程就是根据个数和编码的对应关系序列中的0~a~,0~b~替换成对应个数的0

实际效率

  • 选择测试数据为了比较压缩算法,需要一组文件。通常情况下,有两种选择测试文件的方式:


  1. 使用一个众所周知的数据集

  2. 为测试准备新的数据集


  • 多标准优化通常情况下,现实世界中有许多标准,我们不能优化所有的标准,所以不得不选择一种折衷方案。如果没有详细了解将压缩应用于的具体情况,我们就无法选择最佳的压缩方法。因此,这种情况下便需要讨论多标准优化*(multi criteria optimisation)。1896-1897 年,Pareto 首次对该领域进行了研究,讨论了满足许多排他性标准的问题。1906 年,Pareto 在他的著名著作《Manuale di economia politica, conuna introduzione alla scienca Sociale》中提出了非支配解决方案(non-dominated solutions)*的概念。其在经济学术语中提出这样一种解决方案:作为一种解决方案,没有任何一个人可以更满意而别人一点不满意。目前,称此解决方案为Pareto最优解,即,不是非劣势解的解为劣势解。 


有一些标准 Q~1~,Q~2~...,Q~m~取决于一些变量:(1) Q~i~ = Q~i~(q~1~,q~2~,...,q~r~), 当 i = 1, 2, ... , m 一组变量:(2) q = <q~1~,q~2~,...,q~r~>被称为优化中的一个点。点 q 被称为 Pareto-optimal,如果没有其他点 p 例如(3) ∀1≤i≤m Q~i~(p) ≥ Q~i~(q)多标准优化的目标是找到所有Pareto最优点的集合。Pareto 最优集(方程 3)的公式适用于所有标准 Q~i~最大化的情况。一般情况下,所有或某些标准可以被最小化。压缩质量至少有三个标准:压缩比、压缩速率、解压速率。通过每个输入字符(bpc)的平均输出位数度量压缩比,因此压缩比越小,效果越好

算法比较

检验算法

  • A02 —— 基于 BWT 的算法,反演频率变换作为第二阶段,结果来自 Arnavut 的工作

  • acb —— Buyanovsky 的关联编码器,压缩结果来自于 acb 2.00c 项目的实验

  • B97 —— Bunton 提出的 PPM 算法的最佳版本

  • boa —— 由 Sutton 编写的 boa 0.58b 压缩程序,是 PPM 算法的实现

  • BS99 —— Balkenhol 和 Shtarkov 提出的基于 BWT 的算法

  • BW94 —— 初始 Burrows-Wheeler 算法

  • Bzip —— Seward 编写的 bzip 0.21 压缩程序,实现了与 Fenwick 方法的相同压缩比

  • CTW —— Willems 等提出的上下文树加权方法

  • DM —— 基于 BWT 的改进算法,第二阶段是移动到前端的变换

  • DW —— 基于 BWT 的改进算法,第二阶段是加权频率计数变换

  • F96 —— Fenwick 提出的基于 BWT 的算法,在 Silesia corpus 实验的 bzip 0.21 程序中取得了相同压缩比

  • gzip —— 标准 gzip 程序,是著名的 LZ77 算法的实现

  • LDMC —— 目前最好的动态 Markov 编码算法,最初由 Cormack 和 Horspool 引入,是由 Bunton 改进的 LazyDMC 版本

  • lgha —— 速度优化的 ha 压缩程序,由 Lyapko 提供实现

  • LZMA —— Pavlov 提出的 Ziv-Lempel 算法,结果来自 7-zip 程序的实验

  • LZW —— 标准 UNIX 压缩程序,是 LZW 算法的一个实现

  • MH —— Shkarin 提出的 cPPMII 算法,结果来自 PPMonstr var. H 程序的实验

  • MI4 —— Shkarin 的 cPPMII 算法,结果来自 4 阶 PPMonstr var. I 程序的实验

  • MI64 —— Shkarin 的 cPPMII 算法,结果来自 64 阶 PPMonstr var. I 程序的实验

  • PPMdH —— Shkarin 提出的 PPMII 算法,结果来自 PPMd var. H 程序的实验

  • PPMN —— Smirnov 的 PPMN 算法,结果来自*ppmnb1+*程序的实验

  • rar —— rar 2.90 压缩程序

  • szip —— Schindler 提出的基于 BWT 的算法,结果来自 szip 程序的实验

  • T98 —— Teahan 提出的 PPMD+算法,结果来自*ppmd+*程序的实验

  • ufa —— Pavlov 提出的二进制 PPM 算法,结果来自* ufa 0.04 Beta 1*程序的实验

  • VW98 —— Volf 和 Willems 提出的切换算法

  • WM01 —— 基于 BWT 的最佳算法,无第二阶段,结果来自 Wirth 和 Moffat 的工作

  • ybs —— 基于 BWT 的压缩程序,距离编码器变换作为第二阶段,是 Yoockin 的实现





表 1:以 bpc 为单位的压缩比 



表 2:以 bpc 为单位的标准化压缩比 



表 3:以秒为单位的压缩时间 



表 4:以秒为单位的解压时间 


以上其中几幅表对解压速度和压缩比进行了比较。我们可以看到,PPM 算法的解压速度几乎与其压缩速度相同;LZ 算法解压比压缩快得多;基于 BWT 算法的解压与压缩速度之间有着明显的差异,但低于 LZ 算法;PPMdH 算法仅支配了两种基于 BWT 的算法,但其平均解压缩速度的标准差远远高于这两种算法;DM 算法是 Pareto 最优的,而其在基于 BWT 的算法中取得了最佳压缩比;测试中的 LZMA 算法实现了 LZ 系列中的最佳压缩比,但其压缩速度慢,比最慢的基于 BWT 的算法慢两倍以上,解压速度方面优于所有基于 BWT 的算法及 LZW 算法。



实验结论


  • 从多准则优化的角度对实验结果进行分析,可将这些方法粗略地分为三组:


  1. 包括 PPM、CTW、DMC 算法,达到了最佳压缩比,但速度较慢

  2. 包括 LZ 算法,速度较快,但压缩比较差

  3. 包括基于 BWT 系列算法,比 PPM 运行速度快,比 LZ 有更好的压缩比


在基于 BWT 系列中,最佳压缩比的是本文改进算法——DW,其运行速度与其他 BWT 系列算法相当。对不同大小文件的测试表明,DW 的压缩与解压速度比其他基于 BWT 的大尺寸块算法相对更稳定。

Lempel-Ziv Parsing

概述

Lempel-Ziv 算法由 Abraham LempelJacob Ziv 在《A Universal Algorithm for Sequential Data Compression》最早引入。和 Burrows-Wheeler 算法一样,Lempel-Ziv 的名称也是由其发明者命名。


Lempel-Ziv 算法有两个版本,根据发明日期分别为 1977 年的 LZ77 和 1978 年的 LZ78,其后又衍生出了不少像 deflate,lzx,lzma 这样优秀的变体算法。



这里有一个比较有意思的事情,仔细看,会发现先发明出的 LZ77 算法的变体比 LZ78 多,是因为 LZ77 被人们使用的时间长吗?并不是,这是因为 LZ78 算法在 1984 年被 Sperry 申请了其变体 lzw 算法的专利,并开始起诉相关软件供应商等在没有许可证的情况下使用率 GIF 格式,之后 LZ78 算法的普及逐渐衰减。尽管 LZW 的专利问题已经平息,并出现了很多 LZW 变体,但目前只有在 GIF 压缩中被普遍使用,占据主导地位的仍是 LZ77 算法。


尽管 Lempel-Ziv 算法有很多变体,但它们都有一个共同的思想:<u>如果一些文本不是均匀随机的,也就是说,所有字母出现的可能性不一样,那么已经出现过的子串会比没有看过的子串更可能再次出现。</u>举个例子,在我们日常生活中,我们都有一些日用语,比如“你好”,“你好吗”;那么,“你好”,“你好吗”,“你好吗”中包含字串“你好”,我们便可以把“你好”简化为更短的二进制码,来替换“你好吗”中的“你好”,从而简化编码。

LZ78

LZ78 算法通过构建出现在⽂本中的⼦字符串字典来⼯作。


算法有两种情况:


  1. 若当前字符未出现在字典中,则将该字符编码进字典

  2. 若当前字符出现在字典中,则从当前字符开始与字符做最长匹配,并将匹配到的最长子串后的第一个字符做特殊处理,并编码进字典。


举例:假设我们有字符串 AABABBBABA ,我们使用 LZ78 算法对其进行压缩



① 先从左边最短并从未出现过的短语开始,这里是A,放入字典。



② 接下来考虑剩下的字符串,由于之前已经见过A了,匹配最长字串A,并取最长字串的下一个字符做特殊处理,取AB放入字典



③ 再考虑剩下的字符串,由于之前已经见过A了,继续匹配下一位B,此时最长字串为AB,继续匹配下一位,未匹配到最长字串,取ABB编入词典



④ 考虑剩下的字符串,第一个字符是B,未匹配到最长字串,编入词典



⑤ 同理,匹配剩下的字符,匹配到最长字串AB,连同下一位编入词典



由于序号(index)2 的字串AB中有A,可以用A的序号来替换字串A,编码AB1B。同理,序号(index)3 的字串ABB中有最长字串AB,可以用AB的序号替换ABB中的AB,编码为2B。序号(index)4 的字串B与前面的字串没有匹配,为空集Ø,编码为0B。序号(index)5 的ABA编码为2A



此时,我们就用字典将原来的字串编码成了一个更简单的串,简化了相关变量,此时我们只需要给 A 和 B 赋值即可得到最终编码的二进制串。这里假设A=0B=1



  • LZ78 算法动态构建其字典,只遍历数据一次,这意味着不必在开始编码之前接收整个⽂档。

双标准数据压缩

概述

  • 问题:解决 LZ77 解析的<u>压缩空间大小</u>和<u>解压缩时间</u>的问题。

  • 目标:


  1. 确定一个 LZ77 解析,<u>在给定的时间 T 最小化压缩文件的空间占用</u>

  2. 相应的,交换时间与空间两种角色,<u>在预先给定压缩空间中最小化压缩时间</u>


  • 如何实现目标:


  1. 引入新的 Bicriteria LZ77-Parsing 问题,它以一种原则性的方式形式化了数据压缩器传统上通过启发式方法处理问题

  2. 通过证明和部署加权图的一些特定结构属性,在 O(n log n²) 时间和 O(n) 空间字中有效地解决了这个问题,直到可以忽略的附加常数输入文件的 LZ77 解析

  3. 进行初步实验,表明所制作的新型压缩器对市面上高度工程化的竞争对手 (如 Snappy,LZMA,Bzip2)都具有很强的竞争力。

介绍

压缩思想

随着<u>海量数据集的出现</u>以及<u>随之而来的高性能分布式存储系统的设计</u>,不少大厂纷纷行动,企图制作出一款可以实现<u>有效压缩比</u>和非常<u>高效的解压缩速度</u>的压缩器,例如 Google 的<a herf="BigTable_百度百科 (baidu.com)">BigTable </a>,Facebook 的<a herf="cassandra(开源分布式NoSQL数据库系统)_百度百科 (baidu.com)">Cassandra</a>,Apache 的<a herf="Hadoop_百度百科 (baidu.com)">Hadoop</a>等等,这些无不都重新点燃了科学界对更优秀的无损压缩器的设计的激情。


解决无损压缩器的有效压缩比与实现非常高效的解压缩速度之间的问题,打破性能瓶颈的方法有很多种,但从很多无损压缩器相关的论文中,都有一种思想:"<u><font color="red">compress once,decompress many times</font></u>"。(参考翻译软件及个人理解,翻译为:一次压缩,多次解压缩)。


这种思想又可以被分为两大家族,<font size="2" color="red">①</font><u>基于 Burrows-Wheeler 变换的压缩器</u>和<font size="2" color="red">②</font><u>基于 Lempel-Ziv 解析方案的压缩器</u>。



这两大家族的压缩器在压缩和解压数据时需要的时间都是线性的,并且需要的压缩空间可以用输入的 K 阶经验熵来约束。

对两个问题的思考

一直以来,时间和空间似乎一直是算法中相互对立,但又相互依存的两个因素,经常刷 leetcode 的人一定对此深有感触,当我们解开一道算法题,很多人又会精进自己的算法,试图用“空间换时间”,“时间换空间”,以及尝试平衡两者来降低自己的执行用时和内存消耗,来获得更多的效益。



压缩算法也是如此,要么牺牲有效压缩比,要么牺牲解压缩速度,或者尝试用强大的技巧来平衡两者,一直以来研究这个无损压缩器的人归根到底都是在研究这个问题。由于研究困难,于是引出了两个应用方面具有挑战性的问题:


  • 分布式存储系统问题(时间是主要影响因素):分布式存储系统,将数据分散存储在多台独立的设备上,可以拓展存储空间,Google,阿里等互联网公司,管理超过千万亿字节级别的大数据,它们对性能的要求很高,需要更低的解压缩时间。于是 Snappy,LZ4 等压缩器出现,帮助解决分布式存储系统上对解压缩时间要求更低的情况。

  • 空间是主要影响因素的问题:我们日常用的手机,手表,平板等等,这些设备对空间拓展比较难,需要尽可能在不改变其解压缩速度的情况下降低其压缩比,来让这些难以拓展内存的设备更好地利用内存。


Bicriteria Data Compression(双标准数据压缩),即解决这个问题:



简单描述,两个参数(输入文件 S限定时间 T),解决一个目标(<u>控制解压缩时间这个变量,尽可能的降低其压缩比</u>),再反过来(<u>控制其压缩比,尽可能地降低其解压缩时间</u>)。


想要解决这个问题,我们就要解决<font color="red">两个因素</font>:


  • ① 将该双标准优化将在 S 的压缩版本中进行。解决这个因素,原文采取基于 LZ77 的压缩器类别,因为它们在理论上和实践中占主导地位。使用主流压缩器,可以借鉴前人经验,帮助我们解决更多问题。

  • ② 衡量待优化资源的计算模型对于这个因素,可以从几个常用计算模型中得到启发,这些模型对多级内存层次和连续内存字的获取进行了抽象。

三大贡献:

  • 提出新的图模型在《On the bit-complexity of Lempel-Ziv compression》中,提出了一个特殊的加权 DAG,这个 DAG 由<font size="2" color="red">①</font><u>n=|S| 个 节点(nodes),每个节点代表 S 的一个字符</u>和<font size="2" color="red">②</font><u>m=O(n²) 条边(edges),每条边代表 LZ77 解析 S 后可能出现的短语</u>组成:


具有两个权重(时间权重,空间成本)的新的图模型,<u><font color="red">时间权重</font>即解压缩短语的时间(根据上面提到的分层记忆模型派生)</u>,<u><font color="red">空间成本</font>即用于计算存储与该边关联的 LZ77 短语所需的位数(根据压缩机中采用的整数 编码器导出)</u>


  • 证明并使用加权 DAG 的一些结构特性之后证明了上述的加权 DAG 的一些结构特性,使得我们能够设计一种算法,在 O(n log² n ) 时间和 O(n) 的工作空间内近似地解决我们版本的 WCSPP。

  • 将新的压缩器与其它压缩器对比最后提出了一组初步的实验结果,将我们的压缩器的实现与最先进的基于 LZ77 的算法(Snappy、LZMA、LZ4、gzip)和基于 BWT 的算法(具有有界和无界 的内存占用)进行比较。


首先,它们为本文开始时 提出的两个相关问题提供了实际依据,并为文中新颖的双标准数据压缩问题引入的理论分析。



实验结果表现出文中解析策略通过表现出接近 Snappy 和 LZ4(即已知 最快的)的解压速度,以及接近基于 BWT 和 LZMA 的压缩器(即更简洁的)的压缩率, 在所有高度工程化的竞争对手中占了优势。

连续小波变换

**连续小波变换(CWT)**通常被用于信号分析,即科学研究类。小波变换现在被大量不同的应用领域采纳,有时甚至会取代了傅里叶变换的位置,在许多领域都有这样的转变。例如很多物理学的领域亦经历了这个转变,包括分子动力学,从头计算(ab initio calculations),天文物理学,密度矩阵局部化,地球物理学,光学,湍流,和量子力学。其他经历了这种变化的学科有图像处理,血压,心率和心电图分析,DNA分析,蛋白质分析,气象学,通用信号处理,语言识别,计算机图形学,和多分形分析


小波分析的产生是由于,最初用于处理信息的技术,FT 傅里叶变换,仅可在忽略时频分量的情况下进行,但是相对于实际应用情形,绝大多数信息的时频分量是一个不可忽视的因素,为此对 FT 进行一定程度的优化,得到STFT即短时傅里叶变换。短时距傅立叶变换是傅立叶变换的一种变形用于决定随时间变化的信号局部部分的正弦频率和相位。实际上,计算短时距傅立叶变换(STFT)的过程是将长时间信号分成数个较短的等长信号,然后再分别计算每个较短段的傅立叶转换。通常拿来描绘频域与时域上的变化,为时频分析中其中一个重要的工具。但是在实际应用的过程中我们又遇见了新的问题,人们无法知道信号的确切时频表示,即人们无法获知在何种时间实例中存在何种频谱分量。人们可知晓的是某些频段存在的时间间隔,(其根源可以追溯到海森堡不确定性原理,但在这里我们不做详细论述。)这是一个分辨率问题。

例证:

  • 我们使用的窗口函数只是一个高斯函数,形式为 e^{-a \left( \frac{t^2}{2} \right)}其中 a 确定窗口的长度,t 是时间。下图显示了由 a 的值确定的不同支持区域的四个窗口函数。请忽略 a 的数值,因为计算此函数的时间间隔也决定了函数。只需记下每个窗口的长度即可。上面给出的示例是使用第二个值 a = 0.001 计算得出的。现在,我们将显示上面给出的与其他窗口计算的相同信号的 STFT。


首先,让我们看一下第一个最窄的窗口。我们预计 STFT 具有非常好的时间分辨率,但频率分辨率相对较差:



下图显示了此 STFT。该图从顶部鸟瞰图显示,并带有一个角度,以便更好地解释。请注意,这四个峰值在时间上彼此之间有很好的分离。另请注意,在频域中,每个峰值都覆盖一个频率范围,而不是单个频率值。现在,让我们将窗口变宽,并查看第三个窗口(第二个窗口已在第一个示例中显示)。



请注意,与之前的情况不同,峰值在时间上彼此之间没有很好的分离,但是,在频域中,分辨率会进一步提升,我们进一步增加窗口的宽度。左图就明显的体现出了当窗口过宽时分辨率比较差。



鉴于上述问题 CWT(连续小波变换)应运而生。

STFT 与 CWT 之间的两个主要区别

  1. 不采用窗口信号的傅里叶变换,因此将看到对应于正弦的单个峰值,即不计算负频率。

  2. 当为每个光谱分量计算变换时,窗口的宽度会发生变化,这可能是小波变换最重要的特征。


公式表达:


CWT_x^\psi(\tau,s) = \Psi_x^\psi(\tau,s) = \frac{1}{\sqrt{|s|}} \int x(t) \psi^* \left( \frac{t - \tau}{s} \right) dt


如上面的等式所示,变换后的信号是两个变量的函数,tau 和 s,分别是平移标度参数。\psi(t) 是变换函数,称为母小波,母小波是用于生成其他窗口函数的原型



如图所示,信号由 30 Hz、20 Hz、10 Hz 和 5 Hz 的四个频率分量组成。


请注意,轴是平移和缩放,而不是时间和频率。然而,平移与时间严格相关,因为它指示母小波的位置。母小波的平移可以被认为是自 t = 0 以来经过的时间。


较小的刻度对应于较高的频率,即频率随着刻度的增加而降低,因此,比例约为零的图形部分实际上对应于分析中的最高频率,而具有高尺度的标度对应于最低频率。



信号首先具有 30 Hz(最高频率)分量,这在 0 到 30 的转换时以最低刻度显示。然后是 20 Hz 分量,第二高频率,依此类推。5 Hz 分量出现在平移轴的末端(如预期的那样),并按预期再次以较高的比例(较低频率)显示。


OpenHarmony 内核子系统之 Linux

OpenHarmony 的 Linux 内核基于开源Linux内核LTS 4.19.y / 5.10.y 分支演进,在此基线基础上,回合 CVE 补丁及 OpenHarmony 特性,作为 OpenHarmony Common Kernel 基线。针对不同的芯片,各厂商合入对应的板级驱动补丁,完成对 OpenHarmony 的基线适配。

EROFS 文件系统

EROFS 文件系统代表增强型只读文件系统。与其他只读文件系统不同,它旨在为灵活性、可扩展性而设计,但要保持简单和高性能。EROFS 由华为于 2018 年开源,现已合入 Linux 内核主线,在 4.19 版本发布:


数据压缩

  • EROFS 实现了 LZ4 固定大小算法的输出压缩,与其他现有的固定大小的输入解决方案相比,它从可变大小的输入生成固定大小的压缩数据块。使用固定大小的输出压缩可以获得相对更高的压缩率,因为现在流行的数据压缩算法大多基于 LZ77,这种固定大小的输出方法可以从历史字典中受益。

  • 具体来说,原始数据被转换成几个可变大小的范围,同时被压缩成物理集群。为了记录每个可变大小的范围,引入逻辑簇作为压缩索引的基本单元,以指示是否在范围内生成新的范围。


         |<-    variable-sized extent    ->|<-       VLE         ->|       clusterofs                        clusterofs              clusterofs         |                                 |                       |_________v_________________________________v_______________________v________... |    .         |              |        .     |              |  .   ...____|____._________|______________|________.___ _|______________|__.________    |-> lcluster <-|-> lcluster <-|-> lcluster <-|-> lcluster <-|         (HEAD)        (NONHEAD)       (HEAD)        (NONHEAD)    .          .             CBLKCNT            .                    .           .                               .                  .            .                              .                .      _______._____________________________.______________._________________         ... |              |              |              | ...      _______|______________|______________|______________|_________________             |->      big pcluster       <-|-> pcluster <-|
复制代码


由此可见,操作系统性能的提升能力一定程度上取决于其所采用的文件系统,压缩算法是文件系统设计上尤其重要同时又是不可或缺的一环。按照以上思路,我们得到如下具体实例:


/dev/block/dm-6 on / type erofs (ro,seclabel,relatime,user_xattr,lz4asm)tmpfs on /dev type tmpfs (rw,seclabel,nosuid,relatime,size=3827176k,nr_inodes=956794,mode=755)devpts on /dev/pts type devpts (rw,seclabel,relatime,mode=600,ptmxmode=000)proc on /proc type proc (rw,relatime,gid=3009,hidepid=2)sysfs on /sys type sysfs (rw,seclabel,relatime)selinuxfs on /sys/fs/selinux type selinuxfs (rw,relatime)tmpfs on /mnt type tmpfs (rw,seclabel,nosuid,nodev,noexec,relatime,size=3827176k,nr_inodes=956794,mode=755,gid=1000)tmpfs on /apex type tmpfs (rw,seclabel,nosuid,nodev,noexec,relatime,size=3827176k,nr_inodes=956794,mode=755)/dev/block/dm-5 on /patch_hw type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/sdd66 on /metadata type ext4 (rw,seclabel,nosuid,nodev,noatime,discard,data=ordered)/dev/block/dm-7 on /cust type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /hw_product type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-9 on /odm type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-10 on /preas type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-11 on /preload type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-12 on /vendor type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-13 on /vendor/modem/modem_driver type ext4 (ro,seclabel,relatime,data=ordered)/dev/block/dm-14 on /vendor/preavs type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-15 on /version type erofs (ro,seclabel,relatime,user_xattr,lz4asm)none on /dev/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)none on /dev/cg2_bpf type cgroup2 (rw,nosuid,nodev,noexec,relatime)none on /dev/cpuctl type cgroup (rw,nosuid,nodev,noexec,relatime,cpu)none on /acct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct)none on /dev/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset,noprefix,release_agent=/sbin/cpuset_release_agent)none on /dev/memcg type cgroup (rw,nosuid,nodev,noexec,relatime,memory)none on /dev/stune type cgroup (rw,nosuid,nodev,noexec,relatime,schedtune)debugfs on /sys/kernel/debug type debugfs (rw,seclabel,relatime)none on /config type configfs (rw,nosuid,nodev,noexec,relatime)bpf on /sys/fs/bpf type bpf (rw,nosuid,nodev,noexec,relatime)pstore on /sys/fs/pstore type pstore (rw,seclabel,nosuid,nodev,noexec,relatime)none on /dev/iolimit type cgroup (rw,relatime,iolimit)overlay on /system/lib type overlay (ro,seclabel,relatime,lowerdir=/patch_hw/overlay/system/lib:/system/lib)overlay on /system/lib64 type overlay (ro,seclabel,relatime,lowerdir=/patch_hw/overlay/system/lib64:/system/lib64)none on /mnt/update_engine type tmpfs (rw,seclabel,nosuid,nodev,relatime,size=3827176k,nr_inodes=956794,mode=700)none on /dev/workingset type cgroup (rw,nosuid,nodev,noexec,relatime,workingset)adb on /dev/usb-ffs/adb type functionfs (rw,relatime)hdb on /dev/usb-ffs/hdb type functionfs (rw,relatime)none on /dev/frz type cgroup (rw,relatime,freezer)/dev/block/sdd7 on /sec_storage type ext4 (rw,context=u:object_r:teecd_data_file:s0,nosuid,nodev,noatime,discard,nodelalloc,data=journal)tracefs on /sys/kernel/debug/tracing type tracefs (rw,seclabel,relatime)/dev/block/sdd18 on /splash2 type ext4 (rw,context=u:object_r:splash2_data_file:s0,nosuid,nodev,noatime,data=ordered)/dev/block/sdd72 on /data type f2fs (rw,seclabel,nosuid,nodev,noatime,background_gc=on,discard,no_heap,user_xattr,inline_xattr,acl,inline_data,inline_dentry,extent_cache,mode=adaptive,inline_encrypt,sdp_encrypt,active_logs=6,alloc_mode=default,fsync_mode=posix)/dev/block/sdd23 on /cache type ext4 (rw,seclabel,nosuid,nodev,noatime,data=ordered)overlay on /system/product/priv-app type overlay (ro,seclabel,relatime,lowerdir=/preas/priv-app:/system/product/priv-app)overlay on /system/product/app type overlay (ro,seclabel,relatime,lowerdir=/preas/app:/system/product/app)overlay on /system/product/etc/permissions type overlay (ro,seclabel,relatime,lowerdir=/preas/china/permissions:/system/product/etc/permissions)/dev/block/sdd3 on /mnt/modem/modem_secure type ext4 (rw,context=u:object_r:modem_secure_file:s0,noatime,noauto_da_alloc,data=ordered)/dev/block/sdd51 on /vendor/modem/modem_fw type ext4 (ro,context=u:object_r:modem_fw_file:s0,relatime,data=ordered)/dev/block/sdd10 on /mnt/modem/mnvm2:0 type ext4 (rw,context=u:object_r:modem_nv_file:s0,nosuid,nodev,noatime,noauto_da_alloc,data=ordered)tmpfs on /storage type tmpfs (rw,seclabel,nosuid,nodev,noexec,relatime,size=3827176k,nr_inodes=956794,mode=755,gid=1000)/dev/block/loop2 on /apex/com.android.apex.cts.shim@1 type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop2 on /apex/com.android.apex.cts.shim type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop3 on /apex/com.android.conscrypt@292103000 type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop3 on /apex/com.android.conscrypt type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop4 on /apex/com.android.media@292103016 type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop4 on /apex/com.android.media type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop5 on /apex/com.android.media.swcodec@292103012 type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop5 on /apex/com.android.media.swcodec type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop6 on /apex/com.android.resolv@292103001 type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop6 on /apex/com.android.resolv type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop7 on /apex/com.android.runtime@1 type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop7 on /apex/com.android.runtime type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop8 on /apex/com.android.tzdata@292103002 type ext4 (ro,dirsync,seclabel,nodev,noatime)/dev/block/loop8 on /apex/com.android.tzdata type ext4 (ro,dirsync,seclabel,nodev,noatime)none on /sys/fs/cgroup type tmpfs (rw,seclabel,relatime,size=3827176k,nr_inodes=956794,mode=750,gid=1000)none on /sys/fs/cgroup/pids type cgroup (rw,relatime,pids)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/translation.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/voicekit.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/dm-ondeviceai.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-facecluster-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-facecompare-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-videomulti-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-videosemantic-common-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-txtimagesr-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/compatible-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-screenshotocr-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-headpose-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-segsemantic-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-tableocr-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/asr.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/nlu-full.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/tts.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-labelobjectdetect-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-portraitseg-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/computecapability-common.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-videoanalysis-common-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-faceparsing-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-labeldetect-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-focusocr-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-scene-common-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-multiobjectdetect-cpu-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-sisr-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-facedetect-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-barcode-common-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-carddetect-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-aestheticsfull-cpu-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-docconverter-common-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-facerating-cpu-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-faceattribute-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-facelandmark-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-clothing-orlando-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-docrefine-common-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-8 on /data/app/com.huawei.hiai-N_iI4NIgGtBfIypkf94yJw==/visionplugin-tracking-common-china-release.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-6 on /data/app/com.huawei.systemmanager-d1_lLcBuvKjGe4gAL6voYA==/AiSecurityPlugin.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-6 on /data/app/com.huawei.systemmanager-d1_lLcBuvKjGe4gAL6voYA==/AntimalPlugin.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-6 on /data/app/com.huawei.systemmanager-d1_lLcBuvKjGe4gAL6voYA==/WlanSecurePlugin.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-6 on /data/app/com.huawei.behaviorauth-qn46_LzogY1uYUaAKOhlnA==/HwBehaviorAuth.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-6 on /data/app/com.android.settings-uITFrNjy4jz1Gl0p_aRLBQ==/Resolution.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/dev/block/dm-6 on /data/app/com.android.settings-uITFrNjy4jz1Gl0p_aRLBQ==/SettingsTheme.apk type erofs (ro,seclabel,relatime,user_xattr,lz4asm)/data/media on /mnt/runtime/default/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=1015,multiuser,mask=6,derive_gid,default_normal,reserved=20MB,unshared_obb)/data/media on /storage/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=1015,multiuser,mask=6,derive_gid,default_normal,reserved=20MB,unshared_obb)/data/media on /mnt/runtime/read/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=9997,multiuser,mask=23,derive_gid,default_normal,reserved=20MB,unshared_obb)/data/media on /mnt/runtime/write/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=9997,multiuser,mask=7,derive_gid,default_normal,reserved=20MB,unshared_obb)/data/media on /mnt/runtime/full/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=9997,multiuser,mask=7,derive_gid,default_normal,reserved=20MB,unshared_obb)/data/misc_ce/0/kdfs/storage on /mnt/mdfs/.hmdfs type hmdfs (rw,relatime,sensitive,merge_enable,ra_pages=128,account=10143583112313917499,recv_uid=1023,cache_dir=/data/misc_ce/0/kdfs/cache/16448759908547494974,real_dst=/mnt/mdfs/.hmdfs,offline_stash,dentry_cache)/data/misc_ce/0/kdfs/storage on /mnt/mdfs/account_trust type hmdfs (rw,relatime,sensitive,merge_enable,ra_pages=128,account=10143583112313917499,recv_uid=1023,cache_dir=/data/misc_ce/0/kdfs/cache/16448759908547494974,real_dst=/mnt/mdfs/.hmdfs,offline_stash,dentry_cache)/data/media/0 on /mnt/mdfs/sdcard type hmdfs (rw,relatime,insensitive,merge_disable,ra_pages=128,account=10143583112313917499,recv_uid=1023,cache_dir=/data/misc_ce/0/kdfs/cache/16448759910518911873,real_dst=/mnt/mdfs/sdcard,offline_stash,dentry_cache)/mnt/media_rw on /mnt/mdfs/external_storage type hmdfs (rw,relatime,insensitive,merge_disable,ra_pages=128,account=10143583112313917499,recv_uid=1023,cache_dir=/data/misc_ce/0/kdfs/cache/14998924782874330279,real_dst=/mnt/mdfs/external_storage,no_offline_stash,dentry_cache,external_storage)/data/misc_ce/0/kdfs/storage on /mnt/mdfs/10143583112313917499 type hmdfs (rw,relatime,sensitive,merge_enable,ra_pages=128,account=10143583112313917499,recv_uid=1023,cache_dir=/data/misc_ce/0/kdfs/cache/16448759908547494974,real_dst=/mnt/mdfs/.hmdfs,offline_stash,dentry_cache)/dev/fuse on /mnt/appfuse/10008_2 type fuse (rw,fscontext=u:object_r:app_fusefs:s0,context=u:object_r:app_fuse_file:s0,nosuid,nodev,noexec,noatime,user_id=0,group_id=0,default_permissions,allow_other)mdfs on /mnt/mdfs/groups type fuse (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other)
复制代码


我们对其进行整理,得到如下参考表格:


LZ4 固定大小输出算法

块格式

  • LZ4 是 LZ77 型压缩器,具有固定的、面向字节的编码没有熵编码器后端,也没有成帧层。假设后者由系统的其他部分处理,这种设计有利于简易及速度,有助于以后进行优化、紧凑及增强功能。

压缩块格式

  • LZ4 压缩块由序列组成。序列是一组文字(未压缩的字节),后跟一个匹配副本。每个序列都从一个标记开始。标记是一个字节值,分为两个 4 位字段。因此,每个字段的范围从 0 到 15。第一个字段使用了标记的 4 个高比特位,它提供了要遵循的文字的长度。

  • 如果字段值为 0,则没有文字。如果是 15,那么需要多加一些字节来表示全长,然后每个额外的字节代表一个从 0 到 255 的值,该值被添加到前一个值以产生总长度。当字节值为 255 时,必须读取并添加另一个字节,以此类推。标记后面可以有任意数量的值为“255”的字节,无大小限制:


示例 1:文字长度 48 表示为:  15:4 位高字段的值  33 : (=48-15) 剩余长度达到 48
示例 2:文字长度 280 表示为: 15:4 位高字段的值 255 : 后面的字节最大,因为 280-15 >= 255 10 : (=280 - 15 - 255) ) 剩余长度达到 280
示例 3:文字长度 15 表示为: 15:4 位高字段的值 0 : (=15-15) 必须输出零
复制代码


  • 在标记和可选长度字节之后,是文字本身。它们的数量与之前解码的一样多(字面量长度),字面量可能为零。文字之后是匹配复制操作。它从偏移量开始,是一个 2 字节的值,采用小端格式(第一个字节是“低”字节,第二个是“高”字节),偏移量表示要复制的匹配的位置。例如,1 表示“当前位置 - 1 个字节”。最大偏移值为 6553565536 及以上无法编码。0 是无效的偏移值。这种值的存在表示无效*(损坏)*块。

  • 然后可以提取匹配长度。为此,我们使用第二个标记字段,即低 4 位。显然,这个值的范围是 0 到 15。但是在这里,0 意味着复制操作是最小的匹配的最小长度称为 minmatch,为 4。因此,0 值表示 4 个字节,15 值表示 19+ 个字节。与文字长度类似,在达到可能的最高值 (15) 时,必须读取额外的字节,一次一个,值范围从 0 到 255。它们被添加到总数中以提供最终匹配长度。 255 值意味着还有另一个字节要读取和添加。可以存在的可选“255”字节的数量没有限制。(注意:这指向大约 250 的最大可实现压缩比)。

  • 解码匹配长度到达当前序列的末尾。下一个字节是另一个序列的开始。但在移动到下一个序列之前,这时需要使用解码的匹配位置和长度了。解码器将 matchlength 字节从匹配位置复制到当前位置

  • 在某些情况下,matchlength 可以大于 offset。因此,由于 match_pos + matchlength > current_pos,稍后要复制的字节尚未解码,这称为**“重叠匹配”**,需要特别小心处理。<u>常见的情况是偏移量为 1,这意味着最后一个字节重复 matchlength 次。</u>

区块限制终止

  • 终止 LZ4 块需要特定的限制:


  1. 最后一个序列只包含文字,块在他们之后结束

  2. 输入的最后 5 个字节始终是文字。因此,最后一个序列至少包含 5 个字节

  3. 特别的,如果输入小于 5 个字节,则只有一个序列,它包含整个输入作为文字。空输入可以用零字节表示,解释为没有文字和匹配的最终标记

  4. 最后一个匹配必须在块结束前至少 12 个字节开始,紧随其后的是最后一个序列,它只包含文字

  5. 需要注意,不能压缩 < 13 字节的独立块,因为匹配必须复制“某些东西”,因此至少需要一个前字节

  6. 但是,当一个块可以引用另一个块的数据时,它可以立即以匹配方式而非文字开始,因此可以压缩正好为 12 个字节的块


当某一个块不符合以上这些终止条件时,允许一致的解码器将会视该块为错误从而拒绝;这些条件是为了确保与各种历史解码器之间的兼容性,解码器在面向速度的设计中依赖它们。

参考文献

[1] Deorowicz S . Universal Lossless Data Compression Algorithms[J]. Philosophy Dissertation Thesis, 2003.[2] Burrows M , Wheeler D J . A Block-Sorting Lossless Data Compression Algorithm[J]. technical report digital src research report, 1995.[3] Gao X , Dong M , Miao X , et al. EROFS: a compression-friendly readonly file system for resource-scarce devices. 2019.[4] Ni G . Research on BWT and Classical Compression Algorithms[J]. Computer & Digital Engineering, 2010.[5] Farruggia A , Ferragina P , Frangioni A , et al. Bicriteria data compression[J]. Society for Industrial and Applied Mathematics, 2013.[6] Alakuijala J , Farruggia A , Ferragina P , et al. Brotli: A General-Purpose Data Compressor[J]. ACM Transactions on Information Systems, 2018, 37(1):1-30.[7] Overview - The Hitchhiker's Guide to Compression (go-compression.github.io)[8] Wavelet Tutorial - Part 1[9] Wavlet Tutorial - Part 2[10] Wavelet Tutorial - Part 3

发布于: 刚刚阅读数: 3
用户头像

ELT.ZIP

关注

商务合作可私信 2022.02.19 加入

ELT<=>Elite(精英),.ZIP为压缩格式,ELT.ZIP即压缩精英。

评论

发布
暂无评论
【ELT.ZIP】OpenHarmony啃论文成长计划——多维探秘通用无损压缩_算法_ELT.ZIP_InfoQ写作平台