Pinned Memory (AKA page-locked memory)

  • Pinned Memory,也称为页锁定内存,是一种特殊的内存分配方式,它确保内存始终驻留在物理内存中,不会被操作系统分页或交换到磁盘上。这种内存分配方式对于需要频繁访问的内存区域非常有用,因为它可以提高数据传输的速度。

  • Pageable Memory,也称为可分页内存,是由操作系统 API(如 malloc() )在主机上分配的内存。这种内存可以被操作系统分页和交换到磁盘上,以释放物理内存供其他程序使用。Pageable memory 的优点是可以更有效地利用物理内存,但在数据传输时可能会受到限制,因为数据可能需要先从磁盘加载到内存中。

pinned memory 和 pageable memory 主要关注的是 CPU 内存如何被操作系统管理以及是否可以被分页到磁盘

当使用 pinned 内存时,操作系统会将内存块标记为“固定”,这意味着该内存块不会被分页或交换到磁盘上。这种固定的内存块可以被硬件设备(如 GPU)直接访问,从而实现更快的数据传输。

异步实现 device 计算和数据传输时,host 必须是 pinned memory.

CUDA 等 GPU 计算框架使用 DMA 来高效地将数据从主机内存传输到 Device 内存,DMA 是一种允许硬件直接访问内存的机制,无需 CPU 的干预,从而显著提高数据传输速度。然而,标准的系统内存(分页内存)可能会被操作系统分页到磁盘上。如果在 DMA 传输过程中,操作系统将主机内存页面交换到磁盘,DMA 就会失败,就是GPU直接访问不到了。

Pinned memory,也称为固定内存或页面锁定内存,是一种特殊的内存区域,操作系统保证其始终驻留在物理内存中,不会被分页到磁盘。因此,使用 Pinned memory 进行异步数据传输可以确保 DMA 传输的可靠性和效率。

当异步地将数据从主机复制到设备时,CUDA 运行时可以立即启动 DMA 传输,而无需等待 CPU 。在数据传输完成之前,CPU 可以继续执行其他任务,从而实现真正的异步操作。

简而言之,Pinned memory 保证了内存的连续性和稳定性,避免了异步 DMA 传输过程中可能出现的页面错误,从而确保了异步数据传输的可靠性和效率。

C++ 中,直接使用 newmalloc 等标准库函数开辟内存空间时,不会自动区分 pinned 内存和 pageable 内存。 这些函数分配的是默认的可分页内存 (pageable memory)。***

简言之:这是因为异步数据传输依赖于DMA(Direct Memory Access)引擎,而 DMA 引擎需要访问物理上连续的内存区域 。Pinned memory 保证了内存的物理连续性,从而允许 DMA 引擎直接访问 Host 内存,而无需经过操作系统的页面置换,从而实现真正意义上的异步传输。

again

Pinned memory 减少传输时间的原理:在传统的内存分配方式中,数据可能会被存储在可分页内存中,这种内存可能会被操作系统分页或交换到磁盘上。当需要将数据传输到 GPU 时,首先需要将数据从可分页内存复制到临时的 pinned 内存,然后再从 pinned 内存复制到GPU。这个过程涉及到额外的内存拷贝操作,会增加传输时间。而使用 pinned 内存可以直接将数据从 pinned 内存传输到 GPU。

DMA:C++ 中默认的内存访问方式是通过 CPU 进行的,而不是 DMA。 DMA 的使用通常隐藏在操作系统和硬件驱动程序的底层实现中,C++ 程序员通常不需要直接与 DMA 交互。对于 C++ 和 CUDA 程序员来说,DMA 通常是透明的。不需要直接控制 DMA 的细节。 DMA 的细节被抽象掉了,由底层系统处理。

如何分配 pinned memory

使用 CUDA 提供的特定 API (cudaMallocHost 或 cudaHostAlloc)分配内存就能保证是 Pinned memory 了。