csapp 第六章读书笔记 part1

29 篇文章 0 订阅
28 篇文章 0 订阅

csapp 第六章读书笔记 part1

作为程序员,需要理解内存层次结构,因为它对你的应用程序的性能有很大影响。如果你的程序需要的数据存储在CPU寄存器中,那么它们可以在指令执行期间以0个周期的时间访问。如果存储在缓存中,则需要4到75个周期。如果存储在主内存中,则需要数百个周期。如果存储在磁盘中,则需要数千万个周期!

如果你了解系统如何在内存层次结构中传递数据,那么你可以编写应用程序,使其数据项存储在更高的层次,这样CPU可以更快地访问它们。

locality:
Programs with good locality tend to access the same set of data items over and over again, or they tend to access sets of nearby data items. 具有良好局部性的程序往往会反复访问相同的一组数据项,或者它们会访问附近的一组数据项。

Storage Technologies

Random Access Memory

随机存取存储器(RAM)有两种类型:静态RAM(SRAM)和动态RAM(DRAM)。静态RAM比动态RAM更快,但价格也显著更高。静态RAM用于CPU芯片上和CPU芯片外的高速缓存存储器。动态RAM用于主内存以及图形系统的帧缓冲区。通常,桌面系统的静态RAM容量不会超过几十兆字节,而动态RAM容量可能达到几百或几千兆字节。

Static RAM

在这里插入图片描述

静态随机存取存储器(SRAM)是一种常见的计算机内存技术,用于存储和访问数据。与动态随机存取存储器(DRAM)相比,SRAM具有更快的访问速度和更低的功耗。

SRAM使用一种称为双稳态存储单元的电路来存储数据。每个存储单元由多个晶体管组成,通常是6个晶体管。这种电路具有两个稳定的状态,分别对应于逻辑0和逻辑1。当电源关闭时,SRAM可以保持存储的数据,而无需刷新。

由于SRAM使用的电路比DRAM更复杂,因此SRAM的成本更高。因此,SRAM通常用于需要快速访问速度和较小容量的存储器,例如CPU的高速缓存存储器(cache memory)。SRAM还可以用于其他高性能应用,如网络交换机和嵌入式系统。

尽管SRAM的访问速度较快,但它的存储密度相对较低。这意味着相同的物理空间内,SRAM存储的数据量比DRAM少。因此,大容量存储器通常使用DRAM。

总之,SRAM是一种速度快、功耗低的存储技术,适用于需要快速访问和较小容量的存储器应用。

在这里插入图片描述
总结:SRAM和DRAM存储器的特性。只要有电源供应,SRAM就是持久的。与DRAM不同,不需要刷新。SRAM的访问速度比DRAM快。SRAM不对光线和电气噪声等干扰敏感。权衡是SRAM单元使用的晶体管比DRAM单元多,因此密度较低,更昂贵,耗电量更大。

Dynamic RAM

DRAM将每个位存储为电容上的电荷。这个电容非常小 - 通常约为30飞秒法拉德,即30×10-15法拉。然而,法拉是一个非常大的度量单位。DRAM存储可以非常密集 - 每个单元由一个电容和一个单个访问晶体管组成。然而,与SRAM不同,DRAM存储单元对任何干扰都非常敏感。当电容电压受到干扰时,它将永远无法恢复。暴露在光线下会导致电容电压发生变化。实际上,数码相机和摄像机中的传感器本质上就是DRAM单元的阵列。

各种泄漏电流源导致DRAM单元在大约10至100毫秒的时间段内失去电荷。幸运的是,对于以纳秒为单位测量时钟周期的计算机来说,这个保持时间相当长。内存系统必须定期刷新每个内存位,通过读取并重新写入它来实现。1 毫秒(ms)= 1,000,000 纳秒(ns)
一些系统还使用纠错码,其中计算机字使用更多的位进行编码(例如,一个64位字可以使用72位进行编码),以便电路可以检测和纠正字中的任何单个错误位。

Conventional DRAMs

DRAM芯片中的单元(位)被划分为d个超单元,每个超单元由w个DRAM单元组成。一个d * w的DRAM存储器总共存储了dw个位的信息。超单元被组织成一个具有r行和c列的矩形阵列,其中rc = d。每个超单元具有形式为(i,j)的地址,其中i表示行,j表示列。
在这里插入图片描述

Information flows in and out of the chip via external connectors called pins. Each pin carries a 1-bit signal.
每个DRAM芯片都连接到一些电路,称为内存控制器,它可以一次传输w位。

To read the contents of supercell (i, j ), the memory controller sends the row address i to the DRAM, followed by the column address j . The DRAM responds by sending the contents of supercell (i, j ) back to the controller. The row address i is called a RAS (row access strobe) request. The column address j is called a CAS (column access strobe) request. Notice that the RAS and CAS requests share the same
DRAM address pins. Notice that the RAS and CAS requests share the same DRAM address pins.
在这里插入图片描述

Memory Modules

在这里插入图片描述

DRAM chips are packaged in memory modules that plug into expansion slots on the main system board (motherboard). Core i7 systems use the 240-pin dual inline memory module (DIMM),which transfers data to and from the memory controller in 64-bit chunks.

DRAM芯片被封装在内存模块中,插入主系统板(主板)上的扩展插槽中。Core i7系统使用240引脚的双列直插内存模块(DIMM),它以64位块的形式将数据传输到内存控制器和从内存控制器传输数据。
使用8个64-Mbit 8M × 8 DRAM芯片,编号为0到7。每个超单元存储1个字节的主存储器,主存储器中A地址的64位由相应的8个超单元地址为(i,j)在不同的DRAM芯片组成。DRAM 0存储第一个(低位)字节,DRAM 1存储下一个字节,以此类推。

Main memory can be aggregated by connecting multiple memory modules to the memory controller. In this case, when the controller receives an address A, the controller selects the module k that contains A, converts A to its (i, j ) form, and sends (i, j ) to module k.
先选择memory module k, 转化地址A成为(i,j), 在发送(i,j) 到module k的memory controller 。

Enhanced DRAMs

有许多种类的DRAM存储器,并且随着制造商努力跟上处理器速度的快速增长,市场上会定期出现新的种类。每种DRAM存储器都基于传统的DRAM单元,通过优化来提高基本DRAM单元的访问速度。

Fast page mode DRAM (FPM DRAM)

Fast Page Mode DRAM (FPM DRAM)是一种动态随机存取存储器(DRAM),在20世纪90年代的个人电脑中广泛使用。FPM DRAM是对早期的扩展数据输出(EDO DRAM)的改进,它提供了更快的访问时间和改进的性能。

FPM DRAM的关键特点是它能够在同一行内访问多个存储位置,而无需为每个位置重新访问行地址。这是通过使用页面模式实现的,其中行地址被锁存并保持恒定,而多个列地址被提供以访问该行内的不同存储位置。这显著降低了在同一行内连续内存访问的访问时间。

FPM DRAM的总线速度为33 MHz或更低,典型的访问时间为70-80纳秒。它使用72针SIMM(单行内存模块)或168针DIMM(双行内存模块)的形式因子安装在主板上。

尽管相对于以前的DRAM技术有着改进的性能,但FPM DRAM仍存在一些限制。它消耗电力高,产生大量热量。它的内存密度有限,通常在4MB到128MB之间。此外,FPM DRAM无法以更高的总线速度运行,使其在现代计算需求下不太适用。

由于这些限制,FPM DRAM已经基本被更先进的内存技术(如同步DRAM和其后续技术)所取代。

Extended data out DRAM

Extended Data Out DRAM (EDO DRAM)是一种动态随机存取存储器(DRAM),它在20世纪90年代广泛应用于个人电脑。EDO DRAM是对早期的Fast Page Mode DRAM(FPM DRAM)的改进,提供了更高的性能和速度。

EDO DRAM的主要改进是它能够在读取数据后继续输出数据,即使列地址已经改变。在传统的FPM DRAM中,一旦列地址改变,输出数据就会被禁用,导致在内存访问期间浪费时间。而EDO DRAM允许在列地址改变后的一小段时间内继续输出数据,从而实现更快的连续内存访问。

EDO DRAM的总线速度为66 MHz或更低,典型的访问时间为50-60纳秒。它使用72针SIMM(单行内存模块)或168针DIMM(双行内存模块)的形式因子安装在主板上。

相比于FPM DRAM,EDO DRAM在内存访问速度方面提供了更高的性能。然而,它仍然存在一些限制,如较高的功耗和热量产生。此外,EDO DRAM的内存密度有限,通常在4MB到128MB之间。

随着更先进的内存技术的出现,如同步DRAM(SDRAM)及其后续技术,EDO DRAM已经被逐渐淘汰,不再常用于现代计算系统中。

Synchronous DRAM (SDRAM)

同步动态随机存取存储器(Synchronous DRAM,SDRAM)是一种内存技术,它在计算机系统中被广泛使用。与传统的动态随机存取存储器(DRAM)相比,SDRAM具有更高的性能和速度。

SDRAM与系统总线同步工作,这意味着内存访问速度与系统总线速度保持一致。它使用了内部时钟来同步数据传输,这使得SDRAM能够以更高的速度传输数据。

SDRAM具有多个内部存储区域,称为“bank”。每个bank都有一个地址线和一个数据线。通过选择不同的地址线,可以同时访问多个bank,从而提高内存访问效率。

SDRAM还具有预取功能,它可以在一次内存访问中预取多个连续的数据。这意味着,当CPU请求一块数据时,SDRAM会提前将其后续的数据预取到内部缓存中,以便下一次访问时能够更快地提供数据。

SDRAM有多种类型,包括SDR SDRAM(Single Data Rate SDRAM)和DDR SDRAM(Double Data Rate SDRAM)。DDR SDRAM是SDRAM的一种进化版本,它在每个时钟周期内能够传输两次数据,从而提供了更高的带宽和性能。

SDRAM广泛用于计算机内存、图形处理器和其他需要高速数据传输的应用中。随着技术的不断发展,SDRAM的速度和容量不断提高,成为现代计算机系统中的主要内存类型。

Double Data-Rate SynchronousDRAM(DDR SDRAM)

双倍数据速率同步动态随机存取存储器(Double Data-Rate Synchronous DRAM,DDR SDRAM)是一种内存技术,它在计算机系统中被广泛使用。DDR SDRAM是SDRAM的一种进化版本,提供了更高的数据传输速度和带宽。

DDR SDRAM能够在每个时钟周期内传输两次数据,这意味着它的数据传输速度是SDRAM的两倍。这是通过在上升沿和下降沿时都传输数据来实现的,从而使得DDR SDRAM能够在同样的时钟频率下传输两倍的数据。

DDR SDRAM还引入了“预取”和“双倍预取”功能,以提高内存访问效率。预取是指在一次内存访问中预取多个连续的数据,而双倍预取则是在每个时钟周期内预取两次数据。这样,当CPU请求一块数据时,DDR SDRAM能够提前将其后续的数据预取到内部缓存中,以便下一次访问时能够更快地提供数据。

DDR SDRAM有多个版本,包括DDR、DDR2、DDR3和DDR4。每个版本都提供了更高的数据传输速度和带宽,同时也引入了新的技术和改进。例如,DDR2 SDRAM引入了高频率操作和更高的内存密度,而DDR3和DDR4 SDRAM进一步提高了数据传输速度和能效。

DDR SDRAM广泛用于计算机内存、图形处理器、服务器和其他需要高速数据传输的应用中。它已成为现代计算机系统中的主要内存类型,为系统提供了更高的性能和响应能力。

Video RAM (VRAM)

视频随机存取存储器(Video RAM,VRAM)是一种专门用于图形显示的内存技术。它被广泛应用于计算机图形卡和视频游戏机等设备中。

VRAM具有与普通随机存取存储器(RAM)相似的功能,但它具备一些特殊的特点,使其适用于处理图形和视频数据。

首先,VRAM具有双端口结构,即它可以同时进行读取和写入操作。这使得图形处理器能够在读取数据的同时,将图像数据写入VRAM,从而实现快速的图像渲染和显示。

其次,VRAM具有高带宽和低延迟的特性。这使得它能够快速地传输大量的图像数据,以满足高分辨率和高帧率的显示需求。与普通RAM相比,VRAM的带宽更高,能够更快地将图像数据传输到显示器。

此外,VRAM还具有一些特殊的功能,如行缓冲(Line Buffer)和颜色扩展(Color Expansion)。行缓冲是指VRAM中存储了一行图像数据,这样图形处理器可以快速地访问和处理整行数据。颜色扩展是指VRAM中存储了额外的颜色信息,使得图像处理器能够实现更丰富的颜色显示。

VRAM广泛应用于计算机图形卡、游戏机和其他需要高性能图像处理的设备中。它通过提供高带宽、低延迟和特殊的功能,为这些设备提供了流畅、高质量的图像和视频显示。随着技术的发展,VRAM的容量和性能不断提升,为图形和视频应用带来更多可能性。

Nonvolatile Memory

DRAMs and SRAMs are volatile.

ROM(只读存储器)根据可以重新编程(写入)的次数和重新编程机制进行区分。

ROM是一种存储器技术,其数据内容在制造过程中被预先编程,并且在正常操作期间无法被修改。然而,有一些ROM类型可以通过特定的机制进行重新编程。

根据可以重新编程的次数,ROM可以分为以下几种类型:

  1. 只读存储器(Read-Only Memory,ROM):这是最基本的ROM类型,其数据内容在制造过程中被编程,无法被修改。
  2. 一次可编程存储器(One-Time Programmable Memory,OTP):这种ROM类型可以被编程一次,但编程后的数据内容无法被修改。
  3. 可擦写可编程存储器(Erasable Programmable Memory,EPROM):这种ROM类型可以通过使用紫外线擦除器擦除数据,并通过特定的编程设备重新编程。EPROM可以多次擦除和重新编程,但其擦除过程需要特殊设备。
  4. 电可擦可编程存储器(Electrically Erasable Programmable Memory,EEPROM):这种ROM类型可以通过电子方式擦除和重新编程,无需特殊设备。EEPROM可以多次擦除和重新编程,且擦除过程相对简单。
  5. 闪存存储器(Flash Memory):这种ROM类型是一种特殊的EEPROM,具有更高的存储密度和更快的擦除/编程速度。闪存是一种常见的存储介质,广泛应用于移动设备、存储卡和固态硬盘等设备中。

总之,ROM根据可重新编程的次数和机制的不同,可以分为只读存储器、一次可编程存储器、可擦写可编程存储器、电可擦可编程存储器和闪存存储器等类型。每种类型的ROM都有其特定的用途和适用场景。

Accessing Main Memory

总线

总线是计算机系统中用于在不同组件之间传输数据和控制信号的物理通道。它可以看作是计算机系统中的公共高速公路,连接了处理器、内存、输入输出设备和其他外部设备。

总线通常由多条并行的电气导线组成,每条导线承载一个或多个比特的数据或控制信号。这些导线被分为不同的信号线,包括数据线、地址线和控制线。

数据线用于传输二进制数据,可以是单向或双向的。它们承载着处理器和内存之间的数据传输,以及与输入输出设备之间的数据交换。

地址线用于指示要访问的内存位置或外设的寻址。它们传输的是二进制地址信号,告诉内存或外设在哪里读取或写入数据。

控制线用于传输控制信号,用于协调和同步不同组件之间的操作。它们包括读写控制信号、时钟信号、中断信号等,用于控制数据传输和处理器的操作。

总线的速度和宽度是衡量其性能的重要指标。总线的速度决定了数据传输的速率,而总线的宽度决定了每次传输的数据量。较高的总线速度和宽度可以提高计算机系统的性能和响应速度。

总线还可以根据连接的设备类型和功能进行分类。例如,内部总线用于连接处理器和内存,外部总线用于连接处理器和外部设备,如硬盘驱动器、键盘、鼠标等。

总之,总线在计算机系统中起着重要的作用,它提供了组件之间的通信和数据传输渠道,使得计算机系统能够高效地运行和协调各个组件的工作。

control wires

控制线是计算机系统中的一种总线信号线,用于传输控制信号以协调和同步不同组件之间的操作。它们起着控制和管理数据传输和处理器操作的重要作用。

控制线可以包括以下几种类型的信号:

  1. 读写控制信号:用于指示数据传输的方向。读控制信号表示从内存或外设中读取数据,写控制信号表示将数据写入内存或外设。

  2. 时钟信号:用于同步各个组件的操作。时钟信号以固定的频率发出脉冲,使得各个组件可以按照同步的节奏进行数据传输和处理。

  3. 中断信号:用于通知处理器发生了某个特定事件,需要处理器中断当前操作并执行相应的中断处理程序。

  4. 重置信号:用于将系统的各个组件恢复到初始状态。当系统启动时或发生故障时,重置信号可以清除各个组件的状态,使其重新初始化。

  5. 控制命令信号:用于发送特定的控制命令,例如启动、停止、暂停等。这些命令可以控制数据传输和处理器的操作。

控制线的数量和功能取决于计算机系统的设计和架构。不同的计算机系统可能具有不同的控制信号和控制线数量。

总的来说,控制线在计算机系统中起着关键的作用,它们通过传输各种控制信号,协调和同步不同组件之间的操作,确保计算机系统的正常运行和正确执行各种任务。

chipset

芯片组(chipset)是计算机系统中的重要组成部分,它包含一系列集成电路芯片,用于协调和控制计算机系统中各个组件的通信和操作。

芯片组通常由北桥和南桥两个部分组成,它们分别负责不同的功能和任务。

  1. 北桥(Northbridge):北桥是芯片组中的核心部分,主要负责处理器和内存之间的通信。它通常包括内存控制器、图形接口、PCI Express接口等。北桥起着连接处理器和内存的桥梁作用,它控制着内存的访问和数据传输速度,并处理图形数据的传输和显示。

  2. 南桥(Southbridge):南桥是芯片组中的辅助部分,主要负责处理输入输出设备和存储设备的连接和控制。它通常包括SATA接口、USB接口、音频接口、以太网接口等。南桥负责管理和控制各种外部设备的数据传输和操作,例如硬盘驱动器、键盘、鼠标、打印机等。

芯片组的功能是通过各个芯片之间的高速总线来实现的。北桥和南桥之间通常使用高速总线(如前面总线或直接互连总线)进行通信,以实现快速和高效的数据传输。

芯片组的选择对计算机系统的性能和功能有重要影响。不同的芯片组可以支持不同的处理器架构、内存类型和外设接口,因此在设计计算机系统时需要根据需求选择适合的芯片组。

总之,芯片组是计算机系统中的关键部分,它通过协调和控制各个组件之间的通信和操作,确保计算机系统的正常运行和高效性能。

I/O bridge

I/O桥(I/O bridge),也被称为南桥(Southbridge),是计算机系统中的一个关键组件,用于管理和控制输入输出(I/O)设备的连接和操作。

I/O桥通常位于芯片组中的南桥部分,与北桥(或称为系统桥)相对应。北桥负责处理器和内存之间的通信,而I/O桥则负责处理处理器和外部设备之间的通信。

I/O桥具有以下主要功能:

  1. 外设连接:I/O桥提供各种接口和端口,用于连接各种外部设备,如硬盘驱动器、光驱、USB设备、音频设备、以太网设备等。它通常包括SATA接口、USB接口、音频接口、以太网接口等。

  2. 数据传输:I/O桥负责管理和控制外部设备与计算机系统之间的数据传输。它处理数据的读取和写入,确保数据在设备之间的正确传输。

  3. 控制信号:I/O桥通过控制信号与外部设备进行通信和控制。它发送和接收控制信号,以控制设备的操作,例如启动、停止、暂停等。

  4. 中断处理:I/O桥负责处理外部设备发出的中断信号。当外部设备需要引起处理器的注意时,它会发送中断信号给I/O桥,然后I/O桥将该信号传递给处理器,以触发相应的中断处理程序。

  5. 电源管理:I/O桥还负责管理和控制计算机系统的电源管理功能。它可以监测和控制外部设备的电源状态,以实现节能和延长设备寿命。

总的来说,I/O桥在计算机系统中起着重要的作用,它管理和控制外部设备的连接和操作,确保数据的传输和设备的正常工作。通过提供各种接口和功能,I/O桥使计算机系统能够与外部世界进行有效的通信和交互。

system bus

系统总线(System Bus)是计算机系统中的一种通信子系统,用于连接计算机的各个主要组件,例如中央处理器(CPU)、内存、输入输出设备等。它是计算机系统中数据和控制信号传输的主要通道。

系统总线通常由多根并行的导线组成,用于传输数据、地址和控制信号。它可以分为三个主要部分:

  1. 数据总线(Data Bus):用于传输数据,通常是双向的,并且可以同时传输多个字节的数据。数据总线的宽度决定了系统能够一次传输的数据量,例如32位数据总线可以一次传输32位(4字节)的数据。

  2. 地址总线(Address Bus):用于传输内存和外设的地址信息。地址总线的宽度决定了系统能够寻址的内存和外设的数量,例如32位地址总线可以寻址2^32个(4GB)的内存空间。

  3. 控制总线(Control Bus):用于传输控制信号,例如读写信号、时钟信号、中断信号等。控制总线的作用是协调各个组件的操作,确保数据的正确传输和处理。

系统总线起到了连接计算机系统中各个组件的桥梁作用,它使得各个组件能够相互通信和协调工作,实现计算机系统的正常运行。不同的计算机系统可能采用不同的系统总线标准,例如PCI、ISA、USB等。系统总线的性能和带宽对计算机系统的整体性能有着重要的影响。

memory bus

内存总线(Memory Bus)是计算机系统中的一种特殊的总线,用于连接中央处理器(CPU)和内存模块(RAM),以实现CPU对内存的读取和写入操作。

内存总线是一组并行的导线,用于传输地址信号、数据信号和控制信号。它连接了CPU和内存模块之间的数据通路,使得CPU能够直接访问内存中的数据。

内存总线的主要功能包括:

  1. 地址传输:CPU通过内存总线传输要访问的内存地址,以确定要读取或写入的内存单元。

  2. 数据传输:CPU通过内存总线传输要读取或写入的数据。数据传输可以是单个字节、多个字节或者连续的数据块。

  3. 控制信号传输:内存总线还传输一些控制信号,例如读写信号、时钟信号、使能信号等,用于控制内存模块的读写操作。

内存总线的性能和带宽对计算机系统的整体性能有着重要的影响。内存总线的带宽决定了CPU与内存之间数据传输的速度,较高的内存总线带宽可以提高计算机系统的数据处理能力。

在现代计算机系统中,内存总线通常是与其他总线(如系统总线、外设总线)相互连接的,形成一个复杂的总线系统,以实现CPU、内存和外设之间的高效通信。常见的内存总线标准包括DDR(Double Data Rate)和GDDR(Graphics Double Data Rate)等。

memory bus 和 system bus 的区别

内存总线(Memory Bus)和系统总线(System Bus)是计算机系统中两种不同的总线。

  1. 功能不同:内存总线主要用于连接中央处理器(CPU)和内存模块,实现CPU对内存的读取和写入操作;而系统总线用于连接计算机的各个主要组件,如CPU、内存、输入输出设备等,用于数据和控制信号的传输。

  2. 连接的设备不同:内存总线连接CPU和内存模块,是CPU和内存之间的专用通道;而系统总线连接了计算机系统中的各个主要组件,包括CPU、内存、输入输出设备等。

  3. 数据传输方式不同:内存总线主要用于CPU和内存之间的数据传输,通常是高速的并行传输;而系统总线不仅包括数据传输,还包括地址传输和控制信号传输,通常是多路复用的串行传输。

  4. 带宽和性能要求不同:内存总线的带宽通常要求较高,以满足CPU对内存的大量数据读写需求;而系统总线的带宽要求相对较低,因为它连接的是多个组件,数据传输量相对较小。

总之,内存总线和系统总线在功能、连接设备、数据传输方式和带宽要求等方面存在明显的区别。内存总线是CPU和内存之间的专用通道,而系统总线是连接计算机系统各个主要组件的通信子系统。
在这里插入图片描述
Data flows back and forth between the processor and the DRAM main memory over shared electrical conduits called buses. Each transfer of data between the CPU and memory is accomplished with a series of steps called a bus transaction. A read transaction transfers data from the main memory to the CPU. A write transaction transfers data from the CPU to the main memory.
CPU和内存之间的数据传输都是通过总线事务完成。读事务将数据从主存储器传输到CPU。写事务将数据从CPU传输到主存储器。

The I/O bridge translates the electrical signals of the system bus into the electrical signals of the memory bus.

movq A,%rax

当CPU执行一个load操作(例如movq A,%rax),将地址A的内容加载到寄存器%rax时,CPU芯片上的总线接口, bus interface,电路会启动一个读事务。读事务,read transaction,包括三个步骤。首先,CPU将地址A放置在系统总线上。I/O桥将信号传递到内存总线上(图6.7(a))。接下来,主存储器感知到内存总线上的地址信号,从DRAM中读取地址,并将数据写入内存总线。I/O桥将内存总线信号转换为系统总线信号,并将其传递到系统总线上(图6.7(b))。最后,CPU感知到系统总线上的数据,从总线上读取数据,并将数据复制到寄存器%rax中(图6.7©)。

在这里插入图片描述
当CPU执行一个store操作(例如movq %rax,A),将寄存器%rax的内容写入地址A时,CPU会启动一个写事务,write transaction。同样,有三个基本步骤。首先,CPU将地址放置在系统总线上。内存从内存总线上读取地址,并等待数据到达(图6.8(a))。接下来,CPU将%rax中的数据复制到系统总线上(图6.8(b))。最后,主存储器从内存总线上读取数据,并将位存储到DRAM中(图6.8©。

在这里插入图片描述

Disk Storage

Disks are constructed from platters. Each platter consists of two sides, or surfaces, that are coated with magnetic recording material. A rotating spindle in the center of the platter spins the platter at a fixed rotational rate, typically between 5,400 and 15,000 revolutions per minute (RPM). A disk will typically contain one or more of these platters encased in a sealed container.
磁盘由盘片构成。每个盘片由两个被涂覆磁记录材料的表面组成。盘片中心的旋转主轴, rotating spindle,以固定的转速旋转盘片,通常在每分钟5400至15000转之间。一个磁盘通常包含一个或多个这些盘片,封装在一个密封的容器中。

在这里插入图片描述
Figure 6.9(a) shows the geometry of a typical disk surface. Each surface consists of a collection of concentric rings called tracks. Each track is partitioned into a collection of sectors. Each sector contains an equal number of data bits (typically 512 bytes) encoded in the magnetic material on the sector. Sectors are separated by gaps where no data bits are stored. Gaps store formatting bits that identify sectors.
图6.9(a)展示了一个典型磁盘表面的几何结构。每个表面由一系列同心环组成,称为磁道。每个磁道被划分为一系列扇区。每个扇区包含相等数量的数据位(通常为512字节),编码在扇区上的磁性材料中。扇区之间由间隙分隔,其中不存储数据位。间隙存储标识扇区的格式化位。

A disk consists of one or more platters stacked on top of each other and encased in a sealed package, as shown in Figure 6.9(b). The entire assembly is often referred to as a disk drive, although we will usually refer to it as simply a disk. We will sometimes refer to disks as rotating disks to distinguish them from flash-based solid state disks (SSDs), which have no moving parts. Disk manufacturers describe the geometry of multiple-platter drives in terms of cylinders, where a cylinder is the collection of tracks on all the surfaces that are equidistant from the center of the spindle. For example, if a drive has three platters and six surfaces, and the tracks on each surface are numbered consistently, then cylinder k is the collection of the six instances of track k.
一个磁盘由一个或多个盘片堆叠在一起,并封装在一个密封的包装中,如图6.9(b)所示。整个组件通常被称为磁盘驱动器,尽管我们通常将其简称为磁盘。为了与没有移动部件的基于闪存的固态硬盘(SSD)区分开来,我们有时将磁盘称为旋转磁盘。
磁盘制造商通常用柱面来描述多盘驱动器的几何结构,其中柱面是距离主轴中心等距离的所有表面上的磁道的集合。例如,如果一个驱动器有三个盘片和六个表面,并且每个表面上的磁道编号一致,则第k个柱面是包含六个k磁道的集合。

Disk Capacity

The maximum number of bits that can be recorded by a disk is known as its maximum capacity, or simply capacity. 磁盘能够记录的最大位数被称为其最大容量,或简称为容量。Disk capacity is determined by the following technology factors:

Recording density (bits/in). The number of bits that can be squeezed into a 1- inch segment of a track. 可以压缩到一英寸磁道段中的位数
Track density (tracks/in). The number of tracks that can be squeezed into a 1-inch segment of the radius extending from the center of the platter. 可以压缩到从盘片中心延伸的半径的一英寸磁道段中的磁道数
Areal density (bits/in2). The product of the recording density and the track density. Recording density 乘以 Track density

modern high-capacity disks use a technique known as multiple zone recording, where the set of cylinders is partitioned into disjoint subsets known as recording zones. Each zone consists of a contiguous collection of cylinders. Each track in each cylinder in a zone has the same number of sectors, which is determined by the number of sectors that can be packed into the innermost track of the zone.
现代高容量磁盘使用一种被称为多区域记录的技术,其中一组柱面被划分为不相交的子集,称为记录区域。每个区域由一系列连续的柱面组成。每个区域中每个柱面的每个磁道都有相同数量的扇区,这个数量是由该区域最内部磁道上可容纳的扇区数确定的。

在这里插入图片描述

multiple zone recording

多区域记录是一种在现代高容量磁盘中使用的技术。它将磁盘的柱面分成不相交的子集,称为记录区域。每个记录区域由一系列连续的柱面组成。

在每个记录区域中,每个柱面的每个磁道都有相同数量的扇区。这个数量是由该区域最内部磁道上可容纳的扇区数确定的。这意味着在同一个记录区域中,每个磁道都具有相同的扇区数量。

通过使用多区域记录技术,磁盘制造商可以更有效地利用磁盘表面,并提高磁盘的存储容量。相比于早期的分区方式,多区域记录可以根据不同的磁道位置,动态调整每个磁道上的扇区数量,从而更好地适应磁盘表面的变化。

多区域记录技术的优势在于可以提供更高的数据密度和更高的存储容量,同时保持磁盘的性能和可靠性。它是现代高容量磁盘设计的重要组成部分,使得磁盘能够满足不断增长的数据存储需求。

Disk Operation

Disks read and write bits stored on the magnetic surface using a read/write head connected to the end of an actuator arm, as shown in Figure 6.10(a). 磁盘使用连接在执行器臂,actuator arm,末端的读/写头读取和写入存储在磁表面上的位,如图6.10(a)所示。

在这里插入图片描述
By moving the arm back and forth along its radial axis, the drive can position the head over any track on the surface. This mechanical motion is known as a seek. Once the head is positioned over the desired track, then, as each bit on the track passes underneath, the head can either sense the value of the bit (read the bit) or alter the value of the bit (write the bit). Disks with multiple platters have a separate
read/write head for each surface, as shown in Figure 6.10(b). The heads are lined up vertically and move in unison. At any point in time, all heads are positioned on the same cylinder. 通过沿着其径向轴来回移动臂,驱动器可以将头定位在表面上的任何轨道上。这种机械运动被称为寻道。一旦头部定位在所需的轨道上,那么每个位在下方通过时,头部可以感知位的值(读取位)或改变位的值(写入位)。具有多个盘片的磁盘每个表面都有一个单独的读/写头,如图6.10(b)所示。这些头部垂直排列并且同步移动。在任何时刻,所有头部都位于同一圆柱上。

The read/write head at the end of the arm flies (literally) on a thin cushion of air over the disk surface at a height of about 0.1 microns and a speed of about 80 km/h. 位于臂的末端的读/写头在磁盘表面上以约0.1微米的高度和约80公里/小时的速度上(实际上)飞行。

Disks read and write data in sector-size blocks. 磁盘以扇区大小的块读取和写入数据。The access time for a sector has three main components: seek time, rotational latency, and transfer time 寻道时间、旋转延迟和传输时间:

Seek time: 为了读取目标扇区的内容,臂首先将头定位在包含目标扇区的磁道上。移动臂所需的时间称为寻道时间。寻道时间(Tseek)取决于头的先前位置和臂在表面上移动的速度。现代驱动器的平均寻道时间(Tavg seek)通过对随机扇区进行数千次寻道的平均值来衡量,通常在3到9毫秒的数量级上。单次寻道的最长时间(Tmax seek)可能高达20毫秒。

Rotational latency: 一旦头部定位在磁道上,驱动器会等待目标扇区的第一个位通过头部。这一步的性能取决于头部到达目标磁道时表面的位置和磁盘的旋转速度。在最坏的情况下,头部刚好错过目标扇区,并等待磁盘完成一次完整的旋转。因此,最大的旋转延迟,以秒为单位,可以表示为:
在这里插入图片描述
Transfer time: 当目标扇区的第一个位在头部下方时,驱动器可以开始读取或写入扇区的内容。一个扇区的传输时间取决于旋转速度和每个磁道的扇区数。因此,我们可以大致估计一个扇区的平均传输时间(以秒为单位)为:
在这里插入图片描述
the average time to access the contents of a disk sector as the sum of the average seek time, the average rotational latency, and the average transfer time.
举个例子:
在这里插入图片描述
访问磁盘扇区中的512字节的时间主要由寻道时间和旋转延迟决定。访问扇区中的第一个字节需要很长时间,但剩余的字节基本上是免费的。
由于寻道时间和旋转延迟大致相同,两倍的寻道时间是一个简单而合理的规则来估计磁盘访问时间。
存储在SRAM中的64位字的访问时间大约为4纳秒,DRAM为60纳秒。因此,从内存中读取一个512字节的扇区大小的块的时间大约为SRAM的256纳秒和DRAM的4,000纳秒。磁盘访问时间大约为10毫秒,大约比SRAM大40,000倍,比DRAM大2,500倍。

Logical Disk Blocks

逻辑磁盘块(Logical Disk Blocks)是操作系统对磁盘进行管理和访问的基本单位。它是磁盘空间的逻辑划分,通常由多个连续的扇区组成。

逻辑磁盘块的大小可以根据操作系统和文件系统的设计而有所不同,通常是512字节、1KB或4KB。它们用于存储文件和目录的数据,以及文件系统元数据,如索引节点、文件描述符等。

操作系统使用逻辑磁盘块来进行文件的读取和写入。当应用程序请求读取或写入文件时,操作系统会将请求转换为对逻辑磁盘块的操作。读取时,操作系统会将逻辑磁盘块从磁盘读取到内存中,然后将数据返回给应用程序。写入时,操作系统会将数据写入到逻辑磁盘块中,并将其更新到磁盘上的相应位置。

逻辑磁盘块的使用可以提高文件系统的性能和效率。通过将文件数据划分为逻辑磁盘块,可以更好地组织和管理文件,减少磁盘碎片和提高文件的读写速度。此外,逻辑磁盘块还可以简化文件系统的实现和维护,使文件系统更加可靠和稳定。

现代磁盘具有复杂的几何结构,具有多个表面和这些表面上的不同记录区域。为了将这种复杂性隐藏在操作系统之下,现代磁盘将其几何结构以B扇区大小的逻辑块序列的形式呈现出来,编号为0、1、…、B-1。磁盘包, disk package,中的一个名为磁盘控制器的小型硬件/固件设备维护着逻辑块号和实际(物理)磁盘扇区之间的映射关系。当操作系统想要执行诸如将磁盘扇区读入主存储器的I/O操作时,它会向磁盘控制器发送一个命令,要求它读取特定的逻辑块号。控制器上的固件执行快速的表查找,将逻辑块号转换为唯一标识相应物理扇区的(表面、磁道、扇区)三元组。控制器上的硬件解释这个三元组,将磁头移动到适当的柱面,等待扇区通过磁头,将磁头感测到的位拾取到控制器上的小型内存缓冲区中,并将它们复制到主存储器中。

Connecting I/O Devices

在这里插入图片描述
图形卡、显示器、鼠标、键盘和磁盘等输入/输出(I/O)设备通过I/O总线连接到CPU和主存储器。与特定于CPU的系统总线和内存总线不同,I/O总线设计为独立于底层CPU。图6.11显示了连接CPU、主存储器和I/O设备的典型I/O总线结构。
尽管I/O总线速度比系统总线和内存总线慢,但它可以容纳各种各样的第三方I/O设备。例如,图6.11中的总线上连接了三种不同类型的设备:

  1. 通用串行总线(USB)控制器是连接到USB总线的设备的通道,USB总线是一种广泛使用的标准,用于连接各种外围I/O设备,包括键盘、鼠标、调制解调器、数码相机、游戏控制器、打印机、外部磁盘驱动器和固态硬盘。USB 3.0总线的最大带宽为625 MB/s。USB 3.1总线的最大带宽为1,250 MB/s。
  2. 图形卡(或适配器)包含有硬件和软件逻辑,负责代表CPU在显示器上绘制像素。
  3. 主机总线适配器将一个或多个磁盘通过特定主机总线接口, host bus interface,定义的通信协议连接到I/O总线。用于磁盘的两个最流行的接口是SCSI和SATA。SCSI磁盘通常比SATA驱动器更快、更昂贵。SCSI主机总线适配器(通常称为SCSI控制器)可以支持多个磁盘驱动器,而SATA适配器只能支持一个驱动器。
    其他设备,如网络适配器,可以通过将适配器插入主板上的空扩展插槽来连接到I/O总线,这些插槽提供了与总线的直接电连接。

Accessing Disks

memory mapped I/O

内存映射I/O(Memory-mapped I/O)是一种用于处理器与I/O设备之间通信的技术。它通过将I/O设备的寄存器映射到内存地址空间的特定区域,使得处理器可以像访问内存一样访问这些寄存器。

在内存映射I/O中,I/O设备的寄存器被映射到了一个特定的内存地址范围。当处理器需要与I/O设备进行通信时,它可以通过读写这些内存地址来实现对寄存器的操作。这样,处理器可以使用统一的内存访问指令来读取或写入I/O设备的寄存器,而不需要使用特定的I/O指令。

内存映射I/O的优点是简化了对I/O设备的访问,使得编程更加方便。处理器可以使用相同的指令和地址寻址模式来访问内存和I/O设备,减少了编程的复杂性。此外,通过内存映射I/O,可以利用处理器的高速缓存来提高I/O设备的访问速度。

然而,内存映射I/O也存在一些限制。由于I/O设备的寄存器与内存共享地址空间,可能会导致地址冲突。此外,由于寄存器是通过内存访问来操作的,可能会导致性能上的一些损失。

总的来说,内存映射I/O是一种方便的处理器与I/O设备通信的技术,它简化了编程并提高了性能。然而,在设计和实现时需要注意地址冲突和性能问题。
在这里插入图片描述
CPU使用一种称为内存映射I/O的技术来向I/O设备发出命令(图6.12(a))。在具有内存映射I/O的系统中,地址空间中保留了一块用于与I/O设备通信的地址块。这些地址中的每一个都被称为一个I/O端口。每个设备在连接到总线时都会与一个或多个端口相关联(或映射)。

举个例子,假设磁盘控制器被映射到端口0xa0。然后,CPU可以通过执行三个存储指令(store instruction)到地址0xa0来启动磁盘读取操作:第一个指令发送一个命令字(command word),告诉磁盘启动读取操作,并包含其他参数,比如是否在读取完成时中断CPU(我们将在第8.1节讨论中断)。第二个指令指示应该读取的逻辑块号(logical block number)。第三个指令指示磁盘扇区内容应该存储在主存的哪个地址中(main memory address)。

在发出请求后,CPU通常会在磁盘执行读取操作时进行其他工作。一个1 GHz的处理器以1 ns的时钟周期可以在读取磁盘需要的16 ms内执行1600万条指令。仅仅等待并不做任何事情而传输正在进行中将是极其浪费的。

指令数量计算

要计算一个1 GHz的处理器在1 ns的时钟周期下能够执行多少指令,我们需要先将16 ms转换为纳秒。
16 ms = 16,000,000 ns
然后,我们可以使用以下公式来计算指令数量:
指令数量 = 执行时间 / 时钟周期
指令数量 = 16,000,000 ns / 1 ns = 16,000,000 指令
因此,一个1 GHz的处理器在1 ns的时钟周期下可以执行16,000,000个指令。
需要注意的是,这只是一个理论值,实际情况可能受到其他因素的影响,如处理器架构、指令集等。

在CPU向磁盘控制器发送读取命令后,磁盘控制器将逻辑块号(logical block number)转换为扇区地址(sector address),读取扇区的内容,并将内容直接传输到主存储器,无需CPU的任何干预(图6.12(b))。这个过程,即设备在没有CPU参与的情况下自行执行读取或写入总线事务,被称为直接内存访问(DMA)。数据的传输被称为DMA传输(DMA transfer)。

在DMA传输(DMA transfer)完成并且磁盘扇区的内容安全存储在主存储器中之后,磁盘控制器通过向CPU发送中断信号(interrupt signal)来通知CPU(图6.12©)。基本思想是,中断信号会触发CPU芯片上的外部引脚(external pin)。这会导致CPU停止当前正在进行的工作,并跳转到操作系统例程(operating system routine)。该例程记录I/O已经完成的事实,然后将控制返回到CPU被中断的地方。

Solid State Disks

在这里插入图片描述
固态硬盘(SSD)是一种基于闪存存储技术(第6.1.1节)的存储技术,在某些情况下是传统旋转磁盘的有吸引力的替代品。图6.13展示了基本思想。SSD插件(SSD package)插入到I/O总线上的标准磁盘插槽中(通常是USB或SATA),并像任何其他磁盘一样工作,处理来自CPU的读取和写入逻辑磁盘块的请求。SSD插件由一个或多个闪存芯片(flash memory chips)组成,这些芯片取代了传统旋转磁盘中的机械驱动器(mechanical drive),并且还包括一个闪存转换层(flash translation layer),这是一个硬件/固件设备,起到与磁盘控制器相同的作用,将对逻辑块(logical blocks)的请求转换为对底层物理设备(underlying physical device)的访问。

在这里插入图片描述
如图6.13所示,闪存(flash memory)由一系列B个块组成,其中每个块由P个页面组成。通常,页面的大小为512字节到4 KB,并且一个块由32到128个页面组成,总块大小范围从16 KB到512 KB不等。数据以页面为单位进行读写。只有在属于它的整个块被擦除之后(通常意味着块中的所有位都设置为1),才能写入页面。然而,一旦块被擦除,块中的每个页面都可以进行一次写入,而无需进一步擦除。大约经过10万次重复写入后,块会磨损。一旦块磨损,就无法继续使用。

随机写入较慢有两个原因。首先,擦除一个块需要相对较长的时间,大约1毫秒,这比访问一个页面的时间长了一个数量级。其次,如果写操作试图修改一个包含现有数据(即非全1)的页面p,则在写入页面p之前,同一块中具有有用数据的任何页面必须被复制到一个新的(擦除的)块中。制造商在闪存转换层中开发了复杂的逻辑,试图分摊擦除块的高成本,并在写操作中尽量减少内部复制的次数,但随机写入很难像读取一样表现得好。

SSD相对于旋转磁盘具有许多优势。它们由半导体存储器构建,没有移动部件,因此随机访问时间比旋转磁盘快得多,能耗更低,更耐用。然而,它们也存在一些缺点。首先,由于闪存块在重复写入后会磨损,SSD也有可能磨损。闪存转换层中的磨损平衡逻辑通过均匀分布擦除操作来最大程度地延长每个块的寿命。实际上,磨损平衡逻辑(Wear-leveling logic)非常好,SSD需要很多年才能磨损(参见练习问题6.5)。其次,SSD的每字节成本约为旋转磁盘的30倍,因此典型的存储容量明显小于旋转磁盘。然而,随着SSD的普及,其价格正在迅速下降,两者之间的差距正在缩小。

Storage Technology Trends

在这里插入图片描述
不同存储技术的价格和性能特性正在以截然不同的速度变化。图6.15总结了自1985年第一台个人电脑问世以来,存储技术的价格和性能特性。这些数据来自于贸易杂志和网络的旧期刊。尽管这些数据是通过非正式调查收集的,但它们揭示了一些有趣的趋势。

自1985年以来,SRAM技术的成本和性能改善速度大致相同。访问时间和每兆字节成本减少了约100倍(图6.15(a))。然而,DRAM和磁盘的趋势更加戏剧性和分歧。虽然DRAM每兆字节成本减少了44,000倍(超过四个数量级!),但DRAM的访问时间仅减少了10倍(图6.15(b))。磁盘技术遵循了DRAM相同的趋势,而且更加戏剧性。自1980年以来,磁盘存储每兆字节的成本下降了超过3,000,000倍(超过六个数量级!),而访问时间的改善速度要慢得多,只有25倍(图6.15©)。

这些惊人的长期趋势突显了内存和磁盘技术的一个基本真理:增加密度(从而降低成本)比减少访问时间要容易得多。

DRAM和磁盘的性能落后于CPU的性能。如图6.15(d)所示,从1985年到2010年,CPU的周期时间提高了500倍。如果我们看有效周期时间—我们定义为单个CPU(处理器)的周期时间除以其处理器核心数——那么从1985年到2010年的改进将更大,为2000倍。
在这里插入图片描述
CPU性能曲线在2003年左右出现分裂,这反映了多核处理器的引入(请参见第641页的附注)。在这个分裂之后,单个核心的周期时间实际上略微增加,然后再次开始下降,尽管下降速度比之前慢一些。

需要注意的是,尽管SRAM的性能落后,但它大致保持着同步。然而,DRAM和磁盘性能与CPU性能之间的差距实际上正在扩大。直到大约在2003年出现多核处理器之前,这种性能差距是延迟的一个函数,即DRAM和磁盘的访问时间下降速度比单个处理器的周期时间慢。

然而,随着多核的引入,这种性能差距越来越多地成为吞吐量的函数,多个处理器核心并行地向DRAM和磁盘发出请求。

正如我们将在第6.4节中看到的那样,现代计算机广泛使用基于SRAM的高速缓存来尝试弥补处理器-内存差距。这种方法有效的原因是应用程序的一个基本属性,即局部性,在下一节讨论。

Locality

局部性(Locality)通常被描述为具有两种不同形式:时间局部性(temporal locality)和空间局部性(spatial locality)。在具有良好时间局部性的程序中,一个被引用的内存位置在不久的将来很可能会再次被引用多次。在具有良好空间局部性的程序中,如果一个内存位置被引用一次,那么该程序很可能会在不久的将来引用附近的内存位置。

程序员应该理解局部性的原则,因为一般来说,具有良好局部性的程序运行速度比局部性较差的程序要快。现代计算机系统的所有层级,从硬件到操作系统再到应用程序,都被设计成利用局部性。在硬件层面上,局部性原则允许计算机设计师通过引入小型快速存储器(称为缓存存储器(cache memories))来加快对主存的访问,该存储器保存最近引用的指令(instructions)和数据块(data items)。在操作系统层面上,局部性原则允许系统将主存用作最近引用的虚拟地址空间块的缓存。类似地,操作系统使用主存来缓存磁盘文件系统(disk file system)中最近使用的磁盘块(disk blocks)。局部性原则在应用程序的设计中也起着至关重要的作用。例如,Web浏览器通过在本地磁盘上缓存最近引用的文档来利用时间局部性。高流量的Web服务器将最近请求的文档保存在前端磁盘缓存中,以满足对这些文档的请求,而无需服务器的任何干预。

Locality of References to Program Data

在这里插入图片描述
考虑图6.17(a)对向量元素求和的简单函数。例子:sum变量在每次循环迭代中被引用一次,因此在sum方面有良好的时间局部性。另一方面,由于sum是一个标量(scalar),所以在sum方面没有空间局部性。

如图6.17(b)所示,向量(vector) v的元素按顺序逐个读取,按照它们在内存中的存储顺序(假设数组从地址0开始)。因此,对于变量v来说,该函数具有良好的空间局部性,但在时间局部性方面较差,因为每个向量元素只被访问一次。由于该函数对循环体中的每个变量具有良好的空间或时间局部性,我们可以得出结论,sumvec函数具有良好的局部性。

像sumvec这样按顺序访问向量的每个元素的函数被称为步长1的引用模式(stride-1 reference pattern)(相对于元素大小)。我们有时将步长1的引用模式称为顺序引用模式 (sequential reference patterns)。访问连续向量的每第k个元素被称为步长k的引用模式。步长1的引用模式是程序中常见且重要的空间局部性来源。一般来说,随着步长的增加,空间局部性会减少。

在这里插入图片描述

步长对于引用多维数组的程序也是一个重要问题。例如,考虑图6.18(a)中对二维数组元素求和的sumarrayrows函数。

双重嵌套循环(doubly nested loop)按行主序顺序(row-major order)读取数组的元素。也就是说,内部循环(inner loop)按照顺序读取第一行的元素,然后是第二行,依此类推。sumarrayrows函数具有良好的空间局部性,因为它按照与数组存储相同的行主序顺序引用数组(图6.18(b))。结果是一个具有良好空间局部性的步长1的引用模式。

在这里插入图片描述
程序中看似微不足道的更改可能会对其局部性产生重大影响。例如,图6.19(a)中的sumarraycols函数计算的结果与图6.18(a)中的sumarrayrows函数相同。唯一的区别是我们交换了i和j循环。交换循环对其局部性有什么影响?

sumarraycols函数的空间局部性较差,因为它按列而不是按行扫描数组。由于C数组在内存中是按行布局的,结果是一个步长N的引用模式,如图6.19(b)所示。

Locality of Instruction Fetches

由于程序指令存储在内存中并且必须被CPU获取(读取),也可以评估程序相对于其指令获取的局部性。例如,在图6.17中,for循环体中的指令按顺序内存顺序执行,因此循环具有良好的空间局部性。由于循环体被多次执行,它也具有良好的时间局部性。

代码的一个重要特性是它很少在运行时被修改。当程序执行时,CPU从内存中读取其指令。CPU很少覆盖或修改这些指令。

Summary of Locality

介绍了局部性的基本概念,并确定了一些用于定性评估程序局部性的简单规则:

  • 反复引用相同变量的程序具有良好的时间局部性。
  • 对于具有步长k引用模式的程序,步长越小,空间局部性越好。具有步长为1的引用模式的程序具有良好的空间局部性。在内存中跳跃大步长的程序具有较差的空间局部性。
  • 循环相对于指令获取具有良好的时间和空间局部性。循环体越小,循环迭代次数越多,局部性越好。

学习了缓存内存及其工作原理之后,将展示如何以缓存命中和缓存未命中的方式量化局部性的概念。了解为什么具有良好局部性的程序通常比局部性较差的程序运行速度更快。尽管如此,能够快速浏览源代码并对程序的局部性有高层次的了解是程序员需要掌握的一项有用且重要的技能。

The Memory Hierarchy

在这里插入图片描述
Storage technology:
不同的存储技术具有广泛不同的访问时间。更快的技术每字节的成本比较慢的技术更高,并且容量更小。CPU和主存储器速度之间的差距正在扩大。

Computer software:
写得好的程序往往表现出良好的局部性。

在计算机领域中,硬件和软件的这些基本特性恰好相互补充。它们互补的特性为内存系统的组织提供了一种方法,称为内存层次结构(memory hierarchy),这种方法在所有现代计算机系统中都被使用。图6.21显示了一个典型的内存层次结构。

一般来说,随着我们从高层向低层移动,存储设备变得更慢、更便宜和更大。在最高层(L0)是一小部分快速的CPU寄存器(CPU registers),CPU可以在一个时钟周期内访问。接下来是一个或多个基于SRAM的小到中等大小的高速缓存内存(SRAM-based cache memories),可以在几个CPU时钟周期内访问。然后是一个基于DRAM的大容量主内存(DRAM-based main memory),可以在几十到几百个时钟周期内访问。接下来是慢速但巨大的本地磁盘。最后,一些系统甚至在远程服务器上包括额外的磁盘级别,可以通过网络访问。例如,分布式文件系统,如Andrew文件系统(AFS)或网络文件系统(NFS)允许程序访问存储在远程网络连接服务器上的文件。同样,万维网允许程序访问存储在世界各地Web服务器上的远程文件。

AFS

安德鲁文件系统(Andrew File System,AFS)是一个分布式文件系统,最初由卡内基梅隆大学开发。它旨在提供对分布式计算环境中数据的透明访问。AFS允许用户在网络上的不同计算机之间共享文件,并提供对文件的安全访问和管理。

AFS的设计目标是提供高性能、可扩展性和可靠性。它采用了一种称为“全球命名空间”的概念,使用户可以在整个AFS网络中以统一的方式访问文件,而不需要关心文件的物理位置。此外,AFS还提供了对文件的备份和恢复功能,以确保数据的安全性和完整性。

AFS的架构包括文件服务器和客户端。文件服务器存储实际的文件数据,并负责处理对文件的访问请求。客户端通过AFS客户端软件与文件服务器通信,并可以在本地访问和操作远程文件,就好像这些文件存储在本地一样。

总的来说,AFS是一种旨在提供高效、安全和可靠的分布式文件访问解决方案,适用于大型计算环境和需要跨网络共享数据的应用程序。

NFS

NFS是Network File System的缩写,是一种允许不同计算机之间共享文件的分布式文件系统协议。NFS最初由Sun Microsystems开发,现在已成为一种广泛使用的标准,被许多不同厂商的操作系统和网络设备所支持。

NFS允许用户通过网络访问远程计算机上的文件,就像这些文件存储在本地一样。它提供了一种透明的方式来共享文件和目录,使得用户可以在不同的计算机上访问和操作相同的数据。

NFS的工作原理是,远程文件系统被挂载到本地文件系统上,使得远程文件可以像本地文件一样被访问和处理。NFS使用客户端-服务器模型,其中远程计算机上的NFS服务器负责存储和管理文件,而客户端通过NFS协议与服务器通信并访问文件。

NFS提供了对文件的透明访问,并支持文件的读取、写入和执行操作。它还提供了对文件和目录的安全访问控制,以确保数据的完整性和安全性。

总的来说,NFS是一种用于在网络上共享文件的标准化协议,适用于各种不同类型的操作系统和网络环境,使得用户可以方便地共享和访问远程文件。

Caching in the Memory Hierarchy

一般而言,缓存(cache)是一种小型、快速的存储设备,作为较大、较慢设备中存储的数据对象的临时存储区域。使用缓存的过程称为缓存(caching)。

内存层次结构的核心思想是,对于每个级别k,级别k处的更快、更小的存储设备充当了级别k + 1处更大、更慢存储设备的缓存。换句话说,层次结构中的每个级别都会缓存来自下一级别的数据对象。例如,本地磁盘充当了从网络上远程磁盘检索的文件(如Web页面)的缓存,主存储器充当了本地磁盘上数据的缓存,以此类推,直到最小的缓存,即CPU寄存器集。
在这里插入图片描述
图6.22展示了内存层次结构中缓存的一般概念。级别k + 1的存储被划分为连续的数据对象块(block),称为块。每个块都有一个唯一的地址或名称,用于区分它与其他块。块可以是固定大小(通常情况)或可变大小(例如,存储在Web服务器上的远程HTML文件)。例如,图6.22中级别k + 1的存储被划分为16个固定大小的块,编号为0到15。

同样,级别k处的存储也被划分为与级别k + 1处相同大小的一组块。在任何时刻,级别k处的缓存包含了级别k + 1处一部分块的副本。例如,在图6.22中,级别k处的缓存有四个块的空间,当前包含了块4、9、14和3的副本。

数据始终以块大小的传输单元(block-size transfer units)在级别k和级别k + 1之间来回复制。重要的是要意识到,虽然在层次结构中任何特定相邻级别之间的块大小是固定的,但其他级别之间的块大小可能不同。例如,在图6.21中,L1和L0之间的传输通常使用字大小的块(word-size blocks)。L2和L1(以及L3和L2,以及L4和L3)之间的传输通常使用几十字节大小的块(blocks of tens of bytes)。而L5和L4之间的传输使用包含数百或数千字节的块(hundreds or thousands of bytes)。一般来说,在层次结构中较低的设备(距离CPU更远)具有较长的访问时间,因此倾向于使用较大的块大小以摊销这些较长的访问时间。

cache hits

当程序需要从级别k + 1获取特定数据对象d时,它首先在级别k当前存储的块中查找d。如果d恰好被缓存在级别k,那么我们称之为缓存命中。程序直接从级别k读取d,根据内存层次结构的性质,这比从级别k + 1读取d更快。例如,具有良好时间局部性的程序可能从块14中读取数据对象,导致级别k的缓存命中。

cache misses

另一方面,如果数据对象d在级别k处没有被缓存,那么我们称之为缓存未命中(cache miss)。当发生未命中时,级别k的缓存会从级别k + 1的缓存中获取包含d的块,如果级别k的缓存已经满了,可能会覆盖现有的块。

覆盖现有块的这个过程称为替换或驱逐块(replacing or evicting block)。被驱逐的块有时被称为受害块(victim block)。关于替换哪个块的决定受缓存的替换策略控制(cache’s replacement policy)。例如,具有随机替换策略(random replacement policy)的缓存将选择一个随机的受害块。具有最近最少使用(LRU, least recently used)替换策略的缓存将选择最久未访问的块。

在级别k的缓存从级别k + 1获取了块之后,程序可以像以前一样从级别k读取d。例如,在图6.22中,从级别k的缓存中读取块12中的数据对象会导致缓存未命中,因为块12当前未存储在级别k的缓存中。一旦从级别k + 1复制到级别k,块12将留在那里,以期望后续访问时使用。

Kinds of Cache Misses

有时区分不同类型的缓存未命中是有帮助的。如果级别k的缓存是空的,那么任何数据对象的访问都会未命中。空缓存有时被称为冷缓存(cold cache),这种未命中被称为强制未命中或冷未命中(compulsory misses or cold misses)。冷未命中很重要,因为它们通常是暂时的事件,在缓存被重复内存访问热身后可能不会在稳定状态下发生。

每当发生未命中时,级别k的缓存必须实施一些放置策略(placement policy),以确定从级别k + 1检索到的块应放置在何处。最灵活的放置策略是允许将级别k + 1的任何块存储在级别k的任何块中。对于位于内存层次结构较高(靠近CPU)的硬件实现的缓存,速度至关重要,这种策略通常成本太高,因为随机放置的块很难定位。

因此,硬件缓存通常实现了一个更简单的放置策略,将级别k + 1的特定块限制在级别k的一个小子集(有时是单个块)中。例如,在图6.22中,我们可能决定级别k + 1的块i必须放置在级别k的块(i mod 4)中。例如,级别k + 1的块0、4、8和12将映射到级别k的块0;块1、5、9和13将映射到块1;依此类推。注意,我们在图6.22中的示例缓存使用了这种策略。

这种限制性的放置策略会导致一种称为冲突未命中的未命中类型(conflict miss),其中缓存足够大以容纳引用的数据对象,但由于它们映射到相同的缓存块,缓存一直未命中。例如,在图6.22中,如果程序请求块0,然后请求块8,然后请求块0,然后请求块8,依此类推,对这两个块的每个引用都会在级别k的缓存中未命中,即使这个缓存总共可以容纳四个块。

程序通常作为一系列阶段(例如循环)运行,每个阶段访问一些相对恒定的缓存块集。例如,一个嵌套循环可能一遍又一遍地访问相同数组的元素。这组块被称为阶段的工作集(working set)。当工作集的大小超过缓存的大小时,缓存将遇到所谓的容量未命中(capacity misses)。换句话说,缓存对于处理特定的工作集来说太小了。
在这里插入图片描述

Cache Management

内存层次结构的本质是每个级别的存储设备都是下一个更低级别的缓存。在每个级别,都必须有某种形式的逻辑来管理缓存。这意味着必须有一些东西来将缓存存储分成块,在不同级别之间传输块,决定何时发生命中和未命中,然后处理它们。管理缓存的逻辑可以是硬件、软件或两者的组合。

例如,编译器(compiler)管理寄存器文件,这是缓存层次结构中最高级别的。它决定何时发出加载请求(load),当发生未命中时,确定将数据存储(store)在哪个寄存器中。L1、L2和L3级别的缓存完全由内置在缓存中的硬件逻辑(hardware logic)管理。在具有虚拟内存的系统中,DRAM主存储器(DRAM main memory)用作存储在磁盘上的数据块的缓存,并由操作系统软件和CPU上的地址转换硬件(address translation hardware on CPU)的组合管理。对于具有分布式文件系统(如AFS)的计算机,本地磁盘(local disk serves)用作由运行在本地机器上的AFS客户端进程管理的缓存。在大多数情况下,缓存会自动运行,并不需要程序执行任何特定或明确的操作。

Summary of Memory Hierarchy Concepts

基于缓存的内存层次结构之所以有效,是因为较慢的存储比较快的存储更便宜,并且程序往往表现出局部性:
Exploiting temporal locality:
利用时间局部性。由于时间局部性,相同的数据对象很可能会被多次重用。一旦数据对象在第一次未命中时被复制到缓存中,我们可以预期后续会有多次命中该对象。由于缓存速度比下一个更低级别的存储快,这些后续的命中可以比原始未命中得到更快的服务。

Exploiting spatial locality:
利用空间局部性。块通常包含多个数据对象。由于空间局部性,我们可以预期在未命中后复制块的成本将被后续对该块内其他对象的引用所分摊。

缓存在现代系统中随处可见。如图6.23所示,缓存在CPU芯片、操作系统、分布式文件系统和全球网络中都有应用。它们由各种硬件和软件的组合构建和管理。

Cache Memories

早期计算机系统的内存层次结构仅包括三个级别:CPU寄存器、主存储器和磁盘存储。然而,由于CPU和主存储器之间的差距不断增大,系统设计者不得不在CPU寄存器文件和主存储器之间插入一个小的SRAM高速缓存内存(SRAM cache memory),称为L1缓存(L1 cache, level 1 cache, 一级缓存),如图6.24所示。L1缓存的访问速度几乎与寄存器一样快,通常在大约4个时钟周期内完成。
在这里插入图片描述
随着CPU和主存储器之间的性能差距不断增大,系统设计者通过在L1缓存和主存储器之间插入一个更大的缓存,称为L2缓存(L2 cache),来应对这一挑战,其访问速度大约为10个时钟周期。许多现代系统还包括一个更大的缓存,称为L3缓存(L3 cache),它位于内存层次结构中的L2缓存和主存储器(main memory)之间,其访问速度大约为50个时钟周期。虽然排列方式存在相当大的差异,但一般原则是相同的。在下一节的讨论中,我们将假设一个简单的内存层次结构,其中在CPU和主存储器之间只有一个L1缓存。

Generic Cache Memory Organization

考虑一个计算机系统,其中每个内存地址都有m位,形成M = 2^m个唯一地址。如图6.25(a)所示,这样的机器的缓存被组织为一个包含
S = 2^s个缓存组的数组。每个组包含E个缓存行(cache lines)。每行包含一个B = 2 ^b字节的数据块(data block),一个有效位(valid bit),指示该行是否包含有意义的信息,以及t = m - (b + s)个标记位(来自当前块的内存地址的位的一个子集),用于唯一标识存储在缓存行中的块。
在这里插入图片描述
一般来说,缓存的组织可以用元组 (S, E, B, m) 来描述。缓存的大小(或容量),用C表示,是指所有块的总大小。标记位和有效位不包括在内。因此,C = S × E × B。

当CPU被加载指令指示从主内存地址A读取一个字时,它将地址A发送到缓存。如果缓存中保存有地址A处的字的副本,它会立即将该字发送回CPU。那么缓存如何知道它是否包含地址A处的字的副本呢?缓存的组织方式使得它可以通过简单地检查地址的位来找到请求的字,类似于具有极其简单哈希函数的哈希表。它的工作原理如下:

参数S和B将m个地址位分成三个字段,如图6.25(b)所示。地址A中的s个集合索引位(set index bits)形成S集合的索引(an index into the array of S sets)。第一个集合是集合0,第二个集合是集合1,依此类推。当解释为无符号整数(unsigned integer)时,集合索引位(set index bits)告诉我们单词必须存储在哪个集合中。一旦我们知道单词必须包含在哪个集合中,地址A中的t个标记位(t tag bits in A)告诉我们集合中的哪一行(如果有的话)包含该单词。当且仅当有效位被设置并且行中的标记位与地址A中的标记位匹配时,集合中的行才包含该单词。一找到由集合索引确定的集合中的标记所标识的行,那么b个块偏移位(b block offset bits)就给出了数据块中单词的偏移量(以B字节为单位)。

正如您可能已经注意到的,缓存的描述使用了很多符号。图6.26总结了这些符号供您参考。
在这里插入图片描述

Direct-Mapped Caches

根据E,即每个集合中的缓存行数,将缓存分成不同的类。每个集合中恰好有一行缓存(E = 1)的缓存被称为直接映射缓存(direct-mapped cache见图6.27)。直接映射缓存在实现和理解上都是最简单的,因此我们将使用它们来说明关于缓存工作原理的一些通用概念。
在这里插入图片描述
假设有一个系统,包括一个CPU、一个寄存器文件、一个L1缓存和一个主内存。当CPU执行一个读取w(memory word w)的指令时,它会从L1缓存请求这个单元。如果L1缓存中有w的缓存副本,那么我们就有了一个L1缓存命中,缓存会快速提取w并将其返回给CPU。否则,我们就有了一个缓存未命中,CPU必须等待,直到L1缓存从主内存请求包含w的块的副本(the block containing w from the main memory)。当请求的块最终从主内存中到达时,L1缓存会将该块存储在其中一个缓存行中,从存储的块中提取单元w(word w),并将其返回给CPU。缓存经历的确定请求是命中还是未命中,并提取请求单元的过程包括三个步骤:(1) 集合选择set selection,(2) 行匹配 line matching,和(3) 单词提取 word extraction。

Set Selection in Direct-Mapped Caches

在这里插入图片描述
set selection,高速缓存从地址的中间提取s组索引位(the s set index bits)。这些位被解释为一个无符号整数,对应一个组号。换句话说,如果将高速缓存看作是一个一维数组的集合,那么组索引位(set index bits)形成了对这个数组的索引。图6.28展示了直接映射高速缓存中组的选择方式。在这个例子中,组索引位00001被解释为一个整数索引,选择了第1组。

Line Matching in Direct-Mapped Caches

在这里插入图片描述
在上一步中,已经选择了一些集合i (set i),接下来的步骤是确定单词w的副本是否存储在集合i中包含的某个高速缓存行中。在直接映射高速缓存中,因为每个集合中恰好只有一行。当有效位被设置并且高速缓存行中的标记与单词w的地址中的标记匹配时,该行中包含单词w的副本。
图6.29展示了在直接映射高速缓存(direct-mapped cache)中行匹配的工作原理。在这个例子中,所选集合中恰好只有一行高速缓存行。该行的有效位被设置,因此知道标记和块中的位是有意义的。由于高速缓存行中的标记位与地址中的标记位匹配,知道单词的副本确实存储在该行中。换句话说,我们命中了高速缓存。
另一方面,如果有效位未设置或标记不匹配,则会发生高速缓存未命中。

Word Selection in Direct-Mapped Caches

缓存命中了,可以确定w在块中的某个位置。最后一步确定了所需单词在块中的起始位置。如图6.29所示,块偏移位(the block offset bits)给出了所需单词的第一个字节的偏移量(the offset of the first byte in the desired word)。类似于将高速缓存视为line数组,可以将块(block)视为字节数组,并且字节偏移量(byte offset)是该数组的索引。举个例子,块偏移位(block offset bits)100表示w的副本从块的第4个字节开始.(假设单词长度为4个字节)

Line Replacement on Misses in Direct-Mapped Caches

如果缓存未命中,那么它需要从内存层次结构中的下一级中检索所请求的块,并将新块存(new block)储在由组索引位(the set index bits)指示的缓存行中。一般来说,如果组中装满了有效的缓存行,那么必须淘汰一个现有的行。对于直接映射的缓存,每个组包含一行的情况,替换策略只能是:当前行被新获取的行替换。

Putting It Together: A Direct-Mapped Cache in Action

假设有一个由(S, E, B, m) = (4, 1, 2, 4)描述的直接映射缓存。换句话说,该缓存有四个组,每个组有一行,每个块有2个字节,地址为4位。还假设每个字是一个字节。当然,这些假设是完全不现实的,但它们将帮助我们简化示例。

memory word

在计算机存储系统中,一个word是指在一次内存访问中可以被处理器读取或写入的数据单元的大小。而一个block(也称为cache块或内存块)是指在内存中连续存储的数据单元的集合。通常情况下,一个block包含多个连续的word。

关系在于,一个block通常包含多个word,这样在处理器访问内存时,可以一次性地将整个block加载到处理器的高速缓存中,而不是逐个word进行加载。这样可以提高内存访问的效率,因为处理器在处理数据时往往需要访问相邻的数据单元,而不是单独的word。

在这里插入图片描述
在这里插入图片描述
关于这个枚举空间,有一些事情值得注意:
标记(tag)和索引位(set index)的串联唯一地标识了内存中的每个块。例如,块0由地址0和1组成,块1由地址2和3组成,块2由地址4和5组成,依此类推。

由于有八个内存块,但只有四个高速缓存组(cache sets),因此多个块映射到同一个高速缓存组(即它们具有相同的组索引)。例如,块0和块4都映射到组0,块1和块5都映射到组1,依此类推。

映射到相同高速缓存组(cache set)的块由标记位(tag bit)唯一标识。例如,块0的标记位为0,而块4的标记位为1;块1的标记位为0,而块5的标记位为1,依此类推。

模拟CPU执行一系列读操作时缓存的工作情况。本例中假设CPU读取的是1字节的字。
在这里插入图片描述
表中的每一行代表一个高速缓存行(cache line)。第一列表示行所属的组(set),这不是高速缓存的实际组成部分。接下来的四列表示每个高速缓存行中的实际位(bits)。现在,让我们看看当CPU执行一系列读取操作时会发生什么:

在这里插入图片描述

  1. Read word at address 0. 由于组0 (set 0)的有效位(valid bit)为0,这是一次缓存未命中(cache miss)。缓存从内存(或更低级别的缓存)中获取块0(block 0),并将该块存储在组0(set 0)中。然后缓存从新获取的缓存行的块0(block[0],set 0的 cache line 的第一个cache block)返回m[0] (m[0] 是 memory address 0 的位置的内容)。

空cache line 导致的 cache miss

在一般情况下,当发生空缓存行(没有任何有效数据)导致的缓存未命中时,通常会将整个缓存行的所有缓存块从内存中加载到缓存中。这是因为空缓存行需要完全填充,以确保缓存行中的所有缓存块都包含有效数据,从而提高后续对该缓存行的访问效率。因此,在空缓存行导致的缓存未命中时,会更新整个缓存行的所有缓存块。

  1. Read word at address 1 (address 1 对应 0001), 所以在set 0的cache line. 这是一个缓存命中。缓存立即从缓存行的块[1](block[1], set 0的 cache line 的第二个cache block)中返回m[1]。缓存的状态不会改变。
    在这里插入图片描述
  2. Read word at address 13 (address 13 对应 1101), 所以在set 10的cache line, 由于集合2(set 2)中的缓存行无效,这是一个缓存未命中。缓存将块6加载到集合2中,并从新缓存行的块[1]返回m[13]。

在这里插入图片描述
4. Read word at address 8 (address 8 对应 1000), 因为tag 不匹配,所以是cache miss。缓存将块4(block number 4的内容)加载到集合0 (set 0)中(替换了从地址0读取的行),并从新缓存行的块[0]返回m[8]。

在这里插入图片描述
5. Read word at address 0. 这是另一个未命中,因为不幸的是,在先前引用地址8时刚刚替换了块0。这种未命中,即使缓存中有足够的空间,但不断交替引用映射到同一集合的块的情况,是冲突未命中(conflict miss)的一个例子。

Conflict Misses in Direct-Mapped Caches

在直接映射缓存中,冲突未命中通常发生在程序访问大小为2的幂的数组时。
好的spatial locality不一定会对应很多cache hit。
在这里插入图片描述
假设浮点数占用4个字节,x被加载到从地址0开始的32个连续内存字节中,而y则紧接着x从地址32开始。
为了简化,假设一个块(block)大小为16个字节(足够容纳四个浮点数),并且缓存由两个集合(set)组成,总共32个字节的缓存大小。将假设变量sum实际上存储在CPU寄存器中,因此不需要内存引用。在这些假设下,每个x[i]和y[i]将映射到相同的缓存集合。
在这里插入图片描述
如图所示,x[0] - x[3] 对应的是set0, y[0] - y[3] 对应的也是set 0, 在第一次迭代的时候,loop引用x[0], 因为cache为空,所以出现cache miss, 下一次引用y[0], 会覆盖缓存里的x[0] -x[3],之后会重复这个conflict miss的过程,The term thrashing describes any situation where a cache is repeatedly loading and evicting the same sets of cache blocks. 缓存返回load和evict同一个set的block称之为 thrashing (缓存抖动)。

在这里插入图片描述
一个简单的解决方案是在每个数组的末尾添加B字节的填充。定义数组不是x[8], 而是x[12],假设y的地址是紧邻x的,此时,x[i]和y[i] 不会映射到同一个set, 避免thrashing。

补充

ns和ms转换

要将纳秒(ns)转换为毫秒(ms),可以使用以下公式:
毫秒 = 纳秒 / 1,000,000
毫秒 = 秒 × 1,000
纳秒 = 秒 × 1,000,000,000

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值