论文部分内容阅读
近年来基于GPU的并行技术发展迅猛,许多计算量很大的应用通过GPU并行计算获得了近百倍的加速比。然而,GPU的异构并行在内存管理方面面临着诸多问题。首先,GPU端显存的分配与访问、GPU与CPU的数据传输十分耗时。其次,应用GPU处理的问题越来越复杂,涉及的分配与释放的变量数量也越来越多,尺寸也越来越大。这对GPU端的内存管理提出了更高的要求。可是目前GPU端尚没有一个同时针对高效数据传输和提高内存利用率这两个目标设计的GPU内存管理系统。针对这个的问题,我们设计了一个可以高效稳定地管理GPU端内存分配的系统。首先,我们提出对变量进行分组管理,以减少数据分配和传输时间。其次,我们设计了一个"两阶段的内存管理机制"。在内存相对充裕的第一阶段,栈式内存管理机制可以帮助我们快速完成数据分配。在内存紧张的第二阶段,链式的内存管理机制可以保证程序正常运行。关于数据传输耗时的问题,由于数据传输的发起动作本身就很耗时,当程序需要传输多个小数据时,一般的数据传输方式意味着大量时间花费在了发起动作。将数据组织在一起传输过去可以减少数据传输消耗的时间。然而,将内存组织在一起需要程序员自己计算每个变量的地址偏移量。还需要考虑地址对齐等问题。这使得代码难读又容易出错。我们提出在数据的分配和传输阶段,将变量分组的技术。注册在同一组的变量会拥有相邻的地址空间,一次分配操作就可以为各个变量分配好各自的CPU端和GPU端地址。在没有内存管理系统的情况下,由于变量申请和释放时间的随机性,GPU端的内存会随着程序的进行,碎片化会越来越严重。由于GPU内存分配要求一个变量占用的内存空间连续,这就会出现即使GPU可用内存足够,仍旧无法满足内存申请的情况。连续内存便于寻址和数据传输,为了同时利用连续内存访问的好处并保证内存利用率,我们设计了一个双阶段的内存分配机制。首先,在内存资源不是约束条件的状态下,我们采用基于栈式的内存分配机制。通过移动栈顶指针来分配和释放内存。在释放不与栈顶相邻的内存时,我们就把它存入链式自由空间以备之后使用。栈式的内存管理在内存资源不是瓶颈的情况下,充分利用连续内存的优势,快速完成内存分配任务。其次,当内存资源紧张的时候,栈顶之上的自由内存可能无法满足内存分配的要求。这时就要使用之前释放的不连续内存来完成内存分配。在链式内存分配阶段,若存在一个尺寸大于申请的内存块,我们采用"首次适应"原则分配内存。若存在多块不连续内存尺寸之和可以满足一次内存分配,我们以尽量少的不连续内存块为链式内存分配的首要原则,"首次适应"为次要原则来完成不连续内存的分配。同时,针对不连续内存的情况,为了让程序可以快速获得地址,我们设计了一个以线程块(block)为单位的地址索引结构来加速地址的寻址。综上所述,我们建立了一个GPU端的内存管理系统。对变量的分组可以加速数据的传输,减少内存的碎片化,帮助编程人员组织变量。通过双阶段的内存管理,可以在内存相对充裕的情况下快速完成数据传输,在内存紧张的情况下,保证程序正确运行。实验结果表明,我们设计的内存管理系统可以在GPU端高效的运行。