如何在python上加快我的脚本速度?

时间:2013-09-15 15:10:02

标签: python performance parallel-processing

我在python中有一个脚本,但运行到最后需要20多个小时。

由于我的代码非常大,我将发布一个简化代码。

代码的第一部分:

flag = 1
mydic = {}
for i in mylist:
    mydic[flag] = myfunction(i)
    flag += 1

mylist有超过700个条目,每次拨打myfunction它都会运行大约20秒。

所以,我在想是否可以使用并行编程将迭代分成两组并同时运行它。这可能吗,我需要比以前更长的时间吗?

代码的第二部分:

mymatrix = []
for n1 in range(0,flag):
    mat = []
    for n2 in range(0,flag):
        if n1 >= n2:
            mat.append(0)
        else:
            res = myfunction2(mydic(n1),mydic(n2))
            mat.append(res)
    mymatrix.append(mat)

所以,如果mylist有700个条目,我想创建一个700x700矩阵,它是上三角矩阵。但myfunction2()每次需要大约30秒。我不知道我是否也可以在这里使用并行编程。

我无法简化myfunction()myfunction2(),因为它们是我调用外部api并返回结果的函数。

您是否有任何建议我如何更改它以使其更快。

2 个答案:

答案 0 :(得分:1)

根据您的评论,我认为30秒的时间很可能主要是由于外部API调用。我会添加一些时序代码来测试代码的哪些部分实际上对缓慢负责。

如果它来自外部API调用,则有一些简单的修复。外部API调用阻塞,所以如果你可以移动到一个并行模型你会获得加速(虽然30秒的阻塞声音对我来说很大)。

我认为通过将2个循环的输出作为传递给函数的参数矩阵来创建快速的“任务列表”是最容易的。然后我将它们导入Celery以运行任务。这应该会给你一个体面的加速,只需要很少的工作量。

使用threadingmultiprocessing模块运行任务(或部分)可能会节省更多时间,甚至可以在Twisted python中全部写入 - 但这通常需要比简单的芹菜功能更长。

使用Celery方法的一个警告是,您将调度大量工作 - 因此您必须具有一些功能来轮询结果。这可能是while循环只有sleeps(10)并重复自己,直到芹菜为每项任务都有结果。如果您在Twisted中执行此操作,则可以在完成时访问/跟踪结果。我从来没有用多处理做这样的事情,所以不知道它会如何适应。

答案 1 :(得分:0)

如何使用生成器代替第二部分而不是for循环之一

def fn():
    for n1 in range(0, flag):
        yield n1

generate = fn()

while True:
    a = next(generate)
    for n2 in range(0, flag):
        if a >= n2:
            mat.append(0)
        else:
            mat.append(myfunction2(mydic(a),mydic(n2))
            mymatrix.append(mat)