背景知识:线程与进程

在计算机的发展中,有两个持续的追求:让计算机能做更多事情和让计算机运行的更快。这两个目标都可以通过让 CPU 同时执行多个任务来实现。于是衍生出了两个概念:

  • 并发(Concurrency):系统中存在多个同时进行的活动。
  • 并行(Parallelism):利用并发来提高系统运行速度。

并行可以在计算机的多个层次上体现,以下从高到低说明三种类型。

并行和并发的形式

线程级并发(Thread-Level Concurren)

线程级并发基于进程的概念,可以让多个控制流同时执行。

  • 时间共享(time-sharing):20 世纪 60 年代,出现了时间共享系统,计算机通过快速上下文切换实现模拟并发执行。

Categorizing different processor configurations.

  • 单处理器系统(Uniprocessor):通过时间共享实现模拟并发。

  • 多处理器系统(Multiprocessor):多个 CPU(核心)由操作系统统一控制,可实现真正的并行。

    • 多核处理器(Multi-core):在同一颗芯片上集成多个 CPU 核心,每个核心有独立的 L1、L2,共享 L3 和 RAM。
    • 超线程技术 / 同时多线程(Hyperthreading/Simultaneous Multi-Threading):单个 CPU(核心)可以同时执行多个线程,利用空闲资源提高性能.如 AMD RYZEN 9 9950X 的 16 核 CPU 可以同时执行 32 个线程。
image.png

Multi-core processor organization.

指令级并行

了解指令级并行,需要先了解几个和 CPU 时钟有关的概念。

  • CPU 时钟(Clock):CPU时钟是中央处理器自带的计时单元,其基本工作单位为时钟周期,即处理器执行操作的最小时间单位。
  • 时钟周期(Clock Cycle):时钟频率的倒数,是计算机中最基本的、最小的时间单位。在一个时钟周期内,CPU 仅完成一个最基本的动作。
  • 时钟频率 / 时钟速度(Clock Frequency / Clock Rate):CPU 每秒能完成的时钟周期数,单位为 Hz、GHz。决定 CPU 执行指令的速度。时钟频率越高,理论上 CPU 执行指令越快。

时钟周期时间= 1 时钟频率

  • 指令周期 / 提取-执行周期(Instruction cycle / fetch-and-execute cycle):CPU 完成一条机器指令所需要的时钟周期数。

指令执行时间=指令周期数 × 时钟周期时间

  • CPU 主频(CPU Clock Speed / CPU Clock Rate):CPU 内部核心运行的时钟频率。
  • 总线频率(Bus / Front Side Bus, FSB):CPU 与内存、外围设备通信的频率,影响数据传输速度。
  • 超频(Overclocking):提高 CPU 时钟频率以提升性能,但会增加功耗和发热,需要散热和稳定性保证。

回到指令级并行,现代处理器可以同时执行多条指令:

  • 早期微处理器(如 8086)执行一条指令需要多个时钟周期。
  • 现代处理器可以在一个时钟周期内处理 2~4 条指令。
  • 超标量处理器(Superscalar Processors):能在一个周期内执行多条指令,具体比较复杂,以后会进一步研究。

但是,时钟周期的定义中有在一个时钟周期内,CPU 仅完成一个最基本的动作,为什么现代处理器可以在一个时钟周期内处理 2~3 条指令呢?

理论上,CPU 时钟周期很短,每个周期只能驱动一个基本操作(如寄存器读取、ALU 加法、内存访问等),所以如果没有优化,CPU 执行一条完整指令需要多个时钟周期。

这就和几个技术相关:

  • 流水线(Pipelining):简单来说,流水线技术就是将指令执行分解为多个阶段,每个阶段同时处理不同指令的不同部分。具体深入相当复杂,这里部研究。
  • 超标量 / 多发射(Superscalar / Multiple Issue):现代 CPU 核心有多个执行单元(ALU、FPU、加载/存储单元),在一个时钟周期内,可以同时发射多条指令到不同单元执行。结合流水线,每个时钟周期实际上可能有 2–4 条指令同时在不同阶段执行。
  • 高级技术:太过复杂,这里不做研究。
    • 超流水线(Deep Pipeline)
    • 向量化 / SIMD
    • 多核并行

所以在现代 CPU 中,单条指令仍然需要多个周期完成。流水线 + 超标量 + 高级并行技术让 CPU 可以在同一时钟周期处理多条指令,看起来像一个周期完成多条指令,实质是硬件并行。

应用程序可以通过优化代码,提高指令级并行,从而让程序运行更快。

SIMD 并行(单指令、多数据并行)

这是最底层的并行方式,涉及 CPU 底层,不深究。

并行和并发的区别

Erlang 之父 Joe Armstrong 用一张漫画解释了并行和并发:

image.png

并发和并行都是对“多任务”处理的描述,其中并发是轮流处理,而并行是同时处理。

展开来讲,并发是多个任务同时使用一个 CPU 核心,依赖时间共享,通过上下文切换,在不同任务之间切换 CPU 控制权。多个任务使用核心的时间不一定是一样的。看起来同时在进行,但实际上 CPU 核心一次只能处理一个任务。可以类比单核 CPU 的多任务。

并行是多个任务使用多个 CPU 核心,从物理上同时执行,可以类比多核 CPU。

所以,可以概括出:

  • 并发是对多任务调度和组织的描述,关注“如何让任务能一起推进”。
  • 并行是对物理执行方式的描述,关注“如何让多个任务真同时运行”。
  • 并发可以没有并行(单核 CPU 靠时间共享和上下文切换)。
  • 并行必然包含并发(多核多任务调度)。

为什么说并行必然包含并发?

这就涉及到任务调度和执行本质的理解。

  1. 从任务角度看
    • 并发:多个任务同时存在,并且都在推进。
    • 并行:多个任务在物理上真正同时运行。
      • 也就是说,要实现并行,前提是系统中多个任务并存,而“多个任务并存”就是并发的定义。
  2. 从操作系统看

并行执行时,多个核心同时跑不同任务。但是核心数往往 < 任务数,比如 4 核 CPU 跑 100 个任务。这时,操作系统依然要用并发调度(时间片 + 上下文切换),把更多任务“并发地”映射到有限的核心上。所以,并行只是并发的一种特殊实现形式。

总结

并发和并行是理解现代计算机性能优化的核心概念。随着多核处理器、超线程、GPU 并行计算等技术的发展,今天的软件开发者不仅需要理解操作系统层面的并发模型,还要学会利用底层硬件提供的并行能力,从而让程序真正跑得更快。了解并发和并行,是学习并发编程的第一块敲门砖。

参考文献

Bryant, R. E., & O’Hallaron, D. R. (2015). Computer Systems: A Programmer’s Perspective (3rd ed.). Pearson.