我在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并返回结果的函数。
您是否有任何建议我如何更改它以使其更快。
答案 0 :(得分:1)
根据您的评论,我认为30秒的时间很可能主要是由于外部API调用。我会添加一些时序代码来测试代码的哪些部分实际上对缓慢负责。
如果它来自外部API调用,则有一些简单的修复。外部API调用阻塞,所以如果你可以移动到一个并行模型你会获得加速(虽然30秒的阻塞声音对我来说很大)。
我认为通过将2个循环的输出作为传递给函数的参数矩阵来创建快速的“任务列表”是最容易的。然后我将它们导入Celery
以运行任务。这应该会给你一个体面的加速,只需要很少的工作量。
使用threading
或multiprocessing
模块运行任务(或部分)可能会节省更多时间,甚至可以在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)