前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python进阶之多进程

python进阶之多进程

作者头像
公众号guangcity
发布2019-09-20 14:37:53
4490
发布2019-09-20 14:37:53
举报
文章被收录于专栏:光城(guangcity)光城(guangcity)

python进阶之多进程

0.导语1.进程与线程初识1.1 导包1.2 定义被调函数1.3 创建线程和进程1.4 启动线程和进程2.输出结果存放至Queue2.1 导包2.2 定义被调函数2.3 启动多进程,存放结果3.进程与线程效率对比3.1 导入多进程包3.2 定义被调函数3.3 封装多进程3.4 导入线程包3.5 封装多线程3.6 封装普通方法3.7 主函数调用3.8 输出结果4.进程池4.1 导入进程包4.2 定义被调函数4.3 封装函数4.4 主函数调用5.共享内存6.进程锁6.1 不同进程争夺资源6.2 通过锁机制解决争夺资源问题7.参考资料

0.导语

今天来学习python进阶知识,一起来实战嗨起来~ 欢迎留言,哈哈,我会对经常留言的后面发福利!

1.进程与线程初识

1.1 导包

代码语言:javascript
复制
# 导入线程进程标准模块
import multiprocessing as mp
import threading as td

1.2 定义被调函数

代码语言:javascript
复制
# 定义一个被线程和进程调用的函数
def job(a,d):
    print('aaaaa')

1.3 创建线程和进程

代码语言:javascript
复制
# 创建线程和进程
t1 = td.Thread(target=job, args=(1,2)) # (1,2,)与(1,2)一样效果
p1 = mp.Process(target=job, args=(1,2)) # (1,2,)与(1,2)一样效果

1.4 启动线程和进程

代码语言:javascript
复制
if __name__ == '__main__':
    # 启动线程和进程
    t1.start()
    p1.start()
    # 连接线程和进程
    t1.join()
    p1.join()

2.输出结果存放至Queue

2.1 导包

代码语言:javascript
复制
import multiprocessing as mp

2.2 定义被调函数

这里传入Queue对象

代码语言:javascript
复制
def job(q):
    res = 0
    for i in range(1000000):
        res += i + i ** 2 + i ** 3
    q.put(res)

2.3 启动多进程,存放结果

代码语言:javascript
复制
if __name__ == '__main__':
    q = mp.Queue()
    p1 = mp.Process(target=job, args=(q,))
    p2 = mp.Process(target=job, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    res1 = q.get()
    res2 = q.get()
    print(res1+res2)

3.进程与线程效率对比

3.1 导入多进程包

代码语言:javascript
复制
import multiprocessing as mp

3.2 定义被调函数

代码语言:javascript
复制
def job(q):
    res = 0
    for i in range(1000000):
        res += i + i ** 2 + i ** 3
    q.put(res)

3.3 封装多进程

代码语言:javascript
复制
# 多核/多进程
def multicore():
    q = mp.Queue()
    p1 = mp.Process(target=job, args=(q,))
    p2 = mp.Process(target=job, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    res1 = q.get()
    res2 = q.get()
    print('multicore:', res1 + res2)

3.4 导入线程包

代码语言:javascript
复制
import threading as td

3.5 封装多线程

代码语言:javascript
复制
# 多线程
def multithread():
    q = mp.Queue()
    t1 = td.Thread(target=job, args=(q,))
    t2 = td.Thread(target=job, args=(q,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    res1 = q.get()
    res2 = q.get()
    print('multithread:', res1 + res2)

3.6 封装普通方法

代码语言:javascript
复制
def normal():
    res = 0
    for _ in range(2):
        for i in range(1000000):
            res += i + i ** 2 + i ** 3
    print('normal:',res)

3.7 主函数调用

三种方法对比效率

代码语言:javascript
复制
import time
if __name__ == '__main__':
    st = time.time()
    normal()
    st1 = time.time()
    print('normal time:', st1 - st)
    multithread()
    st2 = time.time()
    print('multithread time:', st2 - st1)
    multicore()
    st3 = time.time()
    print('multicore time:', st3 - st2)

3.8 输出结果

代码语言:javascript
复制
normal: 499999666667166666000000
normal time: 1.779979944229126
multithread: 499999666667166666000000
multithread time: 1.8090195655822754
multicore: 499999666667166666000000
multicore time: 1.2929792404174805

结论:多进程 < 普通 < 多线程

4.进程池

说在前面:有了池子之后,就可以让池子对应某一个函数,我们向池子里丢数据,池子就会返回函数返回的值。

Pool和之前的Process的不同点是丢向Pool的函数有返回值,而Process的没有返回值。

4.1 导入进程包

代码语言:javascript
复制
import multiprocessing as mp

4.2 定义被调函数

代码语言:javascript
复制
def job(x):
    return x*x

4.3 封装函数

map() 与 apply_async() 两种方式 返回结果

代码语言:javascript
复制
def multicore():
    '''
    Pool默认调用是CPU的核数,传入processes可自定义CPU核数
    map()放入迭代参数,返回多个结果
    apply_async()只能放入一组参数,并返回一个结果,如果想得到map()的效果需要通过迭代
    '''
    pool = mp.Pool(processes=2)
    res = pool.map(job, range(10))
    print(res)
    '''
    apply_async()只能传递一个值,它只会放入一个核进行运算,传入的值因为必须是可迭代的,
    所以在传入值后需要加逗号,同时需要用get()方法获取返回值。
    '''
    res = pool.apply_async(job, (2,))
    multi_res = [pool.apply_async(job, (i,)) for i in range(10)]
    print(res.get()) # 获取单个结果
    print([res.get() for res in multi_res]) # 获取多个结果

4.4 主函数调用

代码语言:javascript
复制
if __name__ == '__main__':
    multicore()

5.共享内存

代码语言:javascript
复制
import multiprocessing as mp

'''
使用Value数据存储在一个共享的内存表中
d表示一个双精浮点类型,i表示一个带符号的整型
'''
value1 = mp.Value('i', 0)
value2 = mp.Value('d', 3.14)

'''
Array类,可以和共享内存交互,来实现在进程之间共享数据。
这里的Array和numpy中的不同,它只能是一维的,不能是多维的。
同样和Value 一样,需要定义数据形式,否则会报错。
'''
array = mp.Array('i', [1,2,3,4])

6.进程锁

6.1 不同进程争夺资源

代码语言:javascript
复制
import multiprocessing as mp
import time
def job(v, num):
    for _ in range(5):
        time.sleep(0.1)
        v.value += num
        print(v.value,end="\n")

def multicore():
    v = mp.Value('i',0) # 定义共享变量
    p1 = mp.Process(target=job, args=(v,1))
    p2 = mp.Process(target=job, args=(v,3)) # 设定不同的number看如何抢夺内存
    p1.start()
    p2.start()
    p1.join()
    p2.join()

if __name__ == '__main__':
    multicore()

6.2 通过锁机制解决争夺资源问题

代码语言:javascript
复制
import multiprocessing as mp
import time
def job(v, num, l):
    l.acquire() # 锁住
    for _ in range(5):
        time.sleep(0.1)
        v.value += num
        print(v.value,end="\n")
    l.release() # 释放

def multicore():
    l = mp.Lock() # 定义一个进程锁
    v = mp.Value('i',0) # 定义共享变量
    p1 = mp.Process(target=job, args=(v,1,l)) # 需要将lock传入
    p2 = mp.Process(target=job, args=(v,3,l)) # 设定不同的number看如何抢夺内存
    p1.start()
    p2.start()
    p1.join()
    p2.join()

if __name__ == '__main__':
    multicore()

7.参考资料

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • python进阶之多进程
    • 0.导语
      • 1.进程与线程初识
        • 1.1 导包
        • 1.2 定义被调函数
        • 1.3 创建线程和进程
        • 1.4 启动线程和进程
      • 2.输出结果存放至Queue
        • 2.1 导包
        • 2.2 定义被调函数
        • 2.3 启动多进程,存放结果
      • 3.进程与线程效率对比
        • 3.1 导入多进程包
        • 3.2 定义被调函数
        • 3.3 封装多进程
        • 3.4 导入线程包
        • 3.5 封装多线程
        • 3.6 封装普通方法
        • 3.7 主函数调用
        • 3.8 输出结果
      • 4.进程池
        • 4.1 导入进程包
        • 4.2 定义被调函数
        • 4.3 封装函数
        • 4.4 主函数调用
      • 5.共享内存
        • 6.进程锁
          • 6.1 不同进程争夺资源
          • 6.2 通过锁机制解决争夺资源问题
        • 7.参考资料
        相关产品与服务
        数据保险箱
        数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档