我在这里写了一些多线程的学习总结,在这里写了一些多进程的学习笔记,在这片文章中,就它们并串行执行的情况进行一下对比。
直接上程序
import multiprocessing as mp # 多进程的模块
import threading as td
from queue import Queue
import time
def job(q, n): # 进程调用测程序,传递的参数为一个queue(队列)对象
res = 0
for i in range(n):
res += i**2
q.put(res) # 把结果(就是主进程中函数的返回值)存入队列
# 多进程的执行方案
def multicore(m, n):
q = mp.Queue()
plist = []
signle_size = int(n/m) # 分配给每个进程的执行规模
# 把规模n分配给m个进程执行,每个进行执行n/m(即signle_size)
for e in range(m):
p = mp.Process(target=job, args=(q, signle_size))
# 生成进程,并传入要执行的操作(函数),args=参数列表,只传一个参数的时候注意要在参数后面加一个逗号,因为args需要一个可迭代的参量
p.start() # 进程操作开始执行
plist.append(p)
# .join()必须要和进程创建操作分开
for pp in plist:
pp.join() # 将进程操作设定为关键路径
result = 0
for e in range(m):
result += q.get() # 从结果队列中取值
print(result)
# 多线程执行方案
def multithread(m, n):
q = Queue()
tlist = []
signle_size = int(n / m) # 分配给每个线程的执行规模
# 把规模n分配给m个线程执行,每个进行执行n/m(即signle_size)
for e in range(m):
t = td.Thread(target=job, args=(q, signle_size))
# 生成进程,并传入要执行的操作(函数),args=参数列表,只传一个参数的时候注意要在参数后面加一个逗号,因为args需要一个可迭代的参量
t.start() # 进程操作开始执行
tlist.append(t)
# .join()必须要和进程创建操作分开
for tt in tlist:
tt.join() # 将进程操作设定为关键路径
result = 0
for e in range(m):
result += q.get() # 从结果队列中取值
print(result)
# 串行执行方案
def normol(m, n):
q = Queue()
signle_size = int(n / m) # 分配给每个进程的执行规模
# 把规模n分配给m个步骤执行,每个步骤执行n/m(即signle_size)
for e in range(m):
job(q, signle_size)
result = 0
for e in range(m):
result += q.get() # 从结果队列中取值
print(result)
if __name__ == '__main__':
n_size = 1000000 # 总规模
n_mul = 2 # 多线程/进程数,即总规模分配给几个线程/进程执行
# 多进程执行,计算执行时间
smp = time.time()
multicore(n_mul, n_size)
emp = time.time()
print('time_multicore:',emp-smp)
# 多线程执行,计算执行时间
smp = time.time()
multithread(n_mul, n_size)
emp = time.time()
print('time_multithread:',emp-smp)
# 串行分步执行,计算执行时间
smp = time.time()
normol(n_mul, n_size)
emp = time.time()
print('time_normal:',emp-smp)
OutPut1(设置规模n=1000000,分(m=2)个进程/进程/步骤执行)
83333083333500000
time_multicore: 0.37401270866394043
83333083333500000
time_multithread: 0.3429744243621826
83333083333500000
time_normal: 0.3250463008880615
OutPut2(设置规模n=1000000,分(m=10)个进程/进程/步骤执行)
3333283333500000
time_multicore: 0.6909716129302979
3333283333500000
time_multithread: 0.33600425720214844
3333283333500000
time_normal: 0.33300042152404785
OutPut3(设置规模n=10000000,分(m=2)个进程/进程/步骤执行)
83333308333335000000
time_multicore: 2.0039618015289307
83333308333335000000
time_multithread: 3.3349993228912354
83333308333335000000
time_normal: 3.418002128601074
OutPut4(设置规模n=10000000,分(m=10)个进程/进程/步骤执行)
3333328333335000000
time_multicore: 1.0810012817382812
3333328333335000000
time_multithread: 3.432995557785034
3333328333335000000
time_normal: 3.3250246047973633
其中n4=n3=10n2=10n1
简单说明一下上面的程序,是在总规模n下,分别分m个进程,m个线程,串行分m步执行的对比。
可以看到,当规模小的时候,使用多线程并没有什么优势,相反生成多进程/线程的操作过程会浪费一定的时间。但是当运算规模变大的时候,多进程会展现出更快的运算速度,并且速度随着进程数的增加而又更大幅度的提升,同样也可以发现,效率的提升并不与进程数的倒数呈严格的线性相关,应该是因为开进程需要时间,临界资源(只允许单点访问)。而多线程在效率上并没有什么提升,反而有所下降,因为多线程是通过分时而实现的伪并行的原因。多线程当然也有其存在的意义,就是“并行”,可以实现多个程序同时运行,并且线程是省资源的,多线程间是共享资源的,不像多进程那样每个进程都需要单独的开销。这么看来这还是多线程的优势,在不多占用资源的前提下,实现了多个程序同时运行,效率上的损失也不是太大。