多进程原理与应用示例
更新时间为二零一九年二月二十八日十四点三十分十五秒, 作者是牧野。
这篇文章主要介绍了多进程原理与应用, 它结合了具体的实例形式, 对基于包的多进程概念进行了详细的分析, 深入讲解了其核心原理以及相关的实际操作技巧, 有需要的用户可以参考这些内容。
本文实例主要是讲述多进程原理与应用的事情, 现在分享给大家来供大家参考, 具体内容如下:
包里面的多进程管理包, 可以利用那个对象来创建进程, 这个对象上面, 是有这些方法的, 比如说启动方法, 还有join方法, run方法, 以及启动方法。
该模块的核心功能, 就是把管理进程变得和管理线程那样轻松顺手, 因为每一个进程都拥有自己独立的GIL, 所以就不会出现进程相互争抢GIL的情况, 这样一来, 在多核CPU运行环境下, 能够把执行运行的效率给大幅度地提升上去。
这是使用这个功能的例子。
import multiprocessing
import time
import cv2
def daemon1(image):
name = multiprocessing.current_process().name
for i in range(50):
image = cv2.GaussianBlur(image, (3, 3), 1)
time.sleep(0.1)
print 'daemon1 done!
'
cv2.imshow('daemon1', image)
def daemon2(image):
name = multiprocessing.current_process().name
for i in range(50):
image = cv2.GaussianBlur(image, (3, 3), 1)
time.sleep(0.5)
print 'daemon2 done!
'
cv2.imshow('daemon2', image)
if __name__ == '__main__':
t1 = time.time()
number_kernel = multiprocessing.cpu_count()
print 'We have {0} kernels'.format(number_kernel)
p1 = multiprocessing.Process(name='daemon1',
target=daemon1,args= (cv2.imread('./p1.jpg'),))
p1.daemon = False
p2 = multiprocessing.Process(name='daemon2',
target=daemon2, args=(cv2.imread('./p2.jpg'),))
p2.daemon = False
p1.start()
p2.start()
print 'p1 is {0}'.format(p1.is_alive())
p1.terminate()
p1.join()
print 'p1 is {0}'.format(p1.is_alive())
print 'p2 is {0}'.format(p2.is_alive())
p2.join()
t2 = time.time()
print '!
!!!!!!!!!!!!!!!!!!!OK!!!!!!!!!!
!!!!!!!!!!!
'
print 'total time is {0}'.format(t2-t1)
print 'p1.exitcode = {0}'.format(p1.exitcode)
print 'p2.exitcode = {0}'.format(p2.exitcode)
“中”这里指的是一个类别, 它的作用是用来创建进程, 同时还包含了定义进程相关方法的功能, 该类所对应的构造函数形式如下:
def __init__(self, group=None, target=None, name=None, args=(), kwargs={})
这个地方的参数指的是啥意思呢?
程序解读:
在中使用pool
如果需要进行操作的是多个子进程, 那么采用进程池的方式进行统一管控, 会对每个子进程实施自动化管理, 这样的做法显然是更加便利且高效的。
from multiprocessing import Pool
import os, time
def long_time_task(name):
print 'Run task {0} ({1})'.format(name,os.getpid())
start = time.time()
time.sleep(3)
end = time.time()
print 'Task {0} runs {1:.2f} seconds.'.format(name,end - start)
if __name__=='__main__':
print 'Parent process ({0})'.format(os.getpid)
p = Pool()
for i in range(12):
p.apply_async(long_time_task, args=(i,))
print 'Waiting for all subprocesses done...'
p.close()
p.join()
print 'All subprocesses done.'
跟通过类的实例化方法来创建进程的方式不一样, Pool是借由(func,args=(args))这种办法来生成进程的。在每一个进程池里面, 能够并行处理的任务数量等于咱们这台机器上面所有CPU核心的总数目。
要是弄出来的子进程的数量超过了这个上限, 那么在同一时间里, 就只允许有那一个个数的进程在执行。只有当里面的某一个进程把活儿干完了以后, 才会去启动后续的下一个进程。
存在多个子进程, 而这些多个子进程之间需要互相通信。
在多个子进程进行通信的时候, 是需要使用到.Queue的, .Queue的特点在于它是一个消息队列。比方说存在如下需求, 也就是有一个实例表现为一个子进程向队列里边写入数据, 而另一个进程从该队列里面获取数据这样的情况。
from multiprocessing import Process, Queue
import os, time, random
def write(q):
for value in ['A', 'B', 'C']:
print 'Put {0} to queue...'.format(value)
q.put(value)
time.sleep(random.random())
def read(q):
while True:
if not q.empty():
value = q.get(True)
print 'Get {0} from queue.'.format(value)
time.sleep(random.random())
else:
break
if __name__=='__main__':
q = multiprocessing.Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
pw.start()
pw.join()
pr.start()
pr.join()
Queue的使用方法, 是这样子的。
如果在进程池Pool中尝试使用Queue, 是会出错的, 所以, 应该改用那个带有点号的.Queue才行。
from multiprocessing import Process, Queue
import os, time, random
def write(q):
for value in ['A', 'B', 'C']:
print 'Put {0} to queue...'.format(value)
q.put(value)
time.sleep(random.random())
def read(q):
while True:
if not q.empty():
value = q.get(True)
print 'Get {0} from queue.'.format(value)
time.sleep(random.random())
else:
break
if __name__=='__main__':
manager = multiprocessing.Manager()
q = manager.Queue()
p = Pool()
pw = p.apply_async(write, args=(q,))
time.sleep(2)
pr = p.apply_async(read, args=(q,))
p.close()
p.join()
if not q.empty():
print 'q is not empty...'
else:
print 'q is empty...'
print 'OK'
if not q.empty():
print 'q is not empty...'
else:
print 'q is empty...'
print 'done...'
父进程与子进程共享内存
定义普通的变量,不能实现在父进程和子进程之间共享:
import multiprocessing
from multiprocessing import Pool
def changevalue(n, a):
n = 3.14
a[0] = 5
if __name__ == '__main__':
num = 0
arr = range(10)
p = Pool()
p1 = p.apply_async(changevalue, args=(num, arr))
p.close()
p.join()
print num
print arr[:]
导致最终输出的 num 的数值, 依然是由父进程那边定义的 0, 同时 arr 的第一个元素的值, 也依旧是 0。
使用那个, 来把共享的这个对象进行创建的。
import multiprocessing
def changevalue(n, a):
n.value = 3.14
a[0] = 5
if __name__ == '__main__':
num = multiprocessing.Value('d', 0.0)
arr = multiprocessing.Array('i', range(10))
p = multiprocessing.Process(target=changevalue, args=(num, arr))
p.start()
p.join()
print num.value
print arr[:]
最终输出的结果是num这个变量的值被修改成了3.14, 而这个修改的动作发生在子进程内部。与此同时, arr数组里的第一个元素值,也被更改为了数字5。
共享内存是在那个叫做pool的地方进行使用的, 具体的情况说明如下面所说的一样。
import multiprocessing
from multiprocessing import Pool
def changevalue(n, a):
n.value = 3.14
a[0] = 5
if __name__ == '__main__':
num = multiprocessing.Value('d', 0.0)
arr = multiprocessing.Array('i', range(10))
p = Pool()
p1 = p.apply_async(changevalue, args=(num, arr))
p.close()
p.join()
print num.value
print arr[:]
更多关于相关内容感兴趣的读者可查看本站专题:《进程与线程操作技巧总结》、《数据结构与算法教程》、《函数使用技巧总结》、《字符串操作技巧汇总》、《入门与进阶经典教程》、《+MySQL数据库程序设计入门教程》及《常见数据库操作技巧汇总》
本人希望在此文本中所阐述的相关内容, 能够对各位朋友在程序设计的方面, 带来一定的、并且是有益的参考与帮助。