是否可以并行化 bz2 的解压?

Is it possible to parallelize bz2's decompression?

我正在使用 pythons bz2 模块生成(并压缩)一个大的 jsonl 文件(bzip2 压缩后 17GB)。

不过后来我用pbzip2解压的时候好像只用了one CPU-core解压,速度很慢

当我用 pbzip2 压缩它时,它可以在解压缩时利用多个内核。有没有办法以 pbzip2 兼容格式在 python 内进行压缩?

import bz2,sys
from Queue import Empty
#...
compressor = bz2.BZ2Compressor(9)
f = open(path, 'a')

    try:
        while 1:
            m = queue.get(True, 1*60)
            f.write(compressor.compress(m+"\n"))
    except Empty, e:
        pass
    except Exception as e:
        traceback.print_exc()
    finally:
        sys.stderr.write("flushing")
        f.write(compressor.flush())
        f.close()

一个pbzip2流只不过是多个bzip2流的串联。

使用 shell 的示例:

bzip2 < /usr/share/dict/words > words_x_1.bz2
cat words_x_1.bz2{,,,,,,,,,} > words_x_10.bz2
time bzip2 -d < words_x_10.bz2 > /dev/null
time pbzip2 -d < words_x_10.bz2 > /dev/null

我从来没有使用过python的bz2模块,但是在'a'ppend模式下close/reopen一个流应该很容易,每隔这么多字节,以获得相同的结果。请注意,如果 BZ2File 是从现有的类似文件的对象构造的,则关闭 BZ2File 不会关闭基础流(这就是您在这里想要的)。

我没有测量多少字节最适合分块,但我猜每 1-20 兆字节 - 它肯定需要大于 bzip2 块大小 (900k)。

另请注意,如果记录每个块的压缩和未压缩偏移量,则可以进行相当高效的随机访问。这就是 dictzip 程序的工作方式,尽管它基于 gzip.

如果你绝对必须在解压时使用pbzip2这对你没有帮助,但替代lbzip2可以执行"normal" .bz2文件的多核解压,例如与 Python 的 BZ2File 或传统的 bzip2 命令生成的一样。这避免了您描述的 pbzip2 的限制,如果文件也使用 pbzip2 压缩,它只能实现并行解压缩。参见 https://lbzip2.org/

作为奖励,基准测试表明 lbzip2 在解压缩(30%)和压缩(40%)方面比 pbzip2 快得多,同时实现了略微优越的压缩率。此外,它的 RAM 使用峰值不到 pbzip2 使用的 RAM 的 50%。参见 https://vbtechsupport.com/1614/