C++/C 多个线程同时读取 gz 文件
C++/C Multiple threads to read gz file simultaneously
我正在尝试从多个线程读取gzip压缩文件。
我认为这将显着加快解压缩过程,因为我在多个线程中的gzread
函数从不同的文件偏移量(使用 gseek
(开始,因此它们读取文件的不同部分。
简化的代码就像
// in threads
auto gf = gzopen("file.gz",xxx);
gzseek(gf,offset);
gzread(xx);
gzclose(gf);
令我惊讶的是,我的多线程版本程序根本没有加速。20 线程版本使用的时间与单线程版本完全相同。我很确定这与磁盘瓶颈相去甚远。
我想 zlib 膨胀功能可能需要解压缩整个文件才能读取一小部分,但我未能从他们的手册中获得任何线索。
有人知道如何在我的情况下加快速度吗?
简短回答:由于放气流的串行性质,gzseek()
必须解码从启动到请求的寻道点的所有压缩数据。因此,您无法通过尝试做的事情获得任何收益。事实上,花费的总周期会随着压缩数据长度的平方而增加!所以不要那样做。
dr:zlib 不是为随机访问而设计的。似乎可以实现,但需要完整的通读才能构建索引,因此在您的情况下可能没有帮助。
Gzseek是gzseek64的包装器,其中包含:
/* if within raw area while reading, just go there */
if (state->mode == GZ_READ && state->how == COPY &&
state->x.pos + offset >= 0) {
如果我们正在处理一个压缩文件,"在原始区域内"听起来不太正确。让我们在gzguts.h中查找state->how
的含义:
int how; /* 0: get header, 1: copy, 2: decompress */
右。在gz_open
结束时,对gz_reset
的调用将how
设置为 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 确实会解压缩整个文件。
zlib 实现没有多线程(http://www.zlib.net/zlib_faq.html#faq21 - "zlib 线程安全吗?-是的。...当然,你一次只能对来自单个线程的任何给定 zlib 或 gzip 流进行操作。并将"整个文件"解压缩到搜索位置。
并且 zlib 格式具有错误的对齐(位对齐(/没有偏移场(放气格式(以实现并行解压缩/查找。
你可以尝试z(deflate/inflate(的另一个实现,例如 http://zlib.net/pigz/(或者从单核时代的古代压缩切换到非zlib现代并行格式,xz/lzma/谷歌的东西(
Pigz代表gzip的并行实现,是gzip的全功能替代品,在压缩数据时利用多个处理器和多个内核。 Pigz 由 Mark Adler 编写,使用 zlib 和 pthread 库。要编译和使用 pigz,请阅读源代码分发中的自述文件。您可以在此处阅读pigz手册页面。
手册页 http://zlib.net/pigz/pigz.pdf,其中包含有用的信息。
它使用与 zlib 兼容的格式,但采用并行压缩:
每个部分原始放气流都由一个空的存储块终止......为了在字节边界处结束该部分位流。
尽管如此,DEFLATE 格式对并行解压缩不利:
解压缩不能并行化,至少如果没有为此目的专门准备的放气流。Asaresult,pigz 使用单个线程(主线程(进行解压,但会创建另外三个线程用于读取、写入和检查计算,这在某些情况下可以加快解压缩速度。
- 理解boost::asio-async_read在无需读取内容时的行为
- 使用新行和不使用新行读取文件
- 读取文件并输入到矢量中
- 用c++从输入文件中读取另一行
- 读取文件的最后一行并输入到链接列表时出错
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 无法找到/读取配置文件.conf-FileIOException
- 如何使用Luacneneneba API正确读取字符串和表参数
- C++将文本文件中的数据读取到结构数组中
- 正在将csv文件读取为双精度矢量
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 为什么在读取文件大小时文件IO速度会发生变化
- 正在读取二进制文件(is_open)
- 如何在c++中从文本文件中逐行读取整数
- SSH通过/sbin/SSH无法读取RSA密钥文件(从控制台运行)
- 独立读取-修改-写入顺序
- 使用gzbuffer快速读取GZ的文件,然后按行划分内容
- 使用 boost::iostreams 和 zlib 读取.gz文件的运行时错误
- 在c++中读取压缩的gz文件(重文件)的有效方法
- C++/C 多个线程同时读取 gz 文件