一种面向GPU集群环境的避免GPU资源争用的方法转让专利

申请号 : CN201711326972.X

文献号 : CN107943592B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 东方师晓敏罗军舟查付政王睿孙斌

申请人 : 中通服咨询设计研究院有限公司东南大学

摘要 :

本发明公开了一种面向GPU集群环境的避免GPU资源争用的方法,包括支持多应用程序细粒度并发执行的插件,应用程序行为特征抽取和应用程序任务调度。针对同一个NVIDIA GPU节点上运行的多个应用程序可能会引起的GPU资源争用问题,构建一个支持多应用程序细粒度并发执行的平台,使得多个应用程序在同一个GPU节点上可以尽可能的并发执行。其次,抽取每个应用程序的GPU行为特征,包括GPU使用模式和GPU资源需求信息。根据应用程序的GPU行为特征,以及当前GPU集群中各个GPU节点的资源使用状态,调度应用程序到适合的GPU节点上,从而最小化多个独立应用程序在同一个GPU节点上的资源争用。

权利要求 :

1.一种面向GPU集群环境的避免GPU资源争用的方法,其特征在于,包括以下步骤:

步骤1,构建一个支持多应用程序细粒度并发执行的插件:该插件包含一个自行编写的GPU运行时伪函数库和一个自行编写的本地服务器进程,GPU运行时伪函数库与NVIDIA自带的GPU运行时函数库有相同的函数原型,但各个函数实现体的基本功能包括:变换同步函数为异步函数;向本地服务器进程转发相关的函数执行请求;该细粒度并发执行插件的作用为:同一个GPU节点上的多个应用程序对GPU运行时库函数的调用,均需通过GPU运行时伪函数库变换、转发,并通过本地服务器进程执行;

步骤2,在GPU集群的头结点,使用自行编写的GPU运行时伪函数库替换NVIDIA自带的GPU运行时函数库,该伪函数库将GPU内存创建类函数、GPU内存拷贝类函数、GPU内核执行函数、GPU同步类函数的函数体替换为相应函数的字符输出信息;当一个用户向GPU集群中的头结点提交待执行的GPU应用程序时,在GPU集群的头结点中运行该应用程序,即能够在避免真实运行的模式下,获得该应用程序运行过程中所需执行的GPU关键函数信息,从而获得该应用程序的GPU使用模式;另一方面,使用NVIDIA自带工具CUOBJDUMP、PTXAS,静态解析该应用程序中的GPU内核函数,能够抽取应用程序所需使用的GPU资源需求信息;

步骤3,根据步骤2中的获取应用程序的GPU使用模式和GPU资源需求信息,以及当前GPU集群中各个GPU节点的资源使用状况,在GPU集群的头结点中,调度所到达的GPU应用程序到适宜的GPU节点上运行;

步骤1中,所述的同步函数专指GPU内存拷贝类同步函数、GPU内核执行函数和GPU设备同步函数,而对应的异步函数专指对应的GPU内存拷贝类异步函数、GPU内核执行函数和GPU流同步函数。

2.根据权利要求1所述的方法,其特征在于,步骤1包括以下步骤:

步骤1-1,应用程序调用GPU运行时库函数时,若所需调用的GPU运行时库函数为同步函数,则将其变换为对应的异步函数;

步骤1-2,将应用程序对GPU运行时库函数的调用请求,包括函数名和参数,转发到本节点的服务器进程;

步骤1-3,本地服务器端进程根据所接收到的调用请求,执行相应的NVIDIA自带GPU运行时库函数,并返回执行结果给调用方。

3.根据权利要求2所述的方法,其特征在于,步骤2中,所述GPU关键函数信息包括应用程序申请GPU内存类操作、在主机和GPU设备之间拷贝数据类操作、执行GPU内核函数操作、GPU设备流同步操作和GPU设备同步操作;所述GPU使用模式是由GPU关键函数构成的有向图;所述GPU资源需求信息包括执行GPU内核函数所需的块CUDABlock数量、线程CUDAThread数量、全局内存数量、共享内存数量和寄存器数量。

4.根据权利要求3所述的方法,其特征在于,步骤2中,所述获得该应用程序的GPU使用模式,具体包括以下步骤:步骤2-1,在GPU运行时函数库为伪库的环境下,执行应用程序代码,依次获得GPU关键函数信息;

步骤2-2,根据各个GPU关键函数信息,构造描述GPU函数调用顺序的有向图,从而获得GPU使用模式;

步骤2-3,根据各个GPU关键函数信息,获取该应用程序所需的块CUDA Block数量、线程CUDA Thread数量和全局内存数量信息。

5.根据权利要求4所述的方法,其特征在于,步骤2中,所述抽取应用程序的GPU资源需求信息,具体包括以下步骤:步骤2-4,使用NVIDIA自带工具CUOBJDUMP,抽取应用程序中GPU内核函数的并行线程执行PTX代码;

步骤2-5,使用NVIDIA自带工具PTXAS,解析所有的并行线程执行PTX代码,获取GPU内核函数所需的共享内存数量和寄存器数量信息;

步骤2-6,将步骤2-3中获取的块CUDA Block数量、线程CUDA Thread数量和全局内存数量信息,与步骤2-5中获取的共享内存数量和寄存器数量信息结合,即获得了该应用程序所需使用的GPU资源需求信息。

6.根据权利要求5所述的方法,其特征在于,步骤3包括以下步骤:

步骤3-1,在GPU集群的头结点中维护一个列表,其中记录各个GPU计算节点当前拥有的GPU资源信息,包括:块CUDABlock数量、线程CUDAThread数量、全局内存数量、共享内存数量和寄存器数量,这些信息的初始值为GPU计算节点硬件支持的各种资源的数量;

步骤3-2,寻找当前GPU集群中是否存在空闲的GPU计算节点,若存在,则将到达的应用程序调度到最近的空闲GPU计算节点,转到步骤3-6;否则,转到步骤3-3;

步骤3-3,从最近被调度节点的下一个节点开始,根据待调度应用程序的GPU使用模式和GPU资源需求信息,以及各个GPU计算节点当前拥有的GPU资源信息,寻找第一个能满足该应用程序资源需求的GPU计算节点,若找到,则转到步骤3-6;否则,该应用程序放入待调度队列,并转到步骤3-4;

步骤3-4,当有GPU计算节点向头结点汇报其上的一个应用程序执行结束时,头结点检查待调度队列中是否有等待被调度的应用程序,若存在,则从队头开始,找到一个应用程序,并转到步骤3-5;否则,转到步骤3-7;

步骤3-5,判断该GPU计算节点能否满足该应用程序资源需求,若该GPU计算节点能够满足,则转步骤3-6;否则,找后一个等待被调度的应用程序,转步骤3-5;

步骤3-6,将应用程序调度到所选定的GPU计算节点上,并在GPU集群的头结点维护的列表中,更新对应GPU计算节点的GPU资源信息;

步骤3-7,结束步骤3的流程。

说明书 :

一种面向GPU集群环境的避免GPU资源争用的方法

技术领域

[0001] 本发明涉及GPU高性能计算领域,尤其涉及一种面向GPU集群环境的避免GPU资源争用的方法。

背景技术

[0002] GPU加速计算是指同时利用图形处理器(GPU)和CPU,加快科学、分析、工程、消费和企业应用程序的运行速度。GPU加速计算可以提供非凡的应用程序性能,能将应用程序计算密集部分的工作负载转移到GPU,同时仍由CPU运行其余程序代码。从用户的角度来看,应用程序的运行速度明显加快。利用GPU加速应用程序的执行,目前已经越来越流行。如在科学计算领域,科研人员使用GPU加速蒙特卡洛仿真实验;使用GPU加速数值计算;在图像处理领域,人们利用GPU处理大规模医学影像数据;在数据挖掘领域,利用GPU加速数据挖掘算法的执行;在人工智能领域,利用GPU加速算法的训练等。目前,国内外许多大规模云服务提供商均已支持GPU服务,如亚马逊EC2、微软Azure、百度云等。
[0003] 随着技术的发展,新一代的GPU中容纳了更多的多流处理器(Streaming Multiprocessors,SM、SMX)和流处理器(Streaming processors,SP),也支持了更多有用的特性,如Hyper-Q、动态并行(Dynamic Parallelism)等。但是,GPU利用率低下问题日趋凸显。其主要原因在于:
[0004] 1)受限于当前GPU计算模型。目前GPU编程通常经过以下步骤:首先,使用CPU将位于硬盘上的待处理数据拷贝到主机内存;第二,在GPU设备上开辟空间,并将主机内存上的数据拷贝到GPU设备的内存空间中;第三,GPU设备执行相应的内核函数进行并行计算,并将结果写回GPU设备内存;最后,GPU设备内存的数据需要拷贝回主机内存。另外,若存在网络通信,则还需要依靠CPU来辅助完成。在编程过程中,有些代码无法或者不适合在GPU上完成,如一些无法并行执行的代码;数据迁移的代价大于并行计算带来的好处的代码;I/O操作等。因此程序员需要事先指定CPU和GPU上执行代码的比例,这导致GPU出现空闲,从而使得GPU利用率低下。
[0005] 2)GPU指派方式不合理。很多GPU应用程序会显式的指定所要使用的GPU设备。当大量应用程序都指定使用同一个GPU设备时,会导致该GPU节点过度负载。当应用程序到达某GPU节点的频率过低时,会导致该GPU节点欠负载。
[0006] 因此,为了提高GPU利用率,其中一种方法是根据GPU集群中各个节点的资源状态,以及到达的应用程序的GPU行为特征,将其调度到合适的GPU节点上。为达到该目标,需要解决的主要问题有:1)在应用程序到达的时候,快速、透明、准确的获取应用程序的GPU行为特征;2)提出合理、高效的调度策略;3)提高多个独立应用程序在同一个GPU上执行时并发度,减少资源争用。
[0007] 根据现有对应用程序GPU行为特征提取的研究可知,现有的方法主要有NVIDIA CUPTI、PAPI、Tau、Vampir等。NVIDIA CUPTI主要通过注册相应回调函数方法,在应用程序执行期间,实时获取应用程序调用GPU运行时库函数的信息。当应用程序执行完毕后,才能获得所有GPU函数调用信息。PAPI、Tau、Vampir是通过在源代码中插桩的方法,使应用程序在执行过程中能够触发所插入代码的执行,从而获取应用程序对GPU函数调用的信息。上述已有方法均要在应用程序执行完毕后,才能获取其GPU行为特征。但在本应用场景中,应用程序一到达就需要获取其GPU行为特征,为后续调度做出决策依据。
[0008] 根据现有对应用程序在GPU上并发执行的研究可知,在NVIDIA CUDA4.0及以后,允许一个进程的多个线程共享一个上下CUDA上下文,且这些线程之间能够并发执行。但是该方法并不能使得多个独立应用程序之间细粒度并发执行。NVIDIA MPS(Multi-Process Service)服务允许多个进程并发执行,但是它更适用于MPI程序,并不推荐在独立应用程序之间使用。NVIDIA Hyper-Q技术支持32路独立硬件管理的工作队列并发执行,但是它也只适用于同一个上下文中,不同流之间的GPU操作并发执行。
[0009] 综上所述,目前针对快速、透明、准确、提前的获取应用程序的GPU行为特征,多个独立应用程序细粒度并发方面的研究起步不久,目前还未有能有效、快速、透明、提前的获取GPU行为特征的方法,也未提出能有效提高多个独立应用程序在同一个GPU上执行时并发度的方法。对这些问题的解决,充满着困难与挑战。

发明内容

[0010] 针对现有技术的问题,本发明公开了一种面向GPU集群环境的避免GPU资源争用的方法,包括如下步骤:
[0011] 步骤1,构建一个支持多应用程序细粒度并发执行的插件:该插件包含一个自行编写的GPU运行时伪函数库(libcudart.so)和一个自行编写的本地服务器进程,前者(GPU运行时伪函数库)与NVIDIA自带的GPU运行时函数库(libcudart.so)有相同的函数原型,但各个函数实现体的基本功能包括:变换同步函数为异步函数;向后者(本地服务器进程)转发相关的函数执行请求。该细粒度并发执行插件的作用为:同一个GPU节点上的多个应用程序对GPU运行时库函数的调用,均通过GPU运行时伪函数变换、转发,并通过本地服务器进程执行,从而提高了多个独立应用程序执行的并发度;
[0012] 步骤2,在GPU集群的头结点,使用自行编写的GPU运行时伪函数库(libcudart.so)替换NVIDIA自带的GPU运行时函数库(libcudart.so)。该伪函数库将GPU内存创建类函数(cudaMalloc等)、GPU内存拷贝类函数(cudaMemcpy等)、GPU内核执行函数(ccudaConfigureCall)、GPU同步类函数(cudaDeviceSynchronize等)的函数体替换为相应函数的字符输出信息。当一个用户向GPU集群中的头结点提交待执行的GPU应用程序时,在GPU集群的头结点中运行该应用程序,即可在避免真实运行的模式下,获得该应用程序所需执行的GPU关键函数信息,从而获得该应用程序的GPU使用模式;另一方面,使用NVIDIA自带工具CUOBJDUMP、PTXAS,静态解析该应用程序中的GPU内核函数,抽取应用程序所需使用的GPU资源需求信息;
[0013] 步骤3,根据步骤2中的获取应用程序的GPU使用模式和GPU资源需求信息,以及当前GPU集群中各个GPU节点的资源使用状况,在GPU集群的头结点中,调度所到达的应用程序到适宜的GPU节点上运行。
[0014] 步骤1中,所述的同步函数专指GPU内存拷贝类同步函数(cudaMemcpy等)、GPU内核执行函数(ccudaConfigureCall,不含有流参或使用默认流参)、GPU设备同步函数(cudaDeviceSynchronize)。而对应的异步函数专指对应的GPU内存拷贝类异步函数(cudaMemcpyAsync等)、GPU内核执行函数(ccudaConfigureCall,含有流参)、GPU流同步函数(cudaStreamSynchronize)。
[0015] 步骤1包括以下步骤:
[0016] 步骤1-1,应用程序调用GPU运行时库函数时,若所需调用的GPU运行时库函数为同步函数,则将其变换为对应的异步函数;
[0017] 步骤1-2,将应用程序对GPU运行时库函数的调用请求,包括函数名和参数,转发到本节点的服务器进程;
[0018] 步骤1-3,本地服务器端进程根据所接收到的调用请求,执行相应的NVIDIA自带GPU运行时库函数,并返回执行结果给调用方。
[0019] 步骤2中,所述GPU关键函数信息包括应用程序申请GPU内存类操作、在主机和GPU设备之间拷贝数据类操作、执行GPU内核函数操作、GPU设备流同步操作和GPU设备同步操作;所述GPU使用模式是由GPU关键函数构成的有向图;所述GPU资源需求信息包括执行GPU内核函数所需的块(CUDABlock)数量、线程(CUDAThread)数量、全局内存数量、共享内存数量和寄存器数量。
[0020] 步骤2中,所述获得该应用程序的GPU使用模式,具体包括以下步骤:
[0021] 步骤2-1,在GPU运行时函数库为伪库的环境下,执行应用程序代码,依次获得GPU关键函数信息;
[0022] 步骤2-2,根据各个GPU关键函数信息,构造描述GPU函数调用顺序的有向图,从而获得GPU使用模式;
[0023] 步骤2-3,根据各个GPU关键函数信息,获取该应用程序所需的块(CUDABlock)数量、线程(CUDAThread)数量和全局内存数量信息。
[0024] 步骤2中,所述抽取应用程序的GPU资源需求信息,具体包括以下步骤:
[0025] 步骤2-4,使用NVIDIA自带工具CUOBJDUMP,抽取应用程序中GPU内核函数的并行线程执行(Parallel Thread eXecution,PTX)代码;
[0026] 步骤2-5,使用NVIDIA自带工具PTXAS,解析该应用程序的所有并行线程执行(Parallel Thread eXecution,PTX)代码,获取GPU内核函数所需的共享内存数量和寄存器数量信息;
[0027] 步骤2-6,将步骤2-3中获取的块(CUDABlock)数量、线程(CUDAThread)数量和全局内存数量信息,与步骤2-5中获取的共享内存数量和寄存器数量信息结合,即获得了该应用程序所需使用的GPU资源需求信息。
[0028] 步骤3包括以下步骤:
[0029] 步骤3-1,在GPU集群的头结点中维护一个列表,其中记录各个GPU计算节点当前拥有的GPU资源信息,包括:块(CUDABlock)数量、线程(CUDAThread)数量、全局内存数量、共享内存数量和寄存器数量。这些信息的初始值为GPU计算节点硬件支持的各种资源的数量。
[0030] 步骤3-2,寻找当前GPU集群中是否存在空闲的GPU计算节点,若存在,则将到达的应用程序调度到最近的空闲GPU计算节点,转到步骤3-6;否则,转到步骤3-3;
[0031] 步骤3-3,从最近被调度节点的下一个节点开始,根据待调度应用程序的GPU使用模式和GPU资源需求信息,以及各个GPU计算节点当前拥有的GPU资源信息,寻找第一个能满足该应用程序资源需求的GPU计算节点,若找到,则转到步骤3-6;否则,该应用程序放入待调度队列,并转到步骤3-4;
[0032] 步骤3-4,当有GPU计算节点向头结点汇报其上的一个应用程序执行结束时,头结点检查待调度队列中是否有等待被调度的应用程序,若存在,则从队头开始,找到一个应用程序,并转到步骤3-5;否则,转到步骤3-7;
[0033] 步骤3-5,判断该GPU计算节点能否满足该应用程序资源需求,若该GPU计算节点能够满足,则转步骤3-6;否则,找后一个等待被调度的应用程序,转步骤3-5;
[0034] 步骤3-6,将应用程序调度到所选定的GPU计算节点上,并在GPU集群的头结点维护的列表中,更新对应GPU计算节点的GPU资源信息;
[0035] 步骤3-7,结束步骤3的流程。
[0036] 本发明方法主要解决多个独立应用程序在NVIDIAGPU集群中运行时,同一个GPU上的多个应用程序之间争用其上的GPU资源,从而导致应用程序性能下降的问题。
[0037] 本发明主要针对GPU集群环境中GPU利用率低下的问题,提出了一种避免多个应用程序在同一个GPU节点上执行时出现GPU资源争用的中间件,能够在应用程序到达时,快速、透明的抽取其GPU行为特征,并根据相应的调度算法,将其调度到合适的GPU节点上运行。此外,为了最大程度的避免同一个GPU节点上多个应用程序之间GPU资源争用问题,在每个GPU节点上,构建了一个支持多个应用程序细粒度并发执行的插件。本发明所提出的中间件,在保障应用程序执行性能(周转时间)的前提下,提高了GPU的利用率和系统吞吐率。
[0038] 有益效果:
[0039] 本发明的有效之处在于:
[0040] 通过在应用程序到达时快速、透明的抽取应用程序GPU行为特征,结合支持多个独立应用程序细粒度并发执行的插件,可以有效避免多个应用程序在一个GPU上执行时的资源争用,保障应用程序执行性能,提高GPU的利用率和系统吞吐率。
[0041] 本发明与现有技术相比,具有以下优点:
[0042] 1、本发明能够快速、透明、准确、提前的抽取应用程序的GPU使用模式和GPU资源需求信息,可以在应用程序执行之前快速获取其GPU行为特征,为有此类需求的研究提供了参考;
[0043] 2、对支持多个独立应用程序细粒度并发执行的插件,可以帮助一个GPU设备上多个独立应用程序细粒度并发执行,为优化应用程序的执行性能,提高GPU利用率的相关研究提供了新思路;
[0044] 3、将抽取GPU行为特征、冲突避免的调度机制、细粒度并发执行插件有机结合,为有效解决GPU集群环境中的GPU利用率低下的问题提供了新思路;
[0045] 4、本发明提出的避免GPU资源争用的中间件,可扩展性高,计算复杂度低,可以适用于大规模的GPU集群环境。
[0046] 5、模块化的设计使得系统的各个组件之间耦合度较低,各个模块之间交互简单,可以适应新的需求和扩展。
[0047] GPU高性能计算作为一种热门的技术,发展前景令人期待;GPU集群计算作为GPU高性能计算中最重要的问题之一值得人们关注。在此背景下,本发明针对GPU集群利用率低下的问题,通过对到达的应用程序GPU行为特征进行抽取,根据GPU集群中GPU计算节点的资源状态,对应用程序进行调度,并结合多个独立应用程序细粒度并发执行的插件,有效避免多个应用程序在一个GPU上执行时的资源争用,保障应用程序执行性能,提高GPU的利用率和系统吞吐率。

附图说明

[0048] 下面结合附图和具体实施方式对本发明做更进一步的具体说明,本发明的上述或其他方面的优点将会变得更加清楚。
[0049] 图1为GPU集群示意图。
[0050] 图2为本发明实现的各个组件框架图。
[0051] 图3为本发明实现的应用程序调度模块算法流程图。
[0052] 图4为本发明实现的GPU节点上应用程序GPU运行时函数执行过程序列图。
[0053] 图5a为关键函数信息。
[0054] 图5b为本发明实现的表示关键函数调用顺序的有向图,即应用程序的GPU使用模式图。

具体实施方式

[0055] 下面结合附图及实施例对本发明做进一步说明。
[0056] 本发明公开了一种面向GPU集群环境的避免GPU资源争用的方法,结合GPU集群平台中已有的功能,在平台中增加三个模块,分别是应用程序GPU行为特征抽取模块、应用程序调度模块和支持多应用程序细粒度并发模块。具体实现方法如下:
[0057] 在应用程序GPU行为特征抽取模块中,主要目的是在应用程序正式运行之前,抽取应用程序的GPU使用模式和GPU资源需求信息,为应用程序的调度做出决策依据。主要执行如下流程,如图2所示:
[0058] 步骤1,在GPU集群的头结点中,用户的一个GPU应用程序到达;
[0059] 步骤2,在GPU集群的头结点中,运行该应用程序(头结点中GPU运行时函数库为一伪库);
[0060] 步骤3,获取该应用程序在运行过程中所调用的关键函数信息;
[0061] 步骤4,根据所给的关键函数信息,构造表示关键函数调用顺序的有向图,即应用程序的GPU使用模式;
[0062] 步骤5,根据所给的关键函数信息,获取该应用程序所需的块(CUDABlock)数量、线程(CUDA Thread)数量、GPU全局内存数量信息;
[0063] 步骤6,根据应用程序的可执行文件,使用NVIDIA自带的CUOBJDUMP工具,提取GPU内核函数的并行线程执行(Parallel Thread eXecution,PTX)代码;
[0064] 步骤7,使用NVIDIA自带的PTXAS工具,解析并行线程执行(Parallel Thread eXecution,PTX)代码,获取应用程序所需的共享内存数量、寄存器数量信息,结合步骤5,即获得了应用程序的GPU资源需求信息。
[0065] 在应用程序调度模块中,根据应用程序的GPU行为特征,以及GPU集群中各个GPU计算节点所拥有的资源状态信息,调度应用程序到相应的GPU计算节点。本模块主要执行流程,如图3所示。具体步骤如下所述:
[0066] 步骤1,寻找GPU集群中空闲的GPU计算节点;
[0067] 步骤2,如果找到,则将应用程序调度到该GPU计算节点,调度完成;否则转到步骤3;
[0068] 步骤3,从最近被调度节点的下一个节点开始,寻找第一个能满足该应用程序资源需求的GPU计算节点;
[0069] 步骤4,如果找到,则将应用程序调度到该GPU计算节点,调度完成;否则转到步骤5;
[0070] 步骤5,寻找待调度队列中后一个待调度的应用程序;
[0071] 步骤6,若找到,则转到步骤3。
[0072] 当某个GPU计算节点上的一个应用程序运行完毕后,主要执行如下步骤:
[0073] 步骤7,寻找待调度队列中第一个待调度的应用程序;
[0074] 步骤8,判断该GPU计算节点能否满足该应用程序的资源需求;
[0075] 步骤9,如果满足,则将应用程序调度到该GPU计算节点,调度完成;否则转到步骤3;
[0076] 步骤10,寻找待调度队列中后一个待调度的应用程序;
[0077] 步骤11,如果找到,则转到步骤8。
[0078] 在支持多应用程序细粒度并发模块中,主要作用是帮助多个独立的应用程序在同一个GPU节点上细粒度并发执行。该模块包括一个GPU运行时伪函数库和一个服务器进程,前者供应用程序调用,后者用于真正执行GPU命令。本模块能够实现多个独立应用程序细粒度并发的原理是一个GPU设备只创建一个CUDA上下文,从而避免CUDA上下文切换的开销。另一方面,来自应用程序的GPU同步函数操作将变换为对应的异步函数操作,从而使得多个应用程序的GPU操作,能够在服务器端细粒度并发执行。该模块将被部署到GPU集群中的所有计算节点上,其主要执行如下流程,如图2和图4所示:
[0079] 步骤1,一个GPU应用程序被调度到GPU计算节点上,并调用GPU运行时库函数;
[0080] 步骤2,GPU运行时伪函数库拦截到应用程序的调用请求;
[0081] 步骤3,若所请求的为GPU同步函数操作,则将其转化为对应的异步函数;
[0082] 步骤4,若所请求的为GPU内核计算操作,则为其加上流参数,并加上一个流同步函数;
[0083] 步骤5,将该更新的请求发送给本节点的服务器进程;
[0084] 步骤6,服务器进程执行相应的GPU操作,并将结果返回给调用者。
[0085] 将应用程序GPU行为特征抽取模块、应用程序调度模块部署到GPU集群的头结点中;支持多应用程序细粒度并发模块部署到GPU集群的每个计算节点中,可以有效避免多个应用程序在一个GPU上执行时的资源争用,保障应用程序执行性能,提高GPU的利用率和系统吞吐率。
[0086] 实施例
[0087] 结合图1和图2,GPU集群中分为两类节点:GPU头结点和GPU计算节点。其中GPU头结点为一个,其余均为GPU计算节点,节点之间通过以太网或Infiniband进行连接。GPU集群中各个节点配置相同数量、型号的NVIDIA Kepler GPU。在各个GPU计算节点,安装CUDA7.0或以上版本的GPU运行环境。
[0088] 结合GPU集群平台中已有的功能,在平台中增加三个模块:应用程序GPU行为特征抽取模块、应用程序调度模块和支持多应用程序细粒度并发模块。具体的实施步骤将结合一个实例进行描述:
[0089] 在应用程序GPU行为特征抽取模块中,抽取的信息包括:GPU内存申请类操作(cudaMalloc等)、主机和GPU设备之间拷贝数据类操作(cudaMemcpy等)、执行GPU内核函数操作(cudaConfigureCall)、GPU设备流同步操作(cudaStreamSynchronize)、GPU设备同步操作(cudaDeviceSynchronize)、内核函数所需的块(CUDABlock)数量、线程(CUDAThread)数量、GPU全局内存数量、共享内存数量、寄存器数量。
[0090] 上述GPU行为特征数据中,GPU内存申请操作、主机和GPU设备之间拷贝数据操作、执行GPU内核函数操作、GPU设备流同步操作、GPU设备同步操作可以通过GPU头节点中维护的一块共享内存中读取。头节点的GPU运行时伪函数库会向该共享内存写入上述关键函数信息。块(CUDABlock)数量、线程(CUDAThread)数量、全局内存数量可以通过上述关键函数信息获取。共享内存数量、寄存器数量可以通过NVIDIA CUOBJDUMP、PTXAS工具解析后得到的。
[0091] 在GPU集群的头结点,使用自行编写的GPU运行时伪函数库(libcudart.so)替换NVIDIA自带的GPU运行时函数库(libcudart.so)。该伪函数库将GPU内存创建类函数(cudaMalloc等)、GPU内存拷贝类函数(cudaMemcpy等)、GPU内核执行函数(cudaConfigureCall)、GPU同步类函数(cudaDeviceSynchronize等)的函数体替换为相应函数的字符输出信息。这些函数即为本发明所述的关键函数。
[0092] 当一个GPU应用程序到达GPU集群的头节点时,在头结点中运行该应用程序,即可在避免真实运行的模式下,获得该应用程序在运行过程中所需调用的cudaMalloc、cudaMemcpy、cudaConfigureCall、cudaDeviceSynchronize等函数及其参数信息。图5a为一个应用程序所输出的关键函数信息的示例。其中,每一行表示一个关键函数信息,开头是关键函数的名称,其后是该函数的参数信息。
[0093] 其次,对包含上述关键函数信息进行分析:拥有不同流参的关键函数之间可以并发执行,拥有同一个流参的关键函数之间只能串行执行。从而可以构造一个表示关键函数调用顺序的有向图,如图5b所示。至此,该应用程序的GPU使用模式获取完毕。
[0094] 最后,从所输出的关键函数信息中,可以获取块(CUDABlock)数量、线程(CUDAThread)数量、全局内存数量。具体的,如图5a所示,从cudaMalloc等内存申请类函数的参数中,获取该应用程序所需要的全局内存数据;从cudaConfigureCall函数的参数中,获取块(CUDABlock)数量、线程(CUDAThread)数量。另一方面,通过使用NVIDIA自带工具CUOBJDUMP、PTXAS工具,再获取执行该应用程序GPU内核函数所需的共享内存数量、寄存器数量。至此,该应用程序的GPU资源需求信息获取完毕。
[0095] 在应用程序调度模块中,以抽取到的GPU使用模式和GPU资源需求信息作为输入,结合各个GPU计算节点当前拥有的资源信息,输出所到达的应用程序需要被调度到的GPU计算节点编号。该模块的核心调度算法如图3所示。因前文已详细描述,此处不再赘述。
[0096] 在支持多应用程序细粒度并发模块中,其核心为一个支持多应用程序细粒度并发执行的插件:该插件包含一个自行编写的GPU运行时伪函数库(libcudart.so)和一个自行编写的本地服务器进程,前者(GPU运行时伪函数库)与NVIDIA自带的GPU运行时函数库(libcudart.so)有相同的函数原型,但各个函数实现体的基本功能包括:变换同步函数为异步函数;向后者(本地服务器进程)转发相关的函数执行请求。
[0097] 当应用程序被调度到某个GPU计算节点上运行时,该GPU计算节点上的GPU运行时伪函数库将会拦截到该信息,并将其经过函数变换后,发往一块共享内存中,并等待返回值。另一方面,本节点上的服务器进程会读取该共享内存中的信息,并执行读到的GPU命令,并返回相应的结果。服务器端再将结果写回该共享内存,供调用方读取。
[0098] 针对图5b所对应的应用程序,当其要调用cudaMalloc函数时,则GPU运行时伪函数库不经过函数变换,直接将其发往共享内存中;当其要调用cudaMemcpy函数时,则GPU运行时伪函数库会将其变换为对应的异步函数cudaMemcpyAsync函数,并发往共享内存中;当其要调用cudaConfigureCall函数时,因其本身就含有流参,因此直接将其发往共享内存即可;当其要调用cudaDeviceSynchronize函数时,则GPU运行时伪函数库会将其变换为对应的cudaStreamSynchronize函数,并发往共享内存中。另一方面,该GPU计算节点上的本地服务器进程会依次读取、执行该共享内存中的信息,并返回结果给调用方。
[0099] 本发明提供了一种面向GPU集群环境的避免GPU资源争用的方法,具体实现该技术方案的方法和途径很多,以上所述仅是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。本实施例中未明确的各组成部分均可用现有技术加以实现。