帮助中心 >
  关于网络安全 >
  CPU和GPU之间的内存墙是怎么拆掉的?
CPU和GPU之间的内存墙是怎么拆掉的?
时间 : 2025-12-13 13:27:46
编辑 : Jtti

在一台配置了GPU的云服务器上跑深度学习训练或者科学计算任务时,经常会发现一个头疼的问题:程序很大一部分时间并不是花在GPU疯狂计算上,而是消耗在准备数据上。具体来说,就是数据在CPU管理的主内存和GPU自带的显存之间来回搬运。这个过程慢是CPUGPU存在各自独立内存空间。传输需通过PCIe总线这条走廊进行复制式的搬运。为了提高效率CUDA引入一套机制核心叫做统一虚拟地址空间和内存映射,目标就是在这堵墙上打开一扇更直接的门,甚至试图推倒这堵墙。

传统的工作流程很直接但效率不高。CPU在系统内存中准备好数据,然后调用一个显式的拷贝函数,比如`cudaMemcpy`,数据才会经由PCIe总线进入GPU显存。GPU计算完成后,结果又需要一次显式的拷贝才能回传到系统内存供CPU使用。这两次拷贝,尤其是当数据量很大或者交互频繁时,会成为整个流程的拖累。CUDA的内存映射机制,有时也被称为零拷贝内存,提供了一种不同的思路。它的核心是允许GPU线程直接访问存放在系统主内存中的数据,省去了中间显式的拷贝步骤。这并不是说数据凭空移动了,而是通过内存管理单元和驱动的协作,让GPU能够透过PCIe总线,直接对系统内存的特定区域进行读写操作。

实现这一点的技术基石是统一虚拟地址。在64位的操作系统和支持的GPU上,CUDA驱动会创建一个巨大的、统一的虚拟地址空间。这个空间涵盖了主机内存、GPU显存以及其他设备的内存。对于程序中的任何一个指针,CUDA运行时都能判断出它实际指向的是哪个物理位置。有了这个基础,接下来就可以进行关键的一步:创建映射内存。程序员可以使用`cudaHostAlloc`函数,并指定`cudaHostAllocMapped`这个标志,来分配一种特殊的主机内存。这块内存在分配时就被锁定在物理内存中,不会出现操作系统交换到硬盘上,同时驱动会在GPU的页表中为这块相同的物理内存创建映射。于是,同一块物理内存在主机侧有一个虚拟地址指针,在设备侧也有一个对应的虚拟地址指针。GPU的线程只需要使用设备侧的指针,其访问请求就会被GPU的内存管理单元捕获,并通过PCIe总线直接转发到系统内存完成读写。从编程模型上看,数据仿佛就在GPU身边,尽管物理上它可能离得很远。

```c
float *host_ptr, *device_ptr;
size_t size = N * sizeof(float);
// 在主机上分配可被GPU直接映射访问的内存
cudaHostAlloc(&host_ptr, size, cudaHostAllocMapped);
// 获取这块内存在GPU地址空间中的对应指针
cudaHostGetDevicePointer(&device_ptr, host_ptr, 0);
// 现在,GPU内核可以直接使用device_ptr来读写host_ptr指向的主机内存
my_kernel<<<...>>>(device_ptr, N);

当然,这种便利性并非没有代价。最直接的代价就是访问延迟和带宽。GPU通过PCIe访问系统内存的速度,远低于访问自身高速显存的速度。因此,映射内存最适合那些访问模式不那么频繁,或者数据只被GPU一次性读取的场景。例如,作为数据输入的缓冲区,或者用来接收GPU计算产生的少量结果。如果一个数据需要在GPU核心中被反复、密集地读写,那么先将其拷贝到显存中再进行计算,效率会高得多。另一个关键点是同步。既然CPUGPU都能直接访问同一块物理内存,那么就必须小心翼翼地协调它们的访问顺序,否则就会导致数据竞争和错误。通常需要使用CUDA事件或者流同步来确保CPU在安全的时间点去读取GPU写入的数据,反之亦然。

在云环境中,你可能会使用不同型号的GPU实例,它们的PCIe带宽和拓扑结构可能有所不同。对于PCIe带宽较高的实例,使用映射内存的收益会更明显。一个实用的模式是将映射内存用作一个灵活的、大小可超显存容量的缓冲池。当处理的数据集非常大,无法一次性装入显存时,可以循环使用一块映射内存,让GPU分批处理。不过,需要仔细评估这种分批处理中,PCIe数据传输带来的开销是否可以被GPU的计算吞吐所掩盖。另一种常见用法是处理需要频繁在CPUGPU之间交换的中间结果,避免多次拷贝的开销。

CUDA后续版本推出的统一内存概念,可以看作是这种映射思想的进一步发展和自动化。统一内存系统提供了一个统一的内存池,程序员从一个池中分配指针,数据的物理位置迁移(在系统内存和显存之间)由驱动和硬件在背后自动管理,通过页面故障机制来触发。这简化了编程,但底层仍然离不开映射和直接访问这些基础机制的支持。

售前客服
JTTI-Ellis
JTTI-Defl
JTTI-Coco
JTTI-Eom
JTTI-Amano
JTTI-Selina
JTTI-Jean
技术支持
JTTI-Noc
标题
电子邮件地址
类型
销售问题
销售问题
系统问题
售后问题
投诉与建议
市场合作
信息
验证码
提交