多线程数据生成器

时间:2014-09-12 20:04:28

标签: python linux multithreading

我有一个小的python脚本用于为文件生成大量数据,生成6GB数据大约需要6分钟,但是,我的目标数据大小可达1TB,对于线性计算,大约需要1000分钟生成1TB数据,我认为这对我来说是不可接受的。

所以我想知道多线程会帮助我缩短时间吗?为什么会这样?如果没有,我还有其他选择吗?

谢谢!

3 个答案:

答案 0 :(得分:2)

Currently, typical hard drives可以写入每秒100 MB的顺序。

您的程序在6分钟内写入6 GB,这意味着整体吞吐量约为17 MB / s。

因此,您的程序不会将数据推送到接近最大速率的任何位置(假设您有一个典型的硬盘驱动器)。

所以你的问题实际上可能是CPU限制的。

如果这是"背后的信息"计算是正确的,如果您有一台具有多个处理器的计算机,使用多个进程可以帮助您更快地生成更多数据,然后可以将其发送到将数据写入磁盘的单个进程。


请注意,如果您使用的是最常见的Python实现CPython,那么GIL(全局解释器锁定)会阻止多个线程同时运行。因此,要进行并发计算,您需要使用多个进程而不是多个线程。 multiprocessingconcurrent.futures模块可以为您提供帮助。


请注意,如果您的硬盘驱动器可以写入100 MB / s,那么将1TB写入磁盘仍需要大约160分钟,如果您的多个进程以大于100 MB / s的速率生成数据,那么额外的过程不会导致任何速度增加。

当然,您的硬件可能比这更快或更慢,因此了解您的硬件规格是值得的。

您可以通过简单的实验来估算使用Python写入磁盘的速度:

with open('/tmp/test', 'wb') as f:
    x = 'A'*10**8
    f.write(x)

% time python script.py

real    0m0.048s
user    0m0.020s
sys 0m0.020s

% ls -l /tmp/test
-rw-rw-r-- 1 unutbu unutbu 100000000 2014-09-12 17:13 /tmp/test

这表示100 MB是用0.511写的。因此有效吞吐量约为195 MB / s。

请注意,如果您在循环中调用f.write

with open('/tmp/test', 'wb') as f:
    for i in range(10**7):
        f.write('A')

然后有效吞吐量急剧下降到~3MB / s。所以你如何构建你的程序 - 即使只使用一个过程 - 也可以产生很大的不同。这是collecting your data into fewer but bigger writes如何提高效果的示例。


正如Max Noel和kipodi已经指出的那样,你也可以尝试写入/ dev / null:

with open(os.devnull, 'wb') as f:

计算当前脚本的缩短版本。这将显示CPU计算消耗的时间(主要是)。它可以通过使用并发进程来改善整个运行时的这一部分。如果它很大,那么希望多处理可以提高性能。

答案 1 :(得分:1)

多线程很可能无法帮助你。

您的数据生成速度是:

  • IO限制(即受硬盘速度限制),加快速度的唯一方法是获得更快的存储设备。可以帮助您的唯一类型的并行化是找到一种方法将您的写入分散到多个设备上(您可以使用多个硬盘吗?)。

  • 受CPU限制,在这种情况下,Python的GIL意味着您无法在一个进程中利用多个CPU核心。加快程序速度的方法是使它能够运行它的多个实例(多个进程),每个实例都生成数据集的一部分。

无论如何,您需要做的第一件事是分析您的程序。哪些部分很慢?他们为什么慢?您的进程是IO绑定还是CPU绑定?为什么呢?

答案 2 :(得分:1)

6分钟生成6GB意味着您需要一分钟才能生成1 GB。典型的硬盘驱动器在新的时候能够达到80-100 MB / s的吞吐量。这使您的IO限制大约为6 GB /分钟。
所以看起来限制因素是CPU,这是个好消息(运行更多实例可以帮助你)。
但是我不会因为GIL而对Python使用多线程。更好的想法是运行一些脚本在不同的进程中写入不同的偏移量或者编写Python的多处理模块。
我会检查它,但运行它写入/ dev / null以确保你真正受CPU限制。