tvm.contrib

TVM python 包的 Contrib API。

Contrib API 提供了许多有用的非核心功能。其中一些是与第三方库和工具交互的实用工具。

tvm.contrib.cblas

BLAS 库的外部函数接口。

tvm.contrib.cblas.matmul(lhs, rhs, transa=False, transb=False, **kwargs)

创建一个外部算子,使用 CrhsLAS 计算 A 和 rhs 的矩阵乘法。此函数用作如何调用外部库的示例。

参数:
  • lhs (Tensor) – 左矩阵操作数

  • rhs (Tensor) – 右矩阵操作数

  • transa (bool) – 是否转置 lhs

  • transb (bool) – 是否转置 rhs

返回:

C – 结果张量。

返回类型:

Tensor

tvm.contrib.cblas.batch_matmul(lhs, rhs, transa=False, transb=False, iterative=False, **kwargs)

创建一个外部算子,使用 CBLAS 计算 A 和 rhs 的批量矩阵乘法。此函数用作如何调用外部库的示例。

参数:
  • lhs (Tensor) – 左矩阵操作数

  • rhs (Tensor) – 右矩阵操作数

  • transa (bool) – 是否转置 lhs

  • transb (bool) – 是否转置 rhs

返回:

C – 结果张量。

返回类型:

Tensor

tvm.contrib.clang

用于调用系统中 clang 的工具。

tvm.contrib.clang.find_clang(required=True)

在系统中查找 clang。

参数:

required (bool) – 是否为必需,如果编译器是必需的,则会引发运行时错误。

返回:

valid_list – 可能路径的列表。

返回类型:

list of str

注意

此函数将首先搜索与构建 tvm 的主要 llvm 版本匹配的 clang

tvm.contrib.clang.create_llvm(inputs, output=None, options=None, cc=None)

创建 llvm 文本 ir。

参数:
  • inputs (list of str) – 输入文件名或代码源列表。

  • output (str, optional) – 输出文件,如果为 None,则创建临时文件

  • options (list) – 附加选项字符串的列表。

  • cc (str, optional) – clang 编译器,如果未指定,我们将尝试猜测匹配的 clang 版本。

返回:

code – 生成的 llvm 文本 IR。

返回类型:

str

tvm.contrib.cc

用于调用系统中 C/C++ 编译器的工具。

tvm.contrib.cc.get_cc()

返回默认 C/C++ 编译器的路径。

返回:

out – 默认 C/C++ 编译器的路径,如果未找到,则为 None。

返回类型:

Optional[str]

tvm.contrib.cc.create_shared(output, objects, options=None, cc=None, cwd=None, ccache_env=None)

创建共享库。

参数:
  • output (str) – 目标共享库。

  • objects (List[str]) – 对象文件列表。

  • options (List[str]) – 附加选项字符串的列表。

  • cc (Optional[str]) – 编译器命令。

  • cwd (Optional[str]) – 当前工作目录。

  • ccache_env (Optional[Dict[str, str]]) – ccache 的环境变量。设置为 None 默认禁用 ccache。

tvm.contrib.cc.create_staticlib(output, inputs, ar=None)

创建静态库。

参数:
  • output (str) – 目标共享库。

  • inputs (List[str]) – 输入文件列表。每个输入文件可以是对象 tarball 或对象文件。

  • ar (Optional[str]) – 要使用的 ar 命令的路径

tvm.contrib.cc.create_executable(output, objects, options=None, cc=None, cwd=None, ccache_env=None)

创建可执行二进制文件。

参数:
  • output (str) – 目标可执行文件。

  • objects (List[str]) – 对象文件列表。

  • options (List[str]) – 附加选项字符串的列表。

  • cc (Optional[str]) – 编译器命令。

  • cwd (Optional[str]) – 当前工作目录。

  • ccache_env (Optional[Dict[str, str]]) – ccache 的环境变量。设置为 None 默认禁用 ccache。

tvm.contrib.cc.get_global_symbol_section_map(path, *, nm=None) Dict[str, str]

通过 nm -g 从库中获取全局符号

参数:
  • path (str) – 库路径

  • nm (str) – nm 命令的路径

返回:

symbol_section_map – 从定义的全局符号到其节区的映射

返回类型:

Dict[str, str]

tvm.contrib.cc.get_target_by_dump_machine(compiler)

get_target_triple 的函子,可以使用编译器获取目标三元组。

参数:

compiler (Optional[str]) – 编译器。

返回:

out – 一个函数,可以根据编译器的 dumpmachine 选项获取目标三元组。

返回类型:

Callable

tvm.contrib.cc.cross_compiler(compile_func, options=None, output_format=None, get_target_triple=None, add_files=None)

通过使用选项专门化 compile_func 来创建交叉编译器函数。

此函数可用于构造可以传递给 AutoTVM 测量或 export_library 的编译函数。

参数:
  • compile_func (Union[str, Callable[[str, str, Optional[str]], None]]) – 执行实际编译的函数

  • options (Optional[List[str]]) – 附加可选字符串列表。

  • output_format (Optional[str]) – 库输出格式。

  • get_target_triple (Optional[Callable]) – 可以根据编译器的 dumpmachine 选项获取目标三元组的函数。

  • add_files (Optional[List[str]]) – 要作为编译一部分传递的其他对象、源文件、库文件的路径列表。

返回:

fcompile – 可以传递给 export_library 的编译函数。

返回类型:

Callable[[str, str, Optional[str]], None]

示例

from tvm.contrib import cc, ndk
# export using arm gcc
mod = build_runtime_module()
mod.export_library(path_dso,
                   fcompile=cc.cross_compiler("arm-linux-gnueabihf-gcc"))
# specialize ndk compilation options.
specialized_ndk = cc.cross_compiler(
    ndk.create_shared,
    ["--sysroot=/path/to/sysroot", "-shared", "-fPIC", "-lm"])
mod.export_library(path_dso, fcompile=specialized_ndk)

tvm.contrib.cublas

cuBLAS 库的外部函数接口。

tvm.contrib.cublas.matmul(lhs, rhs, transa=False, transb=False, dtype=None)

创建一个外部算子,使用 cuBLAS 计算 A 和 rhs 的矩阵乘法

参数:
  • lhs (Tensor) – 左矩阵操作数

  • rhs (Tensor) – 右矩阵操作数

  • transa (bool) – 是否转置 lhs

  • transb (bool) – 是否转置 rhs

返回:

C – 结果张量。

返回类型:

Tensor

tvm.contrib.cublas.batch_matmul(lhs, rhs, transa=False, transb=False, dtype=None)

创建一个外部算子,使用 cuBLAS 计算 A 和 rhs 的批量矩阵乘法

参数:
  • lhs (Tensor) – 左矩阵操作数

  • rhs (Tensor) – 右矩阵操作数

  • transa (bool) – 是否转置 lhs

  • transb (bool) – 是否转置 rhs

返回:

C – 结果张量。

返回类型:

Tensor

tvm.contrib.dlpack

包装函数,以桥接具有 DLPack 支持的框架到 TVM

tvm.contrib.dlpack.convert_func(tvm_func, tensor_type, to_dlpack_func)
将 tvm 函数转换为接受来自另一个框架的张量的函数

框架,前提是另一个框架支持 DLPACK

参数:
  • tvm_func (Function) – 在数组上运行的已构建 tvm 函数

  • tensor_type (Type) – 目标框架的张量的类型

  • to_dlpack_func (Function) – 将源张量转换为 DLPACK 的函数

tvm.contrib.dlpack.to_pytorch_func(tvm_func)

将 tvm 函数转换为接受 PyTorch 张量的函数

参数:

tvm_func (Function) – 在数组上运行的已构建 tvm 函数

返回:

wrapped_func – 在 PyTorch 张量上运行的包装后的 tvm 函数

返回类型:

Function

tvm.contrib.emcc

用于调用系统中 emscripten 编译器的工具。

tvm.contrib.emcc.create_tvmjs_wasm(output, objects, options=None, cc='emcc', libs=None)

创建旨在与 tvmjs 一起运行的 wasm。

参数:
  • output (str) – 目标共享库。

  • objects (list) – 对象文件列表。

  • options (str) – 附加选项。

  • cc (str, optional) – 编译字符串。

  • libs (list) – 要添加到 wasm 中的用户定义的库文件列表(例如 .bc 文件)。

tvm.contrib.miopen

MIOpen 库的外部函数接口。

tvm.contrib.miopen.conv2d_forward(x, w, stride_h=1, stride_w=1, pad_h=0, pad_w=0, dilation_h=1, dilation_w=1, conv_mode=0, data_type=1, group_count=1)

创建一个外部算子,使用 MIOpen 计算 2D 卷积

参数:
  • x (Tensor) – 输入特征图

  • w (Tensor) – 卷积权重

  • stride_h (int) – 高度步幅

  • stride_w (int) – 宽度步幅

  • pad_h (int) – 高度填充

  • pad_w (int) – 权重填充

  • dilation_h (int) – 高度膨胀

  • dilation_w (int) – 宽度膨胀

  • conv_mode (int) – 0: miopenConvolution 1: miopenTranspose

  • data_type (int) – 0: miopenHalf (fp16) 1: miopenFloat (fp32)

  • group_count (int) – 组数

返回:

y – 结果张量

返回类型:

Tensor

tvm.contrib.miopen.softmax(x, axis=-1)

使用 MIOpen 计算 softmax

参数:
返回:

ret – 结果张量

返回类型:

tvm.te.Tensor

tvm.contrib.miopen.log_softmax(x, axis=-1)

使用 MIOpen 计算 log softmax

参数:
返回:

ret – 结果张量

返回类型:

tvm.te.Tensor

tvm.contrib.ndk

用于调用 NDK 编译器工具链的工具。

tvm.contrib.ndk.create_shared(output, objects, options=None)

创建共享库。

参数:
  • output (str) – 目标共享库。

  • objects (list) – 对象文件列表。

  • options (list of str, optional) – 附加选项。

tvm.contrib.ndk.create_staticlib(output, inputs)

创建静态库

参数:
  • output (str) – 目标静态库。

  • inputs (list) – 对象文件或 tar 文件列表

tvm.contrib.ndk.get_global_symbol_section_map(path, *, nm=None) Dict[str, str]

通过 NDK 中的 nm -gU 从库中获取全局符号

参数:
  • path (str) – 库路径

  • nm (str) – nm 命令的路径

返回:

symbol_section_map – 从定义的全局符号到其节区的映射

返回类型:

Dict[str, str]

tvm.contrib.nnpack

NNPACK 库的外部函数接口。

tvm.contrib.nnpack.is_available()

检查 NNPACK 是否可用,即 nnp_initialize() 是否返回 nnp_status_success

tvm.contrib.nnpack.fully_connected_inference(lhs, rhs, nthreads=1)

创建一个外部算子,使用 nnpack 计算 1D 张量 lhs 和 2D 张量 rhs 的全连接。

参数:
  • lhs (Tensor) – lhs 1D 数组 input[input_channels],包含 FP32 元素

  • rhs (Tensor) – lhs 2D 矩阵 kernel[output_channels][input_channels],包含 FP32 元素

返回:

C – lhs 1D 数组 out[output_channels],包含 FP32 元素。

返回类型:

Tensor

tvm.contrib.nnpack.convolution_inference(data, kernel, bias, padding, stride, nthreads=1, algorithm=0)

创建一个外部算子,使用 nnpack 对 4D 张量数据、4D 张量内核和 1D 张量偏差进行推理卷积。

参数:
  • data (Tensor) – data 4D 张量,输入格式为 input[batch][input_channels][input_height][input_width],数据类型为 FP32 元素。

  • kernel (Tensor) – kernel 4D 张量,格式为 kernel[output_channels][input_channels][kernel_height] [kernel_width],数据类型为 FP32 元素。

  • bias (Tensor) – bias 1D 数组,格式为 bias[output_channels][input_channels][kernel_height] [kernel_width],数据类型为 FP32 元素。

  • padding (list) – padding 4 维列表 [pad_top, pad_bottom, pad_left, pad_right],指示特征图周围的填充。

  • stride (list) – stride 2 维列表 [stride_height, stride_width],指示步幅。

返回:

output – output 4D 张量,输出格式为 output[batch][output_channels][output_height][output_width],数据类型为 FP32 元素。

返回类型:

Tensor

tvm.contrib.nnpack.convolution_inference_without_weight_transform(data, transformed_kernel, bias, padding, stride, nthreads=1, algorithm=0)

创建一个外部算子,使用 nnpack 对 4D 张量数据、4D 预转换张量 kernel 和 1D 张量 bias 进行推理卷积。

参数:
  • data (Tensor) – data 4D 张量,输入格式为 input[batch][input_channels][input_height][input_width],数据类型为 FP32 元素。

  • transformed_kernel (Tensor) – transformed_kernel 4D 张量,格式为 kernel[output_channels][input_channels][tile] [tile],数据类型为 FP32 元素。

  • bias (Tensor) – bias 1D 数组,格式为 bias[output_channels][input_channels][kernel_height] [kernel_width],数据类型为 FP32 元素。

  • padding (list) – padding 4 维列表 [pad_top, pad_bottom, pad_left, pad_right],指示特征图周围的填充。

  • stride (list) – stride 2 维列表 [stride_height, stride_width],指示步幅。

返回:

output – output 4D 张量,输出格式为 output[batch][output_channels][output_height][output_width],数据类型为 FP32 元素。

返回类型:

Tensor

tvm.contrib.nnpack.convolution_inference_weight_transform(kernel, nthreads=1, algorithm=0, dtype='float32')

创建一个外部算子,使用 nnpack 对 3D 张量数据、4D 张量 kernel 和 1D 张量 bias 进行推理卷积。

参数:

kernel (Tensor) – kernel 4D 张量,格式为 kernel[output_channels][input_channels][kernel_height] [kernel_width],数据类型为 FP32 元素。

返回:

output – output 4D 张量,输出格式为 output[output_channels][input_channels][tile][tile],数据类型为 FP32 元素。

返回类型:

Tensor

tvm.contrib.nvcc

用于调用系统中 nvcc 编译器的实用工具

tvm.contrib.nvcc.compile_cuda(code, target_format='ptx', arch=None, options=None, path_target=None)

使用 NVCC 从环境中编译 CUDA 代码。

参数:
  • code (str) – CUDA 代码。

  • target_format (str) – nvcc 编译器的目标格式。

  • arch (str) – CUDA 架构。

  • options (strlist of str) – 附加选项。

  • path_target (str, optional) – 输出文件路径。

返回:

cubin – cubin 的字节数组

返回类型:

bytearray

tvm.contrib.nvcc.find_cuda_path()

查找 CUDA 路径的实用函数

返回:

path – CUDA 根目录的路径。

返回类型:

str

tvm.contrib.nvcc.get_cuda_version(cuda_path=None)

获取 CUDA 版本的实用函数

参数:

cuda_path (Optional[str]) – CUDA 根目录的路径。如果传入 None,将使用 find_cuda_path() 作为默认值。

返回:

version – CUDA 版本

返回类型:

float

tvm.contrib.nvcc.parse_compute_version(compute_version)

解析计算能力字符串,将其分为主版本号和次版本号

参数:

compute_version (str) – GPU 的计算能力(例如 “6.0”)

返回:

  • major (int) – 主版本号

  • minor (int) – 次版本号

tvm.contrib.nvcc.have_fp16(compute_version)

判断计算能力是否支持 fp16

参数:

compute_version (str) – GPU 的计算能力(例如 “6.0”)

tvm.contrib.nvcc.have_int8(compute_version)

判断计算能力是否支持 int8

参数:

compute_version (str) – GPU 的计算能力(例如 “6.1”)

tvm.contrib.nvcc.have_tensorcore(compute_version=None, target=None)

判断计算能力是否支持 TensorCore

参数:
  • compute_version (str, optional) – GPU 的计算能力(例如 “7.0”)。

  • target (tvm.target.Target, optional) – 编译目标,如果未指定 compute_version,将用于确定架构。

tvm.contrib.nvcc.have_cudagraph()

判断是否支持 CUDA Graph

tvm.contrib.pickle_memoize

通过 pickle 缓存函数结果,用于缓存测试用例。

class tvm.contrib.pickle_memoize.Cache(key, save_at_exit)

用于结果缓存的缓存对象。

参数:
  • key (str) – 函数的文件键

  • save_at_exit (bool) – 程序退出时是否将缓存保存到文件

property cache

返回缓存,首次使用时初始化。

tvm.contrib.pickle_memoize.memoize(key, save_at_exit=False)

缓存函数结果并多次重用。

参数:
  • key (str) – 文件的唯一键

  • save_at_exit (bool) – 程序退出时是否将缓存保存到文件

返回:

fmemoize – 执行 memoization 的装饰器函数。

返回类型:

function

tvm.contrib.random

随机库的外部函数接口。

tvm.contrib.random.randint(low, high, size, dtype='int32')

从 low(包含)到 high(不包含)返回随机整数。从指定 dtype 的 “离散均匀” 分布的 “半开” 区间 [low, high) 返回随机整数。

参数:
  • low (int) – 从分布中抽取的最小(有符号)整数

  • high (int) – 从分布中抽取的最大(有符号)整数之上加一

返回:

out – 具有指定大小和 dtype 的张量

返回类型:

Tensor

tvm.contrib.random.uniform(low, high, size)

从均匀分布中抽取样本。

样本在半开区间 [low, high) 内均匀分布(包括 low,但不包括 high)。换句话说,给定区间内的任何值都可能被 uniform 均匀抽取。

参数:
  • low (float) – 输出区间的下边界。所有生成的值将大于或等于 low。

  • high (float) – 输出区间的上边界。所有生成的值将小于 high。

  • size (tuple of ints) – 输出形状。如果给定的形状是例如 (m, n, k),则抽取 m * n * k 个样本。

返回:

out – 具有指定大小和 dtype 的张量。

返回类型:

Tensor

tvm.contrib.random.normal(loc, scale, size)

从正态分布中抽取样本。

从正态分布中返回随机样本。

参数:
  • loc (float) – 分布的 loc。

  • scale (float) – 分布的标准差。

  • size (tuple of ints) – 输出形状。如果给定的形状是例如 (m, n, k),则抽取 m * n * k 个样本。

返回:

out – 具有指定大小和 dtype 的张量

返回类型:

Tensor

tvm.contrib.rocblas

rocBLAS 库的外部函数接口。

tvm.contrib.rocblas.matmul(lhs, rhs, transa=False, transb=False)

创建一个外部算子,使用 rocBLAS 计算 A 和 rhs 的矩阵乘法

参数:
  • lhs (Tensor) – 左矩阵操作数

  • rhs (Tensor) – 右矩阵操作数

  • transa (bool) – 是否转置 lhs

  • transb (bool) – 是否转置 rhs

返回:

C – 结果张量。

返回类型:

Tensor

tvm.contrib.rocblas.batch_matmul(lhs, rhs, transa=False, transb=False)

创建一个外部算子,使用 rocBLAS 计算 A 和 rhs 的矩阵乘法

参数:
  • lhs (Tensor) – 左侧批量矩阵操作数

  • rhs (Tensor) – 右侧批量矩阵操作数

  • transa (bool) – 是否转置 lhs

  • transb (bool) – 是否转置 rhs

返回:

C – 结果张量。

返回类型:

Tensor

tvm.contrib.rocm

ROCm 后端的实用工具

tvm.contrib.rocm.find_lld(required=True)

在系统中查找 ld.lld。

参数:

required (bool) – 是否为必需,如果编译器是必需的,则会引发运行时错误。

返回:

valid_list – 可能路径的列表。

返回类型:

list of str

注意

此函数将首先搜索与构建 TVM 的主要 llvm 版本匹配的 ld.lld

使用 lld 将可重定位 ELF 对象链接到共享 ELF 对象

参数:
  • in_file (str) – 输入文件名(可重定位 ELF 对象文件)

  • out_file (str) – 输出文件名(共享 ELF 对象文件)

  • lld (str, optional) – lld 链接器,如果未指定,我们将尝试猜测匹配的 clang 版本。

tvm.contrib.rocm.parse_compute_version(compute_version)

解析计算能力字符串,将其分为主版本号和次版本号

参数:

compute_version (str) – GPU 的计算能力(例如 “6.0”)

返回:

  • major (int) – 主版本号

  • minor (int) – 次版本号

tvm.contrib.rocm.have_matrixcore(compute_version=None)

判断计算能力是否支持 MatrixCore

参数:

compute_version (str, optional) – GPU 的计算能力(例如 “7.0”)。

返回:

have_matrixcore – 如果支持 MatrixCore,则为 True,否则为 False

返回类型:

bool

tvm.contrib.rocm.find_rocm_path()

查找 ROCm 路径的实用函数

返回:

path – ROCm 根目录的路径。

返回类型:

str

tvm.contrib.spirv

用于与 SPIRV 工具交互的实用工具

tvm.contrib.spirv.optimize(spv_bin)

使用 spirv-opt 通过 CLI 优化 SPIRV

请注意,spirv-opt 仍处于实验阶段。

参数:

spv_bin (bytearray) – spirv 文件

返回:

cobj_bin – HSA 代码对象

返回类型:

bytearray

tvm.contrib.tar

用于调用系统中 tarball 的实用工具。

tvm.contrib.tar.tar(output, files)

创建包含根目录中所有文件的 tarball。

参数:
  • output (str) – 目标共享库。

  • files (list) – 要捆绑的文件列表。

tvm.contrib.tar.untar(tar_file, directory)

将所有 tar 文件解压缩到目录中

参数:
  • tar_file (str) – 源 tar 文件。

  • directory (str) – 目标目录

tvm.contrib.tar.normalize_file_list_by_unpacking_tars(temp, file_list)

通过解压缩列表中的 tar 文件来规范化文件列表。

当文件名是 tar 文件时,它会将其解压缩到 temp 目录中的唯一目录中,并返回 tar 文件中的文件列表。当文件名是普通文件时,它将被简单地添加到列表中。

这对于解压缩 tar 文件中的对象,然后将其转换为库非常有用。

参数:
返回:

ret_list – 更新后的文件列表

返回类型:

List[str]

tvm.contrib.utils

常用系统实用工具

exception tvm.contrib.utils.DirectoryCreatedPastAtExit

当在 atexit 钩子运行后创建 TempDirectory 时引发。

class tvm.contrib.utils.TempDirectory(custom_path=None, keep_for_debug=None)

用于在测试期间管理临时目录的辅助对象。

当超出作用域时自动删除目录。

classmethod set_keep_for_debug(set_to=True)

在程序退出后保留临时目录以进行调试。

remove()

删除临时目录

relpath(name)

临时目录中的相对路径

参数:

name (str) – 文件名。

返回:

path – 连接后的路径。

返回类型:

str

listdir()

列出目录中的内容。

返回:

names – 目录的内容

返回类型:

list

tvm.contrib.utils.tempdir(custom_path=None, keep_for_debug=None)

创建临时目录,退出时删除内容。

参数:
  • custom_path (str, optional) – 手动指定确切的临时目录路径

  • keep_for_debug (bool) – 保留临时目录以进行调试

返回:

temp – 临时目录对象

返回类型:

TempDirectory

class tvm.contrib.utils.FileLock(path)

文件锁对象

参数:

path (str) – 锁的路径

release()

释放锁

tvm.contrib.utils.filelock(path)

创建一个文件锁,锁定 path

参数:

path (str) – 锁的路径

返回:

lock

返回类型:

文件锁对象

tvm.contrib.utils.is_source_path(path)

检查路径是否为源代码路径。

参数:

path (str) – 可能的路径

返回:

valid – 路径是否为可能的源路径

返回类型:

bool

tvm.contrib.utils.which(exec_name)

尝试查找 exec_name 的完整路径

参数:

exec_name (str) – 可执行文件名

返回:

path – 如果找到可执行文件,则为可执行文件的完整路径,否则返回 None

返回类型:

str

tvm.contrib.xcode

用于调用 Xcode 编译器工具链的实用工具

tvm.contrib.xcode.xcrun(cmd)

运行 xcrun 并返回输出。

参数:

cmd (list of str) – 命令序列。

返回:

out – 输出字符串。

返回类型:

str

tvm.contrib.xcode.create_dylib(output, objects, arch, sdk='macosx', min_os_version=None)

创建动态库。

参数:
  • output (str) – 目标共享库。

  • objects (list) – 对象文件列表。

  • options (str) – 附加选项。

  • arch (str) – 目标主要架构

  • sdk (str) – 要使用的 SDK。

tvm.contrib.xcode.compile_metal(code, path_target=None, sdk='macosx', min_os_version=None)

使用环境变量中的 CLI 工具编译 Metal。

参数:
  • code (str) – CUDA 代码。

  • path_target (str, optional) – 输出文件路径。

  • sdk (str, 可选) – 目标平台 SDK。

返回:

metallib – metallib 的字节数组

返回类型:

bytearray

tvm.contrib.xcode.compile_coreml(model, model_name='main', out_dir='.')

编译 CoreML 模型并返回编译后的模型路径。