【python】并发编程——多进程

1 一些概念

1.1 并行与并发

并发concurrency

并发指计算机同时管理多个和任务的能力。这些任务并不要求在每时每刻同时执行,但是可能在一段时间内交错执行。并发的任务是处理多个用户输入,管理多个I/O任务,或者处理多个独立任务。并发适合依赖诸如文件和网络数据等外部资源的I/O约束型的操作。

并行parallelism

并行是并发的子集。并发要求多个任务每时每刻同时执行。并行的任务是提升计算效率和加速系统性能。并行需要利用多核CPU特性,适合CPU密集型任务。

concurrency in Python

并发类型

  • processed-based concurrency:multiprocessing
  • thread-based concurrency:threading
  • coroutine-based concurrency:async/await关键字

补充:python提供concurent.future库来提供进程/线程并发

1.2 多处理器系统

多核系统:CPU芯片上集成多个核心,结构上可以是对称多处理SMP(所有核心地位相同)和非对称处理(核心有主从之分)。
集群系统:两个或者多个独立系统通过计算机网络组成。将应用程序的不同部分并行运行在集群的不同系统上的技术称为并行计算技术。集群系统结构上可以是对称或者非对称的。

1.3 CPU,物理核心,逻辑核心,超线程

CPU:中央处理器,一个CPU芯片可以集成多个CPU核心。
CPU物理核心:有独立的电路,L1,L2高速缓存,能独立执行指令。
CPU逻辑核心:应用程序将一个高速运转的CPU物理核心看做一个或者多个核心,应用程序视角下的核心就是逻辑核心。如果一个物理核心对应两个逻辑核心,意味着CPU采用了超线程技术。逻辑CPU数量=同时可执行的线程数。
超线程:超线程可以在一个逻辑核等待指令执行的间隔(等待从cache或内存中获取下一条指令),把时间片分配到另一个逻辑核。CPU在这两个逻辑核之间高速切换,让应用程序感知不到这个间隔,误认为自己是独占了一个核。实现超线程需要在CPU物理核心内设置冗余部件,才能让多个线程运行在一个物理核心上,从而实现一个物理核心对应多个逻辑核心。
在这里插入图片描述

# mac
# 查看CPU型号
sysctl machdep.cpu.brand_string
# 查看CPU物理核心数
sysctl hw.physicalcpu
# 查看CPU逻辑核心数
sysctl hw.logicalcpu

# linux
# 查看CPU型号
cat /proc/cpuinfo | grep "model name"
# 查看CPU物理核心数
~$ lscpu -p | egrep -v '^#' | wc -l
# 查看CPU逻辑核心数
~$ lscpu -p | egrep -v '^#' | sort -u -t, -k 2,4 | wc -l

2 Python多进程

python多线程无法利用多核优势,在执行并发任务需要使用多进程来完成

2.1 进程池

2.1.1 阻塞调用方式

调用进程会在执行p.map()时阻塞,直到所有任务执行完毕返回结果。p.map()返回的结果列表顺序和参数列表顺序一致。p.imap_unordered()返回的结果列表顺序和参数列表顺序不一致。

from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == '__main__':
    with Pool(5) as p:
        print(p.map(f, [1, 2, 3]))  # [1, 4, 9]
        print(p.imap_unordered(f, range(10)))  # arbitrary order
# 数据并行:将数据分成多个部分,分配给多个进程执行

2.1.2 非阻塞调用方式

方式一:使用apply_async
from multiprocessing import Pool, TimeoutError
import time
import os

def f(x):
    return x*x

if __name__ == '__main__':
    # start 4 worker processes
    with Pool(processes=4) as pool:
        # evaluate "f(20)" asynchronously
        res = pool.apply_async(f, (20,))      # runs in *only* one process
        print(res.get(timeout=1))             # prints "400"

        # evaluate "os.getpid()" asynchronously
        res = pool.apply_async(os.getpid, ()) # runs in *only* one process
        print(res.get(timeout=1))             # prints the PID of that process

        # launching multiple evaluations asynchronously *may* use more processes
        multiple_results = [pool.apply_async(os.getpid, ()) for i in range(4)]
        print([res.g
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值