一种支持异构计算核架构的编译器实现方法和系统
技术领域
本发明涉及编译器软件技术领域,具体而言涉及一种支持异构计算核架构的编译器实现方法和系统。
背景技术
根据适用场景的不同,GPGPU指令可分为通用指令(General Instruction)、集群指令(Group Instruction)和线程指令。其中,集群指令是指多个线程操作同一组数据,并为多个线程产生输出,且这些输出之间存在关联。AI相关操作,如卷积、激活函数等相互联系紧密的操作属于这类指令。线程指令是指一组可以并行且独立执行的操作,如图形操作。通用指令是指不同线程有不同操作数和结果的操作,如一般数据类型的计算指令。
假设有一段代码如图1所示,可根据上述标准分为上述三类指令序列。通用指令因其性质,适合由CPU执行;线程指令因其性质,适合由GPU执行;集群指令因其性质,适合由专用芯片(ASIC)执行。
但是,将同一段指令的不同部分放在不同设备执行是一种低效方法,因为其中涉及数据传输开销和同步。目前亟需一种方法,能够将高级语言程序编译成支持异构计算核架构的机器码语言,以避免通过系统总线传输数据,提高指令执行性能。
发明内容
本发明目的在于提供一种支持异构计算核架构的编译器实现方法和系统,能够自动处理多种类型的高级语言程序,将其依次转换成中间表示代码和最终可供执行的机器码指令,根据机器码指令的属性类型将其分发至不同的计算核上执行,避免通过系统总线传输数据,提高指令执行性能。本发明不局限于高级程序语言的操作语句类型,对于AI相关操作,采用自定义内建函数进行处理,对于图形相关操作和一般数据操作,通过兼容现有开源编译器前端(如LLVM Clang)进行处理,提高计算效率,减少开发量。
为达成上述目的,结合图2,本发明提出一种支持异构计算核架构的编译器实现方法,所述方法包括:
S1:将高级语言程序转化为中间表示代码;
S2:再将中间表示代码转化为机器码指令;
S3:根据机器码指令的类型,将不同类型的机器码指令映射至异构计算核架构中对应的计算核上执行,所述机器码指令包括通用指令、集群指令和线程指令;
其中:
对于集群指令,采用对应的自定义内建函数进行转换;对于通用指令和线程指令,采用开源编译器现有内建函数或指令进行转换。
进一步的实施例中,步骤S1中,所述将高级语言程序转化为中间表示代码的过程包括:
S11:针对AI操作语句的类型一一对应地创建自定义内建函数;
S12:遍历高级语言程序,当检测到AI操作语句时,根据操作语句的类型调用对应的自定义内建函数,将该操作语句转换成包含有所述自定义内建函数的中间表示代码。
进一步的实施例中,步骤S2中,所述将中间表示代码转化为机器码指令的过程包括:
遍历中间表示代码,当检测到自定义内建函数时,通过指令选择过程将其映射成具有集群属性的机器码指令。
进一步的实施例中,步骤S11中,所述针对AI操作语句的类型一一对应地创建对应的自定义内建函数的过程包括:
步骤S11中,所述针对AI操作语句的类型一一对应地创建对应的自定义内建函数的过程包括:
在目标描述文件中增加用于描述自定义内建函数的内存访问优化特性的自定义内建函数入口;
所述自定义内建函数入口设置有签名,签名包括返回类型、参数类型和一组标志,标志用于提示对应的自定义内建函数在优化时的处理方式。
进一步的实施例中,步骤S12中,遍历高级语言程序,当检测到图形相关数据的操作语句时,采用LLVM Clang将该操作语句转换成对应的中间表示代码。
进一步的实施例中,步骤S3中,所述根据机器码指令的类型,将不同类型的机器码指令映射至异构计算核架构中对应的计算核上执行的过程包括:
遍历机器码指令,根据机器码指令的属性将不同类型的机器码指令分别调度至与之属性相同的已调度的机器码指令的临近位置,不同属性的已调度的机器码指令之间设置有界定指令;
结合界定指令,采用硬件分发部件将不同属性的已调度的机器码指令映射至异构计算核架构中对应的计算核上执行。
进一步的实施例中,所述集群指令分发至AI Core上执行,所述通用指令分发至CPU上执行,所述线程指令分发至GPGPU Core上执行。
进一步的实施例中,所述方法还包括:
采用调度器对指令分发顺序和/或执行顺序进行调度。
基于前述方法,本发明还提及一种支持异构计算核架构的编译器实现系统,所述系统包括:
程序接收模块,用于接收外部输入的高级语言程序;
第一转换模块,用于将高级语言程序转化为中间表示代码;
第二转换模块,用于将中间表示代码转化为机器码指令;
调度模块,用于遍历机器码指令,根据机器码指令的属性将不同类型的机器码指令分别调度至与之属性相同的已调度的机器码指令的临近位置,并且在不同属性的已调度的机器码指令之间设置界定指令;
硬件分发部件,结合界定指令,将不同属性的已调度的机器码指令映射至异构计算核架构中对应的计算核上执行。
自定义内建函数管理模块,用于创建和管理自定义内建函数,所述自定义内建函数与AI操作语句一一对应。
以上本发明的技术方案,与现有相比,其显著的有益效果在于:
(1)能够自动处理多种类型的高级语言程序,将其依次转换成中间表示代码和最终可供执行的机器码指令,根据机器码指令的属性类型将其分发至不同的计算核上执行,避免通过系统总线传输数据,提高指令执行性能。
(2)本发明不局限于高级程序语言的操作语句类型,对于AI相关操作,采用自定义内建函数进行处理,对于图形相关操作和一般数据操作,通过兼容现有开源编译器前端(如LLVM Clang)进行处理,提高计算效率,减少开发量。
(3)采用的自定义内建函数可在中间标识代码中被调用,编译器后段遍历中间表示代码时,能够根据检测到自定义内建函数将对应的中间表示代码快速转换成对应的具有特定属性的机器码指令,并且快速将其调度到其他同种类的机器码指令的临近位置。
(4)采用界定指令分隔开不同属性的机器码指令,便于硬件分发部件将所有机器码指令分发至对应的计算核。
(5)采用调度器合理安排机器码分发顺序和执行顺序,提高整个程序的执行效率。
应当理解,前述构思以及在下面更加详细地描述的额外构思的所有组合只要在这样的构思不相互矛盾的情况下都可以被视为本公开的发明主题的一部分。另外,所要求保护的主题的所有组合都被视为本公开的发明主题的一部分。
结合附图从下面的描述中可以更加全面地理解本发明教导的前述和其他方面、实施例和特征。本发明的其他附加方面例如示例性实施方式的特征和/或有益效果将在下面的描述中显见,或通过根据本发明教导的具体实施方式的实践中得知。
附图说明
附图不意在按比例绘制。在附图中,在各个图中示出的每个相同或近似相同的组成部分可以用相同的标号表示。为了清晰起见,在每个图中,并非每个组成部分均被标记。现在,将通过例子并参考附图来描述本发明的各个方面的实施例,其中:
图1是现有分设备执行代码的原理示意图。
图2是本发明的支持异构计算核架构的编译器实现方法流程图。
图3是本发明的异构计算核架构执行代码的原理示意图。
图4是本发明的其中一种界定指令示意图。
图5是其中一种具体代码的处理过程示意图。
图6是Relu函数的处理过程示意图。
具体实施方式
为了更了解本发明的技术内容,特举具体实施例并配合所附图式说明如下。
结合图2,本发明提出一种支持异构计算核架构的编译器实现方法,所述方法包括:
S1:将高级语言程序转化为中间表示代码。
S2:再将中间表示代码转化为机器码指令。
S3:根据机器码指令的类型,将不同类型的机器码指令映射至异构计算核架构中对应的计算核上执行,所述机器码指令包括通用指令、集群指令和线程指令。
其中:
对于集群指令,采用对应的自定义内建函数进行转换;对于通用指令和线程指令,采用开源编译器现有内建函数或指令进行转换。
结合图3,由于并行计算应用程序可能在不同计算核上运行,因此GPGPU编译器工具链必须支持在编译生成的应用程序可执行文件或库运行于多个不同性质的计算核,例如AI Core、GPGPU Core、CPU等。继而,为了提高运算效率,所述集群指令分发至AI Core上执行,所述通用指令分发至CPU上执行,所述线程指令分发至GPGPU Core上执行。
本发明的GPGPU编译器驱动程序使用两阶段编译模型:第一阶段将设备端源代码(即kernel)编译为中间表示(Intermedia Representation,IR)代码,第二阶段将IR代码编译链接为目标体系结构的二进制代码。主机端应用程序通过调用用户模式驱动(User ModeDriver,UMD)程序API(如CUDA的cuModuleLoad()和cuModuleGetFunction())在运行时加载、执行第二阶段编译输出的二进制代码。因为二进制代码在编译生成后就与特定架构指令集绑定,因此需要在第二阶段编译时对集群指令和线程指令做特殊处理。
为了达成上述目的,设备端kernel程序和主机端程序分别编译。对设备端kernel程序,除了生成二进制代码外,还根据指令属性,插入界定指令,以便硬件的指令调度模块可将不同属性指令段调度给不同计算核执行,如图4所示。并且,对不同指令段占用的计算资源,如寄存器等也应分别计算,并通过编译器生成的二进制文件中的元数据段传递给硬件。
如图5所示,本发明采用的支持异构计算核架构的编译器实现方法由3个处理过程组成,分别是:高级语言程序转化为中间表示代码,中间表示代码转化为机器码指令,机器码指令被映射到异构计算核架构的不同类型的计算核上执行。
第一步,高级语言程序转化为中间表示代码
步骤S1中,所述将高级语言程序转化为中间表示代码的过程包括:
S11:针对AI操作语句的类型一一对应地创建对应的自定义内建函数。
S12:遍历高级语言程序,当检测到AI操作语句时,根据操作语句的类型调用对应的自定义内建函数,将该操作语句转换成包含有所述自定义内建函数的中间表示代码。
采用高级编程语言编写的计算程序中包含各种功能模块,如完成AI相关的操作、图形相关的操作和一般数据的操作等。这些功能模块经过编译器前端(Compilerfrontend)的处理,转化为中间表示代码(Intermediate Representation)。对于图形相关的操作和一般数据的操作,目前已有的开源编译器前端(如LLVM Clang)已经可以将其很好地变换为线程指令和通用指令。例如,对于如下C语言实现的加法运算:
unsigned add1(unsigned a,unsigned b){
return a+b;
}
可变换为LLVM IR:
但是对于AI相关操作,目前的开源编译器前端尚未支持,如果编译器和AI芯片中没有为AI操作相关软硬件支持,AI操作会被分解为一系列基本计算指令(加、减、乘、除等)。这不仅增加编译器处理复杂度,也降低程序运算速度。对此,本发明提出通过创建自定义内建函数,以完成高级语言到中间表示的变换。即,在本发明中,通过为前述AI操作提供自定义内建函数支持,及相应的机器指令集支持,实现对AI操作的快速转换。例如,对于卷积神经网络中常见的激活函数Relu,在Tensorflow中的调用方式如下:
vector=[0.,-1.5,1.5,2.5,-3.5,-0.1]
r=tf.nn.relu(vector)
为了将tf.nn.relu映射到机器指令ml_relu_i32,需要提供对应的自定义内建函数bi.ml.relu,该函数可在中间表示代码中调用。
步骤S11中,所述针对AI操作语句的类型一一对应地创建对应的自定义内建函数的过程包括:
在目标描述文件中增加用于描述自定义内建函数的内存访问优化特性的自定义内建函数入口;
所述自定义内建函数入口设置有签名,签名包括返回类型、参数类型和一组标志,标志用于提示对应的自定义内建函数在优化时的处理方式。
其中,在LLVM编译框架下增加自定义内建函数需要在目标描述(.td)文件中增加自定义内建函数入口,描述自定义内建函数的内存访问优化特性(控制自定义内建函数是否会被死代码消除、公共子表达式消除优化方法处理等)。
例如,针对卷积神经网络中的激活函数Relu,自定义内建函数bi.ml.relu定义如下:
def int_bi_ml_relu_i32:GCCBuiltin<"__builtin_bi_ml_relu_i32">,
Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem,IntrSpeculatable]>。
Intrinsic<...>中的内容是对自定义内建函数签名,描述该自定义内建应该如何被调用。签名包括三个部分:返回类型、参数类型和一组标志。这组标志提示了在优化时应该如何处理这个自定义内建。
第二步,中间表示代码转化为机器码指令
步骤S2中,所述将中间表示代码转化为机器码指令的过程包括:
遍历中间表示代码,当检测到自定义内建函数时,通过指令选择过程将其映射成具有集群属性的机器码指令。
以前述例子为例,编译器后端遍历中间表示代码时,若检测到自定义内建函数bi.ml.relu,便通过指令选择过程将其映射到机器指令ml_relu_i32。机器指令ml_relu_i32定义如下:
def ML_RELU_I32:MLOP1p_i32<"ml_relu_i32",
[(set i32:$vdst,(int_bi_ml_relu_i32 i32:$src0))]
>;
第三步,机器码指令被映射到异构计算核架构的不同类型的计算核上执行
步骤S3中,所述根据机器码指令的类型,将不同类型的机器码指令映射至异构计算核架构中对应的计算核上执行的过程包括:
遍历机器码指令,根据机器码指令的属性将不同类型的机器码指令分别调度至与之属性相同的已调度的机器码指令的临近位置,不同属性的已调度的机器码指令之间设置有界定指令。
结合界定指令,采用硬件分发部件将不同属性的已调度的机器码指令映射至异构计算核架构中对应的计算核上执行。
仍以前述例子为例,因为机器指令ml_relu_i32是自定义指令,编译器后端自然知道其属性,因而可以将其与其它AI指令调度到临近位置,并通过界定指令告知硬件分发部件(Dispatcher HW),将AI相关的集群指令分发到AI Core上执行。
Relu函数的整体处理过程如图6所示。
对于通用指令和线程指令,现有开源编译器已经能很好地支持,因而在编译器前端和后端不需要做太大修改,只需要在将其与同属性指令调度到临近位置,并通过界定指令告知硬件分发部件,将通用指令和线程指令分别分发到CPU和GPGPU Core上执行。
在一些例子中,针对不同代码中的不同分类的指令数量等信息,本发明提出通过采用调度器对指令分发顺序和/或执行顺序进行调度,优化整个代码处理过程中的各个分步骤,以提高整个代码处理的效率。
例如,可以在其中一条中间表示代码转换成机器码指令后,立刻将其调度至同属性机器码指令的临近位置以便于分发执行,也可以在多条中间表示代码转换完成后,再通过遍历的方式逐一分配至不同的位置进行分发执行等等。
基于前述方法,本发明还提及一种支持异构计算核架构的编译器实现系统,所述系统包括以下几个模块:
(1)程序接收模块,用于接收外部输入的高级语言程序。
(2)第一转换模块,用于将高级语言程序转化为中间表示代码。
(3)第二转换模块,用于将中间表示代码转化为机器码指令。
(4)调度模块,用于遍历机器码指令,根据机器码指令的属性将不同类型的机器码指令分别调度至与之属性相同的已调度的机器码指令的临近位置,并且在不同属性的已调度的机器码指令之间设置界定指令。
(5)硬件分发部件,结合界定指令,将不同属性的已调度的机器码指令映射至异构计算核架构中对应的计算核上执行。
(6)自定义内建函数管理模块,用于创建和管理自定义内建函数,所述自定义内建函数与AI操作语句一一对应。
在本公开中参照附图来描述本发明的各方面,附图中示出了许多说明的实施例。本公开的实施例不必定义在包括本发明的所有方面。应当理解,上面介绍的多种构思和实施例,以及下面更加详细地描述的那些构思和实施方式可以以很多方式中任意一种来实施,这是因为本发明所公开的构思和实施例并不限于任何实施方式。另外,本发明公开的一些方面可以单独使用,或者与本发明公开的其他方面的任何适当组合来使用。
虽然本发明已以较佳实施例揭露如上,然其并非用以限定本发明。本发明所属技术领域中具有通常知识者,在不脱离本发明的精神和范围内,当可作各种的更动与润饰。因此,本发明的保护范围当视权利要求书所界定者为准。