我有一个python脚本,必须对大型数据集进行多次排列,对每个排列进行评分,并且只保留最高得分排列。数据集太大,以至于此脚本需要将近3天才能运行。
当我在Windows中检查我的系统资源时,只有12%的CPU正在使用,而8个内核中只有4个正在工作。即使我将python.exe进程置于最高优先级,这也不会改变。
我的假设是,将更多的CPU使用量用于运行脚本可以使其运行得更快,但我的最终目标是将运行时间减少至少一半。是否有python模块或一些代码可以帮助我这样做?顺便说一句,这听起来像是一个可以从更智能的算法中受益的问题吗?
提前谢谢!
答案 0 :(得分:3)
有几种方法可以解决这个问题,但请查看multiprocessing模块。这是一个标准的库模块,用于创建多个进程,类似于线程,但没有GIL的限制。
您还可以查看优秀的Celery库。这是一个分布式任务队列,具有很多很棒的功能。它安装非常简单,易于上手。
答案 1 :(得分:1)
我可以用一个简单的代码示例回答一个HOW-TO。在运行时,运行/ bin / top并查看您的进程。很简单。注意,我甚至包括如何从键盘中断后清理 - 如果没有,你的子进程将继续运行,你将不得不手动杀死它们。
from multiprocessing import Process
import traceback
import logging
import time
class AllDoneException(Exception):
pass
class Dum(object):
def __init__(self):
self.numProcesses = 10
self.logger = logging.getLogger()
self.logger.setLevel(logging.INFO)
self.logger.addHandler(logging.StreamHandler())
def myRoutineHere(self, processNumber):
print "I'm in process number %d" % (processNumber)
time.sleep(10)
# optional: raise AllDoneException
def myRoutine(self):
plist = []
try:
for pnum in range(0, self.numProcesses):
p = Process(target=self.myRoutineHere, args=(pnum, ))
p.start()
plist.append(p)
while 1:
isAliveList = [p.is_alive() for p in plist]
if not True in isAliveList:
break
time.sleep(1)
except KeyboardInterrupt:
self.logger.warning("Caught keyboard interrupt, exiting.")
except AllDoneException:
self.logger.warning("Caught AllDoneException, Exiting normally.")
except:
self.logger.warning("Caught Exception, exiting: %s" % (traceback.format_exc()))
for p in plist:
p.terminate()
d = Dum()
d.myRoutine()
答案 2 :(得分:0)
您应该生成新进程而不是线程来利用CPU中的核心。我的一般规则是每个核心一个进程。因此,您将问题输入空间拆分为可用的核心数,每个进程都会成为问题空间的一部分。
Multiprocessing最适合这个。您也可以使用Parallel Python。
答案 3 :(得分:0)
聚会很晚 - 但除了使用多处理模块作为reptilicus说,还要确保设置" affinity"。
一些python模块摆弄它,有效地降低了Python可用的核心数量:
答案 4 :(得分:-1)
由于Global Interpreter Lock,一个Python进程无法利用多个内核。但是如果你能以某种方式并行化你的问题(你应该做什么),那么你可以使用multiprocessing
生成尽可能多的Python进程,就像拥有核心一样,并在每个子进程中处理这些数据。