发明内容
本申请的目的是提供一种本地设备与异构设备之间的通信方法、系统、计算机可读存储介质和电子设备,能够实现本地设备与异构设备之间的通信。
为解决上述技术问题,本申请提供一种本地设备与异构设备之间的通信方法,具体技术方案如下:
接收异构设备的通信请求;
为所述异构设备配置对应的独立MPI进程;
在所述独立MPI进程内利用预设异构通信框架执行所述异构设备的第一内存与本地设备的第二内存之间的数据交互,以完成所述本地设备与所述异构设备之间的通信。
可选的,若所述预设异构通信框架包括OpenCL框架,则所述在所述独立MPI进程内利用预设异构通信框架执行所述异构设备的第一内存与本地设备的第二内存之间的数据交互包括:
利用所述OpenCL框架的缓冲区读取机制从所述异构设备的第一内存中读取待通信数据;
利用所述独立MPI进程在所述第二内存中执行所述待通信数据的进程间通信,得到通信响应数据;
将所述通信响应数据存储于本地设备的第二内存;
利用所述OpenCL框架的写缓冲区机制将所述通信响应数据从所述第二内存写入所述第一内存。
可选的,利用所述独立MPI进程在所述第二内存中执行所述待通信数据的进程间通信,得到通信响应数据包括:
在所述第二内存中将所述待通信数据由所述独立MPI进程切换至第二独立MPI进程处理,并在所述第二独立MPI进程中调用所述待通信数据所需的异构通信算子对所述待通信数据进行数据处理,得到通信响应数据。
可选的,在所述第二独立MPI进程中调用异构通信算子对所述待通信数据进行数据处理之前,还包括:
利用Cmake编译工具编译并封装所述异构通信算子;
其中,所述异构通信算子包括Heter_Send、Heter_Recv、Heter_Broadcast、Heter_Scatter、Heter_Gather、Heter_Reduce、Heter_Allreduce、Heter_Allgather中一种或任意几种的组合。
可选的,利用Cmake编译工具编译并封装所述异构通信算子之后,还包括:
对每个所述异构通信算子调用单元测试框架进行功能测试;
若功能测试失败,重新编译并封装所述异构通信算子。
可选的,为所述异构设备配置对应的独立MPI进程之后,还包括:
将所述独立MPI进程和对应的异构设备信息添加至异构设备管理列表;
利用所述异构设备管理列表管理与所述本地设备通信的所有异构设备。
可选的,若所述通信请求为异构设备间通信请求,则所述在所述第二内存中将所述待通信数据由所述独立MPI进程切换至第二独立MPI进程处理,并在所述第二独立MPI进程中调用所述待通信数据所需的异构通信算子对所述待通信数据进行数据处理,得到通信响应数据包括:
在所述第二内存中由所述独立MPI进程将所述待通信数据发送至第二独立MPI进程;所述第二独立MPI进程用于管理与所述本地设备相连的另一异构设备;
在所述第二独立MPI进程中开辟预设存储空间,并在所述预设存储空间中调用所述待通信数据所需的异构通信算子对所述待通信数据进行数据处理,得到通信响应数据。
本申请还提供一种本地设备与异构设备之间的通信系统,包括:
请求接收模块,用于接收异构设备的通信请求;
进程分配模块,用于为所述异构设备配置对应的独立MPI进程;
异构通信模块,用于在所述独立MPI进程内利用预设异构通信框架执行所述异构设备的第一内存与本地设备的第二内存之间的数据交互,以完成所述本地设备与所述异构设备之间的通信。
本申请还提供一种计算机可读存储介质,其上存储有计算机程序,所述计算机程序被处理器执行时实现如上所述的方法的步骤。
本申请还提供一种电子设备,包括存储器和处理器,所述存储器中存有计算机程序,所述处理器调用所述存储器中的计算机程序时实现如上所述的方法的步骤。
本申请提供一种本地设备与异构设备之间的通信方法,包括:接收异构设备的通信请求;为所述异构设备配置对应的独立MPI进程;在所述独立MPI进程内利用预设异构通信框架执行所述异构设备的第一内存与本地设备的第二内存之间的数据交互,以完成所述本地设备与所述异构设备之间的通信。
本申请利用MPI进程对异构设备进行管理,将异构设备的通信过程转化为MPI进程间操作,将异构设备的通信数据经由本地设备和异构设备的内存执行内存间数据交互,从而实现本地设备和异构设备间的异构通信,在此基础上,还可以同时建立本地设备与多个异构设备间的通信,从而实现异构设备与异构设备之间的通信,藉由内存间数据交互解决了异构设备兼容性问题,提高异构并行计算能力,显著增加了异构计算效率。
本申请还提供一种本地设备与异构设备之间的通信系统、计算机可读存储介质和电子设备,具有上述有益效果,此处不再赘述。
具体实施方式
为使本申请实施例的目的、技术方案和优点更加清楚,下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例是本申请一部分实施例,而不是全部的实施例。基于本申请中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本申请保护的范围。
请参考图1,图1为本申请实施例所提供的本地设备与异构设备之间的通信方法的流程图,该方法包括:
S101:接收异构设备的通信请求;
本实施例在此对于异构设备的具体类型不作限定,可以包括GPU、FPGA、DSP等中的一种或几种的组合,或者其他可作为加速器与CPU共同组成异构系统的设备。当然,本实施例以本地设备与某一台异构设备为例对本地设备和异构设备的通信过程进行说明,本领域技术人员在本实施例的基础上有能力将该通信过程应用至其他异构设备。
此外,本实施例对于如何接收异构设备的通信请求不作具体限定,由于异构设备的类型不同,其与本地设备的连接方式可能也存在相应的差异,则相应的接收通信请求所采用的接口、数据类型等存在区别,在此不一一举例限定。
还需要注意的是,本步骤中需要接收异构设备的通信请求,该通信请求可以由异构设备主动发出,也可以为异构设备的通信响应请求。即可以由本地设备先向异构设备发送通信请求,再由异构设备针对该通信请求实现通信响应请求,在本实施例中可以视由异构设备发送的通信响应请求为通信请求。换句话说,本步骤的实行过程等同于本地设备和异构设备建立通信要约。
S102:为所述异构设备配置对应的独立MPI进程;
本步骤旨在接收到异构设备的通信请求后,为该异构设备配置对应的独立MPI(Message Passing Interface,信息传递接口)进程。在利用消息传递进行进程间通信时,各个进程具有自己独立的堆栈,进程之间的通信通过显示调用函数完成。但需要注意的是,本步骤中生成的独立MPI进程区别于本地设备中已经存在的MPI进程,独立MPI进程专用于执行本地设备与异构设备之间的信息交互,负责本地设备与该异构设备的通信过程。
进一步,在本实施例的基础上,为异构设备配置独立MPI进程后,可以将独立MPI进程和对应的异构设备信息添加至异构设备管理列表,以便利用异构设备管理列表管理与本地设备通信的所有异构设备。由于本地设备可能同时对接若干台异构设备,为了便于对异构设备进行管理,同时确保各异构设备与异构设备之间、异构设备与本地设备之间的通信不发生紊乱,可以直接采用异构设备管理列表确认当前本地设备参与通信的异构设备信息,便于管控异构通信。
S103:在所述独立MPI进程内利用预设异构通信框架执行所述异构设备的第一内存与本地设备的第二内存之间的数据交互,以完成所述本地设备与所述异构设备之间的通信。
分配独立MPI进程后,在独立MPI进程中可以调用相应的异构通信框架执行数据交互,在此对于预设异构通信框架不作具体限定,例如可以为OpenMPI、MPICH等通信框架,均可以用于实现异构通信的数据交互。
具体的,需要借助独立MPI进程调用相应的MPI库函数实现CPU的进程间通信,利用预设异构通信框架实现CPU端内存与异构设备端内存之间的数据交互。
以预设异构通信框架为OpenCL框架为例,本步骤具体可以包含如下步骤:
S1031:利用OpenCL框架的缓冲区读取机制从异构设备的第一内存中读取待通信数据;
S1032:利用独立MPI进程在第二内存中执行待通信数据的进程间通信,得到通信响应数据;
S1033:将通信响应数据存储于本地设备的第二内存;
S1034:利用OpenCL框架的写缓冲区机制将通信响应数据从第二内存写入第一内存。
上述步骤S1031至S1034中,第一内存指代异构设备端内存,而第二内存指代CPU端内存。在执行本地设备与异构设备之间的数据交互时,先利用OpenCL框架的缓冲区读取机制从异构设备的内存中读取待通信数据至本地设备的第二内存端,此后由CPU配置完毕的独立MPI进程对该待通信数据进行处理,得到通信响应数据。具体的处理过程应视待通信数据的处理需求而定,若该异构通信过程仅限于本地设备和异构设备,则可以有CPU直接处理待通信数据。若该异构通信过程包括本地设备和多个异构设备,则需要由独立MPI进程执行进程间通信,将待通信数据转发至其余异构设备对应的独立MPI进程。而无论该异构通信过程是否包含其余异构设备,所生成的通信响应数据依旧需要返回独立MPI进程,并再次借助于OpenCL框架的写缓冲区机制写入至异构设备端的第一内存。
本申请实施例利用MPI进程对异构设备进行管理,将异构设备的通信过程转化为MPI进程间操作,将异构设备的通信数据经由本地设备和异构设备的内存执行内存间数据交互,从而实现本地设备和异构设备间的异构通信,藉由内存间数据交互解决了异构设备兼容性问题,提高异构并行计算能力,显著增加了异构计算效率。
基于上述实施例,作为优选的实施例,若在上一实施例的基础上实现异构设备间通信,可以在执行上一实施例中步骤S103时,在第二内存中将待通信数据由独立MPI进程切换至第二独立MPI进程处理,并在第二独立MPI进程中调用待通信数据所需的异构通信算子对待通信数据进行数据处理,得到通信响应数据。该第二独立MPI进程用于管理与本地设备相连的另一异构设备。具体的,在执行另一个异构设备对应的第二独立MPI进程中开辟预设存储空间,并在该预设存储空间中调用待通信数据所需的异构通信算子对待通信数据进行数据处理,从而得到通信响应数据。换句话说,独立MPI进程还可以用于提供异构通信的计算空间。具体的,开启预设存储空间可以通过创建Context上下文实现,当然在此对于预设存储空间的具体大小不作限定,可以根据待通信数据的数据处理需求和数据量作相应配置,也可以预先配置固定大小的存储空间作为预设存储空间。
需要注意的是,各独立MPI进程分别对应管理一个异构设备,并可以调用异构通信算子执行计算,这其中需要占用相应的系统资源,包括CPU资源和内存资源,以及上文的预设存储空间等。在得到通信响应数据后,应当及时释放所占用的资源。但对于独立MPI进程,其可以根据选择释放或者解除独立MPI进程与异构设备的绑定关系。即在本申请的具体应用过程中,独立MPI进程可以为固定数量或者在某一数量范围内波动,也可以根据实时的异构设备通信请求建立相应的独立MPI进程。则相对应的,在异构设备通信过程结束后,独立MPI进程是否结束、或者解绑均可由本领域技术人员进行相应的设定。若采用异构设备管理列表,则需要将对独立MPI进程的后续管理同步至异构设备管理列表中。
为了进一步解决异构设备间通信方式存在差异,导致数据交互效率低下的问题,本实施例可以预先利用Cmake编译工具编译并封装异构通信算子。在此对于异构通信算子的具体内容不作限定,可以包含数据处理过程的任一操作,例如,异构通信算子可以包括Heter_Send、Heter_Recv、Heter_Broadcast、Heter_Scatter、Heter_Gather、Heter_Reduce、Heter_Allreduce、Heter_Allgather中一种或任意几种的组合。通过封装异构通信算法,可以提供异构通信算子的API接口,使得执行数据交互时,直接调用相应算子的API接口实现异构系统中各异构设备的同类设备之间、以及不同类设备之间的自由通信。有助于开发人员充分利用服务器现有计算资源进行异构并行计算,节约资源,同时提升性能。
下文针对上文所举例的八种异构通信算子进行说明:
(1)Heter_Send算子的具体实现方案设计主要包括如下几个步骤:
①首先调用OpenCL库的读buffer函数clEnqueueReadBuffer()从当前独立MPI进程管理的异构设备内存中读取待发送数据到CPU内存;
②然后调用OpenCL库函数clWaitForEvents()等待步骤①中的buffer数据读取完成;
③最后调用MPI接口函数MPI_Send()将待发送数据从当前独立MPI进程的CPU内存发送到指定进程的CPU内存。
(2)Heter_Recv算子的具体实现方案主要包括如下几个步骤:
①首先调用MPI接口函数MPI_Recv()接收其对应进程中MPI_Send()函数发送过来的数据,存储到当前独立MPI进程所在的CPU内存;
②然后调用OpenCL的写buffer函数clEnqueueWriterBuffer()将步骤①中接收到的数据写入指当前独立MPI进程管理的异构设备buffer;
③最后调用OpenCL库函数clWaitForEvents()等待步骤②中的buffer数据写入完成。
(3)Heter_Broadcast算子的详细实现方案设计,主要包括如下几个步骤:
①首先判断当前节点进程是否是指定的root节点进程;若是,执行步骤②,否则跳转至步骤④;
所谓root节点,指的是broadcast的发送数据节点。
②调用OpenCL的读buffer函数clEnqueueReadBuffer()从当前独立MPI进程管理的异构设备中读取待广播数据到当前独立MPI进程的CPU内存;
③等待步骤②中buffer读取操作完成;
④调用MPI接口函数MPI_Bcast()将待广播数据从当前独立MPI进程的CPU内存广播到各个进程的CPU内存;
⑤调用OpenCL库函数clEnqueueWriteBuffer()将数据从CPU内存写入当前独立MPI进程管理的异构设备buffer;
⑥等待步骤⑤的异构设备buffer写入操作完成。
(4)Heter_Scatter算子的详细实现方案设计,主要包括如下两个步骤:
①首先判断当前独立MPI进程是否是指定的root进程,若是,执行步骤②,否则跳转到步骤④执行;
②调用OpenCL库的读buffer函数clEnqueueReadBuffer()从当前独立MPI进程管理的异构设备中读取待Scatter数据到CPU内存;
③等待步骤②中buffer读取操作完成;
④调用MPI接口函数MPI_Scatter将待scatter数据从当前独立MPI进程的CPU内存scatter到各个进程的CPU内存;
⑤调用OpenCL库函数clEnqueueWriteBuffer()将数据从CPU内存写入当前独立MPI进程管理的异构设备buffer;
⑥等待步骤⑤的异构设备buffer写入操作完成。
(5)Heter_Gather算子的详细实现方案设计,主要包括如下几个步骤:
①调用OpenCL库函数clEnqueueReadBuffer()从当前独立MPI进程管理的异构设备中读取待Gather数据到CPU内存;
②等待步骤①的异构设备buffer读取操作完成;
③调用MPI的API接口函数MPI_Gather()将待Gather数据gather到指定的root节点进程,存储在CPU内存;
④判断当前独立MPI进程是否是指定的root节点进程,若是,执行步骤⑤,否则直接跳转到结束;
⑤调用OpenCL库函数clEnqueueWriteBuffer()将步骤③中gather得到的数据从CPU内存写入到当前独立MPI进程管理的异构设备buffer;
⑥等待步骤⑤的异构设备buffer写入操作完成。
(6)Heter_Reduce算子的详细实现方案设计,主要包括如下两个步骤:
①调用OpenCL库函数clEnqueueReadBuffer()从当前独立MPI进程管理的异构设备中读取待reduce数据到CPU内存;
②等待步骤①的异构设备buffer读取操作完成;
③调用MPI的API接口函数MPI_Reduce()将待reduce数据reduce到指定的root节点,存储在CPU内存;
④判断当前独立MPI进程是否是指定的root节点进程,若是,执行步骤⑤,否则直接跳转到结束;
⑤调用OpenCL库函数clEnqueueWriteBuffer()将步骤③中reduce得到的数据从CPU内存写入到当前独立MPI进程管理的异构设备buffer;
⑥等待步骤⑤的异构设备buffer写入操作完成。
(7)Heter_Allreduce算子的详细实现方案设计,主要包括如下两个步骤:
①调用OpenCL库函数clEnqueueReadBuffer()从当前独立MPI进程管理的异构设备中读取待reduce数据到CPU内存;
②等待步骤①中的异构设备buffer读取操作完成;
③调用MPI的API接口函数MPI_Allreduce()将待reduce数据reduce到各个进程的CPU内存;
④调用OpenCL库函数clEnqueueWriteBuffer()将步骤③中reduce得到的数据从CPU内存写入到当前独立MPI进程管理的异构设备buffer;
⑤等待步骤④中的异构设备buffer写入操作完成。
(8)Heter_Allgather算子的详细实现方案设计,主要包括如下两个步骤:
①调用OpenCL库函数clEnqueueReadBuffer()从当前独立MPI进程管理的异构设备中读取待gather数据到CPU内存;
②等待步骤①的异构设备buffer读取操作完成;
③调用MPI的API接口函数MPI_Allgather()将待gather数据gather到各个进程的CPU内存;
④调用OpenCL库函数clEnqueueWriteBuffer()将步骤③中gather得到的数据从CPU内存写入到当前独立MPI进程管理的异构设备buffer;
⑤等待步骤④的异构设备buffer写入操作完成。
上文仅为本申请针对异构通信数据交互过程中常用的八种通信算子的实现过程,在上文公开的几种通信算子的基础上,本领域技术人员还可以对异构通信过程中其他可能应用的通信算子加以封装并应用,也应在本申请的保护范围内。
进一步,利用Cmake编译工具编译并封装异构通信算子之后,还可以对每个异构通信算子调用单元测试框架进行功能测试;若功能测试失败,重新编译并封装异构通信算子。对于每一个异构通信算子在封装后进行功能测试,可以确保封装的通信算子功能正常,避免执行异构数据处理时出现异常,有效保证异构通信交互的稳定性。在此对于如何进行功能测试不作具体限定,可以利用若干中单元测试框架执行,例如采用Google Test,可以通过配置单元测试文件,用于执行异构通信算子的功能测试验证。
下面对本申请实施例提供的一种本地设备与异构设备之间的通信系统进行介绍,下文描述的通信系统与上文描述的本地设备与异构设备之间的通信方法可相互对应参照。
图3为本申请实施例所提供的本地设备与异构设备之间的通信系统结构示意图,该系统可以包括:
请求接收模块100,用于接收异构设备的通信请求;
进程分配模块200,用于为所述异构设备配置对应的独立MPI进程;
异构通信模块300,用于在所述独立MPI进程内利用预设异构通信框架执行所述异构设备的第一内存与本地设备的第二内存之间的数据交互,以完成所述本地设备与所述异构设备之间的通信。
基于上述实施例,作为优选的实施例,若所述预设异构通信框架为OpenCL框架,则异构通信模块300包括:
数据读取单元,用于利用所述OpenCL框架的缓冲区读取机制从所述异构设备的第一内存中读取待通信数据;
进程间通信单元,用于利用所述独立MPI进程在所述第二内存中执行所述待通信数据的进程间通信,得到通信响应数据;
数据读取单元,用于将所述通信响应数据存储于本地设备的第二内存;
数据读取单元,用于利用所述OpenCL框架的写缓冲区机制将所述通信响应数据从所述第二内存写入所述第一内存。
基于上述实施例,作为优选的实施例,进程间通信单元为用于在所述第二内存中将所述待通信数据由所述独立MPI进程切换至第二独立MPI进程处理,并在所述第二独立MPI进程中调用所述待通信数据所需的异构通信算子对所述待通信数据进行数据处理,得到通信响应数据的单元。
基于上述实施例,作为优选的实施例,还包括:
通信算子编译模块,用于利用Cmake编译工具编译并封装所述异构通信算子;
其中,所述异构通信算子包括Heter_Send、Heter_Recv、Heter_Broadcast、Heter_Scatter、Heter_Gather、Heter_Reduce、Heter_Allreduce、Heter_Allgather中一种或任意几种的组合。
基于上述实施例,作为优选的实施例,还可以包括:
通信算子测试模块,用于对每个所述异构通信算子调用单元测试框架进行功能测试;若功能测试失败,重新编译并封装所述异构通信算子。
基于上述实施例,作为优选的实施例,还可以包括:
异构设备管理模块,用于将所述独立MPI进程和对应的异构设备信息添加至异构设备管理列表;利用所述异构设备管理列表管理与所述本地设备通信的所有异构设备。
本申请还提供了一种计算机可读存储介质,其上存有计算机程序,该计算机程序被执行时可以实现上述实施例所提供的步骤。该存储介质可以包括:U盘、移动硬盘、只读存储器(Read-Only Memory,ROM)、随机存取存储器(Random Access Memory,RAM)、磁碟或者光盘等各种可以存储程序代码的介质。
本申请还提供了一种电子设备,可以包括存储器和处理器,所述存储器中存有计算机程序,所述处理器调用所述存储器中的计算机程序时,可以实现上述实施例所提供的步骤。当然所述电子设备还可以包括各种网络接口,电源等组件。
说明书中各个实施例采用递进的方式描述,每个实施例重点说明的都是与其他实施例的不同之处,各个实施例之间相同相似部分互相参见即可。对于实施例提供的系统而言,由于其与实施例提供的方法相对应,所以描述的比较简单,相关之处参见方法部分说明即可。
本文中应用了具体个例对本申请的原理及实施方式进行了阐述,以上实施例的说明只是用于帮助理解本申请的方法及其核心思想。应当指出,对于本技术领域的普通技术人员来说,在不脱离本申请原理的前提下,还可以对本申请进行若干改进和修饰,这些改进和修饰也落入本申请权利要求的保护范围内。
还需要说明的是,在本说明书中,诸如第一和第二等之类的关系术语仅仅用来将一个实体或者操作与另一个实体或操作区分开来,而不一定要求或者暗示这些实体或操作之间存在任何这种实际的关系或者顺序。而且,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、物品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、物品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、物品或者设备中还存在另外的相同要素。