线程开发
# 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