python并发与并行(进程与线程)

在这里插入图片描述
在这里插入图片描述
线程开发
在这里插入图片描述

# print("hello world")
# import numpy as np
# import matplotlib.pyplot as plt
#
# x = np.linspace(1,100,30)
# y = 2*x + 7 + np.random.rand(30)*6
#
# plt.plot(x,y,c='r')
# plt.show()
#
# import torch
# a = torch.zeros(5,3)
# print(a)

import threading
import time
# 启动时,友谊解释器进程,每一个进程都有线程,至少有一个主线程

# target 目标函数
def worker():
    while True:
        time.sleep(1) #真正的情况,都是使用死循环,不停的运行。使用时间模块进行
        print("I am working")
        print('finished')

t = threading.Thread(target=worker,name="worker") # 线程管理对象,不是线程
t.start() #启动线程,系统调用在当前os真正创建爱你一个线程运行,成为工作线程

# 线程结束两种形式
#  1 无事可做,自己退出
#  2 线程崩溃

如果是两个线程的话,可以使用for循环来实现

在这里插入图片描述

# print("hello world")
# import numpy as np
# import matplotlib.pyplot as plt
#
# x = np.linspace(1,100,30)
# y = 2*x + 7 + np.random.rand(30)*6
#
# plt.plot(x,y,c='r')
# plt.show()
#
# import torch
# a = torch.zeros(5,3)
# print(a)

import threading
import time
# 启动时,友谊解释器进程,每一个进程都有线程,至少有一个主线程

# target 目标函数
def worker():
    while True:
        time.sleep(1) #真正的情况,都是使用死循环,不停的运行。使用时间模块进行
        print("I am working")
        print('finished')

for i in range(2):
    t = threading.Thread(target=worker,name="worker-{}".format(i+1)) # 线程管理对象,不是线程
    t.start() #启动线程,系统调用在当前os真正创建爱你一个线程运行,成为工作线程

# 线程结束两种形式
#  1 无事可做,自己退出
#  2 线程崩溃

同一个时刻,线程ID不会重复,名字可以重复,但是ID不会重复,但是可以复用。

# print("hello world")
# import numpy as np
# import matplotlib.pyplot as plt
#
# x = np.linspace(1,100,30)
# y = 2*x + 7 + np.random.rand(30)*6
#
# plt.plot(x,y,c='r')
# plt.show()
#
# import torch
# a = torch.zeros(5,3)
# print(a)

import threading
import time
# 启动时,友谊解释器进程,每一个进程都有线程,至少有一个主线程

# target 目标函数
def worker():
    while True:
        time.sleep(1) #真正的情况,都是使用死循环,不停的运行。使用时间模块进行
        print("I am working")
        print('finished',threading.current_thread().ident) # 可以查看当前执行的线程ID号(可以看出来交替进行,其实就是所谓的假并行)

for i in range(3):
    t = threading.Thread(target=worker,name="worker-{}".format(i+1)) # 线程管理对象,不是线程
    t.start() #启动线程,系统调用在当前os真正创建爱你一个线程运行,成为工作线程 # 启动真正的线程后,才有ID
    print(t.ident,t.name,'~~~~~~~~~~')

# 线程结束两种形式
#  1 无事可做,自己退出
#  2 线程崩溃

多线程
线程和线程是各运行各的
在这里插入图片描述
两个红色框标出来的是主线程运行的
在这里插入图片描述
在这里插入图片描述
GIL全局解释器锁,它是进程级别锁,影响该进程内所有线程
在这里插入图片描述
即使4个线程分布在不同的核上,但是由于有GIL的出现,每次只能出现一个,只能运行一个,所以不能实现真并行。

纯串行

import threading
import logging
import datetime

FORMAT = "%(thread)d%(message)s"
logging.basicConfig(format=FORMAT,level = logging.INFO)

start = datetime.datetime.now()

def calc(): #计算密集型 CPU密集型
    sum = 0
    for i in range(200000000):
        sum += 1
    logging.info('finished') #打印IO操作

#GIL
calc() # 4次
calc()
calc()
calc()
delta = (datetime.datetime.now() - start).total_seconds()
logging.info(delta)  #串行53s 墙上的时间

GIL多线程(CPU)密集型而言,与串行效率相近

import threading
import logging
import datetime

FORMAT = "%(thread)d%(message)s"
logging.basicConfig(format=FORMAT,level = logging.INFO)

start = datetime.datetime.now()

def calc(): #计算密集型 CPU密集型
    sum = 0
    for i in range(200000000):
        sum += 1
    logging.info('finished') #打印IO操作

#GIL
task = []
for i in range(4):
    t = threading.Thread(target=calc,name='cal-{}'.format(i+1))
    task.append(t)
    t.start()

for t in task:
    t.join() #主线程运行jion,被迫等待该线程运行完才能不阻塞

delta = (datetime.datetime.now() - start).total_seconds()
logging.info(delta)
#串行53s 墙上的时间
# 多线程 多线程上下文切换应该多一点点耗时,对于CPU密集代码来说,Python的多下称由于GIL所以没有任何优势

多进程

import threading
import logging
import datetime
import multiprocessing

FORMAT = "%(thread)d%(message)s"
logging.basicConfig(format=FORMAT,level = logging.INFO)

start = datetime.datetime.now()

def calc(): #计算密集型 CPU密集型
    sum = 0
    for i in range(200000000):
        sum += 1
    logging.info('finished') #打印IO操作

#GIL
task = []
for i in range(4):
    # t = threading.Thread(target=calc,name='cal-{}'.format(i+1))
    t = multiprocessing.Process(target=calc,name='cal-{}'.format(i+1))
    task.append(t)
    t.start()

for t in task:
    t.join() #主线程运行jion,被迫等待该线程运行完才能不阻塞

delta = (datetime.datetime.now() - start).total_seconds()
logging.info(delta)
#串行53s 墙上的时间
# 多线程 多线程上下文切换应该多一点点耗时,对于CPU密集代码来说,Python的多下称由于GIL所以没有任何优势

在使用多进程的时候,会出现一个错误
在这里插入图片描述
就是在编译器中运行上述代码的时候,只需要加入一句话就好了

if __name__ == '__main__':
import threading
import logging
import datetime
import multiprocessing

FORMAT = "%(thread)d %(message)s"
logging.basicConfig(format=FORMAT,level = logging.INFO)

start = datetime.datetime.now()

def calc(): #计算密集型 CPU密集型
    sum = 0
    for i in range(200000000):
        sum += 1
    logging.info('finished') #打印IO操作

if __name__ == '__main__':
    #GIL
    task = []
    for i in range(4):
        # t = threading.Thread(target=calc,name='cal-{}'.format(i+1))
        t = multiprocessing.Process(target=calc,name='cal-{}'.format(i+1))
        task.append(t)
        t.start()

    for t in task:
        t.join() #主线程运行jion,被迫等待该线程运行完才能不阻塞

    print('\n')
    delta = (datetime.datetime.now() - start).total_seconds()
    logging.info(delta)
    #串行34-40s左右 墙上的时间
    # 多线程 多线程上下文切换应该多一点点耗时,对于CPU密集代码来说,Python的多下称由于GIL所以没有任何优势
    # 多进程10s左右,要大于34/4

进程池

import threading
import logging
import datetime
import multiprocessing

FORMAT = "%(thread)d %(message)s"
logging.basicConfig(format=FORMAT,level = logging.INFO)

start = datetime.datetime.now()

def calc(): #计算密集型 CPU密集型
    sum = 0
    for i in range(200000000):
        sum += 1
    logging.info('finished') #打印IO操作

if __name__ == '__main__': # 多进程池
    #GIL
    task = []
    pool = multiprocessing.Pool(4)
    for i in range(4):
        # t = threading.Thread(target=calc,name='cal-{}'.format(i+1))
        # t = multiprocessing.Process(target=calc,name='cal-{}'.format(i+1))
       pool.apply_async(calc)

        # task.append(t)
        # t.start()
    pool.close() # 等所有任务完成关闭
    pool.join() # 如果不close,我就卡着

    for t in task:
        t.join() #主线程运行jion,被迫等待该线程运行完才能不阻塞

    print('\n')
    delta = (datetime.datetime.now() - start).total_seconds()
    logging.info(delta)
    #串行34-40s左右 墙上的时间
    # 多线程 多线程上下文切换应该多一点点耗时,对于CPU密集代码来说,Python的多下称由于GIL所以没有任何优势
    # 多进程10s左右,要大于34/4.
    # 进程池实现4个进程 26s
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值