如何使用多线程进行zlib压缩
How to use multiple threads for zlib compression
我有大量数据(大约 2 GB)需要使用 zlib (deflate()) 进行压缩。我目前正在一次读取 500 kb 的数据,将其压缩并写入我的输出文件。
1个线程,一切正常。数据已压缩,我可以将其写入并解压缩。
有 2 个线程时,进程在调用 deflate() 时挂起。
这是我的 2 个 zlib comp 线程调用的函数的概要。
static z_stream z_str;
zlib_compress(...., bool last, bool first)
{
if (first)
deflateInit(&z_str, Z_DEFAULT_COMPRESSION);
if (last)
flush = Z_FINISH;
else
flush = Z_SYNC_FLUSH;
....
....
status = deflate(&z_str, flush);
...
...
if (last)
deflateEnd(&z_str);
}
据我所知,这两个调用在调用 deflate() 时指的是同一个 zstream,这会导致意外行为。
我尝试将z_str作为局部变量,并相应地修改了代码。但是在解压缩时,假设文件的总大小为 512,这实际上只是第一个数据块。
知道如何实现吗?
As I understand, both the calls are referring to the same zstream
while calling deflate(), which is resulting in undesired behaviour.
你预计会发生什么?
每个线程都需要自己的 z_stream
结构才能使用。两个线程同时访问同一个 z_stream
是没有意义的。
可以让多个线程同时压缩数据,只要每个线程都有自己独立的 z_stream 对象即可。每个 z_stream 对象都应该调用 deflateInit(),然后根据需要多次调用 deflate(),然后在所有未压缩数据都传递给 deflate() 之后调用 deflateEnd()。使用这种技术,例如一次压缩两个不同的文件。
不过我怀疑你想做的是加速单个大文件的压缩,不是吗?在那种情况下,您会发现这是不可能的,至少不是以显而易见的方式。不可能的原因是,放气流的后面的字节取决于该流的前面的字节的含义——这意味着它们只有在所有前面的字节都生成之后才能生成,这就排除了生成压缩文件的后半部分与前半部分并行。
您可以做的是生成两个单独的压缩文件;一个是未压缩文件前半部分的压缩内容,另一个是未压缩文件后半部分的压缩内容。这可以并行完成,因为两个压缩流将完全相互独立。请注意,您随后需要编写自己的例程来解压缩这两个文件并将结果再次连接回一个未压缩的文件,因为标准 compression/decompression 实用程序不会意识到这种分而治之的技巧。
正如 zlib 的原作者 (Adler) 所指出的,并行压缩大块数据是可能的,如 pigz 中的示例。本质上,您需要提供 32K 的未压缩数据来处理特定块。
==Chunk 1===
-32K-====Chunk 2=======
--32K--====Chunk 3====
然后就可以合并压缩后的数据了
我有大量数据(大约 2 GB)需要使用 zlib (deflate()) 进行压缩。我目前正在一次读取 500 kb 的数据,将其压缩并写入我的输出文件。
1个线程,一切正常。数据已压缩,我可以将其写入并解压缩。
有 2 个线程时,进程在调用 deflate() 时挂起。
这是我的 2 个 zlib comp 线程调用的函数的概要。
static z_stream z_str;
zlib_compress(...., bool last, bool first)
{
if (first)
deflateInit(&z_str, Z_DEFAULT_COMPRESSION);
if (last)
flush = Z_FINISH;
else
flush = Z_SYNC_FLUSH;
....
....
status = deflate(&z_str, flush);
...
...
if (last)
deflateEnd(&z_str);
}
据我所知,这两个调用在调用 deflate() 时指的是同一个 zstream,这会导致意外行为。
我尝试将z_str作为局部变量,并相应地修改了代码。但是在解压缩时,假设文件的总大小为 512,这实际上只是第一个数据块。
知道如何实现吗?
As I understand, both the calls are referring to the same zstream while calling deflate(), which is resulting in undesired behaviour.
你预计会发生什么?
每个线程都需要自己的 z_stream
结构才能使用。两个线程同时访问同一个 z_stream
是没有意义的。
可以让多个线程同时压缩数据,只要每个线程都有自己独立的 z_stream 对象即可。每个 z_stream 对象都应该调用 deflateInit(),然后根据需要多次调用 deflate(),然后在所有未压缩数据都传递给 deflate() 之后调用 deflateEnd()。使用这种技术,例如一次压缩两个不同的文件。
不过我怀疑你想做的是加速单个大文件的压缩,不是吗?在那种情况下,您会发现这是不可能的,至少不是以显而易见的方式。不可能的原因是,放气流的后面的字节取决于该流的前面的字节的含义——这意味着它们只有在所有前面的字节都生成之后才能生成,这就排除了生成压缩文件的后半部分与前半部分并行。
您可以做的是生成两个单独的压缩文件;一个是未压缩文件前半部分的压缩内容,另一个是未压缩文件后半部分的压缩内容。这可以并行完成,因为两个压缩流将完全相互独立。请注意,您随后需要编写自己的例程来解压缩这两个文件并将结果再次连接回一个未压缩的文件,因为标准 compression/decompression 实用程序不会意识到这种分而治之的技巧。
正如 zlib 的原作者 (Adler) 所指出的,并行压缩大块数据是可能的,如 pigz 中的示例。本质上,您需要提供 32K 的未压缩数据来处理特定块。
==Chunk 1===
-32K-====Chunk 2=======
--32K--====Chunk 3====
然后就可以合并压缩后的数据了