我有大量的整数数组。每个整数都有几千个整数,每个整数通常与之前的整数相同,或者只有一两个或两个不同。我想将每个阵列缩小尽可能小,以减少我的磁盘IO。
Zlib将其缩小至原始尺寸的约25%。这很好,但我不认为它的算法特别适合这个问题。有没有人知道压缩库或简单算法可能对这类信息有更好的效果?
更新:将zlib转换为xor deltas数组后,将其缩小到原始大小的20%左右。
答案 0 :(得分:7)
如果大多数整数与前一个完全相同,并且符号间的差异通常可以表示为单个位翻转,这听起来像是XOR的工作。
获取输入流,如:
1101
1101
1110
1110
0110
并输出:
1101
0000
0010
0000
1000
一些伪代码
compressed[0] = uncompressed[0]
loop
compressed[i] = uncompressed[i-1] ^ uncompressed[i]
我们现在已将大部分输出减少到0,即使更改了高位也是如此。您使用的任何其他工具中的RLE压缩都会有一个字段日。它在32位整数上工作得更好,它仍然可以编码流中突然出现的完全不同的整数。你已经省去了处理自己打包的麻烦,因为一切都是一个整数。
当您想要解压缩时:
uncompressed[0] = compressed[0]
loop
uncompressed[i] = uncompressed[i-1] ^ compressed[i]
这也有一个优点,就是它可以真正,非常快地运行,因为它只是XOR。
答案 1 :(得分:5)
您考虑过Run-length encoding吗?
或者尝试这样做:不存储数字本身,而是存储数字之间的差异。 1 1 2 2 2 3 5变为1 0 1 0 0 1 2.现在,您必须编码的大多数数字都非常小。要存储一个小整数,请使用8位整数,而不是在大多数平台上编码的32位整数。这就是4的因素。如果你确实需要为更大的间隙做好准备,请指定8位整数的高位来说“这个数字也需要接下来的8位”。
您可以将其与行程编码结合使用,以获得更好的压缩率,具体取决于您的数据。
这些选项都没有特别难以实现,并且它们都运行得非常快且内存非常少(而不是bzip)。
答案 2 :(得分:2)
也许答案是以类似Filtering used to create small PNG images的方式预过滤数组。这是我的头脑中的一些想法。我没有尝试过这些方法,但如果你想玩,他们可能很有趣。
将每个中心分成4个字节,所以我 0 ,i 1 ,i 2 ,..., i n 变为b 0,0 ,b 0,1 ,b 0,2 ,b 0,3 ,b 1,0 ,b 1,1 ,b 1,2 ,b 1, 3 ,...,b n,0 ,b n,1 ,b n,2 ,b N,3 子>。然后写出所有b i,0 s,然后是b i,1 s,b i,2 s和b <子> I,3 子>秒。如果大多数情况下你的数字只有一两个差别,你应该得到很好的长时间重复字节,这应该使用像运行长度编码或zlib这样很好地压缩。这是我最喜欢的方法。
如果每个数组中的整数与之前的整数紧密相关,则可以存储原始整数,然后对着前一个条目存储差异 - 这应该给出一组较小的值来绘制,通常会产生更加压缩的形式。
如果你有各种不同的位,你仍然可能有较大的差异,但如果你更可能有大的数字差异(通常)一两位不同,你可能会更好您创建ahebyte数组的方案 - 使用前4个字节对第一个整数进行编码,然后对于每个后续条目,使用0个或更多个字节来指示应翻转哪些位 - 存储0,1,2,...,或字节中的31,带有标记(比如说32)表示你什么时候完成。这可能导致表示所需的原始字节数和平均值接近2的整数,大多数字节来自有限集(0 - 32)。通过zlib运行该流,也许你会感到惊喜。
答案 3 :(得分:2)
您希望预处理数据 - 首先将其可逆地转换为更适合您的后端数据压缩方法的形式。详细信息将取决于后端压缩方法,以及(更关键的)您希望从压缩数据中获得的属性。
在您的情况下,zlib是一种逐字节压缩方法,但您的数据是(32位?)整数。您不需要自己重新实现zlib,但是您需要了解它是如何工作的,这样您就可以弄清楚如何使用易于压缩的数据来呈现它,或者它是否适合您的目的。
Zlib实现了一种Lempel-Ziv编码形式。 JPG和许多其他人使用霍夫曼编码作为他们的后端。行程编码在许多临时用途中很流行。等等...
答案 4 :(得分:0)
你为此尝试过bzip2吗? http://bzip.org/
对我来说,它总是比zlib更好。
答案 5 :(得分:0)
由于您关心的是减少磁盘IO,因此您需要独立压缩每个整数数组,而不引用其他整数数组。
您的方案的一种常见技术是存储差异,因为可以使用短代码字编码少量差异。听起来你需要为差异提出自己的编码方案,因为它们是多位差异,可能使用像这样的8位字节作为起点:
如果存在不同的4位,则存储整数。
如果你有很多完全不同的代码,这个方案可能不合适,因为它们现在每个需要5个字节,而不是4个。
答案 6 :(得分:0)
“Zlib将它缩小了大约4倍。”意味着100K的文件现在占用负 300K;任何定义都令人印象深刻:-)。我认为你的意思是它缩小了75%,即缩小到原始尺寸的1/4。
优化压缩的一种可能性如下(它假设一个32位整数,最多3位从一个元素变为另一个元素)。
这种压缩的最坏情况是每个整数(2 + 5 + 5 + 5位)的3位变化,这将倾向于原始大小的17/32(压缩率为46.875%)。
我说“趋向于”,因为第一个整数总是32位,但对于任何体面大小的数组,第一个整数都是可以忽略的。
最好的情况是一个相同整数的文件(每个整数没有位变化,只有2个零位) - 这将倾向于原始大小的2/32(压缩率为93.75%)。
如果每个连续整数平均有2位不同(正如你所说的那样),你将得到每个整数2 + 5 + 5位,这将趋向于12/32或62.5%压缩。
你的盈亏平衡点(如果zlib给出75%压缩)是每个整数8位,这将是
这意味着你的平均值必须是每个整数1.2位的变化才能使它变得有价值。
我建议看一下7zip - 这是一个非常自由的许可证,您可以将它与您的代码链接(我认为源代码也可用)。
我注意到(至于我的东西)它在Windows平台上比WinZip更好地执行很多,所以它也可能胜过zlib。