2010-06-10 105 views
5

我不得不做大量的I/O绑定操作,即解析大文件并将其从一种格式转换为其他格式。最初我曾经连续做过,即一个接一个地解析。性能非常差(使用时间超过90秒)。所以我决定使用线程来提高性能。我为每个文件创建了一个线程。 (4条)python线程和性能?

for file in file_list: 
      t=threading.Thread(target = self.convertfile,args = file) 
      t.start() 
      ts.append(t) 
for t in ts: 
      t.join() 

但是令我惊讶的是,没有任何性能改善。现在也需要大约90多秒才能完成任务。由于这是I/O界限操作,我曾预计会提高性能。

回答

10

在通常的Python解释器下,由于global interpreter lock(又名GIL),线程将不会为您的程序分配更多CPU内核。

multiprocessing模块可以帮助你在这里。 (请注意,它是在Python 2.6中引入的,但Python 2.5中存在backports。)

正如MSalters所说,如果您的程序是I/O绑定,这是否值得商榷是值得商榷的。但它可能是值得一试:)

达到你想要使用的是什么这个模块:

import multiprocessing 

MAX_PARALLEL_TASKS = 8 # I have an Intel Core i7 :) 

pool = multiprocessing.Pool(MAX_PARALLEL_TASKS) 

pool.map_async(convertfile, filelist) 

pool.close() 
pool.join() 

重要!您传递给map_async的功能必须是可以删除的。一般情况下,实例方法是不可pickleable,除非你设计它们是如此!请注意,convertfile以上是一项功能。

如果您确实需要从convertfile获得结果,那么也有办法做到这一点。多处理文档页面上的例子应该澄清。

+0

感谢delty..But多处理模块有它自己的问题。 1)我不得不重构我的代码,因为我不能使用实例方法.. 2)我有一个实例方法,它有很多文件处理程序..这些文件处理程序在子进程中被关闭是不可接受的。所以我需要再次打开它们。不幸的是,我没有办法知道它们,因为它们是在实例化过程中传递的。 – kumar 2010-06-10 08:43:23

+0

它不一定是在单独的进程中执行的转换函数本身。有什么办法可以在单独的进程中执行实例化部分?例如。编写一个函数,甚至是一个单独的脚本来完成单个实例化和转换;然后编写一个使用多处理模块的“主脚本”来运行这些功能。单独的脚本可以使用[subprocess](http://docs.python.org/library/subprocess.html)模块运行。如果有很多共享数据,那么是的,这就是多处理复杂化的地方。但是该模块中有更多的工具:) – detly 2010-06-10 08:54:29

2

线程允许操作系统为您的程序分配更多的CPU核心。如果它是I/O限制的,这意味着速度受I/O系统速度而不是CPU速度的限制。在这些情况下,分配更多CPU内核并不一定有帮助 - 您仍在等待I/O子系统。

+0

但我相信线程切换发生在一个线程正在等待I/O subsyetm时,不是吗?所以我现在正在做的事情,这意味着我可以期待一些性能改进? – kumar 2010-06-10 07:48:24

+5

Python中的线程不会为程序分配更多的CPU内核。 – detly 2010-06-10 07:48:35

+0

@kumar:正如响应所述,如果您受I/O限制 - 您的I/O将尽其所能 - 更多的CPU时间或并行处理不会使I/O更早完成。 – Josh 2010-06-11 01:00:42