NVPL TENSOR 函数#

辅助函数#

辅助函数用于初始化 nvplTENSOR,创建张量描述符,检查错误代码,以及检索库版本。


nvpltensorCreate()#

nvpltensorStatus_t nvpltensorCreate(nvpltensorHandle_t *handle)#

初始化 nvplTENSOR 库并为库上下文分配内存。

用户负责调用 nvpltensorDestroy 以释放与句柄关联的资源。

备注

阻塞,不可重入,且线程安全

参数:

handle[out] 指向 nvpltensorHandle_t 的指针

返回值:

NVPLTENSOR_STATUS_SUCCESS – 成功时返回此值,否则返回错误代码


nvpltensorDestroy()#

nvpltensorStatus_t nvpltensorDestroy(nvpltensorHandle_t handle)#

释放与提供的库句柄相关的所有资源。

备注

阻塞,不可重入,且线程安全

参数:

handle[inout] 指向 nvpltensorHandle_t 的指针

返回值:

NVPLTENSOR_STATUS_SUCCESS – 成功时返回此值,否则返回错误代码


nvpltensorCreateTensorDescriptor()#

nvpltensorStatus_t nvpltensorCreateTensorDescriptor(
const nvpltensorHandle_t handle,
nvpltensorTensorDescriptor_t *desc,
const uint32_t numModes,
const int64_t extent[],
const int64_t stride[],
nvpltensorDataType_t dataType,
uint32_t alignmentRequirement,
)#

创建张量描述符。

这会分配少量主机内存。

用户负责调用 nvpltensorDestroyTensorDescriptor() 以在不再使用张量描述符时释放相关资源。

备注

非阻塞,不可重入,且线程安全

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • desc[out] 指向将存储已分配的张量描述符对象地址的指针。

  • numModes[in] 模式数量。

  • extent[in] 每个模式的范围(必须大于零)。

  • stride[in] stride[i] 表示第 i 个模式中两个连续元素之间的位移(步幅)。如果 stride 为 NULL,则假定为紧密排列的广义列主序内存布局(即,步幅从左到右单调递增)。每个步幅必须大于零;准确地说,可以通过完全省略此模式来实现零步幅;例如,与其编写 strideA(a) = 0 的 C[a,b] = A[b,a],不如直接编写 C[a,b] = A[b];然后 nvplTENSOR 将自动推断 A 中的 a 模式应进行广播。

  • dataType[in] 存储条目的数据类型。

  • alignmentRequirement[in] 将与此张量描述符一起使用的基指针的对齐方式(以字节为单位)。

返回值:
  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。

  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果不支持请求的描述符(例如,由于不支持的数据类型)。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。

先决条件:

extent 和 stride 数组必须各自至少包含 sizeof(int64_t) * numModes 字节


nvpltensorDestroyTensorDescriptor()#

nvpltensorStatus_t nvpltensorDestroyTensorDescriptor(
nvpltensorTensorDescriptor_t desc,
)#

释放与提供的张量描述符相关的所有资源。

备注

阻塞,不可重入,且线程安全

参数:

desc[inout] 将被释放的 nvpltensorTensorDescriptor_t 对象。

返回值:

NVPLTENSOR_STATUS_SUCCESS – 成功时返回此值,否则返回错误代码


nvpltensorGetErrorString()#

const char *nvpltensorGetErrorString(const nvpltensorStatus_t error)#

返回错误代码的描述字符串。

备注

非阻塞,不可重入,且线程安全

参数:

error[in] 要转换为字符串的错误代码。

返回值:

The – 以 null 结尾的错误字符串。


nvpltensorGetVersion()#

size_t nvpltensorGetVersion()#

返回 NVPLTENSOR 库的版本号。


逐元素操作#

以下函数执行张量之间的逐元素操作。


nvpltensorCreateElementwiseTrinary()#

nvpltensorStatus_t nvpltensorCreateElementwiseTrinary(
const nvpltensorHandle_t handle,
nvpltensorOperationDescriptor_t *desc,
const nvpltensorTensorDescriptor_t descA,
const int32_t modeA[],
nvpltensorOperator_t opA,
const nvpltensorTensorDescriptor_t descB,
const int32_t modeB[],
nvpltensorOperator_t opB,
const nvpltensorTensorDescriptor_t descC,
const int32_t modeC[],
nvpltensorOperator_t opC,
const nvpltensorTensorDescriptor_t descD,
const int32_t modeD[],
nvpltensorOperator_t opAB,
nvpltensorOperator_t opABC,
const nvpltensorComputeDescriptor_t descCompute,
)#

此函数创建一个操作描述符,用于编码逐元素的三元运算。

所述三元运算具有以下通用形式

\[ D_{\Pi^C(i_0,i_1,...,i_n)} = \Phi_{ABC}(\Phi_{AB}(\alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)}), \beta op_B(B_{\Pi^B(i_0,i_1,...,i_n)})), \gamma op_C(C_{\Pi^C(i_0,i_1,...,i_n)})) \]

其中

  • A、B、C、D 是多模张量(具有任意数据类型)。

  • \(\Pi^A, \Pi^B, \Pi^C \) 是分别置换 A、B 和 C 模式的置换运算符。

  • \(op_{A},op_{B},op_{C}\) 是一元逐元素运算符(例如,IDENTITY、CONJUGATE)。

  • \(\Phi_{ABC}, \Phi_{AB}\) 是二元逐元素运算符(例如,ADD、MUL、MAX、MIN)。

请注意,广播(模式)可以通过简单地从相应张量中省略该模式来实现。

此外,模式可以以任何顺序出现,从而为用户提供更大的灵活性。唯一的限制

  • 出现在 A 或 B 中的模式必须也出现在输出张量中;仅出现在输入中的模式将被收缩,此类操作将由 nvpltensorContractnvpltensorReduce 覆盖。

  • 每个模式在每个张量中最多出现一次。

即使对应标量的值为零,也可以读取输入张量。

示例

  • \( D_{a,b,c,d} = A_{b,d,a,c}\)

  • \( D_{a,b,c,d} = 2.2 * A_{b,d,a,c} + 1.3 * B_{c,b,d,a}\)

  • \( D_{a,b,c,d} = 2.2 * A_{b,d,a,c} + 1.3 * B_{c,b,d,a} + C_{a,b,c,d}\)

  • \( D_{a,b,c,d} = min((2.2 * A_{b,d,a,c} + 1.3 * B_{c,b,d,a}), C_{a,b,c,d})\)

调用 nvpltensorElementwiseTrinaryExecute 以执行实际操作。

请使用 nvpltensorDestroyOperationDescriptor 在不再使用描述符时将其释放。

支持的数据类型组合为

typeA

typeB

typeC

descCompute

NVPLTENSOR_R_32F

NVPLTENSOR_R_32F

NVPLTENSOR_R_32F

NVPLTENSOR_COMPUTE_DESC_32F

NVPLTENSOR_R_64F

NVPLTENSOR_R_64F

NVPLTENSOR_R_64F

NVPLTENSOR_COMPUTE_DESC_64F

NVPLTENSOR_C_32F

NVPLTENSOR_C_32F

NVPLTENSOR_C_32F

NVPLTENSOR_COMPUTE_DESC_32F

NVPLTENSOR_C_64F

NVPLTENSOR_C_64F

NVPLTENSOR_C_64F

NVPLTENSOR_COMPUTE_DESC_64F

备注

调用异步函数,不可重入,且线程安全

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • desc[out] 此不透明结构体将被分配并填充用于编码请求的逐元素操作的信息。

  • descA[in] 一个描述符,其中包含有关 A 的数据类型、模式和步幅的信息。

  • modeA[in] 大小为 descA->numModes 的数组,其中包含 A 的模式名称(例如,如果 \(A_{a,b,c}\) 则 modeA = {‘a’,’b’,’c’})。modeA[i] 对应于 extent[i] 和 stride[i],与提供给 nvpltensorCreateTensorDescriptor 的参数相关。

  • opA[in] 将在进一步处理之前应用于 A 的每个元素的一元运算符。此张量的原始数据保持不变。

  • descB[in] 一个描述符,其中包含有关 B 的数据类型、模式和步幅的信息。

  • modeB[in] 大小为 descB->numModes 的数组,其中包含 B 的模式名称。modeB[i] 对应于 nvpltensorCreateTensorDescriptor 的 extent[i] 和 stride[i]

  • opB[in] 将在进一步处理之前应用于 B 的每个元素的一元运算符。此张量的原始数据保持不变。

  • descC[in] 一个描述符,其中包含有关 C 的数据类型、模式和步幅的信息。

  • modeC[in] 大小为 descC->numModes 的数组,其中包含 C 的模式名称。modeC[i] 对应于 nvpltensorCreateTensorDescriptor 的 extent[i] 和 stride[i]。

  • opC[in] 将在进一步处理之前应用于 C 的每个元素的一元运算符。此张量的原始数据保持不变。

  • descD[in] 一个描述符,其中包含有关 D 的数据类型、模式和步幅的信息。请注意,我们目前要求 descD 和 descC 相同。

  • modeD[in] 大小为 descD->numModes 的数组,其中包含 D 的模式名称。modeD[i] 对应于 nvpltensorCreateTensorDescriptor 的 extent[i] 和 stride[i]。

  • opAB[in] 逐元素二元运算符(参见上面的 \(\Phi_{AB}\))。

  • opABC[in] 逐元素二元运算符(参见上面的 \(\Phi_{ABC}\))。

  • descCompute[in] 确定执行此操作的精度。

返回值:
  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。


nvpltensorElementwiseTrinaryExecute()#

nvpltensorStatus_t nvpltensorElementwiseTrinaryExecute(
const nvpltensorHandle_t handle,
const nvpltensorPlan_t plan,
const void *alpha,
const void *A,
const void *beta,
const void *B,
const void *gamma,
const void *C,
void *D,
)#

为三个输入张量执行逐元素张量运算(参见 nvpltensorCreateElementwiseTrinary

此函数执行以下形式的逐元素张量运算

\[ D_{\Pi^C(i_0,i_1,...,i_n)} = \Phi_{ABC}(\Phi_{AB}(\alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)}), \beta op_B(B_{\Pi^B(i_0,i_1,...,i_n)})), \gamma op_C(C_{\Pi^C(i_0,i_1,...,i_n)})) \]

有关详细信息,请参见 nvpltensorCreateElementwiseTrinary()

备注

调用异步函数,不可重入,且线程安全

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • plan[in] 持有有关所需逐元素运算的所有信息的不透明句柄(由 nvpltensorCreateElementwiseTrinary 后跟 nvpltensorCreatePlan 创建)。

  • alpha[in] 指向存储 A 的缩放因子的内存的指针(请参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE) 以查询预期的数据类型)。如果 alpha 为零,则不读取 A,并且不应用相应的一元运算符。

  • A[in] 指向存储多模张量的内存的指针(由 descAnvpltensorCreateElementwiseTrinary 中描述)。

  • beta[in] 指向存储 B 的缩放因子的内存的指针(请参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE) 以查询预期的数据类型)。如果 beta 为零,则不读取 B,并且不应用相应的一元运算符。

  • B[in] 指向存储多模张量的内存的指针(由 descBnvpltensorCreateElementwiseTrinary 中描述)。

  • gamma[in] 指向存储 C 的缩放因子的内存的指针(请参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE) 以查询预期的数据类型)。如果 gamma 为零,则不读取 C,并且不应用相应的一元运算符。

  • C[in] 指向存储多模张量的内存的指针(由 descCnvpltensorCreateElementwiseTrinary 中描述)。

  • D[out] 指向存储多模张量的内存的指针(由 descDnvpltensorCreateElementwiseTrinary 中描述)。如果 CD 相同,则仅当 descC == descD 时才可以。

返回值:
  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果不支持数据类型或操作的组合

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果张量维度或模式具有非法值

  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成,没有错误

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。


nvpltensorCreateElementwiseBinary()#

nvpltensorStatus_t nvpltensorCreateElementwiseBinary(
const nvpltensorHandle_t handle,
nvpltensorOperationDescriptor_t *desc,
const nvpltensorTensorDescriptor_t descA,
const int32_t modeA[],
nvpltensorOperator_t opA,
const nvpltensorTensorDescriptor_t descC,
const int32_t modeC[],
nvpltensorOperator_t opC,
const nvpltensorTensorDescriptor_t descD,
const int32_t modeD[],
nvpltensorOperator_t opAC,
const nvpltensorComputeDescriptor_t descCompute,
)#

此函数创建一个操作描述符,用于逐元素的二元运算。

二元运算具有以下通用形式

\[ D_{\Pi^C(i_0,i_1,...,i_n)} = \Phi_{AC}(\alpha \Psi_A(A_{\Pi^A(i_0,i_1,...,i_n)}), \gamma \Psi_C(C_{\Pi^C(i_0,i_1,...,i_n)})) \]

调用 nvpltensorElementwiseBinaryExecute 以执行实际操作。

支持的数据类型组合为

typeA

typeC

descCompute

NVPLTENSOR_R_32F

NVPLTENSOR_R_32F

NVPLTENSOR_COMPUTE_DESC_32F

NVPLTENSOR_R_64F

NVPLTENSOR_R_64F

NVPLTENSOR_COMPUTE_DESC_64F

NVPLTENSOR_C_32F

NVPLTENSOR_C_32F

NVPLTENSOR_COMPUTE_DESC_32F

NVPLTENSOR_C_64F

NVPLTENSOR_C_64F

NVPLTENSOR_COMPUTE_DESC_64F

备注

调用异步函数,不可重入,且线程安全

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • desc[out] 此不透明结构体将被分配并填充用于编码请求的逐元素操作的信息。

  • descA[in] 描述符,其中包含有关 A 的数据类型、模式和步幅的信息。

  • modeA[in] 大小为 descA->numModes 的数组,其中包含 A 的模式名称(例如,如果 A_{a,b,c} => modeA = {‘a’,’b’,’c’})。modeA[i] 对应于 extent[i] 和 stride[i],与提供给 nvpltensorCreateTensorDescriptor 的参数相关。

  • opA[in] 将在进一步处理之前应用于 A 的每个元素的一元运算符。此张量的原始数据保持不变。

  • descC[in] 描述符,其中包含有关 C 的数据类型、模式和步幅的信息。

  • modeC[in] 大小为 descC->numModes 的数组,其中包含 C 的模式名称。modeC[i] 对应于 nvpltensorCreateTensorDescriptor 的 extent[i] 和 stride[i]。

  • opC[in] 将在进一步处理之前应用于 C 的每个元素的一元运算符。此张量的原始数据保持不变。

  • descD[in] 描述符,其中包含有关 D 的数据类型、模式和步幅的信息。请注意,我们目前要求 descD 和 descC 相同。

  • modeD[in] 大小为 descD->numModes 的数组,其中包含 D 的模式名称。modeD[i] 对应于 nvpltensorCreateTensorDescriptor 的 extent[i] 和 stride[i]。

  • opAC[in] 逐元素二元运算符(参见上面的 \(\Phi_{AC}\))。

  • descCompute[in] 确定执行此操作的精度。

返回值:
  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果不支持数据类型或操作的组合

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果张量维度或模式具有非法值

  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成,没有错误

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。


nvpltensorElementwiseBinaryExecute()#

nvpltensorStatus_t nvpltensorElementwiseBinaryExecute(
const nvpltensorHandle_t handle,
const nvpltensorPlan_t plan,
const void *alpha,
const void *A,
const void *gamma,
const void *C,
void *D,
)#

对两个输入张量执行逐元素张量运算 (参见 nvpltensorCreateElementwiseBinary)

此函数执行以下形式的逐元素张量运算

\[ D_{\Pi^C(i_0,i_1,...,i_n)} = \Phi_{AC}(\alpha \Psi_A(A_{\Pi^A(i_0,i_1,...,i_n)}), \gamma \Psi_C(C_{\Pi^C(i_0,i_1,...,i_n)})) \]

详情请参见 nvpltensorCreateElementwiseBinary()

备注

调用异步函数,不可重入,且线程安全

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • plan[in] 不透明句柄,包含有关所需逐元素运算的所有信息(由 nvpltensorCreateElementwiseBinary 后跟 nvpltensorCreatePlan 创建)。

  • alpha[in] 指向存储 A 的缩放因子的内存的指针(请参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE) 以查询预期的数据类型)。如果 alpha 为零,则不读取 A,并且不应用相应的一元运算符。

  • A[in] 指向存储多模张量的内存的指针(由 descAnvpltensorCreateElementwiseBinary 中描述)。

  • gamma[in] 指向存储 C 的缩放因子的内存的指针(请参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE) 以查询预期的数据类型)。如果 gamma 为零,则不读取 C,并且不应用相应的一元运算符。

  • C[in] 指向存储多模张量的内存的指针(由 descCnvpltensorCreateElementwiseBinary 中描述)。

  • D[out] 指向存储多模张量的内存的指针(由 descDnvpltensorCreateElementwiseBinary 中描述)。 如果 descC == descD,则 CD 可以相同,且仅当这种情况成立。

返回值:
  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果不支持数据类型或操作的组合

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果张量维度或模式具有非法值

  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成,没有错误

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。


nvpltensorCreatePermutation()#

nvpltensorStatus_t nvpltensorCreatePermutation(
const nvpltensorHandle_t handle,
nvpltensorOperationDescriptor_t *desc,
const nvpltensorTensorDescriptor_t descA,
const int32_t modeA[],
nvpltensorOperator_t opA,
const nvpltensorTensorDescriptor_t descB,
const int32_t modeB[],
const nvpltensorComputeDescriptor_t descCompute,
)#

此函数创建一个用于张量置换的运算描述符。

张量置换具有以下通用形式

\[ B_{\Pi^B(i_0,i_1,...,i_n)} = \alpha op_A(A_{\Pi^A(i_0,i_1,...,i_n)}) \]

因此,此函数执行异地张量置换,并且是 nvpltensorCreateElementwiseBinary 的一种特例。

其中

  • A 和 B 是多模张量(具有任意数据类型),

  • \(\Pi^A, \Pi^B\) 是分别置换 A、B 模的置换运算符,

  • \(op_A\) 是一元逐元素运算符(例如,IDENTITY、SQR、CONJUGATE),以及

  • \(\Psi\) 在张量描述符 descA 中指定。

广播(一个模)可以通过简单地从各自的张量中省略该模来实现。

模可以以任何顺序出现。唯一的限制

  • 出现在 A 中的模必须也出现在输出张量中。

  • 每个模式在每个张量中最多出现一次。

支持的数据类型组合为

typeA

typeB

descCompute

NVPLTENSOR_R_32F

NVPLTENSOR_R_32F

NVPLTENSOR_COMPUTE_DESC_32F

NVPLTENSOR_R_64F

NVPLTENSOR_R_64F

NVPLTENSOR_COMPUTE_DESC_64F

NVPLTENSOR_C_32F

NVPLTENSOR_C_32F

NVPLTENSOR_COMPUTE_DESC_32F

NVPLTENSOR_C_64F

NVPLTENSOR_C_64F

NVPLTENSOR_COMPUTE_DESC_64F

备注

调用异步函数,不可重入,且线程安全

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • desc[out] 此不透明结构将被分配并填充用于编码所请求置换的信息。

  • descA[in] 描述符,包含有关 A 的数据类型、模和步幅的信息。

  • modeA[in] 大小为 descA->numModes 的数组,其中包含 A 的模的名称(例如,如果 A_{a,b,c} => modeA = {‘a’,’b’,’c’})

  • opA[in] 将在进一步处理之前应用于 A 的每个元素的一元运算符。此张量的原始数据保持不变。

  • descB[in] 描述符,包含有关 B 的数据类型、模和步幅的信息。

  • modeB[in] 大小为 descB->numModes 的数组,其中包含 B 的模的名称

  • descCompute[in] 确定执行此操作的精度。

返回值:
  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果不支持数据类型或操作的组合

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果张量维度或模式具有非法值

  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成,没有错误

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。


nvpltensorPermute()#

nvpltensorStatus_t nvpltensorPermute(
const nvpltensorHandle_t handle,
const nvpltensorPlan_t plan,
const void *alpha,
const void *A,
void *B,
)#

执行由 plan 编码的张量置换(参见 nvpltensorCreatePermutation)。

此函数执行以下形式的逐元素张量运算

\[ B_{\Pi^B(i_0,i_1,...,i_n)} = \alpha \Psi(A_{\Pi^A(i_0,i_1,...,i_n)}) \]

因此,此函数执行异地张量置换。

其中

  • A 和 B 是多模张量(具有任意数据类型),

  • \(\Pi^A, \Pi^B\) 是分别置换 A、B 模的置换运算符,

  • \(\Psi\) 是一元逐元素运算符(例如,IDENTITY、SQR、CONJUGATE),以及

  • \(\Psi\) 在张量描述符 descA 中指定。

备注

调用异步函数,不可重入,且线程安全

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • plan[in] 不透明句柄,包含有关所需张量归约的所有信息(由 nvpltensorCreatePermutation 后跟 nvpltensorCreatePlan 创建)。

  • alpha[in] 指向存储 A 的缩放因子的内存的指针(参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE))。 如果 alpha 为零,则不读取 A,并且不应用相应的单目运算符。

  • A[in] 指向存储多模张量的内存的指针(由 descAnvpltensorCreatePermutation 中描述)。

  • B[inout] 指向存储多模张量的内存的指针(由 descBnvpltensorCreatePermutation 中描述)。

返回值:
  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果不支持数据类型或操作的组合

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果张量维度或模式具有非法值

  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成,没有错误

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。


缩并运算#

以下函数执行张量之间的缩并。


nvpltensorCreateContraction()#

nvpltensorStatus_t nvpltensorCreateContraction(
const nvpltensorHandle_t handle,
nvpltensorOperationDescriptor_t *desc,
const nvpltensorTensorDescriptor_t descA,
const int32_t modeA[],
nvpltensorOperator_t opA,
const nvpltensorTensorDescriptor_t descB,
const int32_t modeB[],
nvpltensorOperator_t opB,
const nvpltensorTensorDescriptor_t descC,
const int32_t modeC[],
nvpltensorOperator_t opC,
const nvpltensorTensorDescriptor_t descD,
const int32_t modeD[],
const nvpltensorComputeDescriptor_t descCompute,
)#

此函数分配一个 nvpltensorOperationDescriptor_t 对象,该对象编码 \( D = \alpha \mathcal{A} \mathcal{B} + \beta \mathcal{C} \) 形式的张量缩并。

desc 分配数据,用于执行以下形式的张量缩并

\[ \mathcal{D}_{{modes}_\mathcal{D}} \gets \alpha op_\mathcal{A}(\mathcal{A}_{{modes}_\mathcal{A}}) op_\mathcal{B}(B_{{modes}_\mathcal{B}}) + \beta op_\mathcal{C}(\mathcal{C}_{{modes}_\mathcal{C}}). \]

请参见 nvpltensorCreatePlan(或 nvpltensorCreatePlanAutotuned)以创建计划(即,选择内核),然后调用 nvpltensorContract 以执行实际缩并。

用户负责调用 nvpltensorDestroyOperationDescriptor 以释放与描述符关联的资源。

支持的数据类型组合为

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • desc[out] 此不透明结构将被分配并填充用于编码张量缩并运算的信息。

  • descA[in] 描述符,包含有关 A 的数据类型、模和步幅的信息。

  • modeA[in] 包含 ‘nmodeA’ 个条目的数组,表示 A 的模。 modeA[i] 对应于 extent[i] 和 stride[i],与提供给 nvpltensorInitTensorDescriptor 的参数相关。

  • opA[in] 将在进一步处理之前应用于 A 的每个元素的一元运算符。此张量的原始数据保持不变。

  • descB[in] 描述符,包含有关 B 的数据类型、模和步幅的信息。

  • modeB[in] 包含 ‘nmodeB’ 个条目的数组,表示 B 的模。 modeB[i] 对应于 extent[i] 和 stride[i],与提供给 nvpltensorInitTensorDescriptor 的参数相关。

  • opB[in] 将在进一步处理之前应用于 B 的每个元素的一元运算符。此张量的原始数据保持不变。

  • modeC[in] 包含 ‘nmodeC’ 个条目的数组,表示 C 的模。 modeC[i] 对应于 extent[i] 和 stride[i],与提供给 nvpltensorInitTensorDescriptor 的参数相关。

  • descC[in] 描述符,包含有关 C 的数据类型、模和步幅的信息。

  • opC[in] 将在进一步处理之前应用于 C 的每个元素的一元运算符。此张量的原始数据保持不变。

  • modeD[in] 包含 ‘nmodeD’ 个条目的数组,表示 D 的模(目前必须与 modeC 相同)。 modeD[i] 对应于 extent[i] 和 stride[i],与提供给 nvpltensorInitTensorDescriptor 的参数相关。

  • descD[in] 描述符,包含有关 D 的数据类型、模和步幅的信息(目前必须与 descC 相同)。

  • descCompute[in] 用于 A * B 中间计算的数据类型 typeCompute T。

返回值:
  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果不支持数据类型或操作的组合

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果张量维度或模式具有非法值

  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成,没有错误

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。


nvpltensorContract()#

nvpltensorStatus_t nvpltensorContract(
const nvpltensorHandle_t handle,
const nvpltensorPlan_t plan,
const void *alpha,
const void *A,
const void *B,
const void *beta,
const void *C,
void *D,
void *workspace,
uint64_t workspaceSize,
)#

此例程计算张量缩并 \( D = alpha * A * B + beta * C \)

\[ \mathcal{D}_{{modes}_\mathcal{D}} \gets \alpha * \mathcal{A}_{{modes}_\mathcal{A}} B_{{modes}_\mathcal{B}} + \beta \mathcal{C}_{{modes}_\mathcal{C}} \]

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • plan[in] 不透明句柄,包含缩并执行计划(由 nvpltensorCreateContraction 后跟 nvpltensorCreatePlan 创建)。

  • alpha[in] 指向存储 A*B 缩放因子的内存的指针。 其数据类型由 ‘descCompute’ 确定(参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE))。

  • A[in] 指向存储多模张量的内存的指针(由 descAnvpltensorCreateContraction 中描述)。

  • B[in] 指向存储多模张量的内存的指针(由 descBnvpltensorCreateContraction 中描述)。

  • beta[in] C 的缩放因子。 其数据类型由 ‘descCompute’ 确定(参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE))。 指向主机内存的指针。

  • C[in] 指向存储多模张量的内存的指针(由 descCnvpltensorCreateContraction 中描述)。

  • D[out] 指向存储多模张量的内存的指针(由 descDnvpltensorCreateContraction 中描述)。 如果 descC == descD,则 CD 可以相同,且仅当这种情况成立。

  • workspace[out] 可选参数,可以为 NULL。 此指针为库提供额外的workspace,以进行额外的优化; workspace必须对齐到 256 字节。

  • workspaceSize[in] workspace数组的大小(以字节为单位); 请参阅 nvpltensorEstimateWorkspaceSize 以查询所需的workspace。 虽然 nvpltensorContract 严格来说不需要workspace来进行缩并,但仍然建议提供一些小的workspace(例如,128 MB)。

返回值:
  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果不支持该操作。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。

  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。


归约运算#

以下函数执行张量归约。


nvpltensorCreateReduction()#

nvpltensorStatus_t nvpltensorCreateReduction(
const nvpltensorHandle_t handle,
nvpltensorOperationDescriptor_t *desc,
const nvpltensorTensorDescriptor_t descA,
const int32_t modeA[],
nvpltensorOperator_t opA,
const nvpltensorTensorDescriptor_t descC,
const int32_t modeC[],
nvpltensorOperator_t opC,
const nvpltensorTensorDescriptor_t descD,
const int32_t modeD[],
nvpltensorOperator_t opReduce,
const nvpltensorComputeDescriptor_t descCompute,
)#

创建 nvpltensorOperatorDescriptor_t 对象,该对象编码 \( D = alpha * opReduce(opA(A)) + beta * opC(C) \) 形式的张量归约。

例如,此函数使用户能够将整个张量归约为标量:C[] = alpha * A[i,j,k];

此函数还能够执行部分归约;例如:C[i,j] = alpha * A[k,j,i]; 在这种情况下,仅沿着 k 模的元素被缩并。

二元 opReduce 运算符提供对应该执行哪种归约的额外控制。 例如,将 opReduce 设置为 NVPLTENSOR_OP_ADD 通过求和来归约 A 的元素,而 NVPLTENSOR_OP_MAX 将找到 A 中的最大元素。

支持的数据类型组合为

typeA

typeB

typeC

typeCompute

NVPLTENSOR_R_32F

NVPLTENSOR_R_32F

NVPLTENSOR_R_32F

NVPLTENSOR_COMPUTE_DESC_32F

NVPLTENSOR_R_64F

NVPLTENSOR_R_64F

NVPLTENSOR_R_64F

NVPLTENSOR_COMPUTE_DESC_64F

NVPLTENSOR_C_32F

NVPLTENSOR_C_32F

NVPLTENSOR_C_32F

NVPLTENSOR_COMPUTE_DESC_32F

NVPLTENSOR_C_64F

NVPLTENSOR_C_64F

NVPLTENSOR_C_64F

NVPLTENSOR_COMPUTE_DESC_64F

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • desc[out] 此不透明结构将被分配并填充用于编码所请求张量归约运算的信息。

  • descA[in] 描述符,包含有关 A 的数据类型、模和步幅的信息。

  • modeA[in] 包含 ‘nmodeA’ 个条目的数组,表示 A 的模。 modeA[i] 对应于 extent[i] 和 stride[i],与提供给 nvpltensorCreateTensorDescriptor 的参数相关。 仅出现在 modeA 中而未出现在 modeC 中的模被归约(缩并)。

  • opA[in] 将在进一步处理之前应用于 A 的每个元素的一元运算符。此张量的原始数据保持不变。

  • descC[in] 描述符,包含有关 C 的数据类型、模和步幅的信息。

  • modeC[in] 包含 ‘nmodeC’ 个条目的数组,表示 C 的模。 modeC[i] 对应于 extent[i] 和 stride[i],与提供给 nvpltensorCreateTensorDescriptor 的参数相关。

  • opC[in] 将在进一步处理之前应用于 C 的每个元素的一元运算符。此张量的原始数据保持不变。

  • descD[in] 目前必须与 descC 相同。

  • modeD[in] 目前必须与 modeC 相同。

  • opReduce[in] 用于归约 A 元素的二元运算符。

  • typeCompute[in] 所有算术运算都使用此数据类型执行(即,它会影响精度和性能)。

返回值:
  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果不支持该操作。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。

  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。


nvpltensorReduce()#

nvpltensorStatus_t nvpltensorReduce(
const nvpltensorHandle_t handle,
const nvpltensorPlan_t plan,
const void *alpha,
const void *A,
const void *beta,
const void *C,
void *D,
void *workspace,
uint64_t workspaceSize,
)#

执行由 plan 编码的张量归约(参见 nvpltensorCreateReduction)。

参数:
  • alpha[in] 指向存储 A 的缩放因子的内存的指针。 其数据类型由 ‘descCompute’ 确定(参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE))。

  • A[in] 指向存储多模张量的内存的指针(由 descAnvpltensorCreateReduction 中描述)。

  • beta[in] 指向存储 C 的缩放因子的内存的指针。 其数据类型由 ‘descCompute’ 确定(参见 nvpltensorOperationDescriptorGetAttribute(desc, NVPLTENSOR_OPERATION_SCALAR_TYPE))。

  • C[in] 指向存储多模张量的内存的指针(由 descCnvpltensorCreateReduction 中描述)。

  • D[out] 指向存储多模张量的内存的指针(由 descDnvpltensorCreateReduction 中描述)。

  • workspace[out] 大小(至少)为 workspaceSize 字节的暂存内存; workspace必须对齐到 256 字节。

  • workspaceSize[in] 请使用 nvpltensorEstimateWorkspaceSize() 查询所需的workspace。

返回值:

NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。


通用运算函数#

以下函数是通用的,适用于所有不同的运算。


nvpltensorDestroyOperationDescriptor()#

nvpltensorStatus_t nvpltensorDestroyOperationDescriptor(
nvpltensorOperationDescriptor_t desc,
)#

释放与提供的描述符相关的所有资源。

备注

阻塞,不可重入,且线程安全

参数:

desc[inout] 将被释放的 nvpltensorOperationDescriptor_t 对象。

返回值:

NVPLTENSOR_STATUS_SUCCESS – 成功时返回此值,否则返回错误代码


nvpltensorOperationDescriptorGetAttribute()#

nvpltensorStatus_t nvpltensorOperationDescriptorGetAttribute(
const nvpltensorHandle_t handle,
nvpltensorOperationDescriptor_t desc,
nvpltensorOperationDescriptorAttribute_t attr,
void *buf,
size_t sizeInBytes,
)#

此函数检索提供的 nvpltensorOperationDescriptor_t 对象的属性(参见 nvpltensorOperationDescriptorAttribute_t)。

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • desc[in] 要查询其属性的 nvpltensorOperationDescriptor_t 对象。

  • attr[in] 指定要检索的属性。

  • buf[out] 此缓冲区(大小为 sizeInBytes)将保存提供的 nvpltensorOperationDescriptor_t 对象的请求属性。

  • sizeInBytes[in] buf 的大小(以字节为单位); 有关确切大小,请参见 nvpltensorOperationDescriptorAttribute_t

返回值:
  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。


nvpltensorOperationDescriptorSetAttribute()#

nvpltensorStatus_t nvpltensorOperationDescriptorSetAttribute(
const nvpltensorHandle_t handle,
nvpltensorOperationDescriptor_t desc,
nvpltensorOperationDescriptorAttribute_t attr,
const void *buf,
size_t sizeInBytes,
)#

设置 nvpltensorOperationDescriptor_t 对象的属性。

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • desc[inout] 将被修改的运算描述符。

  • attr[in] 指定要设置的属性。

  • buf[in] 此缓冲区(大小为 sizeInBytes)确定 attr 将被设置的值。

  • sizeInBytes[in] buf 的大小(以字节为单位)。

返回值:
  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。


nvpltensorCreatePlanPreference()#

nvpltensorStatus_t nvpltensorCreatePlanPreference(
const nvpltensorHandle_t handle,
nvpltensorPlanPreference_t *pref,
nvpltensorAlgo_t algo,
nvpltensorJitMode_t jitMode,
)#

分配 nvpltensorPlanPreference_t,使用户能够限制给定计划/运算的适用内核。

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • pref[out] 指向由此函数分配的 nvpltensorPlanPreference_t 结构的指针。 参见 nvpltensorPlanPreference_t

  • algo[in] 允许用户选择特定的算法。 NVPLTENSOR_ALGO_DEFAULT 让启发式算法选择算法。 任何值 >= 0 选择特定的类 GEMM 算法,并停用启发式算法。 如果指定算法不受支持,则返回 NVPLTENSOR_STATUS_NOT_SUPPORTED。 有关其他选择,请参见 nvpltensorAlgo_t

  • jitMode[in] 确定是否允许 nvplTENSOR 使用 JIT 编译的内核(导致更长的计划创建阶段); 参见 nvpltensorJitMode_t


nvpltensorDestroyPlanPreference()#

nvpltensorStatus_t nvpltensorDestroyPlanPreference(
nvpltensorPlanPreference_t pref,
)#

释放与提供的首选项相关的所有资源。

备注

阻塞,不可重入,且线程安全

参数:

pref[inout] 将被释放的 nvpltensorPlanPreference_t 对象。

返回值:

NVPLTENSOR_STATUS_SUCCESS – 成功时返回此值,否则返回错误代码


nvpltensorPlanPreferenceSetAttribute()#

nvpltensorStatus_t nvpltensorPlanPreferenceSetAttribute(
const nvpltensorHandle_t handle,
nvpltensorPlanPreference_t pref,
nvpltensorPlanPreferenceAttribute_t attr,
const void *buf,
size_t sizeInBytes,
)#

设置 nvpltensorPlanPreference_t 对象的属性。

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • pref[inout] 此不透明结构体限制了可行候选项的搜索空间。

  • attr[in] 指定要设置的属性。

  • buf[in] 此缓冲区(大小为 sizeInBytes)决定了 attr 将被设置成的值。

  • sizeInBytes[in] buf 的大小(以字节为单位);有关确切大小,请参阅 nvpltensorPlanPreferenceAttribute_t

返回值:
  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。


nvpltensorEstimateWorkspaceSize()#

nvpltensorStatus_t nvpltensorEstimateWorkspaceSize(
const nvpltensorHandle_t handle,
const nvpltensorOperationDescriptor_t desc,
const nvpltensorPlanPreference_t planPref,
const nvpltensorWorksizePreference_t workspacePref,
uint64_t *workspaceSizeEstimate,
)#

确定由 desc 编码的给定操作所需的 workspaceSize。

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • desc[in] 此不透明结构体编码了操作。

  • planPref[in] 此不透明结构体限制了可行候选项的空间。

  • workspacePref[in] 此参数影响工作区的大小;有关详细信息,请参阅 nvpltensorWorksizePreference_t

  • workspaceSizeEstimate[out] 给定操作所需的工作区大小(以字节为单位)。

返回值:
  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。


nvpltensorCreatePlan()#

nvpltensorStatus_t nvpltensorCreatePlan(
const nvpltensorHandle_t handle,
nvpltensorPlan_t *plan,
const nvpltensorOperationDescriptor_t desc,
const nvpltensorPlanPreference_t pref,
uint64_t workspaceSizeLimit,
)#

此函数分配一个 nvpltensorPlan_t 对象,为给定操作(由 desc 编码)选择合适的内核,并准备一个编码执行计划。

此函数应用 nvplTENSOR 的启发式方法,为给定操作(通过 nvpltensorCreateContractionnvpltensorCreateReductionnvpltensorCreatePermutationnvpltensorCreateElementwiseBinarynvpltensorCreateElementwiseTrinary 创建)选择候选/内核。然后,可以将创建的计划传递给 nvpltensorContractnvpltensorReducenvpltensorPermutenvpltensorElementwiseBinaryExecutenvpltensorElementwiseTrinaryExecute 以执行实际操作。

参数:
返回值:
  • NVPLTENSOR_STATUS_SUCCESS – 如果找到了可行的候选项。

  • NVPLTENSOR_STATUS_NOT_SUPPORTED – 如果未找到可行的候选项。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。

  • NVPLTENSOR_STATUS_INSUFFICIENT_WORKSPACE – 如果提供的工作区不足。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。


nvpltensorDestroyPlan()#

nvpltensorStatus_t nvpltensorDestroyPlan(nvpltensorPlan_t plan)#

释放与提供的计划相关的所有资源。

备注

阻塞,不可重入,且线程安全

参数:

plan[inout] 将被释放的 nvpltensorPlan_t 对象。

返回值:

NVPLTENSOR_STATUS_SUCCESS – 成功时返回此值,否则返回错误代码


nvpltensorPlanGetAttribute()#

nvpltensorStatus_t nvpltensorPlanGetAttribute(
const nvpltensorHandle_t handle,
const nvpltensorPlan_t plan,
nvpltensorPlanAttribute_t attr,
void *buf,
size_t sizeInBytes,
)#

检索有关已创建计划的信息(请参阅 nvpltensorPlanAttribute_t

参数:
  • plan[in] 表示已创建的计划(例如,通过 nvpltensorCreatePlan 或 nvpltensorCreatePlanAutotuned)

  • attr[in] 请求的属性。

  • buf[out] 成功退出时:保存请求属性的信息。

  • sizeInBytes[in] buf 的大小(以字节为单位)。

返回值:
  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。


nvpltensorPlanPreferenceSetAttribute()#

nvpltensorStatus_t nvpltensorPlanPreferenceSetAttribute(
const nvpltensorHandle_t handle,
nvpltensorPlanPreference_t pref,
nvpltensorPlanPreferenceAttribute_t attr,
const void *buf,
size_t sizeInBytes,
)

设置 nvpltensorPlanPreference_t 对象的属性。

参数:
  • handle[in] 持有 nvplTENSOR 库上下文的不透明句柄。

  • pref[inout] 此不透明结构体限制了可行候选项的搜索空间。

  • attr[in] 指定要设置的属性。

  • buf[in] 此缓冲区(大小为 sizeInBytes)决定了 attr 将被设置成的值。

  • sizeInBytes[in] buf 的大小(以字节为单位);有关确切大小,请参阅 nvpltensorPlanPreferenceAttribute_t

返回值:
  • NVPLTENSOR_STATUS_SUCCESS – 操作成功完成。

  • NVPLTENSOR_STATUS_NOT_INITIALIZED – 如果句柄未初始化。

  • NVPLTENSOR_STATUS_INVALID_VALUE – 如果某些输入数据无效(这通常表示用户错误)。


Logger Functions#

nvpltensorLoggerSetCallback()#

nvpltensorStatus_t nvpltensorLoggerSetCallback(
nvpltensorLoggerCallback_t callback,
)#

此函数设置日志记录回调例程。

参数:

callback[in] 指向回调函数的指针。检查 nvpltensorLoggerCallback_t。


nvpltensorLoggerSetFile()#

nvpltensorStatus_t nvpltensorLoggerSetFile(FILE *file)#

此函数设置日志记录输出文件。

参数:

file[in] 具有写入权限的打开文件。


nvpltensorLoggerOpenFile()#

nvpltensorStatus_t nvpltensorLoggerOpenFile(const char *logFile)#

此函数在给定路径中打开日志记录输出文件。

参数:

logFile[in] 日志记录输出文件的路径。


nvpltensorLoggerSetLevel()#

nvpltensorStatus_t nvpltensorLoggerSetLevel(int32_t level)#

此函数设置日志记录级别的数值。

参数:

level[in]

日志级别,应为以下值之一

  • 0. 关闭

  • 1. 错误

  • 2. 性能跟踪

  • 3. 性能提示

  • 4. 启发式跟踪

  • 5. API 跟踪


nvpltensorLoggerSetMask()#

nvpltensorStatus_t nvpltensorLoggerSetMask(int32_t mask)#

此函数设置日志掩码的值。

参数:

mask[in]

日志掩码,以下各项的按位或

  • 0. 关闭

  • 1. 错误

  • 2. 性能跟踪

  • 4. 性能提示

  • 8. 启发式跟踪

  • 16. API 跟踪


nvpltensorLoggerForceDisable()#

nvpltensorStatus_t nvpltensorLoggerForceDisable()#

此函数禁用整个运行过程的日志记录。