python多线程与多进程使用选择对比

目录

并发和并行

并发和并行含义

CPU与并行并发

进程和线程、并发并行

资源消耗与切换

CPU密集型和IO密集型含义

python解释器和cpu之间的关系

python中的多线程多进程对比

为什么cpu在进程之间切换要比在线程之间切换开销大


并发和并行

并发和并行含义

  • 并发就是操作系统使用时间片轮转算法让各个任务交替执行,但是间隔时间非常短,比如任务1执行0.01秒,任务2执行0.01秒,再切换到任务3,这样反复执行下去,表面上看是交替执行的,但是由于间隔时间短和CPU执行速度实在太快,我们感觉所有的任务都是在同时执行一样。这种执行方式叫做并发,就是在非常短的间隔时间内交替执行多个任务。
  • 并行就是真正的将多个任务同时运行。

CPU与并行并发

一个CPU同时刻只能执行一个进程,并行执行多任务只能在多核CPU上实现

  • 并行:比如有两个核,要执行两个任务,开启两个进程,在同一时刻一个核操作一个进程,这时就是并行
  • 并发:比如有两个核,要执行两个任务,开启两个进程,但是将这两个进程放到一个核上来执行,这时就是并发

对于多核CPU来说

  • 当任务数小于CPU的核心数量时,每个任务都可以在一个核上执行,这时可以用并行,也可以用并发,具体用并发还是并行,程序员无法控制,操作系统通常会尽量将任务分配到不同的核心上以实现并行执行。
  • 当任务数多于CPU核心数量时,操作系统会使用调度算法(如时间片轮转、优先级调度等)来交替执行这些任务,从而实现并发。

进程和线程、并发并行

  • 运行一个程序会产生一个进程
  • 线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程可以并发多个线程,每条线程执行不同的任务。

计算机存在多个进程,每个进程存在一个或者多个线程。多个进程的运行是并行还是并发取决于操作系统,而同一个进程下的多个线程一定是并发。

资源消耗与切换

CPU密集型和IO密集型含义

  • CPU密集型(CPU-bound)是指程序在执行过程中,主要花的时间在CPU上,而非I/O操作(如磁盘读写、网络通信等)。这类任务通常涉及大量的计算和逻辑判断等操作上,例如科学计算、图像处理、加密解密、机器学习中的模型训练和推理等。花在cpu上的时间可能取决两方面原因,一是确实需要大量的计算判断等操作,二是cpu硬件不行。
  • I/O密集型任务,是指程序在执行过程中,花的时间主要在网络、磁盘的IO上,这类任务的特点是CPU少,任务大部分时间都在等待IO。如果cpu的性能非常非常高,则会造成大部分时间是CPU在等待IO。

cpu密集型和io密集型是相对的,cpu时间相对多一些,则为cpu密集型。

常见CPU密集型操作:压缩解压缩(因为涉及到复杂算法的计算)、加解密(因为涉及到复杂算法的计算)、正则表达式搜索。

常见IO密集型:文件处理程序、网络爬虫程序、读写数据库程序。

python解释器和cpu之间的关系

Python解释器是代码与计算机硬件之间的软件逻辑层。当你编写了一段Python程序后,Python解释器会读取这段程序,并将其中的命令翻译成计算机CPU能理解的机器指令语言,然后执行这些指令,从而得到结果。

python中的多线程多进程对比

多线程(threading)

  • 全局解释器锁(GIL):Python的全局解释器锁(GIL)限制了同一时间只有一个线程可以执行Python字节码。这意味着,即使你使用了多线程,Python代码在CPU密集型任务上也不会实现真正的并行执行。但是,对于I/O密集型任务(如网络请求、文件读写等),多线程仍然可以提高效率,因为GIL会在I/O操作期间释放。
  • 共享内存:线程之间共享同一块内存空间,这使得线程间的数据共享和通信变得简单。但是,这也增加了线程同步和互斥的需求,以避免数据竞争和不一致。
  • 开销:线程的创建和销毁通常比进程更轻量级,因为它们不需要分配独立的内存空间。

计算需要用到CPU,但是对于多线程来说,只用了一个CPU,如果每个线程都要进行计算任务,CPU的使用需要在不同线程之间不断切换,既有切换成本,而且其它线程还要等待正在占用cpu的那个线程释放出cpu的时候才有机会使用上cpu,效率不高,因此多个计算密集型任务不适合用多线程,因此计算密集型适合用多进程。用多进程处理计算任务,可以并行处理,因为每个进程有自己的cpu。

多进程(multiprocessing)

  • 并行执行:由于每个进程都有自己的内存空间和Python解释器,因此它们可以并行执行Python代码,而不受GIL的限制。这使得多进程在CPU密集型任务上更具优势。
  • 数据隔离:进程之间的内存是隔离的,这意味着每个进程都有自己的数据副本。这减少了数据竞争和不一致的风险,但也增加了数据共享和通信的复杂性。
  • 开销:进程的创建和销毁通常比线程更重量级,因为它们需要分配独立的内存空间和其他系统资源。

对于IO密集型任务来说,不太使用CPU,如果创建的是多进程,通常意味着至少使用了一个cpu,占用了多个cpu又基本用得少,浪费资源,而且在用的时候,cpu在不同进程之间切换频繁,切换成本大(这里的成本大是比较而言的,指的是cpu在进程之间切换要比在线程之间切换开销大,具体原因见下文)。因此cpu占用和切换会消耗大量资源。

为什么cpu在进程之间切换要比在线程之间切换开销大

(1)上下文切换的开销:

  • 进程切换需要保存和恢复更多的上下文信息。这些上下文信息包括进程的程序计数器、寄存器状态、内存映射、I/O状态等,保存和恢复这些信息需要消耗较多的时间。进程拥有独立的资源,如文件描述符、信号处理器等,进程切换时需要切换和管理这些资源,增加了切换的复杂性和开销。
  • 而线程切换只需要保存和恢复线程的上下文信息,由于线程共享同一进程的地址空间,线程的上下文信息相对较少,因此线程切换的开销较小。线程共享同一进程的资源,因此线程切换不涉及资源的切换和管理,减少了切换的开销。

(2)地址空间的切换:

  • 每个进程都有自己的虚拟地址空间,进程切换时需要切换地址空间的映射关系。这涉及到页表的切换和TLB(Translation Lookaside Buffer)的刷新等操作,开销较大。
  • 线程则共享同一进程的地址空间,线程切换不涉及地址空间的切换,因此开销较小。


end

  • 51
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值