hglink&hgJitLink使用指南(v2.1)
概述
在 PPU 工具链中,hglink 和 hgJitlink 都是处理设备代码链接的关键工具,但它们的应用场景和工作阶段不同:
hglink是编译时静态编译链接工具主要负责在静态编译阶段将多个设备代码模块(如 cubin)链接为单一的设备代码镜像(如
.cubin或库文件.a/.so),同时可在链接时执行跨文件优化,通过解析设备函数/全局变量的跨模块引用,执行代码布局优化等链接时优化。通常在编译器启用
-rdc=true编译多个.cu文件后被自动调用。
hgJitlink是运行时动态编译链接工具主要负责在程序执行阶段动态地链接设备代码,支持加载由
HGRTC(Runtime Compilation)编译的代码片段,实现运行时扩展。通常在用户代码中通过api调用。
在SDK工具链实现中,hglink和hgJitlink使用同一套底层实现,并分别封装为面向静态编译的可执行工具、面向动态编译的库(通过API提供给用户调用)。需要注意的是,hglink和 hgJitlink 暂时不支持PTX文件作为输入。
hglink使用介绍
hglink是通过SDK中的可执行命令行工具提供给用户使用的,其使用方式是:
hglink [options] <objects>
其中<objects>是用户需要执行链接的文件,[options]是可选择的命令行选项,它支持如下命令行选项:
options | alias | Desctiption |
--arch | Specify the 'ppu' name of the target architecture. Allowed values for this option: 'ppu001', 'ppu0015', 'ppu0017'. Default value: 'ppu001'. | |
--emit-hgvm | Emit hgvm file if LTO is used. | |
--help | -h | Print this help information on this tool. |
--hgvm-file | Specify name and location of the output hgvm file. | |
--library-path | -L | ,... Specify library search paths. |
--library ,... | --library=, -l | Specify libraries to be used in the linking stage. The libraries are searched for on the library search paths that have been specified using option '-L'. |
--link-time-opt | -lto, --dlto | Do link-time optimization. |
--output-file | -o | Specify name and location of the output file. |
--register-link-binaries= | Specify name and location of output file that will contain names of hggcRegister routines for each linked file. | |
--register-link-binaries | Specify name and location of output file that will contain names of hggcRegister routines for each linked file. | |
--verbose | -v | Enable verbose mode which prints code generation statistics. |
--version | -V | Print version information on this tool. |
--Xhgvm | Hgvm options (only used with LTO). | |
--XLinker | link options to lld | |
--options-file | Include command line options from specified file |
hgJitLink使用介绍
hgJitLink通过API的形式提供给用户使用,具体的API定义及释义如下表:
函数定义 | 概述 | 参数含义 | 返回值 |
| 创建 JIT 链接器实例 | - handle: 输出句柄指针 - numOptions: JIT 选项数量 - options: JIT 选项字符串数组 |
|
| 从文件添加设备代码 | - handle: 链接器句柄 - inputType: 文件类型(PTX/CUBIN等) - fileName: 文件路径 |
|
| 从内存添加设备代码 | - handle: 链接器句柄 - inputType: 数据类型 - data: 代码指针 - size: 代码大小 - name: 模块标识名 |
|
| 执行链接操作 | - handle: 链接器句柄 |
|
| 获取链接后 CUBIN 大小 | - handle: 链接器句柄 - size: 输出大小值指针 |
|
| 获取链接后 CUBIN 代码 | - handle: 链接器句柄 - cubin: 输出缓冲区指针 |
|
| 获取链接后 PTX 大小 | - handle: 链接器句柄 - size: 输出大小值指针 |
|
| 获取链接后 PTX 代码 | - handle: 链接器句柄 - ptx: 输出缓冲区指针 |
|
| 获取链接、注册后的二进制大小 | - handle: 链接器句柄 - size: 输出大小值指针 |
|
| 获取链接、注册后的二进制文件 | - handle: 链接器句柄 - linkBin: 输出缓冲区指针 |
|
| 获取错误日志大小 | - handle: 链接器句柄 - size: 输出日志大小指针 |
|
| 获取错误日志内容 | - handle: 链接器句柄 - log: 输出日志缓冲区 |
|
| 获取信息日志大小 | - handle: 链接器句柄 - size: 输出大小指针 |
|
| 获取信息日志内容 | - handle: 链接器句柄 - log: 输出日志缓冲区 |
|
| 销毁链接器实例 | - handle: 链接器句柄指针 |
|
| 返回当前hgjitlink的版本 | - version: 输出版本缓冲区 |
|
hgJitLink选项说明
options | alias | Desctiption |
--arch | Specify the 'ppu' name of the target architecture. Allowed values for this option: 'ppu001', 'ppu0015', 'ppu0017'. Default value: 'ppu001'. | |
--link-time-opt | -lto, --dlto | Do link-time optimization. |
--verbose | -v | Enable verbose mode which prints code generation statistics. |
--time | -time | Print timing information to InfoLog |
-g | Generate debug information | |
-ftz= | Flush to zero. | |
-prec-div= | Precise divide. | |
-prec-sqrt= | Precise square root. | |
-fma= | Fast multiply add. | |
-kernels-used= | Pass list of kernels that are used; any not in the list can be removed. This option can be specified multiple times. | |
-variables-used= | Pass list of variables that are used; any not in the list can be removed. This option can be specified multiple times. | |
-optimize-unused-variables | Normally device code optimization is limited by not knowing what the host code references. With this option it can assume that if a variable is not referenced in device code then it can be removed. |
关键类型说明
hgJitLinkHandle不透明
void指针,表示 JIT 链接会话 (typedef void* hgJitLinkHandle)。
hgJitLinkInputType(输入类型枚举)
typedef enum {
hgJitLink_INPUT_NONE = 0, // 错误文件类型
hgJitLink_INPUT_CUBIN = 1, // CUBIN 二进制
hgJitLink_INPUT_PTX, // PTX 文件
hgJitLink_INPUT_LTOIR, // LTO 中间表示
hgJitLink_INPUT_FATBIN, // 多架构 Fatbin文件
hgJitLink_INPUT_OBJECT, // 对象文件
hgJitLink_INPUT_LIBRARY, // 库文件
hgJitLink_INPUT_ANY = 10 // 动态确定为上述类型之一
} hgJitLinkInputType;hgJitLinkResult(错误码枚举)
typedef enum {
hgJitLink_SUCCESS = 0, // 成功
hgJitLink_ERROR_UNRECOGNIZED_OPTION, // 无效选项
hgJitLink_ERROR_MISSING_ARCH, // 未指定架构
hgJitLink_ERROR_INVALID_INPUT, // 无效输入
hgJitLink_ERROR_PTX_COMPILE, // PTX 编译失败
hgJitLink_ERROR_HGVM_COMPILE, // HGVM 编译失败
hgJitLink_ERROR_INTERNAL, // 内部错误
hgJitLink_ERROR_THREADPOOL, // 线程池错误
hgJitLink_ERROR_UNRECOGNIZED_INPUT, // 无法识别的输入
hgJitLink_ERROR_NULL_INPUT, // 空输入
hgJitLink_ERROR_INCOMPATIBLE_OPTIONS, // 不兼容的选项
hgJitLink_ERROR_INCORRECT_INPUT_TYPE, // 不正确的输入类型
hgJitLink_ERROR_ARCH_MISMATCH, // 架构不匹配
hgJitLink_ERROR_OUTDATED_LIBRARY, // 过时的库错误
hgJitLink_ERROR_MISSING_FATBIN // fatbin缺失错误
} hgJitLinkResult;典型工作流代码
hgJitLinkHandle handle;
const char* options[ ] = {"-arch=sm_80"};
hgJitLinkCreate(&handle, 1, options); // Step 1: 创建实例
// Step 2: 添加设备代码 (例如 LTO_IR)
hgJitLinkAddData(handle, hgJitLink_INPUT_LTOIR, ltoir_code, ltoir_size, "my_kernel");
hgJitLinkComplete(handle); // Step 3: 执行链接
// Step 4: 获取链接结果
size_t cubin_size;
hgJitLinkGetLinkedCubinSize(handle, &cubin_size);
void* cubin = malloc(cubin_size);
hgJitLinkGetLinkedCubin(handle, cubin);
// Step 5: 加载到 GPU
HGmodule module;
hgModuleLoadData(&module, cubin);
hgJitLinkDestroy(&handle); // Step 6: 清理资源