Control Functions¶
控制函数(control functions)主要包括控制BMLang使用时的初始化、模式设置、启动编译生成目标文件等。
控制函数常用于BMLang程序的Tensor和Operator之前和之后。 比如在写Tensor和Operator之前,可能需要做初始化和模式设置。 在完成Tensor和Operator编写之后,可能需要启动编译和反初始化。
初始化函数¶
初始化Function,在一个BMLang程序程序的开头使用。 在BMNetC等前端下编写新算子时,内部已经init,用户不需要再init。
初始化函数接口如下所示,包括模式、芯片型号、输出目录的选择。
void init( BmLangMode mode, // [in] set mode const string& chip_name = "BM1682", // [in] set target Sophon TPU const string& out_dir = ""); // [in] set bmodel save directory, default: ./compilation
模式设置¶
BMLang有三种工作模式:COMPUTE_CPU, COMPILE_TPU 和 BOTH 模式。可以通过下面的接口实现:
在初始化时已经设置了模式,初始化后也允许更改模式,但是不管如何更改,都要保证Tensor和Operator语句执行过程中所处的模式是一致的。
// [in] mode void set_mode(BmLangMode mode); typedef enum bmlang_mode { COMPUTE_CPU, COMPILE_TPU, BOTH, UNKNOWN_MODE } BmLangMode;
计算模式(COMPUTE_CPU):使用CPU来模拟计算,该模式是用来Debug BMLang code的计算是否正确。
编译模式(COMPILE_TPU):面向TPU进行编译,生成runtime可运行TPU的bmodel。
BOTH模式:BOTH同时包含COMPUTE_CPU和COMPILE_TPU。
量化计算模式¶
当前很多深度学习网络被量化来减小模型系数量,以及提升网络在后端处理器中的运行性能。 然而,由于后端处理器的计算限制各不相同(不如位宽限制),导致了相同量化计算operator在不同后端处理器有不同的计算结果。
这里BMLang提供了量化计算模式选择接口,以便用户在调试时选择需要的CPU模拟计算 (CPU模拟计算只发生在BMLang工作模式为COMPUTE_CPU或者BOTH)。
量化计算模式选择接口如下所示,其中
DEFAULT_QUANTIZE:默认的量化计算方式,CPU模拟计算时,所有中间累加结果是INT32。
TPU_DEBUG:对应于SOPHON TPU的量化计算,CPU完全模拟TPU的计算结果。比如TPU某些中间结果位宽是16bit,CPU模拟计算同样模拟了16bit位宽的情况。
TFLITE:对应Tensorflow Lite的计算方式,CPU模拟计算在处理Scale值时,会采用TFLite的计算方式。
// [in] mode void set_quantize_mode(BmLangQuantizeMode mode); typedef enum { TFLITE, TPU_DEBUG, DEFAULT_QUANTIZE, UNKNOWN_QUANTIZE_MODE } BmLangQuantizeMode;
启动Compile¶
对初始化到当前的BMLang程序进行编译,生成目标芯片的二进制可执行文件。
启动编译的接口如下所示,其中name为用户设置,Runtime时通过指定该name可启动对应的计算。详细请见NNToolchain文档的 BMRuntime。
opt_level为编译优化级别,目前提供0,1,2三种优化级别,级别越高BMCompiler对性能优化程度越高, 但是BMCompile生成TPU可执行文件时所需要的时间开销也越大。
dyn_cpl表示是否选用动态编译,false: 不采用动态编译,使用静态编译;true:则是使用动态编译。 若使用的是静态编译,在Runtime时,输入的Tensor的shape则是固定不可变的。 若使用的是动态编译,在Runtime时,用户可任意变化输入Tensor的shape值,只要shape值都小于启动 compile时的shape设定即可。
enable_profile即是否打开编译时的Profiling功能。若为true,则启动compile后,会在目标目录中生成 一个编译时的Profile文本文件。Profile文本文件说明请参考NNToolchain中的Profile章节。
void compile( const string& name, // [in] set funtion name int opt_level = 2, // [in] set optimization level bool dyn_cpl = false, // [in] if use dynamic compile bool enable_profile = false); // [in] if generate profiling result
SOPHGO的编译器可在编译时对算子的输出结果进行比对验证,从而保证编译后生成的结果是正确的。若遇到 错误,SOPHGO编译器可报告出那个算子的计算结果出了问题,从而便于调试Compile。
要达到这一功能,需要提供进行比对验证的参考结果,这个参考由BMLang使用者来控制。 使用方式请见以下接口。
接口中,inp_name为要编译的网络的所有输入Tensor名字,inp_data则对应inp_name的数据指针,inp_num为整个网络输入Tensor的数量。 BMCompiler会在编译启动时,使用这些输入数据进行一边编译生成TPU可执行文件,一边使用TPU的c model进行模拟计算。
ref_name为用户想要比对验证的中间Operator输出Tensor的名字,ref_data则对应ref_name的数据指针,ref_num为参考结果的数量。 BMCompiler在编译启动时,会将TPU C model模拟计算的结果与这些给入的参考结果进行比对,若有错则进行报错。
fixpoint_cmp_margin为定点计算结果所运行的最大误差,默认是0。
void compile_with_check( const std::string& name, // [in] set function name char** inp_name, // [in] void** inp_data, // [in] int inp_num, // [in] char** ref_name, // [in] void** ref_data, // [in] int ref_num, // [in] int opt_level = 2, // [in] bool dyn_cpl = false, // [in] bool enable_profile = false, // [in] int fixpoint_cmp_margin = 0); // [in]
这里提供了另一种形式来启动编译时比对验证,如下接口所示。 其中inp_tensor为BMLang编程时所有输入Tensor,ref_tensor则是要进行比对验证的Tensor。
这里要注意的是,该接口仅在BMLang工作模式为BOTH时有效。
void compile_with_check( const std::string& name, // [in] set function name std::vector<Tensor*> inp_tensor, // [in] std::vector<Tensor*> ref_tensor, // [in] int opt_level = 2, // [in] bool dyn_cpl = false, // [in] bool enable_profile = false, // [in] int fixpoint_cmp_margin = 0); // [in]
反初始化¶
在BMLang程序最后,需要进行反初始化结束。只有在反初始化后,之前所启动的 Compile生成TPU可执行目标执行才会存盘到所指定的输出目录中。
void deinit();