欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python多线程与多进程

程序员文章站 2022-07-12 21:31:20
...

    在进行算法优化的时候,我们需要实时性,运行速度越快,效率越高。而平常运行使用程序,我们只使用一个核进行运算,而cpu均含有多核,那么其他核不进行运算,这就造成了巨大的浪费,而为了加速,使用了python所带的多线程与多进程。

多线程:

    多线程即是将一个大任务,分成若干个子任务,cpu每个核分别进行处理若干个子任务,这样进行并行运算,提高了处理速度。推荐使用python带有的multiprocessing的进程池Pool.进程池就是将我们所要运行的东西,放在池子里,Python会自行解决多进程的问题。而进程池的操作,主要包含4种操作:apply,map,apply_async,map_async四个函数,下面分别进行介绍这四个函数。

    在进行函数操作之前,我们先要查看我们的cpu有多少内核,即使用:

import multiprocessing
from multiprocessing import Pool
cpus = multiprocessing.cpu_count()##查看有多少个核,一般就分为多少个线程
pool=Pool(processes=cpus)##打开cpus个线程

1、apply

    同步方式调用,线程阻塞,意味着下一个task需要等待上一个task完成后才能开始运行,这时候使用apply同单进程无区别,而apply函数的输入只能是(func,args),其中func是函数名称,args为列表格式为(a,b,c),一个变量时必须写成(a,)。后面是该函数的参数。pool.close()要放在pool.join()前面。由于pool.close没有完全关闭pool只是把进程池的状态更改为不可插入的状态,而pool.join()则为主进程阻塞,等待子进程的退出,close与join是同时出现的,apply的输出即函数的返回值,若无返回值则为None,若只有join,则线程池必须关闭,否则出问题。

2、map

    map也是同步方式调用,同apply相似,但是map函数的输入可以是(func,iterations[]),其中func是函数名称,而iterations是迭代器,其是一个列表存储的是n个函数的参数,但是不足的是,这样map只能对相同的函数进行操作,没有apply方便。map的返回值是一个列表,里面存储的是n个结果。

3、apply_async()

    其应用的方法与apply相同,皆是输入函数名称和参数,但是其是异步方式调用,线程不堵塞,其他功能与apply类似。假设我有4个核,且正好有4个任务,那么这时候一个核对应一个任务,效率最高,但是我们的任务有时候并不只cpus个数个,因此每个核需要进行多个任务的操作,这会带来任务切换成本。但是比如我们有4个cpu,5个任务,那么,这4个线程谁先运行完谁去执行第5个任务,因此其顺序并不是我们定义的顺序,而是运行速度的顺序。

    在运行中,apply_async的输出不是函数的输出,而是返回一个Applyresult的对象,我们可以通过get函数得到每一个apply_async对应的函数的输出,但是我们不要在apply_async之后立马进行get(),这样会堵塞进程,获取返回值的进程最好放在进程池回收之后进行,这样可以避免堵塞后面的语句。

    并且相对于apply的不同,apply_async其还提供一个回调函数,回调函数是当函数结束后,将函数的输出作用到改回调函数中,相当于get函数。apply_async还提供ready():表示进程函数是否已经启动,successful():表示进程函数是否已经执行成功,get():表示进程函数的返回值。wait():等待进程函数执行完毕。执行完wait()函数,若没有进行pool.close(),便可以继续添加线程。

4、map_async

    其与apply_async相似都是进行异步处理程序,只是map_async是map的异步表示。与apply_async相似,使用ready()函数,表示进程函数是否已经启动,successful表示进程函数是否已经执行成功,get()函数表示得到该迭代器中参数的所有输出。

5、imap与imap_unordered

    两个函数作用与map效果类似,只不过imap的输出直接返回输出值,并且返回值的顺序与迭代器传入的参数顺序相同,而imap_unordered返回也是输出值,只不过返回值的顺序不一定与迭代器传入的参数顺序相同。

6、close\join\terminal

    close:关闭线程池,不允许再添加线程

    join:主线程堵塞,等待子线程的完成,join的方法需要再close与terminal后执行

    terminal:结束工作进程,不再处理还未处理的任务

多线程:

    多线程类似于多进程,函数的使用是相似的,只不过使用的multiprocessing中的进程。

from multiprocessing.dummy import Pool as ThreadPool

用法与pool相同。

 

参考博客:https://jingsam.github.io/2015/12/31/multiprocessing.html

https://morvanzhou.github.io/tutorials/python-basic/multiprocessing/5-pool/

https://feelncut.com/2018/05/14/150.html