并发和并行

计算机的整个历史中,有两个需求是驱动进步的持续动力:一个是我们想计算机做的更多,另一个是我们想计算机运行的更快。当处理器能够同时做更多的事情时,这两个因素都会改进。

术语 **并发(concurrency)**是一个通用的概念,指一个同时具有多个活动的系统;
而术语 **并行(parallelism)**指的是用并发来使一个系统运行的更快。
并行可以在计算机系统的多个抽象层次上运用。
在此,我们按照系统层次结构中由高到低的顺序重点强调三个层次。

线程级并发

构建在进程这个抽象之上,我们能够设计出同时有多个程序执行的系统,这就导致了并发。使用线程,我们甚至能够在一个进程中执行多个控制流。传统意义上,这种并发执行只是模拟出来的,是通过使一台计算机在它正在执行的进程间快速切换来实现的,这种并发形式允许多个用户同时与系统交互。在以前,即使处理器必须在多个任务间切换,大多数实际的计算也都是由一个处理器来完成的。这种配置称为单处理器系统
当构建一个由单操作系统内核控制的多处理器组成的系统时,我们就得到了一个多处理器系统
多核处理器是将多个CPU(称为核)集成到一个集成电路芯片上。下图描述的是一个典型多核处理器的组织结构
,其中微处理器芯片有4个CPU核,每个核都有自己的L1和L2高速缓存,其中的L1高速缓存分为两个部分——一个保存最近取到的指令,另一个存放数据。这些核共享更高层次的高速缓存,以及到主存的接口。
多核处理器的组织结构
超线程,有时称为同时多线程(simultaneous multi-threading),是一项允许一个CPU执行多个控制流的技术。它涉及CPU某些硬件有多个备份,比如程序计数器和寄存器文件,而其他的硬件部分只有一份,比如执行浮点算术运算的单元。常规的处理器需要大约20000个时钟周期做不同线程间的转换,而超线程的处理器可以在单个周期的基础上决定要执行哪一个线程。这使得CPU能够更好的利用它的处理资源。比如,假设一个线程必须等到某些数据被装载到高速缓存中,那CPU就可以继续去执行另一个线程。

多处理器的使用可以从两方面提高系统性能。首先,它减少了在执行多个任务时模拟并发的需要。其次,它可以使应用程序运行的更快,当然,这必须要求程序是以多线程方式来书写的,这些线程可以并行的高效执行。

指令级并行

在较低的抽象层次上,现代处理器可以同时执行多条指令的属性称为指令级并行。其实每条指令从开始到结束需要长的多的时间,大约20个或者更多周期,但是处理器使用了非常多的技巧来同时处理多达100条指令。在流水线的使用中,将执行一条指令所需要的活动划分成不同的步骤,将处理器的硬件组织成一系列的阶段,每个阶段执行一个步骤。这些阶段可以并发的操作,用来处理不同指令的不同部分。

如果处理器可以达到比一个周期一条指令更快的执行速率,就称之为超标量处理器。大多数现代处理器都支持超标量操作。

单指令、多数据并行

在最低层次上,许多现代处理器拥有特殊的硬件,允许一条指令产生多个可以并行执行的操作,这种方式称为单指令、多数据,即SIMID并行。例如,较新几代的Intel和AMD处理器都具有并行的对8对单精度浮点数做加法的指令。

提供这些SIMD指令多是为了提高处理影像、声音和视频数据应用的执行速度。虽然有些编译器会试图从C程序中自动抽取SIMD并行性,但是更可靠的方法是用编译器支持的特殊的向量数据类型来写程序,比如GCC就支持向量数据类型。

计算机系统中抽象的重要性

抽象的使用是计算机科学中最为重要的概念之一。例如,为一组函数规定一个简单的应用程序接口(API)就是一个很好的编程习惯,程序员无须了解它内部的工作便可以使用这些代码。不同的编程语言提供不同形式和等级的抽象支持,例如JAVA类的声明和C语言的函数原型。

在处理器里,指令集架构提供了对实际处理器硬件的抽象。使用这个抽象,机器代码程序表现得就好像运行在一次只执行一条指令得处理器上。底层得硬件远比抽象描述得要复杂精细,它并行的执行多条指令,但又总是与那个简单有序的模型保持一致。只要执行模型一样,不同的处理器实现也能执行同样的机器代码,而又提供不同的开销和性能。
计算机系统提供的一些抽象

  • 文件是对I/O设备的抽象
  • 虚拟内存是对程序存储器的抽象
  • 进程是对一个正在运行的程序的抽象
  • 虚拟机是对整个计算机的抽象