Python 简单的多任务处理
所以我有一系列的函数,它们不依赖于彼此来完成它们的工作,每个函数都需要相当长的时间。所以我想,如果我可以使用多个线程,我就可以保证运行时的安全。例如:Python 简单的多任务处理,python,python-2.7,multiprocessing,python-multiprocessing,Python,Python 2.7,Multiprocessing,Python Multiprocessing,所以我有一系列的函数,它们不依赖于彼此来完成它们的工作,每个函数都需要相当长的时间。所以我想,如果我可以使用多个线程,我就可以保证运行时的安全。例如: axial_velocity = calc_velocity(data_axial, factors_axial) radial_velocity = calc_velocity(data_radial, factors_radial) circumferential_velocity = calc_velocity(data_circ, fac
axial_velocity = calc_velocity(data_axial, factors_axial)
radial_velocity = calc_velocity(data_radial, factors_radial)
circumferential_velocity = calc_velocity(data_circ, factors_circ)
到目前为止,我所有的变量都是列表(列表也很长)
我必须对每个输入文件执行此操作,如果有超过200个。。。(我预计大约1000多人)
为了减少运行时间,我尝试检查并尽可能少地计算数据(特别是健全性检查),这非常有帮助,但下一个改进是为每组数据使用一个线程
我尝试过类似的方法(过于简单):
以及:
这些都不起作用,我也不知道如何使它们起作用。当我想用python进行多处理时,我使用线程,下面的代码应该是在python中使用线程的示例:
from threading import Thread
import time
def time1(a, b):
print a
time.sleep(10)
print time.time(), a
return b
def time2(c, d):
print c
time.sleep(10)
print time.time(), c
return d
if __name__ == '__main__':
# target: the function name (pointer),
# args: a tuple of the arguments that you want to send to your function
t1 = Thread(target = time1, args=(1, 2))
t2 = Thread(target = time2, args=(3, 4))
# start the functions:
a = t1.start()
b = t2.start()
print a
print b
正如您在这段代码中看到的,线程不能返回值,因此有两种方法
要在线程中返回值,一种方法是:将输出写入文件,然后通过try\except块读取文件,或者将全局值更改为要返回的值。如果仍要使用多处理,可以在此处找到一些帮助:
希望对您有所帮助。您的第一个示例就快到了。但是,
Pool
不接受arg
关键字。此外,Pool.map()
只允许将单个参数传递给函数。要传递多个参数,您必须将它们打包到另一个结构中,如元组,就像您在第二个示例中所做的那样
第一个示例的这个修改版本有效
from multiprocessing import Pool
def calc_velocity(work_args):
buffer_list = []
for index, line in enumerate(work_args[0]):
buffer_list.append(work_args[0][index] * work_args[1][index])
return buffer_list
data_axial = [1, 2, 3]
factors_axial = [3, 2, 1]
if __name__ == '__main__':
p = Pool(4)
work_args = (data_axial, factors_axial)
axial_velocity = p.map(calc_velocity, [work_args])
如果calc\u velocity
函数实际上代表了您的函数,那么您可以使用numpy的multiply
函数使其更简单(更快)。您的calc\u velocity
功能将只是:
def calc_velocity(work_args):
return numpy.multiply(work_args[0], work_args[1])
如果您不需要在结果完成后立即获得这些结果,那么一个简单的
多处理.Pool.map()
就足以将您的任务划分为多个并行运行的进程,例如:
import multiprocessing
def worker(args): # a worker function invoked for each sub-process
data, factor = args[0], args[1] # Pool.map() sends a single argument so unpack them
return [e * factor[i] for i, e in enumerate(data)]
if __name__ == "__main__": # important process guard for cross-platform use
calc_pool = multiprocessing.Pool(processes=3) # we only need 3 processes
data = ( # pack our data for multiprocessing.Pool.map() ingestion
(data_axial, factors_axial),
(data_radial, factors_radial),
(data_circ, factors_circ)
)
# run our processes and await responses
axial_velocity, radial_velocity, circumferential_velocity = calc_pool.map(worker, data)
然而,您的问题中令人担忧的部分在于提示您需要传递大量数据—当Python使用多处理时,它不会共享内存,而至少在具有fork
的系统上,它可以使用写时复制优化,在进程之间传递数据总是调用一个非常慢的pickle unpickle例程来打包和发送数据
因此,请确保您交换的数据量最小-例如,如果您正在从文件加载data\u axial
和factors\u axial
,最好只发送文件路径,并让worker()
处理加载/解析文件然后在主进程中加载文件,然后发送加载的数据
如果您需要频繁(随机)访问子进程中的大量(可变)共享数据,我建议您使用一些内存中的数据库来完成任务,类似。Python线程不支持并行执行-一次只运行一个线程,由于上下文切换、GIL跟踪等原因,线程会使OP的任务实际执行速度变慢。我知道,线程一次运行一个函数,但不会一直运行到最后,线程会运行部分函数,然后是一些其他函数,并一次又一次地重复到函数的末尾,如果你有几个函数彼此不依赖来完成它们的工作,那么线程这是一个简单的方法来完成事情,无论如何,有一个链接到一个多处理问题,如果你想从你的函数返回内容,这可能会很有帮助。无论如何,当您运行此代码时,打印的时间相同,两个函数只需等待10秒,而不是20秒。如果您知道这一点,OP的“减少运行时间…”任务的哪一部分让您建议使用线程作为OP问题的解决方案?试着运行代码,只需10秒,而不是20秒,它确实会减少运行时间,当我需要同时运行两件事情时,我总是使用它,我在服务器上使用它,它可以同时为多个用户服务并工作。无论如何,我还提出了一个多处理解决方案。stackoverflow中有很多关于在python中同时运行两件事的问题。不,这不是因为你
time.sleep()
你的线程并不意味着它们并行/同时运行-time.sleep()
只会导致上下文切换。尝试添加实际使用CPU的内容(即而不是time.sleep()
),然后看看会发生什么。仅仅因为它可以在某些上下文中(主要是I/O)用于加速执行,并不意味着它确实可以——请阅读更多内容。这看起来很棒,我明天将在工作中完全试用它。同样令人遗憾的是,我的calc_velocity
没有那么简单,但我认为如果没有整个函数,代码已经足够长了。感谢您的回答,我将研究在子流程中打开所需的文件,因为我在主流程中根本不需要它。现在已实现并正在运行。有趣的是,我花了大约半个小时来重写函数和所有内容,但我花了半天的时间来调整以获得更好的性能。。。
def calc_velocity(work_args):
return numpy.multiply(work_args[0], work_args[1])
import multiprocessing
def worker(args): # a worker function invoked for each sub-process
data, factor = args[0], args[1] # Pool.map() sends a single argument so unpack them
return [e * factor[i] for i, e in enumerate(data)]
if __name__ == "__main__": # important process guard for cross-platform use
calc_pool = multiprocessing.Pool(processes=3) # we only need 3 processes
data = ( # pack our data for multiprocessing.Pool.map() ingestion
(data_axial, factors_axial),
(data_radial, factors_radial),
(data_circ, factors_circ)
)
# run our processes and await responses
axial_velocity, radial_velocity, circumferential_velocity = calc_pool.map(worker, data)