python中进程和线程
进程Process
定义:进程是操作系统分配资源的基本单位,是程序的一次执行过程。每个进程拥有独立的内存空间、代码段和系统资源。
特点:
- 彼此独立,进程间的数据和资源默认不共享。
- 进程切换开销较大(因为涉及到切换内存页表、寄存器等资源)。
- 多核 CPU 上进程可以实现真正的并行执行。
python通过multiprocessing模块创建和管理进程。
from multiprocessing import Process
import timedef worker():print(f"Process {time.process_time()} start")time.sleep(2)print(f"Process {time.process_time()} end")processes = []
for i in range(3):p = Process(target=worker)processes.append(p)p.start()for p in processes:p.join()print("All processes finished.")
线程Thread
定义:线程是进程的一个执行单元,是 CPU 调度的最小单位。一个进程可以包含多个线程,这些线程共享进程的内存空间和资源。
特点:
- 同一进程内的线程共享代码段、数据段和堆区。
- 线程切换开销小,比进程切换更快。
- 线程间共享数据方便,但会引发同步问题(数据竞争、死锁等)。
python中通过threading模块创建和管理线程。
import threading
import timedef worker():print(f"Thread {threading.current_thread().name} start")time.sleep(2)print(f"Thread {threading.current_thread().name} end")threads = []
for i in range(3):t = threading.Thread(target=worker, name=f'Thread-{i}')threads.append(t)t.start()for t in threads:t.join()print("All threads finished.")
Python 的主线程退出,所有子线程会被强制结束。
num_workers
在我们深度学习训练过程中,通过需要设置num_workers,这其实设置的是数据加载的子进程数目。
当num_workers = 0 时,数据加载是在主进程中同步进行;
当num_workers > 0 时,pytorch会启动多个子进程来并行读取和预处理数据,从而加速数据加载,避免GPU因为等待数据而空闲。
num_workers是基于多进程实现的,pytorch 中的DataLoader采用的是python的multiprocessing模块来创建子进程,每个worker相互独立,在内存空间相互隔离。
如何设置num_workers?
一般num_workers = CPU核数
或CPU核数 - 1
:充分利用CPU资源,减少GPU等待;
总结
对比项 | 进程(Process) | 线程(Thread) |
---|---|---|
资源占用 | 资源开销大,独立内存空间 | 资源开销小,线程共享进程资源 |
切换开销 | 切换开销大(保存和加载内存上下文) | 切换开销小 |
通信方式 | 需借助 IPC(队列、管道、共享内存) | 共享内存,通信方便 |
并行能力 | 多核 CPU 上可实现真正并行 | 受 GIL 限制,CPU 密集型无并行 |
适用场景 | CPU 密集型任务,真正的并行计算 | I/O 密集型任务,多任务调度 |
稳定性 | 进程间相互独立,一进程崩溃不影响其他进程 | 一个线程异常可能导致整个进程崩溃 |
ps:面试题