进程、线程、协程、并发、并行
一、进程、线程
概念
- 进程是操作系统资源分配(内存,显卡,磁盘)的最小单位;
- 线程是执行调度(即cpu调度)的最小单位(cpu看到的都是线程而不是进程),一个进程可以有一个或多个线程,线程之间共享进程的资源。
与并行、并发的关系
- 微观上说,多核CPU可以同时执行多个进程,并行执行的最大进程数与CPU核数相当(前提是每个核心拥有自己的MMU内存管理单元,目前英特尔的已具备)。
- 但宏观上说,由于CPU会分时间片执行多个进程,所以实际执行进程个数会远多于CPU核数。
- 如果是下图中,多核共用一个MMU,那么是没办法并行多个进程的;但是同一个进程下的多线程可以在多个核心下并行执行,因为多线程共享同一套进程空间资源。
- 一个进程内的多个线程可以并行在多核上运行(无论是否只有一个MMU):因为cpu的眼里没有进程的概念,线程是cpu的最小调度单位。
python中的多进程、多线程
- 但在 Python 中,无论是单核还是多核,一个进程同时只能由一个线程在执行。其根源是 GIL 的存在。GIL 的全称是 Global Interpreter Lock(全局解释器锁),来源是 Python 设计之初的考虑,为了数据安全所做的决定。某个线程想要执行,必须先拿到 GIL,我们可以把 GIL 看作是“通行证”,并且在一个 Python 进程中,GIL 只有一个。拿不到通行证的线程,就不允许进入 CPU 执行。所以多线程在python中很鸡肋。
二、并行
实现并行计算有三种方式
1)多线程,2)多进程,3)多进程+多线程
- 如果是多进程,因为每个进程资源是独立的(地址空间和数据空间),就要在操作系统层面进行通信,如管道,队列,信号等;
- 多线程的话会共享进程中的地址空间和数据空间,一个线程的数据可以直接提供给其他线程使用,但方便的同时会造成变量值的混乱,所以要通过线程锁来限制线程的执行其他语言,CPU 是多核时是支持多个线程同时执行。
三、与DL分布式训练的关系
- 一般情况下,会为每个GPU重新开辟一个进程(这n个进行基本相同);同时,也可以一个进程控制多个GPU;
- 每个进程需要知道此进程在所有进程中的序号(rank),以及每个进程下GPU的编号(local rank);
四、多个进程同时操作一个文件
- 表示多核之间的各自缓存内有同时指向同一地址的数据的cache line;即多个进程内的逻辑地址同时映射到了同一物理地址;
- 若出现这种情况,一般会通过Snooping-based 或者 Directory-based两个机制来保证这些cache line能保持一致(总之,就是当有一个进程在操作此文件时,要排除其他进程对此文件的操作)。