C ++ / C多个线程同时读取gz文件

时间:2016-06-24 13:36:22

标签: c++ multithreading zlib compression deflate

我试图从多个线程读取一个gzip压缩文件。

我认为这会显着加快解压缩过程,因为多个线程中的gzread函数从不同的文件偏移量开始(使用gseek),因此它们会读取文件的不同部分。

简化代码就像

// in threads
auto gf = gzopen("file.gz",xxx);
gzseek(gf,offset);
gzread(xx);
gzclose(gf);

令我惊讶的是,我的多线程版程序确实加速。 20线程版本使用与单线程版本完全相同的时间。我很确定这远离磁盘瓶颈。

我猜zlib充气功能可能需要解压缩整个文件以便读取一小部分,但我没有从他们的手册中获得任何线索。

任何人都知道如何加快我的速度?

3 个答案:

答案 0 :(得分:4)

简短回答:由于deflate流的串行特性,gzseek()必须解码从启动到请求的搜索点的所有压缩数据。所以你不能通过你想做的事情获得任何好处。实际上,花费的总周期将随着压缩数据长度的平方而增加!所以不要这样做。

答案 1 :(得分:1)

zlib实现没有多线程(http://www.zlib.net/zlib_faq.html#faq21 - “zlib线程安全吗? - 是的.......当然,你应该一次只能从一个线程对任何给定的zlib或gzip流进行操作。 “)并将”整个文件“解压缩到寻找位置。

并且zlib格式具有错误的对齐(位对齐)/无偏移字段(deflate format)以启用并行解压缩/搜索。

您可以尝试z(deflate / inflate)的另一种实现,例如,http://zlib.net/pigz/(或者从单核到非zlib现代并行格式的古代压缩切换,xz / lzma /来自谷歌)

  

pigz,代表gzip的并行实现,是gzip的全功能替代品,在压缩数据时利用多个处理器和多个核心。 pigz由Mark Adler编写,使用zlib和pthread库。要编译和使用pigz,请阅读源代码分发中的README文件。您可以阅读pigz manual page here.

手册页为http://zlib.net/pigz/pigz.pdf,并提供了有用的信息。

它使用与zlib兼容的格式,但采用并行压缩:

  

每个部分原始deflate流都由一个空的存储块终止...以便在字节边界处结束该部分比特流。

但是,DEFLATE格式对并行解压缩不利:

  

无法并行化解压缩,至少在没有为此目的专门准备的收缩流的情况下。 Asaresult,pigz使用单个线程(主线程)进行解压缩,但会创建三个其他线程用于读取,写入和检查计算,这可以在某些情况下加速解压缩。

答案 2 :(得分:1)

tl; dr:zlib不是为随机访问而设计的。 It seems possible to implement虽然需要完整的阅读来构建索引,但在您的情况下可能没有帮助。

让我们看一下zlib sourcegzseekgzseek64的包装,其中包含:

/* if within raw area while reading, just go there */
if (state->mode == GZ_READ && state->how == COPY &&
        state->x.pos + offset >= 0) {

如果我们正在处理一个gzip压缩文件,“在原始区域内”听起来不太对劲。让我们在gzguts.h中查找state->how的含义:

int how; /* 0: get header, 1: copy, 2: decompress */

右。在gz_open结束时,调用gz_resethow设置为0.返回gzseek64,我们最终会对州进行此修改:

state->seek = 1;
state->skip = offset;

gzread,在调用时,通过调用gz_skip处理此问题:

if (state->seek) {
    state->seek = 0;
    if (gz_skip(state, state->skip) == -1)
        return -1;
}

再过一次这个兔子洞,我们发现gz_skip调用gz_fetch,直到gz_fetch处理了足够的输入以进行所需的搜寻。 gz_fetch在其第一次循环迭代时调用gz_look设置state->how = GZIP,这会导致gz_fetch解压缩来自输入的数据。换句话说,您的怀疑是正确的:当您使用gzseek时,zlib会将整个文件解压缩到该点。