Page 53 - 《软件学报》2020年第10期
P. 53

李鼎基  等:基于跨虚拟机零下陷通信的加速器虚拟化框架                                                      3029




















                                      Fig.6    Architecture of prototype system
                                            图 6   原型系统架构图
         4.1   支持 CUDA 调用的 API 转发基础框架
             目前主流的深度学习框架与 GPU 类加速器的交互主要通过调用 NVIDIA 公司推出的 CUDA                          [27] 统一计算
         API.本文在收集了被使用到的 CUDA API 后发现,主流的深度学习框架用到的科学计算库主要有 cudart、
         cuBLAS、cuDNN 和 cuRAND,应用程序通过动态链接的方式调用这些计算库中的 CUDA API.
             本文在实现时,将整个虚拟化系统的基础框架划分为前端模块、通信模块以及后端模块,其中,前端模块放
         置在客户端虚拟机中,后端模块放置在服务端虚拟机中,通信模块用于在两个虚拟机之间实现代理执行.
             (1)  在前端模块中,本系统为所有收集到的 CUDA API 按照官方文档实现了相同函数原型的桩函数,分别封
         装在对应计算库同名的桩函数库中(如 libcudart.so,libcudnn.so 等).这些桩函数库将通过修改环境变量
         LD_LIBRARY_PATH 的方式代替客户端虚拟机中原生的计算库,实现对于应用程序 CUDA 调用的拦截.
             (2)  在后端模块中,本系统首先使用 dlopen 预载用到的 CUDA 计算库,接着向虚拟机监视器注册后端处理
         函数的代理执行入口,然后会 fork 出与 CPU 核数等量的子进程以尽可能多地支持并发的前端请求,每个子进程
         可以对应一个前端模块.最后,后端模块会进入冻结状态,等待来自前端的代理执行.
             (3)  通信模块的具体实现将在本节余下部分详细地加以描述.
             为了减少前后端通信的次数以降低通信开销,本系统对于常用的 CUDA 核函数(kernel)的转发方法做了与
         GVirtuS、vCUDA 等前序工作类似的批处理(batching)优化.一次 CUDA 核函数的调用实际上依次分别调用了 3
         种 CUDA API(1 次 cudaConfigureCallÆ1 次或多次 cudaSetupArgumentÆ1 次 cudaLaunch),因为只有最后的
         cudaLaunch 是真正与设备交互的显式同步点,所以每次拦截到前两种 CUDA API 时不用立即转发到后端,可以
         与最后的 cudaLaunch 一起批量地处理.
             较新的 CUDA 版本支持了统一虚拟内存(unified virtual addressing,简称 UVA)的特性,例如 cublasSdot 的指
         针参数既可能指向主机内存也可能指向设备内存,在原生环境下需要 GPU 的驱动程序对于内存拷贝的方向(比
         如从设备拷贝到主机内存)进行判断,必须根据源地址段和目的地址段的内存类型(主机内存地址或设备内存地
         址)加以决定.在本虚拟化系统中,由于 GPU 的驱动程序与应用程序处在不同的地址空间中,客户端虚拟机中的
         应用程序转发来的地址无法由服务端虚拟机中的驱动程序进行正确的检查和判断,因此本系统基于区间树
         (interval tree)实现了一套高效的 GPU 设备地址的追踪模块,对于诸如 cudaMalloc 等分配设备内存的 API 返回
         的设备内存区间进行记录,在拦截到使用了 UVA 特性的 CUDA API 后,使用追踪模块查询传入的内存地址参数
         所属的内存类型,然后依据具体情况进行处理.
             按照 Wormhole 的设计,在服务器虚拟机启动前,需要主机操作系统将 GPU 设备通过 PCI 直通的方式实现
         透传,启动后需要配置好驱动程序和科学计算库等.双方虚拟机均需要下陷注册自己的相关信息,本系统修改了
         KVM 中 CPUID 的下陷处理函数,在收到注册请求后会根据虚拟机的类型和请求完成相应的操作.
   48   49   50   51   52   53   54   55   56   57   58