博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python:多进程multiprocessing,多进程和多线程的应用
阅读量:4111 次
发布时间:2019-05-25

本文共 2807 字,大约阅读时间需要 9 分钟。

目录


多进程

由于Python的GIL,多线程未必是CPU密集型程序的好的选择

多进程可以完全独立的进程环境中运行程序,可以充分地利用多处理器
但是进程本身的隔离代理的数据不共享也是一个问题,而且线程比进程轻量级

multiprocessing

Process类

Process类遵循了Thread类的API,减少了学习难度;

先看一个例子,前面介绍的单线程、多线程比较的例子的多进程版本

import multiprocessingimport datetimedef cacl(i):    sum = 0    for _ in range(100000000):        sum +=1    print(i,sum)if __name__ == '__main__':    start = datetime.datetime.now()    ps = []    for i in range(5):        p = multiprocessing.Process(target=cacl,args=(i,),name="cacl-{}".format(i))        ps.append(p)        p.start()    for p in ps:        p.join()    delta = (datetime.datetime.now()-start).total_seconds()    print(delta)结果:2 1000000001 1000000004 1000000003 1000000000 1000000005.942173

单线程、多线程都跑了4分钟多,而多进程用了1分半,这是真并行

名称         说明
pid   进程id
exitcode   进程退出状态码,0代表退出,非0代表有问题
terminate() 终止指定的进程

进程间同步

进程间同步提供了和线程一样的类,使用的方法一样,使用的效果也类似

不过,进程间代价要高于线程间,而且底层实现是不同的,只不过Python屏蔽了这些不同之处,让用户简单使用多进程

multiprocessing还提供共享内容,服务器进程来共享数据,还提供了Queue队列、Pipe管道用户进程间通信。

通信方式不同:

  • 多进程就是启动多个解释器进程,进程间通信必须序列化、反序列化
  • 数据的线程安全性问题:由于每个进程中没有实现多线程,GIL可以说没什么用了

进程池举例

multiprocessing.Pool是进程池类。

 

名称 说明
apply(self,func,args=(),kwds={} ) 阻塞执行,导致主进程执行其他子进程就像一个个执行
apply_async(self,func,args=(),kwds={},callback=None,error_callback=None) 与apply方法用法一致,非阻塞执行,得到结果后执行回调
close() 关闭池,池不能接受新的任务
terminate() 结束工作线程,不在处理未处理的任务
join()         在close或terminate之后使用

import loggingimport datetimeimport multiprocessing#日志打印进程ID、进程名、线程id、线程名logging.basicConfig(level=logging.INFO,format='%(process)d %(processName)s %(thread)d %(message)s')#计算def calc(i):    sum = 0    for _ in  range(100000000):        sum +=1    logging.info("{} .in funcating".format(sum))    return sum #进程要return,callback可以拿到这个效果if __name__ == '__main__':    start=datetime.datetime.now()    pool = multiprocessing.Pool(5)    for i in range(5):        #回调函数必须接受一个参数        pool.apply_async(calc,args=(i,),callback=lambda x:logging.info("{}.incallback".format(x))) #异步执行    pool.close()    pool.join()    delta=(datetime.datetime.now()-start).total_seconds()    print(delta)    print("主进程结束")结果:23900 SpawnPoolWorker-1 2800 100000000 .in funcating16320 MainProcess 24952 100000000.incallback19572 SpawnPoolWorker-5 17160 100000000 .in funcating16320 MainProcess 24952 100000000.incallback7272 SpawnPoolWorker-3 19112 100000000 .in funcating16320 MainProcess 24952 100000000.incallback3104 SpawnPoolWorker-4 7044 100000000 .in funcating16320 MainProcess 24952 100000000.incallback12684 SpawnPoolWorker-2 24104 100000000 .in funcating16320 MainProcess 24952 100000000.incallback6.163994主进程结束

多进程、多线程的线程

1、CPU密集型

CPython中使用到了GIL,多线程的时候相互竞争 ,且多核优势不能发挥,Python多进程效率更高

2、IO密集型

适合适用多线程,可以减少多进程间IO的序列化开销。且在IO等待的时候,切换到其他线程继续执行,效率不错

多线程、多进程应用

请求/应答模型:WEB应用总常见的处理模型

master启动多个woker工作进程,一般和CPU数目相同,发挥多核优势

worker工作进程中,往往需要操作网络IO和磁盘IO,启动多线程,提高并发处理能力。worker处理用户的请求,往往需要的等待数据,处理完请求还要通过网络IO返回响应,这就是nginx工作模式

转载地址:http://koesi.baihongyu.com/

你可能感兴趣的文章
关于Content-Length
查看>>
WebRequest post读取源码
查看>>
使用TcpClient可避免HttpWebRequest的常见错误
查看>>
EntityFramework 学习之一 —— 模型概述与环境搭建 .
查看>>
C# 发HTTP请求
查看>>
初试visual studio2012的新型数据库LocalDB
查看>>
启动 LocalDB 和连接到 LocalDB
查看>>
Palindrome Number --回文整数
查看>>
Reverse Integer--反转整数
查看>>
Container With Most Water --装最多水的容器(重)
查看>>
Longest Common Prefix -最长公共前缀
查看>>
Letter Combinations of a Phone Number
查看>>
Single Number II --出现一次的数(重)
查看>>
Valid Parentheses --括号匹配
查看>>
Generate Parentheses--生成匹配括号(重)
查看>>
Remove Element--原地移除重复元素
查看>>
Remove Duplicates from Sorted Array--从有序数组中移除重复元素
查看>>
Count and Say
查看>>
Gas Station
查看>>
Palindrome Partitioning --回文切割 深搜(重重)
查看>>