Python之多进程multiprocessing

0 multiprocessing

multiprocessing是支持大量进程,类似于线程模块的API包.本包提供本地和远程并发,通过使用子进程而不是线程,可有效避免全局解释器锁的单步执行.因此,multiprocessing可充分利用机器上的多个处理器.
进程,是资源(CPU,内存)分配的基本单位,是运行程序的一个实例,程序运行时系统会创建一个进程,并分配资源,然后将进程放入进程就绪队列,进程调度器选中他的时候会为其分配CPU资源,程序真正开始运行.
Linux系统,在父进程中创建子进程,当进程接受到客户端的请求是,可以复制出一个子进程来处理,父进程仅监控请求,然后创建子进程去处理,实现并发.
CPU的核数,表示可以同时执行的进程数,解析一下,CPU可以处理成千上万个进程,但是,CPU每个核每个时刻只能处理一个任务即进程,所以,多任务并行是指同一时刻可以执行的进程数量.
线程,是程序运行的基本单位,是进程的一个执行流,是CPU调度和分配的基本单位,一个进程可由多个线程组成,线程间共享所有资源,每个线程有自己的堆栈和局部变量,线程有CPU独立调度执行,多CPU允许多个线程同时运行.

1 Pool

功能:进程池用于执行在pool类中提交的任务,即进程池用于控制发布任务的工作进程.支持超时和回调的异步结果,具有并行映射实现.进程池数量即为同时可执行的最大任务数量.

1.0 参数

Pool(process[,initializer[,initargs[,maxtasksperchild[,context]]]])

序号参数说明
1processes使用的工作进程数量,若为None,返回os.cpu_count()使用的cpu数量
2initializerinitializer不为None,每个工作进程启动时会调用initializer(*initargs)
3intiargs进程方法的参数
4maxtasksperchild该参数是工作进程在退出并替换为新的工作进程之前处理的最大进程数量,用于释放未使用的资源
5context指定启动工作进程的上下文

1.2 方法

序号方法描述
1close禁止任何任务进入进程池,当所有任务完成后工作进程退出
2terminate立即停止工作进程,不继续进行未完成的工作进程
3join等待工作进程退出,必须在close()或terminate()后使用,等待进程池中的所有子进程完成
4mapmap()内置函数的平行函数
5apply_async以非阻塞方式执行池中的任务,可同时执行开辟的池个数任务量
6apply以阻塞方式执行池中任务,即执行返回结果后,开放进程池,其他任务进入,继续执行

1.3 测试

1.3.1 Demo1

from multiprocessing import Pool
# 执行函数
def f(x):
    return x*x
if __name__ == "__main__":
	# 进程池数量:5
    with Pool(5) as p:
        print(p.map(f, [1, 3, 4]))
[1, 9, 16]

1.3.2 Demo2

进程池个数与任务个数相同.

  • pool_test.py
from multiprocessing import Pool
import os, time, random

def func_1():
    #os.getpid()获取当前的进程的ID
    print("\nRun task func_1, child process id: {}" .format(os.getpid())) 
    start = time.time()
    time.sleep(5) 
    end = time.time()
    print('Task fucn_1, runs {} seconds.'.format(end - start))

def func_2():
    print("\nRun task func_2, child process id: {}".format(os.getpid()))
    start = time.time()
    time.sleep(5)
    end=time.time()
    print('Task func_2 runs {} seconds.'.format(end - start))

def func_3():
    print("\nRun task func_3, child process id: {}".format(os.getpid()))
    start = time.time()
    time.sleep(5)
    end = time.time()
    print('Task func_3 runs {} seconds.'.format(end - start))

def func_4():
    print("\nRun task func_4, child process id: {}".format(os.getpid()))
    start = time.time()
    time.sleep(10)
    end = time.time()
    print('Task func_4 runs {} seconds.'.format(end - start))
        
if __name__=='__main__':
    function_list=  [func_1, func_2, func_3, func_4] 
    print("Parent process id: {}".format(os.getpid()))

    pool = Pool(4)
    for func in function_list:
        #Pool执行函数,apply执行函数,当有一个进程执行完毕后,会添加一个新的进程到pool中
        pool.apply_async(func)     

    print('Waiting for all subprocesses done...')
    # close()执行后不会有新的进程加入到pool
    pool.close()
    # join函数等待所有子进程结束
    pool.join()    
    print ('All subprocesses done.')
  • Result
Parent process id: 8592

Run task func_1, child process id: 9563
Run task func_3, child process id: 9565


Run task func_2, child process id: 9564
Run task func_4, child process id: 9566

Waiting for all subprocesses done...
Task func_3 runs 5.005031585693359 seconds.
Task fucn_1, runs 5.0050342082977295 seconds.
Task func_2 runs 5.003967046737671 seconds.
Task func_4 runs 10.02004051208496 seconds.
All subprocesses done.
  • Analysis
    (1) 进程池中进程最大数为4,即同时可运行4个程序或函数;
    (2) 将4个函数放入进程池,使用apply_async实现非阻塞,即可同时运行4个函数,从前三个的延迟时间都设为5可看出,基本同时输出结果;

1.3.3 Demo3

进程池进程数量小于任务个数.

  • pool_test.py
from multiprocessing import Pool
import os, time, random

def func_1():
    #os.getpid()获取当前的进程的ID
    print("\nRun task func_1, child process id: {}" .format(os.getpid())) 
    start = time.time()
    time.sleep(5) 
    end = time.time()
    print('Task fucn_1, runs {} seconds.'.format(end - start))

def func_2():
    print("\nRun task func_2, child process id: {}".format(os.getpid()))
    start = time.time()
    time.sleep(5)
    end=time.time()
    print('Task func_2 runs {} seconds.'.format(end - start))

def func_3():
    print("\nRun task func_3, child process id: {}".format(os.getpid()))
    start = time.time()
    time.sleep(5)
    end = time.time()
    print('Task func_3 runs {} seconds.'.format(end - start))

def func_4():
    print("\nRun task func_4, child process id: {}".format(os.getpid()))
    start = time.time()
    time.sleep(10)
    end = time.time()
    print('Task func_4 runs {} seconds.'.format(end - start))
        
if __name__=='__main__':
    function_list=  [func_1, func_2, func_3, func_4] 
    print("Parent process id: {}".format(os.getpid()))

    pool = Pool(2)
    for func in function_list:
        #Pool执行函数,apply执行函数,当有一个进程执行完毕后,会添加一个新的进程到pool中
        pool.apply_async(func)     

    print('Waiting for all subprocesses done...')
    # close()执行后不会有新的进程加入到pool
    pool.close()
    # join函数等待所有子进程结束
    pool.join()    
    print ('All subprocesses done.')
  • Result
Parent process id: 8592

Run task func_1, child process id: 10639
Run task func_2, child process id: 10640

Waiting for all subprocesses done...
Task fucn_1, runs 5.004624843597412 seconds.
Task func_2 runs 5.002416610717773 seconds.

Run task func_3, child process id: 10639
Run task func_4, child process id: 10640

Task func_3 runs 5.005084991455078 seconds.
Task func_4 runs 10.010075330734253 seconds.
All subprocesses done.
  • Analysis
    (1) 进程池进程数量为2,任务量为4,即同时执行2个任务,当执行完成一个任务之后,释放资源,并将另一个任务放入进程池;
    (2) close用于控制进程池的开关,即保证线程池内的任务顺利执行,而不被其他未加入进程池的任务打断;
    (3) join保证了进程池中任务的子进程正常进行,即进程池中的任务包含的子进程全部完成后,才最终退出,即上面结果中的时间输出,当所有时间输出后,进程任务结束;

2 Pipe

2.1 功能

返回一对表示管道末端的连接对象(conn1, conn2),进程间的管道内部机制通过启动socket连接来保持进程间的通讯.

2.2 参数

Pipe([duplex])
duplex为True(默认),pipe是双向的,若为False,pipe为单向的,conn1只能接受消息,conn2只能发送消息;

2.3 Demo

from multiprocessing import Process, Pipe
def server_process(con):
    # 向客户端进程发送数据
    con.send("xin")
    # 接受客户端进程数据
    print("From father process: {}".format(con.recv()))
    
if __name__ == "__main__":
    # 实例化管道Pipe,建立socket连接
    # 服务端和客户端,conn1,conn2
    server, client = Pipe()
    # 开始服务端进程
    p = Process(target=server_process, args=(server, ))
    p.start()
    # 客户端接受服务端进程数据
    client_process = client.recv()
    print("Received server data: {}".format(client_process))
    client.send("daqi")
Received server data: xin
From father process: daqi

3 Queue

3.1 功能

返回使用pipe和lock/semaphores实现的共享队列进程,用于进程间通信.先进先出(First Input First Output, FIFO);当一个进程将一个项目放入队列时,会启动一个feeder线程,该线程将对象从缓冲区传送到pipe中.

3.2 参数

Queue(maxsize=0)

参数描述
maxsize整数,设置可放入队列的项目数上限.数据填满队列后,进入阻塞,知道队列内容取出.若maxsize小于等于0,队列数目无限制.

3.3 方法

序号参数描述
1qsize()返回队列数量的近似值
2empty()若队列为空,返回True
3full()队列全部占满,返回True
4put(obj[,block[,timeout]])将obj放入队列,若block为True(默认),timeout=None(默认),队列中无空闲位置时会阻塞,若timeout为正数,阻塞时间最长为timeout秒,若仍无空闲位置,则会调用queue.Full
5get([block[,timeout]])从队列获取对象并移除该对象,若block为True(默认),timeout=None(默认),队列中无空闲位置时会阻塞,若timeout为正数,阻塞时间最长为timeout秒,若阻塞结束后仍不能去除对象,则会调用queue.Empty

3.4 Demo1

from multiprocessing import Queue, Process
# 数据进队列
def queue_test(que):
    que.put("xindaqi")
    
if __name__ == "__main__":
    # 建立队列,10个卡位
    Q = Queue(10)
    # 建立进程,将队列作为参数,传入队列操作函数
    p = Process(target=queue_test, args=(Q, ))
    p.start()
    p.join()
    print("Queue data: {}".format(Q.get()))
Queue data: xindaqi

3.5 Demo2

from multiprocessing import Queue, Pool
import time

def queue_test(q):
    # 数据入队列
    for i in range(2):
        q.put(i)
        # 取出队列数据
        q_output = q.get()
        print("Queue data: {}".format(q_output))
        
if __name__ == "__main__":
    Q = Queue(10)
    start_time = time.time()
    # 建立3个线程,同时执行3个任务
    pool = Pool(3, queue_test, (Q, ))
    pool.terminate()
    end_time = time.time()
    cost_time = end_time - start_time
    print("Cost time: {}".format(cost_time))
Queue data: 0
Queue data: 0
Queue data: 1
Queue data: 0
Queue data: 1
Queue data: 1
Cost time: 0.11123538017272949

4 Process

4.1 功能

表示在运行的独立进程,进程类拥有所有threading.Thread方法.

4.2 参数

Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

序号参数描述
1group设定为None,作用只是为了和threading.Thread兼容
2targetrun()方法调用的可执行对象,如函数
3name进程名称
4argstuple类型的参数
5kwargsdict类型的参数
6daemon进程标志为,若为None(默认为None),该标志从创建的进程中继承

4.3 方法

序号方法描述
1run()表示进程活动的方法
2start()开启进程
3join([timeout])默认timeout=None,结束前(terminate),进程是阻塞的,若timeout为正数,表示最大的阻塞时长(秒)
4name进程名称
5is_alive()返回进程是否活动
6daemon进程守护标志,在start()前使用
7pid返回进程ID,在start()之后,即启动进程后,才有ID,否则返回None
8terminate()结束进程
9kill()杀死进程,类似terminate,只能在Unix
10close()关闭进程,释放资源

4.4 Demo

from multiprocessing import Process
import os

def info(title):
    print("Title: {}".format(title))
    print("module name: {}".format(__name__))
    print("Parent process: {}".format(os.getppid()))
    print("Subprocess id: {}".format(os.getpid()))
def f(name):
    info("function f")
    print("Hello {}".format(name))
    
if __name__ == "__main__":
    info("Main line")
    print("==================")
    p = Process(target=f, args=('xindaqi',))
    p.start()
    p.join()
Title: Main line
module name: __main__
Parent process: 29719
Process id: 29755
==================
Title: function f
module name: __main__
Parent process: 29755
Process id: 17714
Hello xindaqi

[参考文献]
[1]https://docs.python.org/3/library/multiprocessing.html#multiprocessing.pool.Pool
[2]https://www.cnblogs.com/zhehan54/p/6130030.html
[3]http://www.cnblogs.com/wdliu/p/6828070.html
[4]https://www.cnblogs.com/kaituorensheng/p/4465768.html


  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python多进程multiprocessing)是一种并行计算的方式,可以在多个CPU核心上同时执行任务,提高程序的运行效率。它可以通过创建多个进程来实现并行计算,每个进程都有自己的独立内存空间,可以独立运行。在Python中,可以使用multiprocessing模块来实现多进程编程,它提供了一系列的类和函数,可以方便地创建和管理多个进程。使用multiprocessing模块可以有效地提高程序的运行速度,特别是在处理大量数据或计算密集型任务时,效果更加明显。 ### 回答2: Python多进程multiprocessing是一个用来创建并行程序的模块,它允许Python程序同时运行多个进程,从而大幅提高程序的运行效率。在Python中,多进程可以通过fork()系统调用实现,但是由于在Windows上无法完全实现fork(),因此Python在Windows上仅支持多线程,而不支持多进程Python多进程中最基本的概念是进程(Process)。在Python中,创建进程有两种基本的方式:使用Process类和使用Pool类。Process类允许我们创建一个进程对象,可以给进程传递参数并启动进程Pool类则可以创建多个进程,并且自动分配任务到不同的进程中。 Python中还有一些重要的概念和技巧,例如进程间通信(IPC)、共享内存、信号量、锁等。进程间通信是在多进程应用程序中非常常见的技术,它可以让不同的进程之间进行数据交换、资源共享等操作。共享内存则允许不同的进程访问同一个内存区域,从而避免了复制数据的过程,提高了程序的效率。 对于使用Python多进程multiprocessing进行开发的程序,我们需要借助Python标准库中的一些附加模块,例如queue、threading、signal等,以及一些第三方库,例如PyQt、numpy等。对于不同的应用场景,我们可以选择不同的库和技术,从而实现最佳的多进程方案。 总体而言,Python多进程multiprocessing是一个非常强大的模块,可以大幅提高Python程序的运行效率和并发性能。不过,要想熟练地运用这个模块,需要对Python的多线程、操作系统和计算机架构等知识有一定的了解。同时,对于更高级别的多进程应用,可能还需要一些专业的领域知识。 ### 回答3: Python是一种面向对象、解释型、高级编程语言,其简洁、易读、易学的语法特点赢得了大批开发者的青睐。而multiprocessing则是Python的一个重要模块,可用于实现多进程并发编程,充分利用计算机多核心资源,提高Python程序的运行效率。 multiprocessing模块的主要特点包括: 1. 提供了Process、Pool、Queue等多个类和函数,方便实现进程的创建、管理和通信。 2. 可以使用fork进程创建新的进程,并可在进程之间共享数据,也可以将任务分配给多个进程执行,提高效率。 3. 提供了多种进程间通信机制的实现,如Pipe、Queue、Value和Array等,让进程之间的通信更加方便,同时保证数据的正确和安全。 4. 灵活的参数设置和控制,比如可以设置进程数、超时时间等,让程序更加可控和稳定。 使用multiprocessing模块可以带来显著的性能提升,特别适合需要处理大规模数据、密集计算或者需要高并发的应用场景。例如,在爬取大规模网站数据时,可以把每个网站的数据抓取任务分配给不同的进程去执行,节约大量时间。在图像处理和机器学习方面也可以大大加快程序的速度。 总之,Pythonmultiprocessing模块为我们提供了一种易用、高效的多进程编程方法,使我们能够更好地利用计算机资源,提高Python程序的性能和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值