1. 物理内存:真实的内存芯片颗粒,在物理总线上占据一段或几段连续的地址范围。
  2. 虚拟内存:用户程序使用虚拟内存地址访问内存单元,虚拟内存地址总是要翻译成物理总线上的地址。这样一来,物理总线上不连续的内存范围,在虚拟内存地址上也可能是连续的,这满足了用户程序对大块连续内存的使用需求。

在已经运行过一段时间的系统中,分配一个物理地址上连续的、大内存是比较困难的;Linux操作系统的swiotlb会在系统启动早期预留出一块64MB的连续物理内存,用于满足DMA内存请求。

从物理总线上看,地址连续的大内存很难满足;但是从虚拟内存地址上,这可以通过MMU做到。处理器CPU上的每个核都有一个MMU,以及现代GPU也有一个MMU(我们称之为“IOMMU”)。从物理内存来看:

  1. CPU上的每个核和GPU都是主设备,都可以发起对物理内存的访问,物理内存都会响应这种访问;
  2. CPU上的每个核和GPU使用各自的虚拟地址访问物理内存时,经过各自的MMU地址翻译后,最终应该时物理内存所在的物理总线上的地址。

gpu指定虚拟机使用显存上限 虚拟gpu内存_linux

 

CPU使用页表来记录虚拟地址到物理地址的映射关系;GPU也使用类似的机制(我们称之为GART表)。

CPU和GPU的交互要确保:

  1. CPU写的数据能被GPU看到;
  2. GPU写的数据能被CPU看到;

由于存在缓存和写缓冲的机制,CPU访问内存一般有三种属性

  1. UC,无缓存、无写合并(CPU访问内存的效率最差)
  2. WC,无缓存、有写合并
  3. WB,有缓存、有写合并(CPU访问内存的效率最高)

CPU对物理内存的写,一般是无确认写。因此,当CPU完成对内存写之后,为了确保GPU能看到,可能需要:

  1. 内存屏障操作
  2. 缓存同步操作
  3. dummy IO读操作

而GPU在写物理内存之后,要确保CPU能看到,CPU可能需要

  1. 缓存同步操作
  2. GPU提供的硬件锁同步操作