程序的并行与并发
计算机资源充足时,如何通过并行设计提高效率
并行与并发的区别:
并发:宏观上,多个任务同时执行
并行:同一时刻发生
并发:一个CPU核心交替运行多个程序
并行:多个CPU核心同时处理多个程序
利用concurrent库实现并行计算
concurrent.futures库中的Executor对象是并行任务的抽象类
他可以由线程和进程两种方式实现并行计算
Executor可以通过submit()方式执行
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=1) as executor:
future = executor.submit(pow, 323, 2)
print(future.result())
线程池
- Executor对象还支持ThreadPoolExecutor方式,使用线程池实现并发
- 它还支持ProcessPoolExecuter方式,以使用多核CPU
总结
- 并发编程能够更充分利用系统资源
- 使用concurrent.futures库可以实现复杂的并行人物计划
- concurrent.futures库既可以使用多线程模型,也能使用多进程模型
进程和线程的差别
- 在Cpython中,由于存在GIL(全局解释器锁),同一时刻只能有一个线程能执行
- I/O密集型应用可使用多线程模型
- 计算密集型应用应当使用多进程模型
进程通信
-
concurrent并行任务的底层库是multiprocessing库
-
使用multiprocessing库可以实现多进程任务:
from multiprocessing import Poll with Poll(10) as o: p.map(函数对象,参数)
-
多个进程独立执行,无法进行数据交互
-
多进程间通行,可以支持以下几种方式:
-
队列
from multiprocessing import Queue q = Queue(3) q.put("11") q.put("22") q.put("33") # q.put("44") print(q.full()) print(q.empty()) print(q.qsize())
-
管道
from multiprocessing import Pipe a, b = Pipe() # 管道默认情况下是双工的 a,b都有send()和recv()方法 a.send([1, "hello", None]) print(b.recv())
-
共享内存
from multiprocessing import shared_memory shm = shared_memory.SharedMemory(create=True, size=10) buffer = shm.buf buffer_b = shm.buf buffer[:4] = bytearray([22, 33, 44, 55]) buffer[4] = 100 # for i in buffer: # print(i) for i in buffer_b: print(i)
-
总结:
- 多进程用于计算密集型程序
- 多进程的变量无法直接通信,需要使用队列、管道和消息队列机制实现通信