多线程解析比顺序慢

时间:2016-11-20 15:06:53

标签: python multithreading python-2.7

我正在通过线程解析4个大型XML文件,不知怎的,多线程代码比顺序代码慢?

这是我的多线程代码:

  def parse():
    thread_list = []

    for file_name in cve_file:
        t = CVEParser(file_name)
        t.start()
        thread_list.append(t)

    for t in thread_list:
        t.join()
        result = t.result
        for res in result:
            print res
            PersistenceService.insert_data_from_file(res[0], res[1])
            os.remove(res[0])

那就是"更快"代码:

def parse:
thread_list = []

for file_name in cve_file:
    t = CVEParser(file_name)
    t.start()
    t.join()
    thread_list.append(t)

for t in thread_list:
    result = t.result
    for res in result:
        print res
        PersistenceService.insert_data_from_file(res[0], res[1])
        os.remove(res[0])

顺序代码快10分钟,这怎么可能?

3 个答案:

答案 0 :(得分:1)

Python使用GIL (Global Interpreter Lock)来确保一次只有一个线程执行Python代码。这样做是为了防止数据争用和其他一些原因。但是,这意味着默认CPython中的多线程几乎不会给你任何代码加速(如果它不会减慢速度,就像你的情况一样)。
要有效地并行化您的工作负载,请查看Python的multiprocessing模块,该模块将启动不受彼此GIL影响的单独进程

关于该主题的

Here's a SO question

答案 1 :(得分:0)

你在哪里读到多线程甚至多处理应该总是比顺序更快?这完全是错的。 3种模式中哪一种更快取决于要解决的问题,以及瓶颈所在。

  • 如果算法需要大量内存,或者处理多个parralel操作需要锁定,顺序处理通常是最好的选择
  • 如果瓶颈是IO,Python多线程是可行的方法:即使一次只有一个线程可以处于活动状态,其他线程也会在此期间等待完成,您将获得更好的吞吐量 - 甚至如果真正更快的方式是通常在可能的情况下用select轮询io
  • 只有当瓶颈是CPU处理 - 恕我直言不是最常见的用例 - 不同核心的并行化才是胜利者。在Python中,这意味着多处理(*)。这主要涉及繁重的计算

在您的用例中,还有另一个可能的原因:您在连接部分中按顺序等待线程。这意味着如果thread2在thread0之前结束很多,那么你将只在thread0结束后处理它,这是次优的。

这种代码通常更有效,因为只要一个线程完成就允许处理:

active_list = thread_list[:]
while len(active_list) > 0:
    for t in active_list:
        if not t.is_active():
            t.join()
            active_list.remove[t]
            # process t results
            ...
    time.sleep(0.1)

(*)一些专门用于重型或并行计算的库可以允许Python线程同时运行。一个众所周知的例子是numpy:使用numpy并在多个线程中执行的复杂操作实际上可以在不同的核上同时运行。技术上这意味着发布 Global Interpreter Lock

答案 2 :(得分:0)

如果您正在从旋转的磁盘读取这些文件,那么尝试一次读取4会真的减慢这个过程。

磁盘一次只能真正读取一个,并且必须在它们之间来回移动读/写头很多次才能为不同的读取线程提供服务。这比实际读取数据要花费更长的时间,您将不得不等待它。

另一方面,如果您正在使用SSD,那么您将不会遇到此问题。您可能仍然受到I / O速度的限制,但是4线程的情况应该花费与单线程情况相同的时间。