本发明涉及计算机技术领域,尤其是涉及一种cpu与gpu之间的内存数据转移方法。
背景技术:
1999年8月,nvidia公司发布了一款名为geforce256的图形芯片,是第一款提出gpu概念的产品,同时期的opengl和directx7都提供了硬件顶点变换的编程接口,gpu的概念因此而出现。从2003年开始,nvidia和ati发布的新产品都同时具备了良好的可编程性,编程时无需再过度关注于gpu的其他硬件特性,从此,gpu又多了一个可编程的属性,也叫做可编程图形处理单元。
opencl是第一个面向异构系统通用目的并行编程的开放式免费标准,也是一个统一的编程环境,是一个为异构平台编写程序的框架,此异构平台可由cpu,gpu或其他类型的处理器组成。opencl由一门用于编写kernels(在opencl设备上运行的函数)的语言(基于c99)和一组用于定义并控制平台的api组成,opencl提供了基于任务分割和数据分割的并行计算机制。
在异构计算系统上进行的并行计算通常称为异构计算,它所使用的计算资源具有多种类型的计算能力,是一种使计算任务的并行性类型(代码类型)与机器能有效支持的计算类型(即机器能力)最相匹配、最能充分利用各种计算资源的并行和分布计算技术。
本发明是基于opencl语言编程的基础上进行,实现不同结构设备间的内存迁移,为实现gpu加速作准备,同时为更有效实验异构计算作出新的尝试。
技术实现要素:
本发明所要解决的技术问题是提供一种cpu与gpu之间的内存数据转移方法,该方法能够实现不同设备间的内存迁移,实现程序的中断与恢复,实现在程序被中断、资源被抢占之后,依然能够重新从断点处恢复运算,同时实现了gpu的加速,改善了gpu调度的性能,有效利用资源。
本发明所采用的技术方案是,一种cpu与gpu之间的内存数据转移方法,包括下列步骤:
(1)、扫描gpu端的函数程序,将所有函数程序运行的变量获取下来;
(2)、在cpu端开辟一段存储空间,存储空间分为三段:intmem;floatmem;charmem,用于存储三种类型的变量:int、float、char,在gpu端开辟一段存储空间,存储空间分为三个缓冲区:intmembuffer;floatmembuffer;charmembuffer,分别用来存储与cpu相对应的三种类型的变量,三个缓冲区作为gpu与cpu之间数据传递的媒介;
(3)、在cpu端创建指令队列,命名为commandqueue,该指令队列用于存储gpu端所需要的相关操作指令;
(4)、在cpu端构造结构体mcb,用来管理数据的状态;
(5)、在cpu端,将函数的运行过程分成若干个相同的while循环体,在进入每一次循环体时,先从cpu中读取数据,再运行循环体,在函数运行过程中,通过设置一个检查点,然后检测检查点的数值从而来判断函数运行状态,该检查点定义为stepno,若判断到stepno为特定值,则表示函数运行结束,跳出while循环,否则while循环进行运行;
(6)、在gpu端,设置checkpoint()作为同步点,在函数程序中插入checkpoint()来暂停每个work-item的运算,同时通过checkpoint()来同步所有的work-item的运算状态,利用每个workgroup中的第一个work-item来同步workgroup的运算状态;
(7)、在gpu端,在同步点checkpoint()完成工作后,调用指令队列,在同步点处将所有的数据信息写到pcie总线,并由pcie总线将缓冲区中三种类型的数据读取到cpu中对应的存储空间内,存储到结构体中,完成gpu内存数据的迁移,并与函数的其他操作并行进行。
本发明的有益效果是:本发明针对cpu与gpu间不同数据存储方式而设计的内存数据转移方法,实现了变量的备份与恢复,实现了函数的中断与恢复,有利于合理分配资源,同时gpu内存数据通过pcie总线转移到cpu端的操作与其他运算可并行计算,提高函数执行速度,实现gpu的加速。本发明改善了gpu调度的性能,有效利用资源。
作为优先,在步骤(4)中,构造结构体mcb具体过程为:将函数中需要备份的变量数据进行封装就形成一个结构体,结构体中的参数包括内存id、cpu端备份变量数据的变量名、gpu端用于备份三种类型数据的缓冲区地址、cpu端用于备份三种类型数据的地址、变量数组的长度、变量数组的内存大小,变量的数据类型。
作为优先,在步骤(6)中,通过checkpoint()来同步所有的work-item的运算状态,将所有的work-item同步到同一个时间节点。
作为优先,在步骤(7)中,指令队列中的指令在cpu端处于阻塞状态,一旦gpu端数据到达checkpoint()所在位置,将gpu内存中端数据传入cpu端,此时唤醒处于阻塞状态的指令队列中的读指令,并由读指令通过pcie总线实现数据从gpu内存传入cpu端的功能,并与函数其他操作并行进行。
附图说明
图1为本发明中cpu与gpu之间的内存数据转移方法的总体示意图;
图2为本发明中cpu与gpu之间的内存数据转移过程的结构示意图;
图3为本发明实施方式中测试实验方案性能结果示意图;
具体实施方式
以下参照附图并结合具体实施方式来进一步描述发明,以令本领域技术人员参照说明书文字能够据以实施,本发明保护范围并不受限于该具体实施方式。
本发明涉及一种cpu与gpu之间的内存数据转移方法,如图1所示,包括下列步骤:
(1)、扫描gpu端的函数程序,将所有函数程序运行的变量获取下来;
(2)、在cpu端开辟一段存储空间,存储空间分为三段:intmem;floatmem;charmem,用于存储三种类型的变量:int、float、char,在gpu端开辟一段存储空间,存储空间分为三个缓冲区:intmembuffer;floatmembuffer;charmembuffer,分别用来存储与cpu相对应的三种类型的变量,三个缓冲区作为gpu与cpu之间数据传递的媒介;
(3)、在cpu端创建指令队列,命名为commandqueue,该指令队列用于存储gpu端所需要的相关操作指令;
(4)、在cpu端构造结构体mcb,用来管理数据的状态;
(5)、在cpu端,将函数的运行过程分成若干个相同的while循环体,在进入每一次循环体时,先从cpu中读取数据,再运行循环体,在函数运行过程中,通过设置一个检查点,然后检测检查点的数值从而来判断函数运行状态,该检查点定义为stepno,若判断到stepno为特定值,则表示函数运行结束,跳出while循环,否则while循环进行运行;
(6)、在gpu端,设置checkpoint()作为同步点,在函数程序中插入checkpoint()来暂停每个work-item的运算,同时通过checkpoint()来同步所有的work-item的运算状态,利用每个workgroup中的第一个work-item来同步workgroup的运算状态;
(7)、在gpu端,在同步点checkpoint()完成工作后,调用指令队列,在同步点处将所有的数据信息写到pcie总线,并由pcie总线将缓冲区中三种类型的数据读取到cpu中对应的存储空间内,存储到结构体中,完成gpu内存数据的迁移,并与函数的其他操作并行进行。
在步骤(4)中,构造结构体mcb具体过程为:将函数中需要备份的变量数据进行封装就形成一个结构体,结构体中的参数包括内存id、cpu端备份变量数据的变量名、gpu端用于备份三种类型数据的缓冲区地址、cpu端用于备份三种类型数据的地址、变量数组的长度、变量数组的内存大小,变量的数据类型。
在步骤(5)中,函数运行过程中,函数通过调用指令队列来读取gpu端的内存数据指令,该操作与函数的其他操作并行进行。
在步骤(6)中,通过checkpoint()来同步所有的work-item的运算状态,将所有的work-item同步到同一个时间节点。
在步骤(7)中,指令队列中的指令在cpu端处于阻塞状态,一旦gpu端数据到达checkpoint()所在位置,将gpu内存中端数据传入cpu端,此时唤醒处于阻塞状态的指令队列中的读指令,并由读指令通过pcie总线实现数据从gpu内存传入cpu端的功能,并与函数其他操作并行进行。
本发明涉及一种内存数据转移方法,针对cpu与gpu间不同数据存储方式而设计的,可以实现不同设备间的内存状态迁移,实现程序的中断与恢复,实现在程序被中断、资源被抢占之后,依然能够重新从断点处恢复运算,有利于资源的充分利用。同时本发明针对不同设备之间进行涉及,对于通过异构方式解决问题有很大的帮助。
该方法涉及到几个核心部分,包括存储数据缓冲区的设计、存储变量结构体的设计、cpu内存与gpu全局内存的对应关系的设计、同步点的设计以及指令队列commandqueue的设计。通过这几个核心部分的设计与实现,可以完成整个发明过程,从而能够实现不同设备之间的内存状态迁移,方便进行异构设备间的协调运算。
关于存储数据缓冲区的设计:
在cpu内存中开辟一段存储空间分为三个部分,intmem;floatmem;charmem,这三个部分存储空间的地址存储在结构体中,同时在cpu与之间间开辟相对应的三段缓冲区:intmembuffer;floatmembuffer;charmembuffer,作为数据传输的媒介,其中intmembuffer、intmem均用于备份int型变量;floatmembuffer、floatmem均用于备份float型变量;charmembuffer、charmem均用于备份char型变量。
关于存储变量结构体的设计:
在cpu端,将gpu端的函数中需要备份的的变量数据封装为一个结构体(memorycontrolblock,mcb),该结构体参数包括内存id、host端备份变量数据的变量名、gpu全局内存中用于备份三种类型数据的缓冲区地址、主机内存中用于备份三种类型数据的地址、变量数组的长度、变量数组的内存大小,变量的数据类型。结构体可用来管理备份数据的状态。
关于cpu内存与gpu全局内存的对应关系的设计:
在gpu全局内存中开辟出缓冲区进行缓冲数据的存储,同时cpu内存中备份缓冲区的数据。存储在cpu内存的指针指向缓冲区的地址,在程序中通过clenqueuereadbuffer函数将缓冲区的数据读到指定地址的主机内存中去,而通过clenqueuewritebuffer函数将备份在主机内存的数据写到缓冲区,用于恢复缓冲区的数据。
同步点的设计:
在gpu端的程序中,设置阻塞函数barrier同步workgroup中不同workitem的运行状态,阻塞函数由barrier(clk_global_mem_fence)函数实现,该函数为现有函数。用于同步workgroup运行状态的函数(命名为lock函数)的实现原理则是:对每一个workgroup中item0进行原子操作减一,所有的item0在运行时将进入循坏状态,直至最后一个workgroup实现减一,以此可实现workgroup保持统一运行状态,达到同步点的作用。在本发明中,我们将阻塞函数barrier与lock函数组成checkpoint(),将其称之为同步点,其作用则是使得运行程序的所有线程都将处于同样的运行状态。
检查点stepno的设计:
stepno用于记录cpu端程序的运算节点,也称为计步变量,初始值为0,表示第一次运行。每当kernel函数被调用一次,将stepno自加1,表示运行步数的推进。当kernel函数运行完成后,则将stepno设置为-2(特殊值),表示可以跳出kernel函数运行的while循环,即结束kernel函数的运行。
本发明的整体实现思路为,如图2所示,在cpu端开辟三段内存空间(intmem、floatmem、charmem),存储三种类型的变量(int、float、char),同时在gpu的全局内存中开三个缓冲区(intmembuffer;floatmembuffer;charmembuffer),三个缓冲区分别用来存储与主机内存相对应的三种类型的变量(int、float、char),缓冲区作为主机与gpu数据传递的媒介。给gpu中的kernel函数设置同步点,同步点处将调用指令队列(commandqueue),所有的数据信息写到pcie总线,并由pcie总线将缓冲区三种类型数据读取到cpu内存相对应的数据存储空间内,将三种类型数据备份到cpu中,存储到结构体中,与函数其他操作并行进行,kernel函数运行结束后退出。
相关解释:
kernel函数:是指一个用openclc语言编写的、代表一个单一执行实例的代码单元。opencl术语中把这种kernel实例称为work-item(工作项)。
work_item:是定义在一个很大的并行执行空间中的一小部分。是并行操作中每一部分的实例化。通俗来说,可以理解为kernel里定义的执行函数。当kernel启动后会创建大量work_item来同时执行,以完成并行任务。work_item之是的运行是相互独立的,不同步的。
work_group:opencl将全局执行空间划分为大量大小相等的work_item集合,这个集合就是work_group。在work_group内部,各个work_item之间允许一定程度的通信。而有work_group保证并发执行来允许其内部的work_item之间的本地同步。
(上述解释源于opencl的定义,非自己编写)
如图1所示,本发明具体实施分为两部分,一部分为运行在cpu上的主要程序global.c,另一个则是运行在gpu上的设备函数程序kernel.cl。具体实现如下:
kernel.cl
设置计步变量stepno,记录函数运行的状态。
1、进行kernel函数的运算,涉及到kernel函数中变量数值的修改,进行运算后,设置同步点checkpoint()进行运算同步,同步点同步后,调用指令队列(commandqueue),将所有的数据信息写到pcie总线,并存储到结构体mcb中完成gpu内存数据的迁移。
global.c
1、对涉及到的设备kernel函数进行扫描,同时进行预编译;
2、声明存储数据的数据结构体;
3、定义错误函数call_error,用于检查代码运行过程中是否出错;定义platform创建函数createplatform、device创建函数createdevice、program创建函数createprogram、program构造函数buildprogram,为kernel函数提供运行环境;
4、对结构体mcb进行初始化,对结构体元素中结构体长度、结构体大小结构体数据类型、内存编号、对应kernel变量名称进行赋值;
5、对结构体中中用于备份三种类型数据的主机内存地址进行分配空间;
6、创造kernel函数的运行环境;
7、创建三种数据类型的缓冲区,用于迁移结构体mcb的变量数据;创建stepno_buffer,用于存储计步变量stepno;创建mutex_group_buffer,用于控制同步点;
8、设置在gpu中运行的kernel函数的变量;
9、进入while(1)循环;
10、判断计步变量stepno的状态,stepno为0时,表示第一次运行kernel函数,将stepno写入stepno_buffer,用于及时修改运行状态,当stepno不为0时,表示非第一次运行kernel函数,将cpu所开辟的内存空间中存放同步点处gpu内存中的数据赋给gpu中所开辟的三种类型的缓冲区,用于同步点处kernel函数中global变量数据恢复;
11、将workgroup的数量写入mutex_group_buffer,用于kernel函数同步点设置;
12、kernel函数的运行;
13、kernel函数通过pcie总线进行将gpu端的数据保存到cpu。在kernel函数调用指令队列(commandqueue)时,读取gpu内存数据的指令通过指令队列(commandqueue)调用,与函数其他操作可以并行进行。
当以上程序求解结束后,内存迁移的问题得以解决。本发明提出了一种针对cpu与gpu间不同数据存储方式而设计的内存数据转移方法,对内存迁移提出了具体的解决方案。采用该方法,系统在计算机上可实现多平台的内存迁移,同时提高效率,减少运算时间。
利用以上方法,采用nvidiateslak40型号的gpu以及并采用自行编写的加法程序进行验证。
实验平台信息如下:采用nvidiateslak40型号的gpu,1.4tflops性能,12gb内存,288gb/s的吞吐量。
图3展示了测试结果,本测试是基于编写的加法程序进行,展示了程序在中断以及重新调度时,可继续运行,表示数据能够成功备份在cpu内存中,并可以成功从cpu内存中调度到gpu的全局内存中。
本发明提出了一种针对cpu与gpu间不同数据存储方式而设计的内存数据转移方法,设计了一整套的内存迁移方法,包括数据结构的设计、存储空间的设计方案,数据进行迁移与调度的实现方案,同时本发明通过编写加法程序验证了该设计方案的可行性。