python多线程能提高效率吗?

多线程在I/O密集型任务中表现得比较出色。在这种情况下,线程可以在等待I/O操作完成的过程中,切换到其他线程执行,从而充分利用CPU的时间,提高程序的整体效率。典型的I/O操作包括文件读写、网络请求、数据库访问等。由于在等待外部资源时,线程可以进行并发执行,所以多线程在这些场景中通常能带来明显的性能提升。

  然而,对于CPU密集型任务,多线程的优势就不太明显了,甚至可能会导致性能下降。Python的全局解释器锁(GIL)限制了同一时间只能有一个线程执行Python字节码,这意味着多线程在同一时间内无法利用多核处理器的能力,无法实现真正的并行执行。因此,在CPU密集型任务中,多线程可能会由于线程切换的开销以及GIL的限制而导致效率不高。

  总而言之,多线程在Python中在I/O密集型任务中通常能够提高效率,但在CPU密集型任务中可能效果有限。如果要充分利用多核处理器并实现真正的并行,更适合使用多进程。在选择多线程还是多进程时,需要根据任务的性质和要求来权衡。

如何理解 CPU密集型 和 I/O密集型?

说在前面,CPU密集型与I/O密集型是在计算机上执行任务的两种策略,在并发执行任务场景下,我们需要选择使用多线程或多进程;

如果是IO密集型任务,使用多线程,如果是CPU密集型任务,使用多进程。

前者指内存磁盘I/O使用率高,CPU使用率低;相反,后者指CPU使用率高,内存磁盘I/O使用率低。

CPU密集型

CPU密集型,也叫计算密集型,一般是指服务器的硬盘、内存硬件性能相对CPU好很多,或者使用率低很多。系统运行CPU读写I/O(硬盘/内存)时可以在很短的时间内完成,几乎没有阻塞(等待I/O的实时间)时间,而CPU一直有大量运算要处理,因此CPU负载长期过高。

CPU密集几乎无I/O阻塞,CPU一直会全速运行。如果是单核情况下,开多线程是没有意义的,说白了就是一个CPU来回切着运行而已,徒增线程切换的资源消耗,卵用没有。可见,CPU密集任务只有在多核CPU上、开多线程才可能提速。

CPU使用率较高时(如我们训练算法模型、搞训练集),通常线程数只需要设置为CPU核心数的线程个数就可以了。单CPU对应单线程效率最高。

一般其计算公式可遵循:CPU密集型核心线程数 = CPU核数。

I/O密集型

I/O密集型相反,一般是指服务器CPU的性能相对硬盘、内存硬件好很多,或者使用率低很多。系统运行多是CPU在等I/O (硬盘/内存) 的读写操作,此类情景下CPU负载并不高。

I/O密集型的程序一般在达到性能极限时,CPU占用率仍然较低。这可能是因为任务本身需要大量I/O操作,而程序的逻辑做得并不好,没有充分利用CPU能力,导致线程空余时间很多。通常我们会开CPU核心数数倍的线程,在线程进行 I/O 操作 CPU 空闲时,启用其他线程继续使用 CPU,以提高 CPU 的使用率,充分利用CPU资源。

一般其计算公式可遵循:I/O密集型核心线程数 = CPU核数 / (1-阻塞系数)。

阻塞系数在在0到1范围内。一般为0.8~0.9之间,也可以取0.8或者0.9。对于双核CPU来说,它比较理想的线程数就是20,当然这都不是绝对的,需要根据实际情况以及实际业务来调整。

小结

  • I/O密集型:当线程等待时间所占比例越高,需要越多线程,启用其他线程继续使用CPU,以此提高CPU的利用率;
  • CPU密集型:当线程CPU时间所占比例越高,需要越少的线程。任务越多,花在进程、线程切换的时间就越多,通常线程数和CPU核数一致即可,这一类型在开发中主要出现在一些计算业务频繁的逻辑中。

I/O密集型任务的特点是CPU消耗很少,任务的大部分时间都在等待I/O操作完成(磁盘I/O远低于内存、CPU速度)。涉及到网络、磁盘I/O的任务多是I/O密集型任务。I/O密集型任务,线程数越多,CPU效率越高,但也有相对限度。

留下评论