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)