CPU适合做控制密集型的任务,并不擅长进行大量的数据计算,因此现在主流的技术方案都是通过总线将加速器与CPU连接起来,CPU将计算任务提交给加速器,加速器完成计算后将计算结果返回给CPU。这里的加速器,可以是GPGPU, 可以是深度学习ASIC,也可以是FPGA之类的,总之就是专门为并行计算而生的数据计算引擎。如今许多与AI相关的芯片公司都是做这个的。

CPU与加速器是怎么连接的呢? PCIe总线!

CPU与加速器之间的数据交互大致是怎么进行的呢?

大致是基于Producer-Consumer模型,CPU是数据的生产者,加速器是数据的消费者。当CPU想要加速器进行计算时,先将需要计算的数据写入主存中,然后通过Host Memory write的方式,告诉加速器我把数据写到某某地方了,您赶紧去取吧。加速器收到Memory write后,知道需要干活儿了,就按CPU的指示,通过 DMA的方式从主存中将数据搬到自己的本地Memory,然后开展计算工作,计算工作完成后将计算结果通过DMA的方式写入CPU主存中。

在AI训练,图形渲染等应用场景,迭代次数多,会频繁地访问某些地址的数据。而通过上述DMA的方式搬移数据,延迟会非常大,GPU->CPU->DDR,都已经跨越多块芯片了,延迟可想而知。所以,能不能在加速器里面做个cache,将需要频繁使用的主存中的数据缓存在cache中呢?这样一来就会大大缩减加速器设备访问CPU主存的延时。可以是可以的,但是这样会带来缓存一致性的问题,CPU中的多个cache,以及加速器设备中的cache都有可能缓存同一个cache line, 这里就需要某种一致性协议来解决缓存一致性问题。而CXL.cache协议就是为了解决设备cache和CPU cache之间的缓存一致性问题。CXL.cache协议使用的缓存一致性协议是MESI,M(Modified), E(Exclusive),S(Shared),I(Invalid)。CPU里面会有一个叫Home Agent的模块,在必要的时候(比如某个core想要改写主存中某个地址的值,而这个地址有可能在peer cache中有拷贝),会向所有的peer cache发起snoop请求,询问各个peer cache, 你们的cache里有没有缓存这个cache line啊?如果缓存了,你们的状态是啥啊?注意,这里的peer cache既包括其他CPU core的cache,也包括加速器设备中的cache。

CXL一共由CXL.io,CXL.memory,CXL.cache三个子协议组成。CXL.io实际上就是PCIe Gen5的那部分功能,用来枚举,配置,中断等等。CXL.cache的作用我们上面已经讨论了,下面,我们讨论下CXL.memory的作用。

类似于GPGPU这种加速设备,是有自己的memory的,或者是HBM,或者是DDR。这类Device Attached Memory空间还不小,一般可以到几G甚至几十G。目前,在PCIe协议的框架下,只能通过上面提到的Producer-Consumer模型的方式,让设备通过DMA的方式把数据搬移到自己的Momory空间,Host CPU是没办法直接访问的。我们将这种设备自己私有的,具有私有独立编址空间的设备内存叫做PDM(Private Device Memory)。而CXL.memory协议将设备的memory进行系统统一编址,使得在Host CPU看来就像自己的主存一样,可以直接访问。进行统一编制后的设备内存称为HDM(Host-managed Device Memory)。这样一来,CXL.momory就提供了一种“simple reads and wirtes from host to device memory ”的方式。这种简单直接的访问设备内存,对于内存扩展设备是非常方便的。

如何在cpu上加载在gpu上训练的模型 cpu给gpu加速_协议栈

 上图是CXL协议中提到的三种典型的使用场景。其中第一种是NIC(Network Interface Card, 网卡),它使用到了CXL.io和CXL.cache子协议。网卡中有cache, 可以缓存主存中的数据,以至于可以很方便的进行复杂的原子操作。CXL.cache子协议帮助维持cache一致性。第二种就是GPGPU加速卡之类的,三种子协议都使用到了,因为既有memory,又有cache。第三种就是内存扩展卡,没有cache,只使用到了CXL.io和CXL.memory。