6. mcdnn_adv_infer
此实体包含所有其他功能与算法。包括循环神经网络(Rerrent Neural Network,RNN),CTC损失(CTC Loss)和多头注意力机制(Multi-Head Attention)。mcdnn_adv_infer库依赖于mcdnn_ops_infer。
6.1. 数据类型参考
以下为mcdnn_adv_infer.h中的数据类型参考。
6.1.1. 不透明结构类型的指针
这些是指向mcdnn_adv_infer.h中不透明结构类型的指针。
6.1.1.1. mcdnnAttnDescriptor_t
mcdnnAttnDescriptor_t是一个指针,指向包含多头注意力层的参数的不透明结构,例如:
权重和bias张量形状(线性投影前后的向量长度)
在调用函数来求正向响应和梯度的值时可以提前设置且不会更改的参数(注意力头数,softmax平滑/锐化系数)
计算临时缓冲区大小所需的其他设置。
使用mcdnnCreateAttnDescriptor()函数创建注意力描述符对象的实例,使用mcdnnDestroyAttnDescriptor()删除已创建的描述符。使用mcdnnSetAttnDescriptor()函数配置描述符。
6.1.1.2. mcdnnPersistentRNNPlan_t
mcdnnPersistentRNNPlan_t是指向不透明结构的指针,该结构包含执行动态持久RNN的plan。 mcdnnCreatePersistentRNNPlan()用于创建和初始化一个实例。
6.1.1.3. mcdnnRNNDataDescriptor_t
mcdnnRNNDataDescriptor_t是指向不透明结构的指针,该结构包含RNN数据集描述。mcdnnCreateRNNDataDescriptor()函数用于创建一个实例,且必须使用mcdnnSetRNNDataDescriptor()初始化该实例。
6.1.1.4. mcdnnRNNDescriptor_t
mcdnnRNNDescriptor_t是指向不透明结构的指针,该结构包含RNN操作的说明。mcdnnCreateRNNDescriptor()用于创建实例。
6.1.1.5. mcdnnSeqDataDescriptor_t
mcdnnSeqDataDescriptor_t是一个指针,指向包含序列数据容器或缓冲区参数的不透明结构。序列数据容器用于存储由VECT维定义的固定大小的向量。向量排列于另外三个维度:TIME,BATCH和BEAM。 TIME维用于将向量捆绑到向量序列中。实际序列可以短于TIME维,因此需要有关每个序列长度以及如何保存未使用(填充)向量的附加信息。
假定序列数据容器已完全压缩。当向量按地址的升序排布时,TIME、BATCH、BEAM维可以按任何顺序排列。可以使用六种数据布局(TIME、BATCH和BEAM的排列)。
mcdnnSeqDataDescriptor_t对象包含以下参数:
向量使用的数据类型
TIME、BATCH、BEAM和VECT维度
数据布局
沿TIME维度的每个序列的长度
要复制到输出填充向量的可选值
使用mcdnnCreateSeqDataDescriptor()函数创建序列数据描述符对象的实例,使用mcdnnDestroySeqDataDescriptor()删除已创建的描述符。使用mcdnnSetSeqDataDescriptor()函数配置描述符。
多头注意力API函数使用此描述符。
6.1.2. 枚举类型
以下为mcdnn_adv_infer.h中的枚举类型。
6.1.2.1. mcdnnDirectionMode_t
mcdnnDirectionMode_t是一种枚举类型,用于指定mcdnnRNNForwardInference(),mcdnnRNNForwardTrain(),mcdnnRNNBackwardData()和mcdnnRNNBackwardWeights()函数中的循环模式。
值
MCDNN_UNIDIRECTIONAL
网络从第一个输入循环迭代到最后一个输入。
MCDNN_BIDIRECTIONAL
网络的每一层都分别从第一个输入循环迭代到最后一个输入,并从最后一个输入迭代到第一个输入。两个输出在每次迭代时连接,提供层的输出。
6.1.2.2. mcdnnForwardMode_t
mcdnnForwardMode_t是一种枚举类型,指定RNN API中的推理或训练模式。此参数允许mcDNN库更精确地调整工作空间缓冲区的大小,该缓冲区的推理和训练方案可能不同。
值
MCDNN_FWD_MODE_INFERENCE
选择推理模式。
MCDNN_FWD_MODE_TRAINING
选择训练模式。
6.1.2.3. mcdnnMultiHeadAttnWeightKind_t
mcdnnMultiHeadAttnWeightKind_t是一种枚举类型,用于指定mcdnnGetMultiHeadAttnWeight()函数中的一组权重或bias。
值
MCDNN_MH_ATTN_Q_WEIGHTS
选择查询的输入投影权重。
MCDNN_MH_ATTN_K_WEIGHTS
选择键的输入投影权重。
MCDNN_MH_ATTN_V_WEIGHTS
选择值的输入投影权重。
MCDNN_MH_ATTN_O_WEIGHTS
选择输出投影权重。
MCDNN_MH_ATTN_Q_BIASES
选择查询的输入投影bias。
MCDNN_MH_ATTN_K_BIASES
选择键的输入投影bias。
MCDNN_MH_ATTN_V_BIASES
选择值的输入投影bias。
MCDNN_MH_ATTN_O_BIASES
选择输出投影权重。
6.1.2.4. mcdnnRNNBiasMode_t
mcdnnRNNBiasMode_t是一种枚举类型,用于指定RNN函数的bias向量数。有关基于bias模式的每个神经元类型的公式,请参见mcdnnRNNMode_t枚举类型的描述。
值
MCDNN_RNN_NO_BIAS
应用不使用bias的RNN单元(cell)公式。
MCDNN_RNN_SINGLE_INP_BIAS
应用在输入GEMM中使用一个输入bias向量的RNN单元公式。
MCDNN_RNN_DOUBLE_BIAS
应用使用两个bias向量的RNN单元公式。
MCDNN_RNN_SINGLE_REC_BIAS
应用在循环GEMM中使用一个循环bias向量的RNN单元公式。
6.1.2.5. mcdnnRNNClipMode_t
mcdnnRNNClipMode_t是用于选择LSTM单元裁剪(cell clipping)模式的枚举类型。它与mcdnnRNNSetClim()、mcdnnRNGetClim()函数一起在LSTM单元内部使用。
值
MCDNN_RNN_CLIP_NONE
禁用LSTM单元裁剪。
MCDNN_RNN_CLIP_MINMAX
启用LSTM单元裁剪。
6.1.2.6. mcdnnRNNDataLayout_t
mcdnnRNNDataLayout_t是用于选择RNN数据布局的枚举类型。它用于mcdnnGetRNNDataDescriptor()和mcdnnSetRNNDataDescriptor() API调用。
值
MCDNN_RNN_DATA_LAYOUT_SEQ_MAJOR_UNPACKED
使用从一个时间步(time-step)到下一个时间步的外部步幅,来填充数据布局。
MCDNN_RNN_DATA_LAYOUT_SEQ_MAJOR_PACKED
序列长度按基本RNN API中的顺序进行排序和填充。
MCDNN_RNN_DATA_LAYOUT_BATCH_MAJOR_UNPACKED
使用从一个batch到下一个batch的外部步幅,来填充数据布局。
6.1.2.7. mcdnnRNNInputMode_t
mcdnnRNNInputMode_t是一种枚举类型,用于指定mcdnnRNNForwardInference(),mcdnnRNNForwardTrain(),mcdnnRNNBackwardData()和mcdnnRNNBackwardWeights()函数中第一层的行为。
值
MCDNN_LINEAR_INPUT
对第一个循环层的输入执行矩阵乘法加bias。
MCDNN_SKIP_INPUT
不对第一个循环层的输入执行任何操作。如果使用MCDNN_SKIP_INPUT,则输入张量的前导维度(leading dimension)必须等于网络的隐藏状态大小。
6.1.2.8. mcdnnRNNMode_t
mcdnnRNNMode_t是一种枚举类型,用于指定mcdnnRNNForwardInference(),mcdnnRNNForwardTrain(),mcdnnRNNBackwardData()和mcdnnRNNBackwardWeights()函数中使用的网络类型。
值
MCDNN_RNN_RELU
具有ReLU激活函数的单门控循环神经网络。
在正向传递中,给定迭代的输出 \(h_{t}\) 可以从循环输入 \(h_{t - 1}\) 和上一层输入 \(x_{t}\) 计算得到,给定矩阵
W,R和bias向量, 其中 \({ReLU}\ (x)\ = \ \max\ ({x,\ 0})\)。 . 如果rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_DOUBLE_BIAS(默认模式),则应用以下带有 \(b_{W}\) 和 \(b_{R}\) bias的方程式:\(h_{t}\ = \ {ReLU}\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}\ + \ b_{Wi}\ + \ b_{Ri}} \right)\)
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_SINGLE_INP_BIAS或MCDNN_RNN_SINGLE_REC_BIAS,则应用以下带有 bb bias的方程式:\(h_{t}\ = \ {ReLU}\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}\ + \ b_{i}} \right)\)
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_NO_BIAS,则应用以下方程式:\(h_{t}\ = \ {ReLU}\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}} \right)\)
MCDNN_RNN_TANH
具有
tanh激活函数的单门控循环神经网络。在正向传递中,给定迭代的输出 \(h_{t}\) 可以从循环输入 \(h_{t - 1}\) 和上一层输入 \(x_{t}\) 计算得到,给定矩阵
W,R和bias向量,其中tanh是双曲正切函数。如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_DOUBLE_BIAS(默认模式),则应用以下带有 \(b_{W}\) 和 \(b_{R}\) bias的方程式:\(h_{t}\ = \ \tanh\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}\ + \ b_{Wi}\ + \ b_{Ri}} \right)\)
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_SINGLE_INP_BIAS或MCDNN_RNN_SINGLE_REC_BIAS,则应用以下带有 bb bias的方程式:\(h_{t}\ = \ \tanh\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}\ + \ b_{i}} \right)\)
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_NO_BIAS,则应用以下方程式:\(h_{t}\ = \ \tanh\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}} \right)\)
MCDNN_LSTM
没有窥孔连接(peephole connection)的四门长短时记忆(Long Short-Term Memory,LSTM)网络。
在正向传递中,给定迭代的输出 \(h_{t}\) 和单元输出 \(c_{t}\),可以从循环输入 \(h_{t - 1}\),单元输入 \(c_{t - 1}\) 和上一层输入 \(x_{t}\) 计算得到,给定矩阵
W,R和bias向量。此外,还适用以下内容:
\(\sigma\) 是以下方程式的sigmoid运算符:\(\sigma(x)\ = \ 1\ /\ \left( {1\ + e^{- x}\ } \right)\),
\(◦\) 表示逐点乘法,
tanh是双曲正切函数,\(i_{t},\ f_{t},\ o_{t},\ {cʹ}_{t}\) 分别代表输入门,遗忘门,输出门和新门。
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_DOUBLE_BIAS(默认模式),则应用以下带有 \(b_{W}\) 和 \(b_{R}\) bias的方程式:\(i_{t}\ = \ \sigma\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}\ + b_{Wi}\ + \ b_{Ri}} \right)\)
\(f_{t}\ = \ \sigma\ \left( {W_{f}x_{t}\ + \ R_{f}h_{t - 1}\ + b_{Wf}\ + \ b_{Rf}} \right)\)
\(o_{t}\ = \ \sigma\ \left( {W_{o}x_{t}\ + \ R_{o}h_{t - 1}\ + b_{Wo}\ + \ b_{Ro}} \right)\)
\({cʹ}_{t}\ = \ \tanh\ \left( {W_{c}x_{t}\ + \ R_{c}h_{t - 1}\ + b_{Wc}\ + \ b_{Rc}} \right)\)
\(c_{t}\ = \ f_{t}\ ◦\ c_{t - 1}\ + \ i_{t}\ ◦{cʹ}_{t}\)
\(h_{t}\ = \ o_{t}\ ◦\ \tanh\ \left( c_{t} \right)\)
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_SINGLE_INP_BIAS或MCDNN_RNN_SINGLE_REC_BIAS,则应用以下带有 bb bias的方程式:\(i_{t}\ = \ \sigma\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}\ + b_{i}} \right)`\)
\(f_{t}\ = \ \sigma\ \left( {W_{f}x_{t}\ + \ R_{f}h_{t - 1}\ + b_{f}} \right)`\)
\(o_{t}\ = \ \sigma\ \left( {W_{o}x_{t}\ + \ R_{o}h_{t - 1}\ + b_{o}} \right)`\)
\({cʹ}_{t}\ = \ \tanh\ \left( {W_{c}x_{t}\ + \ R_{c}h_{t - 1}\ + b_{c}} \right)`\)
\(c_{t}\ = \ f_{t}\ ◦\ c_{t - 1}\ + \ i_{t}\ ◦{cʹ}_{t}\)
\(h_{t}\ = \ o_{t}\ ◦\ \tanh\ \left( c_{t} \right)\)
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_NO_BIAS,则应用以下方程式:\(i_{t}\ = \ \sigma\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}} \right)\)
\(f_{t}\ = \ \sigma\ \left( {W_{f}x_{t}\ + \ R_{f}h_{t - 1}} \right)\)
\(o_{t}\ = \ \sigma\ \left( {W_{o}x_{t}\ + \ R_{o}h_{t - 1}} \right)\)
\({cʹ}_{t}\ = \ \tanh\ \left( {W_{c}x_{t}\ + \ R_{c}h_{t - 1}} \right)\)
\(c_{t}\ = \ f_{t}\ ◦\ c_{t - 1}\ + \ i_{t}\ ◦{cʹ}_{t}\)
\(h_{t}\ = \ o_{t}\ ◦\ \tanh\ \left( c_{t} \right)\)
MCDNN_GRU
由门控循环单元组成的三门网络。
在正向传递中,给定迭代的输出 \(h_{t}\) 可以从循环输入 \(h_{t - 1}\) 和上一层输入 \(x_{t}\) 计算得到,给定矩阵
W,R和bias向量。此外,还适用以下内容:
\(\sigma\) 是以下方程式的sigmoid运算符:\(\sigma(x)\ = \ 1\ /\ \left( {1\ + e^{- x}\ } \right)\),
\(◦\) 表示逐点乘法,
tanh是双曲正切函数,\(i_{t},\ r_{t},,\ {hʹ}_{t}\) 分别代表输入门,重置门和新门。
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_DOUBLE_BIAS(默认模式),则应用以下带有 \(b_{W}\) 和 \(b_{R}\) bias的方程式:\(i_{t}\ = \ \sigma\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}\ + b_{Wi}\ + \ b_{Ru}} \right)\)
\(r_{t}\ = \ \sigma\ \left( {W_{r}x_{t}\ + \ R_{r}h_{t - 1}\ + b_{Wr}\ + \ b_{Rr}} \right)\)
\({hʹ}_{t}\ = \ \tanh\ \left( {W_{h}x_{t}\ + \ r_{t}\ ◦\ \left( R_{h}h_{t-1}\ + b_{Rh} \right)\ + \ b_{Wh}} \right)\)
\(h_{t}\ = \ \left( 1 - i_{t} \right)\ ◦\ {hʹ}_{t}\ + \ i_{t}\ ◦h_{t-1}\)
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_SINGLE_INP_BIAS,则应用以下带有 bb bias的方程式:\(i_{t}\ = \ \sigma\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}\ + b_{i}} \right)\)
\(r_{t}\ = \ \sigma\ \left( {W_{r}x_{t}\ + \ R_{r}h_{t - 1}\ + b_{r}} \right)\)
\({hʹ}_{t}\ = \ \tanh\ \left( {W_{h}x_{t}\ + \ r_{t}\ ◦\ \left( R_{h}h_{t-1} \right)\ + b_{Wh}} \right)\)
\(h_{t}\ = \ \left( 1 - i_{t} \right)\ ◦\ {hʹ}_{t}\ + \ i_{t}\ ◦h_{t-1}\)
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_SINGLE_REC_BIAS,则应用以下带有 bb bias的方程式:\(i_{t}\ = \ \sigma\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}\ + b_{i}} \right)\)
\(r_{t}\ = \ \sigma\ \left( {W_{r}x_{t}\ + \ R_{r}h_{t - 1}\ + b_{r}} \right)\)
\({hʹ}_{t}\ = \ \tanh\ \left( {W_{h}x_{t}\ + \ r_{t}\ ◦\ \left( R_{h}h_{t-1}\ + b_{Rh} \right)} \right)\)
\(h_{t}\ = \ \left( 1 - i_{t} \right)\ ◦\ {hʹ}_{t}\ + \ i_{t}\ ◦h_{t-1}\)
如果
rnnDesc中mcdnnRNNBiasMode_t biasMode为MCDNN_RNN_NO_BIAS,则应用以下方程式:\(i_{t}\ = \ \sigma\ \left( {W_{i}x_{t}\ + \ R_{i}h_{t - 1}} \right)\)
\(r_{t}\ = \ \sigma\ \left( {W_{r}x_{t}\ + \ R_{r}h_{t - 1}} \right)\)
\({hʹ}_{t}\ = \ \tanh\ \left( {W_{h}x_{t}\ + \ r_{t}\ ◦\ \left( R_{h}h_{t-1} \right)} \right)\)
\(h_{t}\ = \ \left( 1 - i_{t} \right)\ ◦\ {hʹ}_{t}\ + \ i_{t}\ ◦h_{t-1}\)
6.1.2.9. mcdnnRNNPaddingMode_t
mcdnnRNNPaddingMode_t是一种枚举类型,用于启用或禁用填充输入/输出。
值
MCDNN_RNN_PADDED_IO_DISABLED
禁用填充输入/输出。
MCDNN_RNN_PADDED_IO_ENABLED
启用填充输入/输出。
6.1.2.10. mcdnnSeqDataAxis_t
mcdnnSeqDataAxis_t是一种枚举类型,用于索引被传入mcdnnSetSeqDataDescriptor()函数的dimA[]参数中的活动维度,以配置mcdnnSeqDataDescriptor_t类型的序列数据描述符。 mcdnnSeqDataAxis_t常量也用于mcdnnSetSeqDataDescriptor()调用的axis[]参数中,以定义内存中序列数据缓冲区的布局。
有关如何使用mcdnnSeqDataAxis_t枚举类型的详细说明,请参见mcdnnSetSeqDataDescriptor()。
MCDNN_SEQDATA_DIM_COUNT宏定义mcdnnSeqDataAxis_t枚举类型中的常量数。当前该值设为4。
值
MCDNN_SEQDATA_TIME_DIM
标识TIME(序列长度)维度或指定数据布局中的TIME。
MCDNN_SEQDATA_BATCH_DIM
标识BATCH维度或指定数据布局中的BATCH。
MCDNN_SEQDATA_BEAM_DIM
标识BEAM维度或指定数据布局中的BEAM。
MCDNN_SEQDATA_VECT_DIM
标识VECT(向量)维度或指定数据布局中的VECT。
6.2. API参考
6.2.1. API函数
以下为mcdnn_adv_infer.h中的API函数。
6.2.1.1. mcdnnAdvInferVersionCheck()
此函数用于查看库的AdvInfer子集的版本是否与其他子库一致。
mcdnnStatus_t mcdnnAdvInferVersionCheck(void)
返回值
MCDNN_STATUS_SUCCESS
版本与其他子库一致。
MCDNN_STATUS_VERSION_MISMATCH
AdvInfer的版本与其他子库不一致。用户应检查并确保所有子组件安装版本一致。
6.2.1.2. mcdnnBuildRNNDynamic()
当选择MCDNN_RNN_ALGO_PERST_DYNAMIC algo时,此函数使用MXMACA运行时编译库编译RNN持久性代码。代码根据当前GPU和特定超参数(miniBatch)进行定制。此函数调用的运行时消耗大,因此不能频繁调用。请注意,MCDNN_RNN_ALGO_PRESERT_DYNAMIC algo不支持batch中可变长度序列。
mcdnnStatus_t mcdnnBuildRNNDynamic(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
int32_t miniBatch);
参数
handle
输入。已创建的mcDNN上下文的句柄。
rnnDesc
输入。已初始化的RNN描述符。
miniBatch
输入。一个batch中的确切序列数。
返回值
MCDNN_STATUS_SUCCESS
代码已成功构建并链接。
MCDNN_STATUS_MAPPING_ERROR
GPU/MXMACA资源(如纹理对象,共享内存或零拷贝内存)没有所需的空间,或者用户资源与mcDNN内部资源不匹配。例如,在调用mcdnnSetStream()时,可能会出现资源不匹配。调用mcdnnCreate()时,用户提供的MXMACA流与mcDNN句柄中实例化的内部MXMACA事件之间可能不匹配。 此错误状态与纹理尺寸,共享内存大小或零拷贝内存可用性相关时,可能无法纠正。如果mcdnnSetStream()返回MCDNN_STATUS_MAPPING_ERROR,则通常是可纠正的,但是,这意味着mcDNN句柄是在一个GPU上创建的,且传入此函数的用户流与另一个GPU相关联。
MCDNN_STATUS_ALLOC_FAILED
资源无法分配。
MCDNN_STATUS_RUNTIME_PREREQUISITE_MISSING
找不到必备的运行时库。
MCDNN_STATUS_NOT_SUPPORTED
当前超参数无效。
6.2.1.3. mcdnnCreateAttnDescriptor()
此函数通过为不透明的注意力描述符对象分配主机内存,并初始化所有描述符字段,来创建该对象的一个实例。当无法分配注意力描述符对象时,函数将NULL写入attnDesc。
mcdnnStatus_t mcdnnCreateAttnDescriptor(mcdnnAttnDescriptor_t *attnDesc);
使用mcdnnSetAttnDescriptor()函数配置注意力描述符,并使用mcdnnDestroyAttnDescriptor()销毁该描述符并释放分配的内存。
参数
attnDesc
输出。指针,指向要写入新创建的注意力描述符的地址。
返回值
MCDNN_STATUS_SUCCESS
描述符对象创建成功。
MCDNN_STATUS_BAD_PARAM
遇到无效的输入参数(attnDes=NULL)。
MCDNN_STATUS_ALLOC_FAILED
内存分配失败。
6.2.1.4. mcdnnCreatePersistentRNNPlan()
此函数保留API,不再单独实现。使用mcdnnBuildRNNDynamic()代替mcdnnCreatePersistentRNNPlan()。
mcdnnStatus_t mcdnnCreatePersistentRNNPlan(
mcdnnRNNDescriptor_t rnnDesc,
const int minibatch,
const mcdnnDataType_t dataType,
mcdnnPersistentRNNPlan_t *plan)
使用MCDNN_RNN_ALGO_PERSIST_DYNAMIC algo时,此函数创建执行持久RNN的计划。此计划是根据当前的GPU和RNN模型超参数定制的。此函数调用的运行时消耗大,因此不能频繁调用。但是,每次在minibatch中更改输入向量的数量时,用户都必须调用mcdnnCreatePersistentRNNPlan()。更多信息,参见mcdnnRNNDescriptor_t,mcdnnDataType_t,mcdnnPersistentRNNPlan_t。
参数
rnnDesc
输入。已初始化的RNN描述符。
minibatch
输入。一个batch中的确切向量数。
dataType
输入。为RNN权重/偏差以及输入和输出数据指定数据类型。
plan
输出。指针,指向要写入新创建的RNN持久性计划的地址。
返回值
MCDNN_STATUS_SUCCESS
对象创建成功。
MCDNN_STATUS_MAPPING_ERROR
GPU/MXMACA资源(如纹理对象,共享内存或零拷贝内存)没有所需的空间,或者用户资源与mcDNN内部资源不匹配。例如,在调用mcdnnSetStream()时,可能会出现资源不匹配。调用mcdnnCreate()时,用户提供的MXMACA流与mcDNN句柄中实例化的内部MXMACA事件之间可能不匹配。
此错误状态与纹理尺寸,共享内存大小或零拷贝内存可用性相关时,可能无法纠正。如果mcdnnSetStream()返回MCDNN_STATUS_MAPPING_ERROR,则通常是可纠正的,但是,这意味着mcDNN句柄是在一个GPU上创建的,且传入此函数的用户流与另一个GPU相关联。
MCDNN_STATUS_ALLOC_FAILED
资源无法分配。
MCDNN_STATUS_RUNTIME_PREREQUISITE_MISSING
找不到必备的运行时库。
MCDNN_STATUS_NOT_SUPPORTED
当前超参数无效。
6.2.1.5. mcdnnCreateRNNDataDescriptor()
此函数通过分配保存RNN数据描述符不透明结构所需内存的方式,创建RNN数据描述符对象。
mcdnnStatus_t mcdnnCreateRNNDataDescriptor(
mcdnnRNNDataDescriptor_t *RNNDataDesc)
参数
RNNDataDesc
输出。指针,指向要写入新创建的RNN数据描述符的地址。
返回值
MCDNN_STATUS_SUCCESS
RNN数据描述符对象已创建成功。
MCDNN_STATUS_BAD_PARAM
RNNDataDesc参数为NULL。
MCDNN_STATUS_ALLOC_FAILED
资源无法分配。
6.2.1.6. mcdnnCreateRNNDescriptor()
此函数通过分配保存通用RNN描述符不透明结构所需内存的方式,创建通用RNN描述符对象。
mcdnnStatus_t mcdnnCreateRNNDescriptor(
mcdnnRNNDescriptor_t *rnnDesc)
参数
rnnDesc
输出。指针,指向要写入新创建的RNN描述符的地址。
返回值
MCDNN_STATUS_SUCCESS
已成功创建对象。
MCDNN_STATUS_BAD_PARAM
rnnDesc参数为NULL。
MCDNN_STATUS_ALLOC_FAILED
资源无法分配。
6.2.1.7. mcdnnCreateSeqDataDescriptor()
此函数通过为不透明的序列数据描述符对象分配主机内存,并初始化所有描述符字段,来创建该对象的一个实例。当无法分配序列数据描述符对象时,函数将NULL写入seqDataDesc。
mcdnnStatus_t mcdnnCreateSeqDataDescriptor(mcdnnSeqDataDescriptor_t *seqDataDesc);
使用mcdnnSetSeqDataDescriptor()函数配置序列数据描述符,并使用mcdnnDestroySeqDataDescriptor()销毁该描述符并释放分配的内存。
参数
seqDataDesc
输出。指针,指向要写入新创建的序列数据描述符的地址。
返回值
MCDNN_STATUS_SUCCESS
已成功创建描述符对象。
MCDNN_STATUS_BAD_PARAM
遇到无效的输入参数(seqDataDesc=NULL)。
MCDNN_STATUS_ALLOC_FAILED
内存分配失败。
6.2.1.8. mcdnnDestroyAttnDescriptor()
此函数用于销毁注意力描述符对象,并释放其内存。attnDesc参数可以为NULL。使用NULL参数调用mcdnnDestroyAttnDescriptor()是一个空操作(NOP)。
mcdnnStatus_t mcdnnDestroyAttnDescriptor(mcdnnAttnDescriptor_t attnDesc);
mcdnnDestroyAttnDescriptor()函数无法检测attnDesc参数是否包含有效的地址。如果传入无效的指针,mcdnnCreateAttnDescriptor()函数未返回,或者在有效地址的double deletion场景下,将出现未定义的行为。
参数
attnDesc
输入。指针,指向要销毁的注意力描述符对象。
返回值
MCDNN_STATUS_SUCCESS
描述符已销毁成功。
6.2.1.9. mcdnnDestroyPersistentRNNPlan()
此函数保留API,不再单独实现。 此函数用于销毁已创建的RNN持久性计划对象。使用NULL参数调用mcdnnDestroyPersistentRNNPlan()是一个空操作(NOP)。
mcdnnStatus_t mcdnnDestroyPersistentRNNPlan(
mcdnnPersistentRNNPlan_t plan)
mcdnnDestroyPersistentRNNPlan()函数无法检测plan参数是否包含有效的地址。如果传入无效的指针,mcdnnCreatePersistentRNNPlan()函数未返回,或者在有效地址的double deletion场景下,将出现未定义的行为。
参数
plan
输入。指针,指向要销毁的RNN持久性计划对象。
返回值
MCDNN_STATUS_SUCCESS
对象已销毁成功。
6.2.1.10. mcdnnDestroyRNNDataDescriptor()
此函数用于销毁已创建的RNN数据描述符对象。使用NULL参数调用mcdnnDestroyRNNDataDescriptor()是一个空操作(NOP)
mcdnnStatus_t mcdnnDestroyRNNDataDescriptor(
mcdnnRNNDataDescriptor_t RNNDataDesc)
mcdnnDestroyRNNDataDescriptor()函数无法检测RNNDataDesc参数是否包含有效的地址。如果传入无效的指针,mcdnnCreateRNNDataDescriptor()函数未返回,或者在有效地址的double deletion场景下,将出现未定义的行为。
参数
RNNDataDesc
输入。指针,指向要销毁的RNN数据描述符对象。
返回值
MCDNN_STATUS_SUCCESS
RNN数据描述符对象销毁成功。
6.2.1.11. mcdnnDestroyRNNDescriptor()
此函数用于销毁已创建的RNN描述符对象。使用NULL参数调用mcdnnDestroyRNNDescriptor()是一个空操作(NOP)
mcdnnStatus_t mcdnnDestroyRNNDescriptor(
mcdnnRNNDescriptor_t rnnDesc)
mcdnnDestroyRNNDescriptor()函数无法检测rnnDesc参数是否包含有效的地址。如果传入无效的指针,mcdnnCreateRNNDescriptor()函数未返回,或者在有效地址的double deletion场景下,将出现未定义的行为。
参数
rnnDesc
输入。指针,指向要销毁的RNN描述符对象。
返回值
MCDNN_STATUS_SUCCESS
对象已销毁成功。
6.2.1.12. mcdnnDestroySeqDataDescriptor()
此函数用于销毁序列描述符对象,并释放其内存。seqDataDesc参数可以为NULL。使用NULL参数调用mcdnnDestroySeqDataDescriptor()是一个空操作(NOP)。
mcdnnStatus_t mcdnnDestroySeqDataDescriptor(mcdnnSeqDataDescriptor_t seqDataDesc);
mcdnnDestroySeqDataDescriptor()函数无法检测seqDataDesc参数是否包含有效的地址。如果传入无效的指针,mcdnnCreateSeqDataDescriptor()函数未返回,或者在有效地址的double deletion场景下,将出现未定义的行为。
参数
seqDataDesc
输入。指针,指向要销毁的序列数据描述符对象。
返回值
MCDNN_STATUS_SUCCESS
描述符已销毁成功。
6.2.1.13. mcdnnFindRNNForwardInferenceAlgorithmEx()
此函数保留API,不再单独实现。 此函数使用用户分配的GPU内存尝试mcdnnRNNForwardInference()的所有可用mcDNN算法。它将影响算法性能的参数输出到用户分配的mcdnnAlgorithmPerformance_t数组。这些参数指标以一种有序的方式写入,其中第一个元素的计算时间最短。
mcdnnStatus_t mcdnnFindRNNForwardInferenceAlgorithmEx(
mcdnnHandle_t handle,
const mcdnnRNNDescriptor_t rnnDesc,
const int seqLength,
const mcdnnTensorDescriptor_t *xDesc,
const void *x,
const mcdnnTensorDescriptor_t hxDesc,
const void *hx,
const mcdnnTensorDescriptor_t cxDesc,
const void *cx,
const mcdnnFilterDescriptor_t wDesc,
const void *w,
const mcdnnTensorDescriptor_t *yDesc,
void *y,
const mcdnnTensorDescriptor_t hyDesc,
void *hy,
const mcdnnTensorDescriptor_t cyDesc,
void *cy,
const float findIntensity,
const int requestedAlgoCount,
int *returnedAlgoCount,
mcdnnAlgorithmPerformance_t *perfResults,
void *workspace,
size_t workSpaceSizeInBytes);
参数
handle
输入。已创建的mcDNN上下文的句柄。
rnnDesc
输入。已初始化的RNN描述符。
seqLength
输入。要展开的迭代次数。seqLength的值不能超过mcdnnGetRNNWorkspaceSize()函数中用于查询执行RNN所需的工作空间大小。
xDesc
输入。完全压缩的张量描述符数组,描述每个循环迭代的输入(一个迭代一个描述符)。张量的第一维(批大小)可能从元素n减少到元素1,但不会增加。每个张量描述符必须具有相同的第二维(向量长度)。
x
输入。数据指针,指向与xDesc数组中张量描述符关联的GPU内存。数据压缩会在迭代n的最后一个元素结束后直接从迭代n+1的第一个元素开始连续进行。
hxDesc
输入。完全压缩的张量描述符,描述RNN的初始隐藏状态(initial hidden state)。
张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc所描述张量的第一维匹配。 第三维必须与初始化rnnDesc的hiddenSize参数匹配。张量必须为完全压缩格式。
hx
输入。数据指针,指向与张量描述符hxDesc关联的GPU内存。如果传入NULL指针,则网络的初始隐藏状态将初始化为零。
cxDesc
输入。完全压缩的的张量描述符,描述LSTM网络的初始单元(cell)状态。
张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc所描述张量的第一维匹配。 第三维必须与初始化rnnDesc的hiddenSize参数匹配。张量必须为完全压缩格式。
cx
输入。数据指针,指向与张量描述符cxDesc关联的GPU内存。如果传入NULL指针,则网络的初始单元状态将初始化为零。
wDesc
输入。已初始化的卷积核描述符的句柄,描述RNN权重。
w
输入。数据指针,指向与卷积核描述符wDesc关联的GPU内存。
yDesc
输入。完全压缩的张量描述符数组,描述每个循环迭代的输出。
张量的第二维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第二维应与hiddenSize参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第二维应是hiddenSize参数的2倍。
张量n的第一维必须与xDesc中张量n的第一维匹配。
y
输出。数据指针,指向与输出张量描述符yDesc关联的GPU内存。数据压缩会在迭代n的最后一个元素结束后直接从迭代n+1的第一个元素开始连续进行。
hyDesc
输入。完全压缩的张量描述符,描述RNN的最终隐藏状态。
张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc所描述张量的第一维匹配。 第三维必须与初始化rnnDesc的hiddenSize参数匹配。张量必须为完全压缩格式。
hy
输出。数据指针,指向与张量描述符hyDesc关联的GPU内存。如果传入NULL指针,将不会保存网络的最终隐藏状态。
cyDesc
输入。完全压缩的张量描述符,描述LSTM网络的最终单元状态。
张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc所描述张量的第一维匹配。 第三维必须与初始化rnnDesc的hiddenSize参数匹配。张量必须为完全压缩格式。
cy
输出。数据指针,指向与张量描述符cyDesc关联的GPU内存。如果传入NULL指针,将不会保存网络的最终单元状态。
findIntensity
输入。此输入之前未使用。 通过选择要搜索的空间占大的笛卡尔积(Cartesian product)空间的百分比,它在mcDNN中用于控制RNN查找算法的总体运行时。
在(0,1.]范围内设置findIntensity,则是设置要搜索的空间占整个RNN搜索空间的百分比。
当findIntensity设置为1.0时,将对所有RNN参数执行完整搜索。
当findIntensity设置为0.0f时,将执行快速,最小的搜索。此设置可获得最佳运行时。
但是,在这种情况下,此函数返回的参数不会获得算法的最佳性能; 更大范围的搜索可能会发现更好的性能参数。此选项将最多执行三个已配置的RNN problem的实例。 运行时会随RNN problem size而成比例地变化,在其他情况下也是如此,因此不能保证明确的时间限制。
在[-1.,0)范围内设置findIntensity,则是设置要搜索的空间占归约笛卡尔积空间的百分比。为获得良好的性能,已启发式地选择此归约搜索空间。设置为-1.0表示在此归约搜索空间上进行完整搜索。
[-1,1]范围以外的值被截断到[-1,1]范围中,然后按照上述说明进行解释。
此函数对大参数空间上的单个RNN执行进行乘积—一个参数组合一次执行。此函数返回的时间是运行总时间。
requestedAlgoCount
输入。要存储在perfResults中的最大元素数。
returnedAlgoCount
输出。存储在perfResults中的输出元素数。
perfResults
输出。用户分配的数组,用于存储按计算时间升序排序的性能指标。
workspace
输入。数据指针,指向要用作此调用工作空间的GPU内存。
workSpaceSizeInBytes
输入。指定已提供的workspace大小(以字节为单位)。
返回值
MCDNN_STATUS_SUCCESS
此函数启用成功。
MCDNN_STATUS_NOT_SUPPORTED
此函数不支持已提供的配置。
MCDNN_STATUS_BAD_PARAM
需至少满足以下任一条件:
rnnDesc描述符无效。
hxDesc、cxDesc、wDesc、hyDesc、cyDesc描述符中或者xDesc、yDesc描述符中至少有一个是无效的。
xDesc、hxDesc、cxDesc、wDesc、yDesc、hyDesc、cyDesc中至少有一个描述符的步幅或维度不正确。
workSpaceSizeInBytes太小。
MCDNN_STATUS_EXECUTION_FAILED
此函数在GPU上启用失败。
MCDNN_STATUS_ALLOC_FAILED
此函数不能用来分配内存。
6.2.1.14. mcdnnGetAttnDescriptor()
此函数用于从已创建的注意力描述符中检索设置。当不需要检索到的值时,用户可以将NULL分配给除attnDesc之外的任意指针。
mcdnnStatus_t mcdnnGetAttnDescriptor(
mcdnnAttnDescriptor_t attnDesc,
unsigned *attnMode,
int *nHeads,
double *smScaler,
mcdnnDataType_t *dataType,
mcdnnDataType_t *computePrec,
mcdnnMathType_t *mathType,
mcdnnDropoutDescriptor_t *attnDropoutDesc,
mcdnnDropoutDescriptor_t *postDropoutDesc,
int *qSize,
int *kSize,
int *vSize,
int *qProjSize,
int *kProjSize,
int *vProjSize,
int *oProjSize,
int *qoMaxSeqLength,
int *kvMaxSeqLength,
int *maxBatchSize,
int *maxBeamSize);
参数
- attnDesc
输入。注意力描述符。
attnMode
输出。指向二进制注意力标记存储的指针。
nHeads
输出。指向注意力头数存储的指针。
smScaler
输出。指向softmax平滑/锐化系数存储的指针。
dataType
输出。注意力、权重、序列数据输入和输出的数据类型。
computePrec
输出。指向计算精度存储的指针。
mathType
输出。MMA设置。
attnDropoutDesc
输出。应用于softmax输出的丢弃操作的描述符。
postDropoutDesc
输出。应用于多头注意力输出的丢弃操作的描述符。
qSize, kSize, vSize
输出。Q、K、V嵌入向量长度。
qProjSize, kProjSize, vProjSize
输出。输入投影(projection)后的Q、K、V嵌入向量长度。
oProjSize
输出。存储投影后输出向量长度的指针。
qoMaxSeqLength
输出。与Q、O、dQ、dO输入和输出相关的序列数据描述符中的最大序列长度。
kvMaxSeqLength
输出。与K、V、dK、dV输入和输出相关的序列数据描述符中的最大序列长度。
maxBatchSize
输出。mcdnnSeqDataDescriptor_t容器中的最大批大小。
maxBeamSize
输出。mcdnnSeqDataDescriptor_t容器中的最大束宽(beam size)。
返回值
MCDNN_STATUS_SUCCESS
已成功检索到请求的注意力描述符字段。
MCDNN_STATUS_BAD_PARAM
找到一个无效的输入变量。
6.2.1.15. mcdnnGetMultiHeadAttnBuffers()
此函数计算以下函数使用的权重、工作空间和预留空间缓冲区大小:
mcdnnMultiHeadAttnForward()
mcdnnMultiHeadAttnBackwardData()
mcdnnMultiHeadAttnBackwardWeights()
mcdnnStatus_t mcdnnGetMultiHeadAttnBuffers(
mcdnnHandle_t handle,
const mcdnnAttnDescriptor_t attnDesc,
size_t *weightSizeInBytes,
size_t *workSpaceSizeInBytes,
size_t *reserveSpaceSizeInBytes);
将NULL分配给reserveSpaceSizeInBytes参数,表示用户不会调用多头注意力梯度函数:mcdnnMultiHeadAttnBackwardData()和mcdnnMultiHeadAttnBackwardWeights()。此状态出现在推理模式中。
备注
不能将NULL分配给weightSizeInBytes和workSpaceSizeInBytes指针。
用户必须使用mcMalloc()和已报告的缓冲区大小来分配GPU内存中的权重、工作空间和预留空间缓冲区大小。缓冲区也可以从已分配内存的较大块中分离出来,但缓冲区地址必须至少对齐16B。
工作空间缓冲区用于临时存储。其内容可以在相应API启动的所有GPU内核完成后丢弃或修改。预留空间缓冲区用于将中间结果从mcdnnMultiHeadAttnForward()传送到mcdnnMultiHeadAttnBackwardData(),以及从mcdnnMultiHeadAttnBackwardData()传送到mcdnnMultiHeadAttnBackwardWeights()。在上述三个多头注意力API函数启动的所有GPU内核完成之前,预留空间缓冲区的内容无法修改。
所有多头注意力权重和bias张量存储在单个权重缓冲区中。为优化速度,mcDNN API可能会根据提供的注意力参数更改张量布局及其在权重缓冲区中的相对位置。使用mcdnnGetMultiHeadAttnWeights()函数获取每个权重或bias张量的起始地址和形状。
参数
handle
输入。当前的mcDNN上下文句柄。
attnDesc
输入。指针,指向已初始化的注意力描述符。
weightSizeInBytes
输出。存储所有多头注意力可训练参数所需的最小缓冲区大小。
workSpaceSizeInBytes
输出。保存正向和梯度多头注意力API使用的所有临时表面(temporary surface)所需的最小缓冲区大小。
reserveSpaceSizeInBytes
输出。存储在正向和反向(梯度)多头注意力函数之间交换的所有中间数据所需的最小缓冲区大小。在推理模式中将该参数设置为NULL,表示不会调用梯度API。
返回值
MCDNN_STATUS_ARCH_MISMATCH
GPU设备不支持输入数据类型。
MCDNN_STATUS_SUCCESS
已成功计算请求的缓冲区大小。
MCDNN_STATUS_BAD_PARAM
找到一个无效的输入参数。
6.2.1.16. mcdnnGetMultiHeadAttnWeights()
该函数用于获取权重或bias张量的形状。它还用于检索权重缓冲区中张量数据的起始地址。使用wKind参数选择一个特定张量。有关更多枚举类型的说明信息,请参见mcdnnMultiHeadAttnWeightKind_t。
mcdnnStatus_t mcdnnGetMultiHeadAttnWeights(
mcdnnHandle_t handle,
const mcdnnAttnDescriptor_t attnDesc,
mcdnnMultiHeadAttnWeightKind_t wKind,
size_t weightSizeInBytes,
const void *weights,
mcdnnTensorDescriptor_t wDesc,
void **wAddr);
在注意力描述符中设置MCDNN_ATTN_ENABLE_PROJ_BIASES标记时,在输入和输出投影中使用bias。有关控制投影bias的标记的说明,请参见mcdnnSetAttnDescriptor()。
当相应的权重或bias张量不存在时,函数将NULL写入wAddr指向的存储位置,并在wDesc张量描述符中返回零。在这种情况下,mcdnnGetMultiHeadAttnWeights()函数的返回状态为MCDNN_STATUS_SUCCESS。
mcDNN 虽然应该在GPU内存中分配带有权重和bias的缓冲区,但用户可以将其复制到主机内存,并使用主机权重地址调用mcdnnGetMultiHeadAttnWeights()函数以获取主机内存中的张量指针。此方案允许用户直接在CPU内存中检查可训练参数。
参数
handle
输入。当前的mcDNN上下文句柄。
attnDesc
输入。已配置的注意力描述符。
wKind
输入。指定应检索哪个权重或bias张量的枚举类型。
weightSizeInBytes
输入。用于存储所有多头注意力权重和bias的缓冲区大小。
weights
输入。指向主机或设备内存中权重缓冲区的指针。
wDesc
输出。指定权重或bias张量形状的描述符。对于权重,wDesc.dimA[]数组有三个元素:[nHeads, projected size, original size]。对于bias,wDesc.dimA[]数组也有三个元素:[nHeads, projected size, 1]。wDesc.strideA[]数组描述了张量元素在内存中的排列方式。
wAddr
输出。指针,指向应写入所请求张量起始地址的位置。当禁用相应的投影时,写入wAddr的地址为NULL。
返回值
MCDNN_STATUS_SUCCESS
已成功检索设备内存中数据的权重张量描述符和地址。
MCDNN_STATUS_BAD_PARAM
遇到一个无效或不兼容的输入参数。例如,wKind的值无效,或者weightSizeInBytes太小。
6.2.1.17. mcdnnGetRNNBackwardWeightsAlgorithmMaxCount()
此函数保留API,不再单独实现。
6.2.1.18. mcdnnGetRNNBiasMode()
此函数保留API,不再单独实现。使用mcdnnGetRNNDescriptor_v8()代替mcdnnGetRNNBiasMode()。
mcdnnStatus_t mcdnnGetRNNBiasMode(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNBiasMode_t *biasMode)
此函数用于检索已使用mcdnnSetRNNBiasMode()配置的RNN bias模式。在mcdnnCreateRNNDescriptor()之后,rnnDesc中biasMode的默认值为MCDNN_RNN_DOUBLE_BIAS。
参数
rnnDesc
输入。已创建的RNN描述符。
biasMode
输出。指针,指向应保存RNN bias模式的位置。
返回值
MCDNN_STATUS_BAD_PARAM
rnnDesc或biasMode为NULL。
MCDNN_STATUS_SUCCESS
已成功检索biasMode参数。
6.2.1.19. mcdnnGetRNNDataDescriptor()
此函数用于检索已创建的RNN数据描述符对象。
mcdnnStatus_t mcdnnGetRNNDataDescriptor(
mcdnnRNNDataDescriptor_t RNNDataDesc,
mcdnnDataType_t *dataType,
mcdnnRNNDataLayout_t *layout,
int *maxSeqLength,
int *batchSize,
int *vectorSize,
int arrayLengthRequested,
int seqLengthArray[],
void *paddingFill);
参数
RNNDataDesc
输入。已创建和初始化的RNN描述符。
dataType
输出。指针,指向主机内存中用于存储RNN数据张量数据类型的位置。
layout
输出。指针,指向主机内存中用于存储RNN数据张量内存布局的位置。
maxSeqLength
输出。此RNN数据张量内的最大序列长度,包括填充向量。
batchSize
输出。在mini-batch内的序列数。
vectorSize
输出。输入或输出张量在每个时间步的向量长度(即,嵌入大小)。
arrayLengthRequested
输入。用户请求的seqLengthArray元素数。
seqLengthArray
输出。指针,指向主机内存中用于存储描述每个序列长度(即,时间步的数量)的整数数组的位置。如果arrayLengthRequested为0,则允许该指针为NULL。
paddingFill
输出。指针,指向主机内存中存储用户自定义符号的位置。该符号表示与RNN数据张量相同的数据类型。
返回值
MCDNN_STATUS_SUCCESS
已成功获取参数。
MCDNN_STATUS_BAD_PARAM
满足以下任意一种情况:
RNNDataDesc、dataType、layout、maxSeqLength、batchSize、vectorSize、paddingFill中任意一个为NULL。
arrayLengthRequested大于0时,seqLengthArray为NULL。
arrayLengthRequested小于0。
6.2.1.20. mcdnnGetRNNDescriptor_v6()
此函数保留API,不再单独实现。使用mcdnnGetRNNDescriptor_v8()代替mcdnnGetRNNDescriptor_v6()。
mcdnnStatus_t mcdnnGetRNNDescriptor_v6(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
int *hiddenSize,
int *numLayers,
mcdnnDropoutDescriptor_t *dropoutDesc,
mcdnnRNNInputMode_t *inputMode,
mcdnnDirectionMode_t *direction,
mcdnnRNNMode_t *cellMode,
mcdnnRNNAlgo_t *algo,
mcdnnDataType_t *mathPrec);
此函数用于检索由mcdnnSetRNNDescriptor_v6()配置的RNN网络参数。所有传入该函数的指针都应为not-NULL或报告MCDNN_STATUS_BAD_PARAM。该函数不用于检查已检索参数的有效性。
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入。已创建和初始化的RNN描述符。
hiddenSize
输出。指针,指向应存储隐藏状态大小(每个RNN层中使用相同的值)的位置。
numLayers
输出。指针,指向应存储RNN层数的位置。
dropoutDesc
输出。指针,指向应存储已配置的丢弃描述符句柄的位置。
inputMode
输出。指针,指向应存储RNN第一层模式的位置。
direction
输出。指针,指向应存储RNN单向/双向模式的位置。
mode
输出。指针,指向应存储RNN单元类型的位置。
algo
输出。指针,指向应存储RNN算法类型的位置。
mathPrec
输出。指针,指向应存储数学精度类型的位置。
返回值
MCDNN_STATUS_SUCCESS
已从RNN描述符成功检索RNN参数。
MCDNN_STATUS_BAD_PARAM
传入该函数的指针中至少有一个为NULL。
6.2.1.21. mcdnnGetRNNDescriptor_v8()
此函数用于检索由mcdnnSetRNNDescriptor_v8()配置的RNN网络参数。当不需要检索到的值时,用户可以将NULL分配给除rnnDesc之外的任意指针。该函数不用于检查已检索参数的有效性。
mcdnnStatus_t mcdnnGetRNNDescriptor_v8(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNAlgo_t *algo,
mcdnnRNNMode_t *cellMode,
mcdnnRNNBiasMode_t *biasMode,
mcdnnDirectionMode_t *dirMode,
mcdnnRNNInputMode_t *inputMode,
mcdnnDataType_t *dataType,
mcdnnDataType_t *mathPrec,
mcdnnMathType_t *mathType,
int32_t *inputSize,
int32_t *hiddenSize,
int32_t *projSize,
int32_t *numLayers,
mcdnnDropoutDescriptor_t *dropoutDesc,
uint32_t *auxFlags);
参数
rnnDesc
输入。已创建和初始化的RNN描述符。
algo
输出。指针,指向应存储RNN算法类型的位置。
cellMode
输出。指针,指向应存储RNN单元类型的位置。
biasMode
输出。指针,指向应保存RNN bias模式mcdnnRNNBiasMode_t的位置。
dirMode
输出。指针,指向应存储RNN单向/双向模式的位置。
inputMode
输出。指针,指向应存储RNN第一层模式的位置。
dataType
输出。指针,指向应存储RNN权重/bias数据类型的位置。
mathPrec
输出。指针,指向应存储数学精度类型的位置。
mathType
输出。指针,指向保存Tensor Core首选项的位置。
inputSize
输出。指针,指向存储RNN输入向量大小的位置。
hiddenSize
输出。指针,指向应存储隐藏状态大小(每个RNN层中使用相同的值)的位置。
projSize
输出。指针,指向存储循环投影后LSTM单元输出大小的位置。
numLayers
输出。指针,指向应存储RNN层数的位置。
dropoutDesc
输出。指针,指向应存储已配置的丢弃描述符句柄的位置。
auxFlags
输出。指针,指向不需要传入额外数值进行配置的其他RNN选项(标记)。
返回值
MCDNN_STATUS_SUCCESS
已从RNN描述符成功检索RNN参数。
MCDNN_STATUS_BAD_PARAM
找到一个无效的输入参数(rnnDesc为NULL)。
MCDNN_STATUS_NOT_INITIALIZED
RNN描述符是使用旧的mcdnnSetRNNDescriptor_v6()进行配置的。
6.2.1.22. mcdnnGetRNNForwardInferenceAlgorithmMaxCount()
此函数保留API,不再单独实现。
6.2.1.23. mcdnnGetRNNLinLayerBiasParams()
此函数保留API,不再单独实现。使用mcdnnGetRNNWeightParams()代替mcdnnGetRNNLinLayerBiasParams()。
mcdnnStatus_t mcdnnGetRNNLinLayerBiasParams(
mcdnnHandle_t handle,
const mcdnnRNNDescriptor_t rnnDesc,
const int pseudoLayer,
const mcdnnTensorDescriptor_t xDesc,
const mcdnnFilterDescriptor_t wDesc,
const void *w,
const int linLayerID,
mcdnnFilterDescriptor_t linLayerBiasDesc,
void **linLayerBias)
该函数用于获取循环网络中每个伪层(pseudo-layer)的每个RNN bias列向量的指针和描述符(由rnnDesc定义),以及在xDesc中指定的其输入宽度。
备注
在mcDNN中更改了mcdnnGetRNNLinLayerBiasParams()函数,以匹配mcdnnGetRNNLinLayerMatrixParams()的行为。
mcdnnGetRNNLinLayerBiasParams()函数以两个维度返回RNN bias向量大小:行和列。
更多信息,参见mcdnnGetFilterNdDescriptor()。 mcDNN中,格式为:
filterDimA[0]=1,
filterDimA[1]=rows,
filterDimA[2]=1 (number of columns)
当通过mcdnnGetFilterNdDescriptor()检索时,应忽略卷积核描述符的格式字段。 mcDNN中的RNN实现,在单元非线性函数之前使用两个bias向量。请注意,mcDNN中的RNN实现取决于单元非线性函数之前的bias向量数量。有关基于rnnDesc中mcdnnRNNBiasMode_tbiasMode值的枚举类型,请参见mcdnnRNNMode_t说明中的方程式。 如果linLayerID引用了不存在的bias,则该函数将linLayerBiasDesc设置为一个归零卷积核描述符,其中:
filterDimA[0]=0,
filterDimA[1]=0, and
filterDimA[2]=2
并将linLayerBias设置为NULL。请参见函数参数linLayerID的详细信息,以确定基于biasMode的linLayerID的相关值。
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入。已初始化的RNN描述符。
pseudoLayer
输入。要查询的伪层。在单向RNN中,伪层与物理层相同(pseudoLayer=0是RNN输入层,pseudoLayer=1是第一个隐藏层)。 在双向RNN中,伪层的数量是物理层的两倍。
pseudoLayer=0是指物理输入层的正向部分
pseudoLayer=1是指物理输入层的反向部分
pseudoLayer=2是第一个隐藏层的正向部分,依此类推
xDesc
输入。一个完全压缩的张量描述符,描述一个循环迭代的输入(以检索RNN输入宽度)。
wDesc
输入。已初始化的卷积核描述符的句柄,描述RNN权重。
w
输入。数据指针,指向与卷积核描述符wDesc关联的GPU内存。
linLayerID
输入。 Linear ID index of the weight matrix.
若rnnDesc中cellMode设置为MCDNN_RNN_RELU或MCDNN_RNN_TANH:
值0表示与来自上一层的输入或RNN模型的输入结合使用的权重矩阵。
值1表示与上一时间步的隐藏状态或初始隐藏状态结合使用的权重矩阵。
若rnnDesc中cellMode设置为MCDNN_LSTM:
值0、1、2、3表示与来自上一层的输入或RNN模型的输入结合使用的权重矩阵。
值4、5、6、7表示与上一时间步的隐藏状态或初始隐藏状态结合使用的权重矩阵。
值8对应于投影矩阵(如果已启用)。
值及其LSTM门(gate):
linLayerID0和4对应于输入门。
linLayerID1和5对应于遗忘门。
linLayerID2和6对应于双曲正切的新单元状态计算。
linLayerID3和7对应于输出门。
若rnnDesc中cellMode设置为MCDNN_GRU:
值0、1、2表示与来自上一层的输入或RNN模型的输入结合使用的权重矩阵。
值3、4、5表示与上一时间步的隐藏状态或初始隐藏状态结合使用的权重矩阵。
值及其GRU门(gate):
linLayerID0和4对应于重置门。
linLayerID1和4对应于更新门。
linLayerID2和5对应于双曲正切的新隐藏状态计算。
linLayerBiasDesc
输出。已创建的卷积核描述符的句柄。
linLayerBias
输出。数据指针,指向与卷积核描述符linLayerBiasDesc关联的GPU内存。
返回值
MCDNN_STATUS_SUCCESS
查询成功。
MCDNN_STATUS_NOT_SUPPORTED
此函数不支持已提供的配置。
MCDNN_STATUS_BAD_PARAM
需至少满足以下任一条件:
以下任一参数为NULL:handle、rnnDesc、xDesc、wDesc、linLayerBiasDesc、linLayerBias。
检测到rnnDesc和其他描述符之间数据类型不匹配。
不满足w指针对齐的最低要求。
pseudoLayer或linLayerID的值超出范围。
MCDNN_STATUS_INVALID_VALUE
linLayerBias向量的某些元素位于wDesc描述符指定的w缓冲区边界之外。
6.2.1.24. mcdnnGetRNNLinLayerMatrixParams()
此函数保留API,不再单独实现。使用mcdnnGetRNNWeightParams()代替mcdnnGetRNNLinLayerMatrixParams()。
mcdnnStatus_t mcdnnGetRNNLinLayerMatrixParams(
mcdnnHandle_t handle,
const mcdnnRNNDescriptor_t rnnDesc,
const int pseudoLayer,
const mcdnnTensorDescriptor_t xDesc,
const mcdnnFilterDescriptor_t wDesc,
const void *w,
const int linLayerID,
mcdnnFilterDescriptor_t linLayerMatDesc,
void **linLayerMat)
该函数用于获取循环网络中每个伪层的每个RNN权重矩阵的指针和描述符(由rnnDesc定义),以及在xDesc中指定的其输入宽度。
备注
mcdnnGetRNNLinLayerMatrixParams()函数已在mcDNN中得到增强,但未更改其原型。该函数不报告卷积核描述符linLayerMatDesc中每个权重矩阵的元素总数,而是以两个维度返回矩阵大小:行和列。此外,当权重矩阵不存在时(例如,MCDNN_SKIP_INPUT模式),函数在linLayerMat中返回NULL,并且linLayerMatDesc的所有字段均为零。
mcdnnGetRNNLinLayerMatrixParams()函数以两个维度返回RNN矩阵大小:行和列。这允许用户轻松打印和初始化RNN权重矩阵。每个权重矩阵中的元素按行主序(row-major)排列。
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入。已初始化的RNN描述符。
pseudoLayer
输入。要查询的伪层。在单向RNN中,伪层与物理层相同(pseudoLayer=0是RNN输入层,pseudoLayer=1是第一个隐藏层)。 在双向RNN中,伪层的数量是物理层的两倍。
pseudoLayer=0是指物理输入层的正向部分
pseudoLayer=1是指物理输入层的反向部分
pseudoLayer=2是第一个隐藏层的正向部分,依此类推
xDesc
输入。一个完全压缩的张量描述符,描述一个循环迭代的输入(以检索RNN输入宽度)。
wDesc
输入。已初始化的卷积核描述符的句柄,描述RNN权重。
w
输入。数据指针,指向与卷积核描述符wDesc关联的GPU内存。
linLayerID
输入。线性层,获取以下信息:
若rnnDesc中mode设置为MCDNN_RNN_RELU或MCDNN_RNN_TANH:
值0表示应用于输入的bias,输入来自上一层(如果rnnDesc中的biasMode为MCDNN_RNN_SINGLE_INP_BIAS或MCDNN_RNN_DOUBLE_BIAS,则相关)。
值1表示应用于循环输入的bias(如果rnnDesc中的BiasMode为MCDNN_RNN_DOUBLE_BIAS或MCDNN_RNN_SINGLE_REC_BIAS,则相关)。
若rnnDesc中mode设置为MCDNN_LSTM:
值0、1、2表示应用于输入的bias,输入来自上一层(如果rnnDesc中的biasMode为MCDNN_RNN_SINGLE_INP_BIAS或MCDNN_RNN_DOUBLE_BIAS,则相关)。
值4、5、6、7表示应用于循环输入的bias(如果rnnDesc中的BiasMode为MCDNN_RNN_DOUBLE_BIAS或MCDNN_RNN_SINGLE_REC_BIAS,则相关)。
值及其相关门:
值0和4表示输入门。
值1和5表示遗忘门。
值2和6表示新的内存门。
值3和7表示输出门。
若rnnDesc中mode设置为MCDNN_GRU:
值0、1、2表示应用于输入的bias,输入来自上一层(如果rnnDesc中的biasMode为MCDNN_RNN_SINGLE_INP_BIAS或MCDNN_RNN_DOUBLE_BIAS,则相关)。
值3、4、5表示应用于循环输入的bias(如果rnnDesc中的BiasMode为MCDNN_RNN_DOUBLE_BIAS或MCDNN_RNN_SINGLE_REC_BIAS,则相关)。
值及其相关门:
值0和3表示重置门。
值1和4表示更新门。
值2和5表示新的内存门。
有关模式和bias模式的更多信息,请参见mcdnnRNNMode_t。
linLayerMatDesc
输出。已创建的卷积核描述符的句柄。当权重矩阵不存在时,返回的卷积核描述符的所有字段设置为零。
linLayerMat
输出。数据指针,指向与卷积核描述符linLayerMatDesc关联的GPU内存。当权重矩阵不存在时,返回的指针为NULL。
返回值
MCDNN_STATUS_SUCCESS
查询成功。
MCDNN_STATUS_NOT_SUPPORTED
此函数不支持已提供的配置。
MCDNN_STATUS_BAD_PARAM
需至少满足以下任一条件:
以下任一参数为NULL:handle、rnnDesc、xDesc、wDesc、linLayerMatDesc、linLayerMat。
检测到rnnDesc和其他描述符之间数据类型不匹配。
不满足w指针对齐的最低要求。
pseudoLayer或linLayerID的值超出范围。
MCDNN_STATUS_INVALID_VALUE
linLayerMat向量的某些元素位于wDesc描述符指定的w缓冲区边界之外。
6.2.1.25. mcdnnGetRNNMatrixMathType()
此函数保留API,不再单独实现。使用mcdnnGetRNNDescriptor_v8()代替mcdnnGetRNNMatrixMathType()。
mcdnnStatus_t mcdnnGetRNNMatrixMathType(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnMathType_t *mType);
此函数用于检索MMA的首选设置。有关详细信息,请参见mcdnnMathType_t说明。
参数
rnnDesc
输入。已创建和初始化的RNN描述符。
mType
输出。存储Tensor Core首选设置的地址。
返回值
MCDNN_STATUS_SUCCESS
已成功检索到请求的RNN描述符字段。
MCDNN_STATUS_BAD_PARAM
找到一个无效的输入变量(rnnDesc或mType为NULL)。
6.2.1.26. mcdnnGetRNNPaddingMode()
此函数保留API,不再单独实现。使用mcdnnGetRNNDescriptor_v8()代替mcdnnGetRNNPaddingMode()。
mcdnnStatus_t mcdnnGetRNNPaddingMode(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNPaddingMode_t *paddingMode)
此函数从RNN描述符检索RNN填充模式。
参数
rnnDesc
输入/输出。已创建的RNN描述符。
paddingMode
输入。指针,指向保存RNN填充模式的主机内存。
返回值
MCDNN_STATUS_SUCCESS
已成功检索RNN填充模式参数。
MCDNN_STATUS_BAD_PARAM
rnnDesc或 *paddingMode 为NULL。
6.2.1.27. mcdnnGetRNNParamsSize()
此函数保留API,不再单独实现。使用mcdnnGetRNNWeightSpaceSize()代替mcdnnGetRNNParamsSize()。
mcdnnStatus_t mcdnnGetRNNParamsSize(
mcdnnHandle_t handle,
const mcdnnRNNDescriptor_t rnnDesc,
const mcdnnTensorDescriptor_t xDesc,
size_t *sizeInBytes,
mcdnnDataType_t dataType)
此函数用于查询执行rnnDesc描述的RNN所需的参数空间量,以及xDesc定义的输入维度。
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入。已初始化的RNN描述符。
xDesc
输入。一个完全压缩的张量描述符,描述一个循环迭代的输入。
sizeInBytes
输出。使用指定的描述符和输入张量执行RNN所需的最小GPU内存量,作为参数空间。
dataType
输入。参数的数据类型。
返回值
MCDNN_STATUS_SUCCESS
查询成功。
MCDNN_STATUS_BAD_PARAM
需至少满足以下任一条件:
rnnDesc描述符无效。
xDesc描述符无效。
xDesc描述符未完全压缩。
dataType和张量描述符数据类型的组合无效。
MCDNN_STATUS_NOT_SUPPORTED
不支持RNN描述符和张量描述符的组合。
6.2.1.28. mcdnnGetRNNProjectionLayers()
此函数保留API,不再单独实现。使用mcdnnGetRNNDescriptor_v8()代替mcdnnGetRNNProjectionLayers()。
mcdnnStatus_t mcdnnGetRNNProjectionLayers(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
int *recProjSize,
int *outProjSize)
此函数用于检索当前RNN投影参数。在默认情况下,投影功能是禁用的,因此调用此函数将产生与hiddenSize和outProjSize相等的recProjSize(设置为0)。使用mcdnnSetRNNProjectionLayers()启用RNN投影。
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入。已创建和初始化的RNN描述符。
recProjSize
输出。指针,指向应存储循环投影大小的位置。
outProjSize
输出。指针,指向应存储输出投影大小的位置。
返回值
MCDNN_STATUS_SUCCESS
已成功检索RNN投影参数。
MCDNN_STATUS_BAD_PARAM
将一个NULL指针传入了此函数。
6.2.1.29. mcdnnGetRNNTempSpaceSizes()
此函数根据存储在rnnDesc中的RNN网络几何图形,fMode参数定义的指定用法(推理或训练)以及从xDesc检索的当前RNN数据维度(maxSeqLength,batchSize),计算工作空间和预留空间缓冲区大小。当RNN数据维度更改时,必须再次调用mcdnnGetRNNTempSpaceSizes(),因为RNN临时缓冲区大小不是单调性的。
mcdnnStatus_t mcdnnGetRNNTempSpaceSizes(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
mcdnnForwardMode_t fMode,
mcdnnRNNDataDescriptor_t xDesc,
size_t *workSpaceSize,
size_t *reserveSpaceSize);
当不需要检索到的值时,用户可以将NULL分配给workSpaceSize或reserveSpaceSize指针。
参数
handle
输入。当前的mcDNN上下文句柄。
rnnDesc
输入。已初始化的RNN描述符。
fMode
输入。指定是在推理模式还是训练模式中使用临时缓冲区。推理期间不使用预留空间缓冲区。因此,当fMode参数为MCDNN_FWD_MODE_INFERENCE时,返回的预留空间缓冲区大小为0。
xDesc
输入。指定当前RNN数据维度的单个RNN数据描述符:maxSeqLength和batchSize。
workSpaceSize
输出。作为工作空间缓冲区所需的最小GPU内存量(以字节为单位)。工作空间缓冲区不用于在API之间传递中间结果,而是用作临时读/写缓冲区。
reserveSpaceSize
输出。作为预留空间缓冲区所需的最小GPU内存量(以字节为单位)。预留空间缓冲区用于将中间结果从mcdnnRNNForward()传递到RNN BackwardData和BackwardWeights函数,这些函数计算与RNN输入或可训练权重和bias相关的一阶导数。
返回值
MCDNN_STATUS_SUCCESS
已成功计算RNN临时缓冲区大小。
MCDNN_STATUS_BAD_PARAM
检测到一个无效的输入参数。
MCDNN_STATUS_NOT_SUPPORTED
检测到不兼容或不支持的输入参数组合。
6.2.1.30. mcdnnGetRNNTrainingReserveSize()
此函数保留API,不再单独实现。使用mcdnnGetRNNTempSpaceSizes()代替mcdnnGetRNNTrainingReserveSize()。
mcdnnStatus_t mcdnnGetRNNTrainingReserveSize(
mcdnnHandle_t handle,
const mcdnnRNNDescriptor_t rnnDesc,
const int seqLength,
const mcdnnTensorDescriptor_t *xDesc,
size_t *sizeInBytes)
此函数用于查询训练rnnDesc描述的RNN所需的预留空间量,以及xDesc定义的输入维度。必须对mcdnnRNNForwardTraining()、mcdnnRNNBackwardData()和mcdnnRNNBackwardWeights()传入相同的预留空间缓冲区。每一个调用都会覆盖预留空间的内容。但是,如果需要内存重用,则可以在调用之间安全备份和恢复预留空间。
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入。已初始化的RNN描述符。
seqLength
输入。要展开的迭代次数。seqLength的值不能超过mcdnnGetRNNWorkspaceSize()函数中用于查询执行RNN所需的工作空间大小。
xDesc
输入。张量描述符数组,描述每个循环迭代的输入(一个迭代一个描述符)。张量的第一维(批大小)可能从元素n减少到元素n+1,但可能不会增加。每个张量描述符必须具有相同的第二维(向量长度)。
sizeInBytes
输出。使用指定的描述符和输入张量训练RNN所需的最小GPU内存量,作为预留空间。
返回值
MCDNN_STATUS_SUCCESS
查询成功。
MCDNN_STATUS_BAD_PARAM
需至少满足以下任一条件:
rnnDesc描述符无效。
xDesc中至少有一个描述符是无效的。
xDesc中描述符的第二维,步幅或数据类型不一致。
xDesc中描述符的第一维有递增。
xDesc中描述符未完全压缩。
MCDNN_STATUS_NOT_SUPPORTED
xDesc描述的张量的数据类型不受支持。
6.2.1.31. mcdnnGetRNNWeightParams()
此函数用于获取循环网络中每个伪层的每个RNN权重矩阵和bias向量的起始地址和形状。
mcdnnStatus_t mcdnnGetRNNWeightParams(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
int32_t pseudoLayer,
size_t weightSpaceSize,
const void *weightSpace,
int32_t linLayerID,
mcdnnTensorDescriptor_t mDesc,
void **mAddr,
mcdnnTensorDescriptor_t bDesc,
void **bAddr);
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入。已初始化的RNN描述符。
pseudoLayer
输入。要查询的伪层。在单向RNN中,伪层与物理层相同(pseudoLayer=0是RNN输入层,pseudoLayer=1是第一个隐藏层)。在双向RNN中,伪层的数量是物理层的两倍:
pseudoLayer=0是指物理输入层的正向子层
pseudoLayer=1是指物理输入层的反向子层
pseudoLayer=2是第一个隐藏层的正向子层,依此类推
weightSpaceSize
输入。权重空间缓冲区的大小(以字节为单位)。
weightSpace
输入。指向权重空间缓冲区的指针。
linLayerID
输入。权重矩阵或bias向量线性ID索引。
若rnnDesc中cellMode设置为MCDNN_RNN_RELU或MCDNN_RNN_TANH:
值0表示与来自上一层的输入或RNN模型的输入结合使用的权重矩阵或bias向量。
值1表示与上一时间步的隐藏状态或初始隐藏状态结合使用的权重矩阵或bias向量。
若rnnDesc中cellMode设置为MCDNN_LSTM:
值0、1、2、3表示与来自上一层的输入或RNN模型的输入结合使用的权重矩阵或bias向量。
值4、5、6、7表示与上一时间步的隐藏状态或初始隐藏状态结合使用的权重矩阵或bias向量。
值8对应于投影矩阵(如果已启用),此操作中没有bias。
值及其LSTM门(gate):
linLayerID0和4对应于输入门。
linLayerID1和5对应于遗忘门。
linLayerID2和6对应于双曲正切的新单元状态计算。
linLayerID3和7对应于输出门。
若rnnDesc中cellMode设置为MCDNN_GRU:
值0、1、2表示与来自上一层的输入或RNN模型的输入结合使用的权重矩阵或bias向量。
值3、4、5表示与上一时间步的隐藏状态或初始隐藏状态结合使用的权重矩阵或bias向量。
值及其GRU门(gate):
linLayerID0和4对应于重置门。
linLayerID1和4对应于更新门。
linLayerID2和5对应于双曲正切的新隐藏状态计算。
有关模式和bias模式的更多信息,请参见mcdnnRNNMode_t。
mDesc
输出。已创建的张量描述符的句柄。相应的权重矩阵的形状将以以下格式在此描述符中返回:dimA[3] = {1, rows, cols}。当权重矩阵不存在时,报告的张量维数为0。当选择MCDNN_SKIP_INPUT时,第一层的输入GEMM矩阵会出现这种情况;当禁用该功能时,LSTM投影矩阵会出现这种情况。
mAddr
输出。指针,指向权重空间缓冲区内权重矩阵的起始点。当权重矩阵不存在时,返回的地址为NULL。
bDesc
输出。已创建的张量描述符的句柄。相应的bias向量的形状将以以下格式在此描述符中返回:dimA[3] = {1, rows, 1}。当bias向量不存在时,报告的张量维数为0。
bAddr
输出。指针,指向权重空间缓冲区内bias向量的起始点。当bias向量不存在时,返回的地址为NULL。
返回值
MCDNN_STATUS_SUCCESS
查询已成功完成。
MCDNN_STATUS_BAD_PARAM
遇到无效的输入参数。例如,pseudoLayer的值超出范围或linLayerID为负或大于8。
MCDNN_STATUS_INVALID_VALUE
某些权重/bias元素位于权重空间缓冲区边界之外。
MCDNN_STATUS_NOT_INITIALIZED
RNN描述符是使用旧的mcdnnSetRNNDescriptor_v6()进行配置的。
6.2.1.32. mcdnnGetRNNWeightSpaceSize()
此函数用于报告权重空间缓冲区所需的大小(以字节为单位)。权重空间缓冲区包含所有RNN权重矩阵和bias向量。
mcdnnStatus_t mcdnnGetRNNWeightSpaceSize(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
size_t *weightSpaceSize);
参数
handle
输入。当前的mcDNN上下文句柄。
rnnDesc
输入。已初始化的RNN描述符。
weightSpaceSize
输出。所有RNN可训练参数所需的最小GPU内存(以字节为单位)。
返回值
MCDNN_STATUS_SUCCESS
查询成功。
MCDNN_STATUS_BAD_PARAM
遇到无效的输入参数。例如,任意输入参数均为NULL。
MCDNN_STATUS_NOT_INITIALIZED
RNN描述符是使用旧的mcdnnSetRNNDescriptor_v6()进行配置的。
6.2.1.33. mcdnnGetRNNWorkspaceSize()
此函数保留API,不再单独实现。使用mcdnnGetRNNTempSpaceSizes()代替mcdnnGetRNNWorkspaceSize()。
mcdnnStatus_t mcdnnGetRNNWorkspaceSize(
mcdnnHandle_t handle,
const mcdnnRNNDescriptor_t rnnDesc,
const int seqLength,
const mcdnnTensorDescriptor_t *xDesc,
size_t *sizeInBytes)
此函数用于查询执行rnnDesc描述的RNN所需的工作空间量,以及xDesc定义的输入维度。
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入。已初始化的RNN描述符。
seqLength
输入。要展开的迭代次数。根据此函数提供的大小来分配的工作空间,不能用于比seqLength长的序列。
xDesc
输入。张量描述符数组,描述每个循环迭代的输入(一个迭代一个描述符)。张量的第一维(批大小)可能从元素n减少到元素n+1,但可能不会增加。例如,如果batch中有多个时间序列,序列长度可以不同。此维度是序列特定迭代的批大小,因此当batch中的序列终止时,维度应减小。 每个张量描述符必须具有相同的第二维(向量长度)。
sizeInBytes
输出。使用指定的描述符和输入张量执行RNN所需的最小GPU内存量,作为工作空间。
返回值
MCDNN_STATUS_SUCCESS
查询成功。
MCDNN_STATUS_BAD_PARAM
需至少满足以下任一条件:
rnnDesc描述符无效。
xDesc中至少有一个描述符是无效的。
xDesc中描述符的第二维,步幅或数据类型不一致。
xDesc中描述符的第一维在增长。
xDesc中描述符未完全压缩。
MCDNN_STATUS_NOT_SUPPORTED
xDesc描述的张量的数据类型不受支持。
6.2.1.34. mcdnnGetSeqDataDescriptor()
此函数用于从已创建的序列数据描述符中检索设置。当不需要检索到的值时,用户可以将NULL分配给除seqDataDesc之外的任意指针。nbDimsRequested参数适用于dimA[]和axes[]数组。当相应的dimA[]、axes[]或seqLengthArray[]数组为NULL时,将忽略nbDimsRequested或seqLengthSizeRequested的正值。
mcdnnStatus_t mcdnnGetSeqDataDescriptor(
const mcdnnSeqDataDescriptor_t seqDataDesc,
mcdnnDataType_t *dataType,
int *nbDims,
int nbDimsRequested,
int dimA[],
mcdnnSeqDataAxis_t axes[],
size_t *seqLengthArraySize,
size_t seqLengthSizeRequested,
int seqLengthArray[],
void *paddingFill);
mcdnnGetSeqDataDescriptor()函数不用于报告序列数据缓冲区中的实际步幅。这些步幅可用于计算任意序列数据元素的偏移量。用户必须根据mcdnnGetSeqDataDescriptor()函数报告的axes[]和dimA[]数组来预计算步幅。以下为执行此任务的示例代码:
// Array holding sequence data strides.
size_t strA[MCDNN_SEQDATA_DIM_COUNT] = {0};
// Compute strides from dimension and order arrays.
size_t stride = 1;
for (int i = nbDims - 1; i >= 0; i--) {
int j = int(axes[i]);
if (unsigned(j) < MCDNN_SEQDATA_DIM_COUNT-1 && strA[j] == 0) {
strA[j] = stride;
stride *= dimA[j];
} else {
fprintf(stderr, "ERROR: invalid axes[%d]=%d\n\n", i, j);
abort();
}
}
现在,strA[]数组可用于计算任意序列数据元素的索引,例如:
// Using four indices (batch, beam, time, vect) with ranges already checked.
size_t base = strA[MCDNN_SEQDATA_BATCH_DIM] * batch
+ strA[MCDNN_SEQDATA_BEAM_DIM] * beam
+ strA[MCDNN_SEQDATA_TIME_DIM] * time;
val = seqDataPtr[base + vect];
以上代码假定四个索引(batch、beam、time、vect)都小于dimA[]数组中的相应值。示例代码还省略了strA[MCDNN_SEQDATA_VECT_DIM]步幅,因为其值始终为1,即一个向量的元素占用一个连续的内存块。
参数
seqDataDesc
输入。序列数据描述符。
dataType
输出。序列数据缓冲区中使用的数据类型。
nbDims
输出。dimA[]和axes[]数组中的活动维数。
nbDimsRequested
输入。从索引0开始,可写入dimA[]和axes[]数组的连续元素的最大数量。建议设置此参数的值为MCDNN_SEQDATA_DIM_COUNT。
dimA[]
输出。包含序列数据维度的整数数组。
axes[]
输出。mcdnnSeqDataAxis_t数组,用于定义内存中序列数据的布局。
seqLengthArraySize
输出。seqLengthArray[]中保存所有序列长度所需的元素数。
seqLengthSizeRequested
输入。从索引0开始,可写入seqLengthArray[]数组的连续元素的最大数量。
seqLengthArray[]
输出。包含序列长度的整数数组。
paddingFill
输出。指针,指向具有填充值的dataType存储位置,该填充值应写入所有填充向量。未请求输出填充向量的显式初始化时,使用NULL。
返回值
MCDNN_STATUS_SUCCESS
已成功检索到请求的序列数据描述符字段。
MCDNN_STATUS_BAD_PARAM
找到一个无效的输入参数。
MCDNN_STATUS_INTERNAL_ERROR
内部状态不一致。
6.2.1.35. mcdnnMultiHeadAttnForward()
mcdnnMultiHeadAttnForward()函数用于计算多头注意力层的正向响应。当reserveSpaceSizeInBytes=0且reserveSpace=NULL时,在推理模式下,该函数不调用反向(梯度)函数,否则为训练模式。在训练模式中,预留空间用于将中间结果从mcdnnMultiHeadAttnForward()传送到mcdnnMultiHeadAttnBackwardData(),以及从mcdnnMultiHeadAttnBackwardData()传送到mcdnnMultiHeadAttnBackwardWeights()。
mcdnnStatus_t mcdnnMultiHeadAttnForward(
mcdnnHandle_t handle,
const mcdnnAttnDescriptor_t attnDesc,
int currIdx,
const int loWinIdx[],
const int hiWinIdx[],
const int devSeqLengthsQO[],
const int devSeqLengthsKV[],
const mcdnnSeqDataDescriptor_t qDesc,
const void *queries,
const void *residuals,
const mcdnnSeqDataDescriptor_t kDesc,
const void *keys,
const mcdnnSeqDataDescriptor_t vDesc,
const void *values,
const mcdnnSeqDataDescriptor_t oDesc,
void *out,
size_t weightSizeInBytes,
const void *weights,
size_t workSpaceSizeInBytes,
void *workSpace,
size_t reserveSpaceSizeInBytes,
void *reserveSpace);
在推理模式中,currIdx指定要处理的嵌入向量的时间步或序列索引。在此模式下,用户可以对时间步0(currIdx=0)执行一次迭代,然后更新Q,K,V向量和注意力窗口,并执行下一个时间步(currIdx=1)。所有时间步都可以重复迭代过程。
当所有的Q时间步都可用时(例如,在训练模式或自注意力机制编码器端的推理模式中),用户可以为currIdx分配一个负值,mcdnnMultiHeadAttnForward() API将自动扫描所有的Q时间步。
loWinIdx[]和hiWinIdx[]主机数组指定每个Q时间步的注意力窗口大小。在典型自注意力场景下,用户必须包含所有已访问过的嵌入向量,但不包括当前或未来的向量。在这种情况下,用户需要设置:
currIdx=0: loWinIdx[0]=0; hiWinIdx[0]=0; // initial time-step, no attention window
currIdx=1: loWinIdx[1]=0; hiWinIdx[1]=1; // attention window spans one vector
currIdx=2: loWinIdx[2]=0; hiWinIdx[2]=2; // attention window spans two vectors
(...)
当mcdnnMultiHeadAttnForward()中currIdx为负数时,必须为所有时间步完全初始化loWinIdx[]和hiWinIdx[]数组。当用currIdx=0,currIdx=1,currIdx=2等调用mcdnnMultiHeadAttnForward()时,用户只能在调用正向响应函数之前更新loWinIdx[currIdx]和hiWinIdx[currIdx]元素。不会访问loWinIdx[]和hiWinIdx[]数组中的所有其他元素。任意自适应注意力窗口机制都可以通过这种方式实现。
当注意力窗口应为最大尺寸时(例如,交叉注意力),请使用以下设置:
currIdx=0: loWinIdx[0]=0; hiWinIdx[0]=maxSeqLenK;
currIdx=1: loWinIdx[1]=0; hiWinIdx[1]=maxSeqLenK;
currIdx=2: loWinIdx[2]=0; hiWinIdx[2]=maxSeqLenK;
(...)
上述maxSeqLenK值应等于或大于kDesc描述符中的dimA[MCDNN_SEQDATA_TIME_DIM]。更佳选择是使用limits.h中的maxSeqLenK=INT_MAX。
备注
mcdnnSetSeqDataDescriptor()的seqLengthArray[]中定义的任意K序列的实际长度可以短于maxSeqLenK。有效注意力窗口跨度是根据存储在K序列描述符中的seqLengthArray[]以及包含在loWinIdx[]和hiWinIdx[]数组中的索引计算的。
devSeqLengthsQO[]和devSeqLengthsKV[]是指向具有Q,O和K,V序列长度的设备(非主机)数组的指针。请注意,相同的信息也会传入主机端相应的mcdnnSeqDataDescriptor_t类型描述符中。mcDNN调用的异步性质以及专用于GPU内核参数的有限常量内存,使得需要额外的设备数组。当mcdnnMultiHeadAttnForward() API返回时,存储在描述符中的序列长度数组可在下一次迭代中立即修改。但是,由正向调用启动的GPU内核此时可能尚未启动。因此,序列数组需要拷贝到设备端,以便GPU内核直接访问。如果没有设备内存分配和MXMACA流同步,则无法在mcdnnMultiHeadAttnForward()函数内为非常大的K,V输入创建这些拷贝。
为了减少mcdnnMultiHeadAttnForward() API的开销,未验证devSeqLengthsQO[]和devSeqLengthsKV[]设备数组是否包含与序列数据描述符中seqLengthArray[]相同的设置。
kDesc和vDesc描述符中的序列长度应相同。同样,qDesc和oDesc描述符中的序列长度应匹配。用户可以在qDesc、kDesc、vDesc和oDesc描述符中定义六种不同的数据布局。有关这些布局的信息,请参见mcdnnSetSeqDataDescriptor()函数。所有多头注意力API调用都需要在所有序列数据描述符中使用相同的布局。
在Transformer模型中,多头注意力块与层归一化和残差连接(residual connection)紧密耦合。mcdnnMultiHeadAttnForward()不包含层归一化,但可用于处理下图所示的残差连接。
图 6.1 多头注意力块与层归一化和残差连接紧密耦合
查询和残差在mcdnnMultiHeadAttnForward()中共享相同的qDesc描述符。禁用残差连接时,残差指针应为NULL。启用残差连接时,qDesc中的向量长度应与oDesc描述符中指定的向量长度匹配,因此向量加法是可行的。
queries、keys、values 指针不能为NULL,即使K和V是相同的输入或Q,K,V是相同的输入。
参数
handle
输入。当前的mcDNN上下文句柄。
attnDesc
输入。已初始化的注意力描述符。
currIdx
输入。查询中要处理的时间步。当currIdx参数为负值时,将处理所有Q时间步。当currIdx为零或正时,仅为选定的时间步计算正向响应。后一个输入只能在推理模式中使用,以处理一个时间步,同时更新下一个注意力窗口和Q,R,K,V输入之间的调用。
loWinIdx[], hiWinIdx[]
输入。两个主机整数组,指定每个Q时间步的注意力窗口的起始和结束索引。包含K,V集合中的起始索引,而不包含结束索引。
devSeqLengthsQO[]
输入。设备数组,指定查询、残差和输出序列数据的序列长度。
devSeqLengthsKV[]
输入。设备数组,指定键和值输入数据的序列长度。
qDesc
输入。查询和残差序列数据的描述符。
queries
输入。指向设备内存中查询数据的指针。
residuals
输入。指向设备内存中残差数据的指针。如果不需要残差连接,将此参数设置为NULL。
kDesc
输入。键序列数据的描述符。
keys
输入。指向设备内存中键数据的指针。
vDesc
输入。值序列数据的描述符。
values
输入。指向设备内存中值数据的指针。
oDesc
输入。多头注意力输出序列数据的描述符。
out
输出。指针,指向应写入输出响应的设备内存。
weightSizeInBytes
输入。权重缓冲区的大小(以字节为单位),存储了所有多头注意力可训练参数。
weights
输入。指向设备内存中权重缓冲区的指针。
workSpaceSizeInBytes
输入。用于临时API存储的工作空间缓冲区大小(以字节为单位)。
workSpace
输入/输出。指向设备内存中工作空间缓冲区的指针。
reserveSpaceSizeInBytes
输入。用于在正向和反向(梯度)API调用之间进行数据交换的预留空间缓冲区大小(以字节为单位)。此参数在推理模式中应为零,在训练模式中应为非零。
reserveSpace
输入/输出。指向设备内存中预留空间缓冲区的指针。此参数在推理模式中应为NULL,在训练模式中应为非NULL。
返回值
MCDNN_STATUS_SUCCESS
处理API输入参数和启动GPU内核时,未检测到错误。
MCDNN_STATUS_BAD_PARAM
遇到一个无效或不兼容的输入参数。例如:
所需的输入指针为NULL
currIdx的值超出了范围
注意力、查询、键、值、输出的描述符值相互不兼容
MCDNN_STATUS_EXECUTION_FAILED
启动GPU内核的过程返回错误,或之前的内核未成功完成。
MCDNN_STATUS_INTERNAL_ERROR
内部状态不一致。
MCDNN_STATUS_NOT_SUPPORTED
请求的选项或输入参数组合不受支持。
MCDNN_STATUS_ALLOC_FAILED
共享内存不足,无法启动GPU内核。
6.2.1.36. mcdnnRNNForward()
此函数使用x、hx、cx中的输入和weightSpace缓冲区中的权重/bias,以计算rnnDesc描述的循环神经网络的正向响应。将RNN输出写入y、hy、cy缓冲区。多层RNN模型中的x、y、hx、cx、hy、cy信号的位置如下图所示。请注意,时间步之间和层之间的内部RNN信号不会向用户公开。
mcdnnStatus_t mcdnnRNNForward(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
mcdnnForwardMode_t fwdMode,
const int32_t devSeqLengths[],
mcdnnRNNDataDescriptor_t xDesc,
const void *x,
mcdnnRNNDataDescriptor_t yDesc,
void *y,
mcdnnTensorDescriptor_t hDesc,
const void *hx,
void *hy,
mcdnnTensorDescriptor_t cDesc,
const void *cx,
void *cy,
size_t weightSpaceSize,
const void *weightSpace,
size_t workSpaceSize,
void *workSpace,
size_t reserveSpaceSize,
void *reserveSpace);
图 6.2 多层RNN模型中的x、y、hx、cx、hy、cy信号的位置
下图描述了RNN模型为双向时的数据流。在这种模式下,每个RNN物理层由两个连续的伪层组成,每个伪层都有其权重、bias、初始隐藏状态hx,对于LSTM,还有初始单元状态cx。伪层0、2、4会从左到右或在正向(F)方向处理输入向量。奇数伪层1、3、5会从右向左或在反向(R)方向处理输入向量。两个连续的伪层在相同的输入向量上操作,只是顺序不同。伪层0和1访问存储在x缓冲区中的原始序列。F和R单元的输出是串联的,因此输入到下两个伪层的向量的长度为2xhiddenSize或2xprojSize。后续伪层中的输入GEMM将向量长度调整为1xhiddenSize。
图 6.3 RNN模型为双向时的数据流
当fwdMode参数设置为MCDNN_FWD_MODE_TRAINING时,mcdnnRNNForward ()函数将在预留空间缓冲区中存储计算一阶导数所需的中间数据。工作空间和预留空间缓冲区大小应由mcdnnGetRNNTempSpaceSizes()函数计算,该函数的fwdMode设置与mcdnnRNNForward()调用中使用的设置相同。
必须在xDesc和yDesc描述符中指定相同的布局类型。必须在xDesc、yDesc和设备数组devSeqLengths中配置相同的序列长度。mcdnnRNNForward()函数不用于验证存储在GPU内存中devSeqLengths的序列长度与CPU内存中xDesc和yDesc描述符中的是否相同。但是,会检查xDesc和yDesc描述符中的序列长度数组是否一致。
参数
handle
输入。当前的mcDNN上下文句柄。
rnnDesc
输入。已初始化的RNN描述符。
fwdMode
输入。指定推理或训练模式(MCDNN_FWD_MODE_INFERENCE和MCDNN_FWD_MODE_TRAINING)。在训练模式下,其他数据存储在预留空间缓冲区中。此信息用于在反向传递中计算导数。
devSeqLengths
输入。RNN数据描述符xDesc或yDesc中seqLengthArray的拷贝。devSeqLengths数组必须存储在GPU内存中,因为该数组可能在mcdnnRNNForward()函数之后,被GPU内核异步访问。此参数不能为NULL。
xDesc
输入。与RNN模型主输入对应的已初始化的描述符。 dataType、layout、maxSeqLength、batchSize和seqLengthArray必须与yDesc中的匹配。vectorSize参数必须与传入mcdnnSetRNNDescriptor_V8函数的inputSize参数匹配。
x
输入。数据指针,指向与RNN数据描述符xDesc关联的GPU内存。向量应根据xDesc指定的布局在内存中排列。张量中的元素(包括填充向量)必须紧密压缩。
yDesc
输入。已初始化的RNN数据描述符。dataType、layout、maxSeqLength、batchSize和seqLengthArray必须与xDesc中相应参数匹配。 vectorSize参数取决于是否启用了LSTM投影以及网络是否为双向。具体而言:
对于单向模型,vectorSize参数必须与传入mcdnnSetRNNDescriptor_v8()的hiddenSize参数匹配。如果启用了LSTM投影,则vectorSize必须与传入mcdnnSetRNNDescriptor_v8()的projSize参数相同。
对于双向模型,如果RNN cellMode为MCDNN_LSTM且启用了投影功能,则vectorSize参数必须是传入mcdnnSetRNNDescriptor_v8()的projSize参数的2倍。否则,应该为hiddenSize的2倍。
y
输出。数据指针,指向与RNN数据描述符yDesc关联的GPU内存。向量应根据yDesc指定的布局在内存中排布。张量中的元素(包括填充向量中的元素)必须紧密压缩,且不支持步幅。
hDesc
输入。描述RNN初始或最终隐藏状态的张量描述符。隐藏状态数据为完全压缩格式。 张量的第一维取决于传入mcdnnSetRNNDescriptor_v8()函数的dirMode参数。
如果dirMode为MCDNN_UNIDIRECTIONAL,则第一维应与传入mcdnnSetRNNDescriptor_v8()的numLayers参数匹配。
如果dirMode为MCDNN_BIDIRECTIONAL,则第一维应是传入mcdnnSetRNNDescriptor_v8()的numLayers参数的2倍。
第二维必须与xDesc中描述的batchSize参数匹配。 第三维取决于RNN模式是否为MCDNN_LSTM以及是否启用了LSTM投影。具体而言: 如果RNN模式为MCDNN_LSTM且启用了LSTM投影,则第三维必须与传入mcdnnSetRNNProjectionLayers()调用的projSize参数匹配。 否则,第三维必须与传入mcdnnSetRNNDescriptor_v8()调用的hiddenSize参数匹配,其中mcdnnSetRNNDescriptor_v8()是用于初始化rnnDesc。
hx
输入。指针,指向具有RNN初始隐藏状态的GPU缓冲区。数据维度由hDesc张量描述符描述。如果传入NULL指针,则网络的初始隐藏状态将初始化为零。
hy
输出。指针,指向存储RNN最终隐藏状态的GPU缓冲区。数据维度由hDesc张量描述符描述。如果传入NULL指针,将不会保存网络的最终隐藏状态。
cDesc
输入。仅适用于LSTM网络。仅描述LSTM网络初始或最终单元状态的张量描述符。 单元状态数据为完全压缩格式。 张量的第一维取决于传入mcdnnSetRNNDescriptor_v8()函数的dirMode参数。
如果dirMode为MCDNN_UNIDIRECTIONAL,则第一维应与传入mcdnnSetRNNDescriptor_v8()的numLayers参数匹配。
如果dirMode为MCDNN_BIDIRECTIONAL,则第一维应是传入mcdnnSetRNNDescriptor_v8()的numLayers参数的2倍。
第二维必须与xDesc中描述的batchSize参数匹配。否则,第三维必须与传入mcdnnSetRNNDescriptor_v8()调用的hiddenSize参数匹配。
cx
输入。仅适用于LSTM网络。指针,指向存储LSTM初始隐藏状态的GPU缓冲区。数据维度由cDesc张量描述符描述。如果传入NULL指针,则网络的初始单元状态将初始化为零。
cy
输出。仅适用于LSTM网络。指针,指向存储LSTM最终状态数据的GPU缓冲区。数据维度由cDesc张量描述符描述。如果传入NULL指针,将不会保存LSTM单元状态。
weightSpaceSize
输入。指定已提供的权重空间缓冲区的大小(以字节为单位)。
weightSpace
输入。GPU内存中权重空间缓冲区的地址。
workSpaceSize
输入。指定已提供的工作空间缓冲区的大小(以字节为单位)。
workSpace
输入/输出。GPU内存中用于存储临时数据的工作空间缓冲区地址。
reserveSpaceSize
输入。指定预留空间缓冲区的大小(以字节为单位)。
reserveSpace
输入/输出。GPU内存中预留空间缓冲区的地址。
返回值
MCDNN_STATUS_SUCCESS
处理API输入参数和启动GPU内核时,未检测到错误。
MCDNN_STATUS_NOT_SUPPORTED
需至少满足以下任一条件:
在指定MCDNN_RNN_ALGO_PERSIST_STATIC或MCDNN_RNN_ALGO_PERSIST_DYNAMIC时,传入变量序列长度输入
在pre-Pascal设备上请求MCDNN_RNN_ALGO_PERSIST_STATIC或MCDNN_RNN_ALGO_PERSIST_DYNAMICC
“double”浮点类型用于输入/输出和MCDNN_RNN_ALGO_PERSIST_STATIC算法
MCDNN_STATUS_BAD_PARAM
遇到一个无效或不兼容的输入参数。例如:
一些输入描述符为NULL
rnnDesc、xDesc、yDesc、hDesc或cDesc描述符中至少有一个设置无效
weightSpaceSize、workSpaceSize或reserveSpaceSize太小。
MCDNN_STATUS_EXECUTION_FAILED
启动GPU内核的过程返回错误,或之前的内核未成功完成。
MCDNN_STATUS_ALLOC_FAILED
此函数不能用来分配CPU内存。
6.2.1.37. mcdnnRNNForwardInference()
此函数保留API,不再单独实现。使用mcdnnRNNForward()代替mcdnnRNNForwardInference()。
mcdnnStatus_t mcdnnRNNForwardInference(
mcdnnHandle_t handle,
const mcdnnRNNDescriptor_t rnnDesc,
const int seqLength,
const mcdnnTensorDescriptor_t *xDesc,
const void *x,
const mcdnnTensorDescriptor_t hxDesc,
const void *hx,
const mcdnnTensorDescriptor_t cxDesc,
const void *cx,
const mcdnnFilterDescriptor_t wDesc,
const void *w,
const mcdnnTensorDescriptor_t *yDesc,
void *y,
const mcdnnTensorDescriptor_t hyDesc,
void *hy,
const mcdnnTensorDescriptor_t cyDesc,
void *cy,
void *workspace,
size_t workSpaceSizeInBytes)
此函数使用输入x、hx、cx,权重w和输出y、hy、cy来执行rnnDesc描述的循环神经网络。需要工作空间用于中间存储。此函数不用于存储训练所需的中间数据;但mcdnnRNNForwardTraining()用于此目的。
参数
handle
输入。已创建的mcDNN上下文的句柄。
rnnDesc
输入。已初始化的RNN描述符。
seqLength
输入。要展开的迭代次数。seqLength的值不能超过mcdnnGetRNNWorkspaceSize()函数中用于查询执行RNN所需的工作空间大小。
xDesc
输入。完全压缩的张量描述符的seqLength数组。数组中的每个描述符都应具有三个维度,这些维度将输入数据格式描述为一个循环迭代(一个RNN时间步一个描述符)。 张量的第一维(批大小)可能从迭代n减少到迭代n+1,但可能不会增加。每个张量描述符必须具有相同的第二维(RNN输入向量长度inputSize)。每个张量的第三维需要为1。 输入数据应按列主序(column-major)排列,因此xDesc中的步幅应设置如下:
strideA[0]=inputSize, strideA[1]=1, strideA[2]=1
x
输入。数据指针,指向与张量描述符xDesc的数组关联的GPU内存。输入向量压缩会在迭代n的最后一个向量结束后直接从迭代n+1的第一个向量开始连续进行。换言之,所有RNN时间步的输入向量应填充在GPU内存的连续块中,且向量之间没有间隙。
hxDesc
输入。完全压缩的张量描述符,描述RNN的初始隐藏状态(initial hidden state)。 张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc所描述张量的第一维匹配。第三维必须与初始化rnnDesc的hiddenSize参数匹配。张量必须为完全压缩格式。
hx
输入。数据指针,指向与张量描述符hxDesc关联的GPU内存。如果传入NULL指针,则网络的初始隐藏状态将初始化为零。
cxDesc
输入。完全压缩的的张量描述符,描述LSTM网络的初始单元(cell)状态。 张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc中描述的张量的第一维匹配。第三维必须与初始化rnnDesc的hiddenSize参数匹配。张量必须为完全压缩格式。
cx
输入。数据指针,指向与张量描述符cxDesc关联的GPU内存。如果传入NULL指针,则网络的初始单元状态将初始化为零。
wDesc
输入。已初始化的卷积核描述符的句柄,描述RNN权重。
w
输入。数据指针,指向与卷积核描述符wDesc关联的GPU内存。
yDesc
输入。完全压缩的张量描述符数组,描述每个循环迭代输出(一个迭代一个描述符)。 张量的第二维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第二维应与hiddenSize参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第二维应是hiddenSize参数的2倍。
张量n的第一维必须与xDesc中张量n的第一维匹配。
y
输出。数据指针,指向与输出张量描述符yDesc关联的GPU内存。数据压缩会在迭代n的最后一个元素结束后直接从迭代n+1的第一个元素开始连续进行。
hyDesc
输入。完全压缩的张量描述符,描述RNN的最终隐藏状态。 张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc中描述的张量的第一维匹配。第三维必须与初始化rnnDesc的hiddenSize参数匹配。张量必须为完全压缩格式。
hy
输出。数据指针,指向与张量描述符hyDesc关联的GPU内存。如果传入NULL指针,将不会保存网络的最终隐藏状态。
cyDesc
输入。完全压缩的张量描述符,描述LSTM网络的最终单元状态。 张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc所描述张量的第一维匹配。 第三维必须与初始化rnnDesc的hiddenSize参数匹配。张量必须为完全压缩格式。
cy
输出。数据指针,指向与张量描述符cyDesc关联的GPU内存。如果传入NULL指针,将不会保存网络的最终单元状态。
workspace
输入。数据指针,指向要用作此调用工作空间的GPU内存。
workSpaceSizeInBytes
输入。指定已提供的workspace大小(以字节为单位)。
返回值
MCDNN_STATUS_SUCCESS
此函数启用成功。
MCDNN_STATUS_NOT_SUPPORTED
此函数不支持已提供的配置。
MCDNN_STATUS_BAD_PARAM
需至少满足以下任一条件:
rnnDesc描述符无效。
hxDesc、cxDesc、wDesc、hyDesc、cyDesc描述符中或者xDesc、yDesc描述符中至少有一个是无效的。
xDesc、hxDesc、cxDesc、wDesc、yDesc、hyDesc、cyDesc中任一描述符的步幅或维度不正确。
workSpaceSizeInBytes太小。
MCDNN_STATUS_INVALID_VALUE
在RNN描述符中选择MCDNN_RNN_ALGO_PERSIST_DYNAMIC时,在当前函数之前未调用mcdnnSetPersistentRNNPlan()。
MCDNN_STATUS_EXECUTION_FAILED
此函数在GPU上启用失败。
MCDNN_STATUS_ALLOC_FAILED
此函数不能用来分配内存。
6.2.1.38. mcdnnRNNForwardInferenceEx()
此函数保留API,不再单独实现。使用mcdnnRNNForward()代替mcdnnRNNForwardInferenceEx()。
mcdnnStatus_t mcdnnRNNForwardInferenceEx(
mcdnnHandle_t handle,
const mcdnnRNNDescriptor_t rnnDesc,
const mcdnnRNNDataDescriptor_t xDesc,
const void *x,
const mcdnnTensorDescriptor_t hxDesc,
const void *hx,
const mcdnnTensorDescriptor_t cxDesc,
const void *cx,
const mcdnnFilterDescriptor_t wDesc,
const void *w,
const mcdnnRNNDataDescriptor_t yDesc,
void *y,
const mcdnnTensorDescriptor_t hyDesc,
void *hy,
const mcdnnTensorDescriptor_t cyDesc,
void *cy,
const mcdnnRNNDataDescriptor_t kDesc,
const void *keys,
const mcdnnRNNDataDescriptor_t cDesc,
void *cAttn,
const mcdnnRNNDataDescriptor_t iDesc,
void *iAttn,
const mcdnnRNNDataDescriptor_t qDesc,
void *queries,
void *workSpace,
size_t workSpaceSizeInBytes)
该函数是mcdnnRNNForwardInference()函数的扩展版本。mcdnnRNNForwardTrainingEx()函数允许用户对输入x和输出y使用非压缩(填充)布局。在非压缩布局中,mini-batch中的每个序列都被视为固定长度,由其对应的RNNDataDescriptor中的maxSeqLength指定。每个固定长度序列(例如,mini-batch中的第n个序列)都由一个有效段(由其对应的RNNDataDescriptor中的seqLengthArray[n]指定)和一个填充段组成,使组合序列长度等于maxSeqLength。 对于非压缩布局,同时支持序列主要(sequence-major)布局(即,时间主要)和批主要(batch-major)布局。为了向后兼容,支持压缩的序列主要布局。但是,与非扩展函数mcdnnRNNForwardInference()类似,mini-batch中的序列需要根据长度按降序排序。
参数
handle
输入。已创建的mcDNN上下文的句柄。
rnnDesc
输入。已初始化的RNN描述符。
xDesc
输入。已初始化的RNN数据描述符。dataType、layout、maxSeqLength、batchSize和seqLengthArray必须与yDesc中的匹配。
x
输入。数据指针,指向与RNN数据描述符xDesc关联的GPU内存。向量应根据xDesc指定的布局在内存中排列。张量中的元素(包括填充向量中的元素)必须紧密压缩,且不支持步幅。
hxDesc
输入。完全压缩的张量描述符,描述RNN的初始隐藏状态(initial hidden state)。
张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc中描述的batchSize参数匹配。
第三维取决于RNN模式是否为MCDNN_LSTM以及是否启用了LSTM投影。具体而言:
如果RNN模式为MCDNN_LSTM且启用了LSTM投影,则第三维必须与传入mcdnnSetRNNProjectionLayers()调用的recProjSize参数匹配,其中mcdnnSetRNNProjectionLayers()是用于设置rnnDesc的。
否则,第三维必须与初始化rnnDesc的hiddenSize参数匹配。
hx
输入。数据指针,指向与张量描述符hxDesc关联的GPU内存。如果传入NULL指针,则网络的初始隐藏状态将初始化为零。
cxDesc
输入。完全压缩的的张量描述符,描述LSTM网络的初始单元(cell)状态。
张量的第一维取决于初始化rnnDesc的方向参数:
如果方向为MCDNN_UNIDIRECTIONAL,则第一维应与numLayers参数匹配。
如果方向为MCDNN_BIDIRECTIONAL,则第一维应是numLayers参数的2倍。
第二维必须与xDesc中描述的batchSize参数匹配。第三维必须与初始化rnnDesc的hiddenSize参数匹配。
cx
输入。数据指针,指向与张量描述符cxDesc关联的GPU内存。如果传入NULL指针,则网络的初始单元状态将初始化为零。
wDesc
输入。已初始化的卷积核描述符的句柄,描述RNN权重。
w
输入。数据指针,指向与卷积核描述符wDesc关联的GPU内存。
yDesc
输入。已初始化的RNN数据描述符。
dataType、layout、maxSeqLength、batchSize和seqLengthArray必须与dyDesc和dxDesc中的相应参数匹配。vectorSize参数取决于RNN模式是否设置为MCDNN_LSTM,是否启用了LSTM投影以及网络是否为双向。具体而言:
对于单向网络,如果RNN模式为MCDNN_LSTM且启用了LSTM投影,则vectorSize参数必须与传入mcdnnSetRNNProjectionLayers()调用的recProjSize参数匹配,其中mcdnnSetRNNProjectionLayers()是用于设置rnnDesc的。如果网络是双向的,则将该值乘以2。
否则,对于单向网络,vectorSize参数必须与初始化rnnDesc的hiddenSize参数匹配。如果网络是双向的,则将该值乘以2。
y
输出。数据指针,指向与RNN数据描述符yDesc关联的GPU内存。向量应根据yDesc指定的布局在内存中排布。张量中的元素(包括填充向量中的元素)必须紧密压缩,且不支持步幅。
hyDesc
输入。完全压缩的张量描述符,描述RNN的最终隐藏状态。此描述符的设置必须与hxDesc完全一致。
hy
输出。数据指针,指向与张量描述符hyDesc关联的GPU内存。如果传入NULL指针,将不会保存网络的最终隐藏状态。
cyDesc
输入。完全压缩的张量描述符,描述LSTM网络的最终单元状态。此描述符的设置必须与cxDesc完全一致。
cy
输出。数据指针,指向与张量描述符cyDesc关联的GPU内存。如果传入NULL指针,将不会保存网络的最终单元状态。
kDesc
保留。用户可以传入NULL。
keys
保留。用户可以传入NULL。
cDesc
保留。用户可以传入NULL。
cAttn
保留。用户可以传入NULL。
iDesc
保留。用户可以传入NULL。
iAttn
保留。用户可以传入NULL。
qDesc
保留。用户可以传入NULL。
queries
保留。用户可以传入NULL。
workspace
输入。数据指针,指向要用作此调用工作空间的GPU内存。
workSpaceSizeInBytes
输入。指定已提供的workspace大小(以字节为单位)。
返回值
MCDNN_STATUS_SUCCESS
此函数启用成功。
MCDNN_STATUS_NOT_SUPPORTED
需至少满足以下任一条件:
在使用MCDNN_RNN_ALGO_PERSIST_STATIC或MCDNN_RNN_ALGO_PERSIST_DYNAMIC时,传入变量序列长度输入。
在pre-Pascal设备上使用MCDNN_RNN_ALGO_PERSIST_STATIC或MCDNN_RNN_ALGO_PERSIST_DYNAMIC。
双输入/输出用于MCDNN_RNN_ALGO_PERSIST_STATIC。
MCDNN_STATUS_BAD_PARAM
需至少满足以下任一条件:
rnnDesc描述符无效。
xDesc、yDesc、hxDesc、cxDesc、wDesc、hyDesc或cyDesc无效,或者步幅或维度不正确。
reserveSpaceSizeInBytes太小。
workSpaceSizeInBytes太小。
MCDNN_STATUS_INVALID_VALUE
在RNN描述符中选择MCDNN_RNN_ALGO_PERSIST_DYNAMIC时,在当前函数之前未调用mcdnnSetPersistentRNNPlan()。
MCDNN_STATUS_EXECUTION_FAILED
此函数在GPU上启用失败。
MCDNN_STATUS_ALLOC_FAILED
此函数不能用来分配内存。
6.2.1.39. mcdnnRNNGetClip()
此函数保留API,不再单独实现。使用mcdnnRNNGetClip_v8()代替mcdnnRNNGetClip()。
mcdnnStatus_t mcdnnRNNGetClip(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNClipMode_t *clipMode,
mcdnnNanPropagation_t *clipNanOpt,
double *lclip,
double *rclip);
检索当前的LSTM单元裁剪参数,并将其存储在提供的参数中。
参数
clipMode
输出。指针,指向已检索到的clipMode的存储位置。clipMode可以为MCDNN_RNN_CLIP_NONE,在这种情况下不执行LSTM单元状态裁剪;或者为MCDNN_RNN_CLIP_MINMAX,在这种情况下,对激活其他单元的单元状态执行裁剪。
lclip, rclip
输出。指针,指向已检索到的LSTM单元裁剪范围[lclip, rclip]的存储位置。
clipNanOpt
输出。指针,指向已检索到的clipNanOpt的存储位置。
返回值
MCDNN_STATUS_SUCCESS
此函数启用成功。
MCDNN_STATUS_BAD_PARAM
任意已提供的指针参数为NULL。
6.2.1.40. mcdnnRNNGetClip_v8()
检索当前的LSTM单元裁剪参数,并将其存储在提供的参数中。当不需要检索到的值时,用户可以将NULL分配给除rnnDesc之外的任意指针。该函数不用于检查已检索参数的有效性。
mcdnnStatus_t mcdnnRNNGetClip_v8(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNClipMode_t *clipMode,
mcdnnNanPropagation_t *clipNanOpt,
double *lclip,
double *rclip);
参数
rnnDesc
输入。已初始化的RNN描述符。
clipMode
输出。指针,指向已检索到的mcdnnRNNClipMode_t值的存储位置。clipMode可以为MCDNN_RNN_CLIP_NONE,在这种情况下不执行LSTM单元状态裁剪;或者为MCDNN_RNN_CLIP_MINMAX,在这种情况下,对激活其他单元的单元状态执行裁剪。
clipNanOpt
输出。指针,指向已检索到的mcdnnNanPropagation_t值的存储位置。
lclip, rclip
输出。指针,指向已检索到的LSTM单元裁剪范围[lclip, rclip]的存储位置。
返回值
MCDNN_STATUS_SUCCESS
已从RNN描述符成功检索LSTM裁剪参数。
MCDNN_STATUS_BAD_PARAM
找到一个无效的输入参数(rnnDesc为NULL)。
6.2.1.41. mcdnnRNNSetClip()
此函数保留API,不再单独实现。使用mcdnnRNNSetClip_v8()代替mcdnnRNNSetClip()。
mcdnnStatus_t mcdnnRNNSetClip(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNClipMode_t clipMode,
mcdnnNanPropagation_t clipNanOpt,
double lclip,
double rclip);
设置LSTM单元裁剪(cell clipping)模式。默认情况下,LSTM裁剪是禁用的。启用时,裁剪会应用到所有层。可能会多次调用mcdnnRNNSetClip()函数。
参数
clipMode
输入。启用或禁用LSTM单元裁剪。当clipMode设置为MCDNN_RNN_CLIP_NONE时,不会执行LSTM单元状态裁剪。当clipMode为MCDNN_RNN_CLIP_MINMAX时,会对激活其他单元的单元状态执行裁剪。
lclip, rclip
输入。LSTM单元裁剪应设置的范围[lclip, rclip]。
clipNanOpt
输入。当设置为MCDNN_PROPAGATE_NAN时(请参见mcdnnNanPropagation_t的说明),NaN从LSTM单元传播;或者可以设置为裁剪范围边界值之一,以代替传播。
返回值
MCDNN_STATUS_SUCCESS
此函数启用成功。
MCDNN_STATUS_BAD_PARAM
如果lclip > rclip,或者如果lclip或rclip是NaN,则返回该值。
6.2.1.42. mcdnnRNNSetClip_v8()
设置LSTM单元裁剪(cell clipping)模式。默认情况下,LSTM裁剪是禁用的。启用时,裁剪会应用到所有层。此mcdnnRNNSetClip()函数不会影响工作空间、预留空间和权重空间缓冲区大小,且可以多次调用。
mcdnnStatus_t mcdnnRNNSetClip_v8(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNClipMode_t clipMode,
mcdnnNanPropagation_t clipNanOpt,
double lclip,
double rclip);
参数
rnnDesc
输入。已初始化的RNN描述符。
clipMode
输入。启用或禁用LSTM单元裁剪。当clipMode设置为MCDNN_RNN_CLIP_NONE时,不会执行LSTM单元状态裁剪。当clipMode为MCDNN_RNN_CLIP_MINMAX时,会对激活其他单元的单元状态执行裁剪。
clipNanOpt
输入。当设置为MCDNN_PROPAGATE_NAN时(请参见mcdnnNanPropagation_t的说明),NaN从LSTM单元传播;或者可以设置为裁剪范围边界值之一,以代替传播。
lclip, rclip
输入。LSTM单元裁剪应设置的范围[lclip, rclip]。
返回值
MCDNN_STATUS_SUCCESS
函数已成功完成。
MCDNN_STATUS_BAD_PARAM
找到一个无效的输入参数,例如:
rnnDesc为NULL
lclip > rclip
lclip或rclip为NaN
6.2.1.43. mcdnnSetAttnDescriptor()
此函数用于配置多头注意力描述符,此描述符是使用mcdnnCreateAttnDescriptor()函数创建的。该函数用于设置计算内部缓冲区大小、权重和bias张量的维度或选择优化代码路径所需的注意力参数。
mcdnnStatus_t mcdnnSetAttnDescriptor(
mcdnnAttnDescriptor_t attnDesc,
unsigned attnMode,
int nHeads,
double smScaler,
mcdnnDataType_t dataType,
mcdnnDataType_t computePrec,
mcdnnMathType_t mathType,
mcdnnDropoutDescriptor_t attnDropoutDesc,
mcdnnDropoutDescriptor_t postDropoutDesc,
int qSize,
int kSize,
int vSize,
int qProjSize,
int kProjSize,
int vProjSize,
int oProjSize,
int qoMaxSeqLength,
int kvMaxSeqLength,
int maxBatchSize,
int maxBeamSize);
mcdnnMultiHeadAttnForward()、mcdnnMultiHeadAttnBackwardData() 和 mcdnnMultiHeadAttnBackwardWeights() 函数中的输入序列数据描述符会与注意力描述符中存储的配置参数进行对照检查。某些参数必须完全匹配,而 max 参数(如 maxBatchSize 或 qoMaxSeqLength)则为相应的维度设置上限。
多头注意力模型可通过以下公式描述:
\(\mathbf{h}_{i} = \left( {\mathbf{W}_{V,i}\mathbf{V}} \right){softmax}\left( {{smScaler}\left( {\mathbf{K}^{\mathbf{T}}\mathbf{W}_{K,i}^{T}} \right)\left( {\mathbf{W}_{Q,i}\mathbf{q}} \right)} \right),\ {for}\ i\ = 0\ ...\ {nHeads} - 1\) \({MultiHeadAttn}\left( {\mathbf{q},\mathbf{K},\mathbf{V},\mathbf{W}_{Q},\mathbf{W}_{K},\mathbf{W}_{V},\mathbf{W}_{O}} \right) = {\sum\limits_{i = 0}^{{nHeads} - 1}{\mathbf{W}_{O,i}\mathbf{h}_{i}}}\)
其中:
\(nHeads\) 是求值 \(\mathbf{h}_{i}\) 向量的独立注意力头数。
\(\mathbf{q}\) 是一个主要输入,单个
query列向量。\(\mathbf{K},\mathbf{V}\) 是
key和value列向量的两个矩阵。为了简单起见,上述公式使用单个嵌入向量 \(\mathbf{q}\) 表示,但API可以在束搜索(beam search)方案中处理多个 \(\mathbf{q}\) 候选项,可以处理捆绑到一个batch中多个序列的 \(\mathbf{q}\) 向量,或者自动迭代序列的所有嵌入向量(时间步)。 因此通常情况下,\(\mathbf{q}\)、\(\mathbf{K},\mathbf{V}\) 输入是带有附加信息片段的张量,例如每个序列的活动长度或如何保存未使用的填充向量。 在一些发布中, \(\mathbf{W}_{O,i}\) 矩阵被合并成一个输出投影矩阵, \(\mathbf{h}_{i}\) 向量被显式合并成一个向量。 这是等价的。在库中,\(\mathbf{W}_{O,i}\) 矩阵在概念上与 \(\mathbf{W}_{Q,i}\)、\(\mathbf{W}_{K,i}\) 或 \(\mathbf{W}_{V,i}\) 输入投影权重相同。有关详细信息,请参见 mcdnnGetMultiHeadAttnWeights() 函数的说明。
\(\mathbf{W}_{Q,i}\)、\(\mathbf{W}_{K,i}\)、\(\mathbf{W}_{V,i}\)、\(\mathbf{W}_{O,i}\) 权重矩阵发挥类似的作用,调整 \(\mathbf{q}\)、\(\mathbf{K},\mathbf{V}\) 输入和多头注意力最终输出中的向量长度。 用户可以通过将 \(qProjSize\)、\(kProjSize\)、\(vProjSize\) 或 \(oProjSize\) 参数设置为零,来禁用任意或所有投影。 \(\mathbf{q}\)、\(\mathbf{K},\mathbf{V}\) 中嵌入向量的大小和投影后的向量长度,需要以上述矩阵乘法可行的方式进行选择。否则
mcdnnSetAttnDescriptor()函数返回MCDNN_STATUS_BAD_PARAM。 当需要维持 \(\mathbf{W}_{KQ,i} = \mathbf{W}_{K,i}^{T}\mathbf{W}_{{Q,}i}\) 或 \(\mathbf{W}_{{OV},i} = \mathbf{W}_{O,i}\mathbf{W}_{V,i}\) 矩阵的秩亏缺(rank deficiency),以在每个头的线性转换(linear transformation)中消除一个或多个维度时,这四个权重矩阵全都需要使用。这是特征提取(feature extraction)的一种形式。在这种情况下,投影的大小比原始向量长度小。
对于每个注意力头,权重矩阵大小定义如下:
\(\mathbf{W}_{Q,i}\) - size \(\left\lbrack {{qProjSize}\ x\ {qSize}} \right\rbrack,\ i = O\ ..\ {nHeads} - 1\)
\(\mathbf{W}_{K,i}\) - size \(\left\lbrack {{kProjSize}\ x\ {kSize}} \right\rbrack,\ i = 0\ ..\ {nHeads} - 1,\ {kProjSize} = {qProjSize}\)
\(\mathbf{W}_{V,i}\) - size \(\left\lbrack {{vProjSize}\ x\ {vSize}} \right\rbrack,\ i = 0\ ..\ {nHeads} - 1\)
\(\mathbf{W}_{O,i}\) - size \(\left\lbrack {{oProjSize}\ x\ \left( {{vProjSize}\ > \ 0\ ?\ {vProjSize}\ :\ {vSize}} \right)} \right\rbrack,\ i = 0\ ..\ {nHeads} - 1\)
当禁用输出投影 \(\left( {{oProjSize} = 0} \right)\) 时,输出向量长度为 \({nHead}{s~}^{*}\ \left( {{vProjSize}\ > \ 0\ ?\ {vProjSize}\ :\ {vSize}} \right)\),即输出是所有 \(\mathbf{h}_{i}\) 向量的串联。
在另一种解释中,连接矩阵 \(\mathbf{W}_{O} = \left\lbrack {\mathbf{W}_{O,0},\ \mathbf{W}_{O,1},\ \mathbf{W}_{O,2},\ ...} \right\rbrack\) 构成了单位矩阵(Identity Matrix)。 Softmax是一个标准化的指数向量函数,它接受和输出相同大小的向量。多头注意力API利用
MCDNN_SOFTMAX_ACCURATE类型的softmax来降低浮点溢出的可能性。
smScaler参数是softmax锐化/平滑系数。当smScaler=1.0时,softmax使用自然指数函数exp(x)或2.7183*。当smScaler<1.0时,例如smScaler=0.2,由于exp(0.2*x)\(\approx\)1.2214*,softmax块使用的函数不会增长得那么快。
smScaler参数可以调整来处理输入到softmax的值的更大范围。当范围过大(或smScaler对于给定范围不够小)时,softmax块的输出向量变为类别向量(categorical vector),这意味着一个向量元素接近1.0,其他输出为0或非常接近于0。 发生这种情况时,softmax块的雅可比(Jacobian)矩阵也接近于0,因此,除非通过残差连接(如果启用了这些连接),增量(delta)在训练期间不会从输出到输入进行反向传播。 用户可以将smScaler设置为任何正浮点值,甚至可以设置为零。smScaler参数不可训练。
qoMaxSeqLength、kvMaxSeqLength、maxBatchSize、maxBeamSize参数分别声明 mcdnnSeqDataDescriptor_t 容器中的最大序列长度,最大批大小和最大束宽。 提供给正向和反向(梯度)API函数的实际维度不应超过max限制。需要谨慎设置max参数,因为过大的值将导致因工作空间和预留空间缓冲区过大而使用过多内存。
attnMode参数被视为二进制掩码,其中设置了各种开/关选项。这些选项可以影响内部缓冲区大小,强制执行某些参数检查,选择优化的代码执行路径或启用不需要额外数值参数的注意力变量。 例如,在输入和输出投影中加入bias。
attnDropoutDesc和postDropoutDesc参数是描述符,用于定义训练模式中的两个活动丢弃层。attnDropoutDesc定义的第一个丢弃操作直接应用于softmax输出。由postDropoutDesc指定的第二个丢弃操作,用于在添加残差连接的点之前,更改多头注意力输出。
备注
mcdnnSetAttnDescriptor() 函数执行 attnDropoutDesc 和 postDropoutDesc 的浅拷贝(shallow copy),这意味着两个丢弃描述符的地址都存储在注意力描述符中,而不是存储在整个结构中。
因此,用户应在注意力描述符的整个生命周期内保留丢弃描述符。
参数
attnDesc
输出。要配置的注意力描述符。
attnMode
输入。启用不需要额外数值的各种注意力选项。用户应为此参数指定一组首选的bitwise OR-ed标记。
nHeads
输入。注意力头数。
smScaler
输入。Softmax平滑(1.0 >= smScaler >= 0.0)或锐化(smScaler > 1.0)系数。不允许负数值。
dataType
输入。用于表示注意力输入,注意力权重和注意力输出的数据类型。
computePrec
输入。计算精度。
mathType
输入。MMA设置。
attnDropoutDesc
输入。应用于softmax输出的丢弃操作的描述符。
postDropoutDesc
输入。丢弃操作的描述符,此操作应用于在添加残差连接的点之前。
qSize, kSize, vSize
输入。Q、K、V嵌入向量长度。
qProjSize, kProjSize, vProjSize
输入。输入投影后的Q、K、V嵌入向量长度。使用零以禁用相应的投影。
oProjSize
输入。输出投影后的 \(h_{i}\) 向量长度。使用零以禁用此投影。
qoMaxSeqLength
输入。与 Q, O, dQ 和 dO 输入和输出相关的序列数据描述符中的最大序列长度。
kvMaxSeqLength
输入。与 K, V, dK 和 dV 输入和输出相关的序列数据描述符中的最大序列长度。
maxBatchSize
输入。任意mcdnnSeqDataDescriptor_t容器中的最大批大小。
maxBeamSize
输入。任意mcdnnSeqDataDescriptor_t容器中的最大束宽。
支持的attnMode标记
MCDNN_ATTN_QUERYMAP_ALL_TO_ONE
当束宽大于 \(\mathbf{Q}\) 输入中的一个值时,\(\mathbf{Q}\) 和 \(\mathbf{K},\mathbf{V}\) 向量之间映射的正向声明。
同一束中的多个 \(\mathbf{Q}\) 向量映射到相同的 \(\mathbf{K},\mathbf{V}\) 向量中。 这意味着 \(\mathbf{K},\mathbf{V}\) 组中的束宽都等于1。
MCDNN_ATTN_QUERYMAP_ONE_TO_ONE
当束宽大于 \(\mathbf{Q}\) 输入中的一个值时,\(\mathbf{Q}\) 和 \(\mathbf{K},\mathbf{V}\) 向量之间映射的正向声明。
同一束中的多个 \(\mathbf{Q}\) 向量映射到不同的 \(\mathbf{K},\mathbf{V}\) 向量中。这需要 \(\mathbf{K},\mathbf{V}\) 组的束宽与 \(\mathbf{Q}\) 输入中的相同。
MCDNN_ATTN_DISABLE_PROJ_BIASES
不在注意力输入和输出投影中使用bias。
MCDNN_ATTN_ENABLE_PROJ_BIASES
在注意力输入和输出投影中使用额外的bias。
在这种情况下,投影 \(\overline{\mathbf{K}}\) 向量计算为 \(\overline{\mathbf{K}_{i}} = \mathbf{W}_{K,i}\mathbf{K} + \mathbf{b}*\left\lbrack {1,1,\operatorname{...,}1} \right\rbrack_{1 \times n}\) ,其中 \(n\) 是 \(\mathbf{K}\) 矩阵中的列数。 换言之,在权重矩阵相乘之后,相同的列向量 \(\mathbf{b}\) 添加到 \(\mathbf{K}\) 的所有列中。
支持的dataType、computePrec和mathType组合
mcdnnSetAttnDescriptor()支持的组合
dataType |
computePrec |
mathType |
|---|---|---|
MCDNN_DATA_DOUBLE |
MCDNN_DATA_DOUBLE |
MCDNN_DEFAULT_MATH |
MCDNN_DATA_FLOAT |
MCDNN_DATA_FLOAT |
MCDNN_DEFAULT_MATH MCDNN_TENSOR_OP_MATH _ALLOW_CONVERSION |
MCDNN_DATA_HALF |
MCDNN_DATA_HALF MCDNN_DATA_FLOAT |
MCDNN_DEFAULT_MATH MCDNN_TENSOR_OP_MATH MCDNN_TENSOR_OP_MATH _ALLOW_CONVERSION |
不支持的功能
目前,所有多头注意力函数会忽略mcdnnSeqDataDescriptor_t中的paddingFill参数。
返回值
MCDNN_STATUS_SUCCESS
注意力描述符配置成功。
MCDNN_STATUS_BAD_PARAM
遇到无效的输入参数。例如:
post-projection Q 和 K 大小不相等
dataType、computePrec或mathType无效
以下一个或多个参数为负值或零:nHeads、qSize、kSize、vSize、qoMaxSeqLength、kvMaxSeqLength、maxBatchSize、maxBeamSize
以下一个或多个参数为负值:qProjSize、kProjSize、vProjSize、smScaler
MCDNN_STATUS_NOT_SUPPORTED
请求的选项或输入参数组合不受支持。
6.2.1.44. mcdnnSetPersistentRNNPlan()
此函数保留API,不再单独实现。 此函数用于设置在使用rnnDesc和MCDNN_RNN_ALGO_PERSIST_DYNAMIC算法时要执行的持久性RNN计划。
mcdnnStatus_t mcdnnSetPersistentRNNPlan(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnPersistentRNNPlan_t plan)
返回值
MCDNN_STATUS_SUCCESS
计划设置成功。
MCDNN_STATUS_BAD_PARAM
在rnnDesc中选择的算法不是MCDNN_RNN_ALGO_PERSIST_DYNAMIC。
6.2.1.45. mcdnnSetRNNAlgorithmDescriptor()
此函数保留API,不再单独实现。
6.2.1.46. mcdnnSetRNNBiasMode()
此函数保留API,不再单独实现。使用mcdnnSetRNNDescriptor_v8()代替mcdnnSetRNNBiasMode()。
mcdnnStatus_t mcdnnSetRNNBiasMode(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNBiasMode_t biasMode)
mcdnnSetRNNBiasMode()函数用于为已创建和初始化的RNN描述符设置bias向量的数量。调用此函数以在RNN中启用指定的bias模式。在mcdnnCreateRNNDescriptor()之后,rnnDesc中biasMode的默认值为MCDNN_RNN_DOUBLE_BIAS。
参数
rnnDesc
输入/输出。已创建的RNN描述符。
biasMode
输入。设置bias向量的数量。更多信息,参见mcdnnRNNBiasMode_t。
返回值
MCDNN_STATUS_BAD_PARAM
rnnDesc为NULL或biasMode有一个无效的枚举值。
MCDNN_STATUS_SUCCESS
biasMode设置成功。
MCDNN_STATUS_NOT_SUPPORTED
非默认bias模式(除MCDNN_RNN_DOUBLE_BIAS之外的枚举类型)应用于MCDNN_RNN_ALGO_STANDARD以外的RNN算法。
6.2.1.47. mcdnnSetRNNDataDescriptor()
此函数用于初始化已创建的RNN数据描述符对象。此数据结构旨在支持扩展的RNN推理和训练函数的输入和输出非压缩(填充)布局。还支持压缩(无填充)布局以实现向后兼容。
mcdnnStatus_t mcdnnSetRNNDataDescriptor(
mcdnnRNNDataDescriptor_t RNNDataDesc,
mcdnnDataType_t dataType,
mcdnnRNNDataLayout_t layout,
int maxSeqLength,
int batchSize,
int vectorSize,
const int seqLengthArray[],
void *paddingFill);
参数
RNNDataDesc
输入/输出。已创建的RNN描述符。更多信息,参见mcdnnRNNDataDescriptor_t。
dataType
输入。RNN数据张量的数据类型。更多信息,参见mcdnnDataType_t。
layout
输入。RNN数据张量的内存布局。
maxSeqLength
输入。此RNN数据张量内的最大序列长度。在非压缩(填充)布局中,此输入应包含每个序列中的填充向量。在压缩(未填充)布局中,此输入应等于seqLengthArray中的最大元素。
batchSize
输入。在mini-batch内的序列数。
vectorSize
输入。输入或输出张量在每个时间步的向量长度(嵌入大小)。
seqLengthArray
输入。整数组,由元素的batchSize数组成。描述每个序列的长度(时间步数量)。seqLengthArray中的每个元素必须大于或等于0,但小于或等于maxSeqLength。在压缩布局中,元素应按降序排序,类似于非扩展RNN计算函数所需的布局。
paddingFill
输入。用于填充RNN输出中填充位置的用户定义符号。仅在描述符描述RNN输出且已指定压缩布局时有效。该符号应在主机内存中,表示与RNN数据张量相同的数据类型。如果传入NULL指针,则不会定义输出中的填充位置。
返回值
MCDNN_STATUS_SUCCESS
对象设置成功。
MCDNN_STATUS_NOT_SUPPORTED
dataType不是MCDNN_DATA_HALF、MCDNN_DATA_FLOAT或MCDNN_DATA_DOUBLE。
MCDNN_STATUS_BAD_PARAM
满足以下任意一种情况:
RNNDataDesc为NULL。
maxSeqLength、batchSize或vectorSize中的任意一个小于或等于0。
seqLengthArray的元素小于0或大于maxSeqLength。
layout不是MCDNN_RNN_DATA_LAYOUT_SEQ_MAJOR_UNPACKED、MCDNN_RNN_DATA_LAYOUT_SEQ_MAJOR_PACKED 或者 MCDNN_RNN_DATA_LAYOUT_BATCH_MAJOR_UNPACKED。
MCDNN_STATUS_ALLOC_FAILED
内部数组存储分配失败。
6.2.1.48. mcdnnSetRNNDescriptor_v6()
此函数保留API,不再单独实现。使用mcdnnSetRNNDescriptor_v8()代替mcdnnSetRNNDescriptor_v6()。
mcdnnStatus_t mcdnnSetRNNDescriptor_v6(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
const int hiddenSize,
const int numLayers,
mcdnnDropoutDescriptor_t dropoutDesc,
mcdnnRNNInputMode_t inputMode,
mcdnnDirectionMode_t direction,
mcdnnRNNMode_t mode,
mcdnnRNNAlgo_t algo,
mcdnnDataType_t mathPrec)
此函数用于初始化已创建的RNN描述符对象。
备注
较大的网络(例如,较长的序列或更多的层)预计比较小的网络效率更高。
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入/输出。已创建的RNN描述符。
hiddenSize
输入。每个层内部隐藏状态的大小。
numLayers
输入。堆叠层数。
dropoutDesc
输入。已创建和初始化的丢弃描述符的句柄。丢弃会在层之间应用,例如,单层网络将不应用任何丢弃。
inputMode
输入。指定第一层输入的行为。
direction
输入。指定循环方式,例如双向。
mode
输入。指定要计算的RNN的类型。
algo
输入。指定应使用哪个RNN算法来计算结果。
mathPrec
输入。数学精度。此参数用于控制RNN中的数学精度。适用以下内容:
对于FP16的输入/输出,mathPrec参数可以是MCDNN_DATA_HALF或MCDNN_DATA_FLOAT。
对于FP32的输入/输出,mathPrec参数只能是MCDNN_DATA_FLOAT。
对于FP64和双精度类型的输入/输出,mathPrec参数只能是MCDNN_DATA_DOUBLE。
返回值
MCDNN_STATUS_SUCCESS
对象设置成功。
MCDNN_STATUS_BAD_PARAM
hiddenSize或numLayers参数中至少有一个为0或负值;inputMode、direction、mode、algo或dataType中任一具有无效的枚举值;dropoutDesc是无效的丢弃描述符或rnnDesc未正确创建。
6.2.1.49. mcdnnSetRNNDescriptor_v8()
此函数用于初始化已创建的RNN描述符对象。通过mcdnnSetRNNDescriptor_v8()配置的RNN描述符得到了增强,可以存储在RNN模型中计算可调整权重/bias总数所需的所有信息。
mcdnnStatus_t mcdnnSetRNNDescriptor_v8(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNAlgo_t algo,
mcdnnRNNMode_t cellMode,
mcdnnRNNBiasMode_t biasMode,
mcdnnDirectionMode_t dirMode,
mcdnnRNNInputMode_t inputMode,
mcdnnDataType_t dataType,
mcdnnDataType_t mathPrec,
mcdnnMathType_t mathType,
int32_t inputSize,
int32_t hiddenSize,
int32_t projSize,
int32_t numLayers,
mcdnnDropoutDescriptor_t dropoutDesc,
uint32_t auxFlags);
参数
rnnDesc
输入。已初始化的RNN描述符。
algo
输入。RNN算法(MCDNN_RNN_ALGO_STANDARD,MCDNN_RNN_ALGO_PERSIST_STATIC或MCDNN_RNN_ALGO_PERSIST_DYNAMIC)。
cellMode
输入。指定整个模型中的RNN单元类型(MCDNN_RNN_RELU、MCDNN_RNN_TANH、MCDNN_RNN_LSTM、MCDNN_RNN_GRU)。
biasMode
输入。设置bias向量的数量(MCDNN_RNN_NO_BIAS、MCDNN_RNN_SINGLE_INP_BIAS、MCDNN_RNN_SINGLE_REC_BIAS、MCDNN_RNN_DOUBLE_BIAS)。这两个单独的bias设置在功能上与RELU,TANH和LSTM单元类型的相同。有关GRU单元的差异,请参见mcdnnRNNMode_t枚举类型中MCDNN_GRU的说明。
dirMode
输入。指定循环模式:MCDNN_UNIDIRECTIONAL或MCDNN_BIDIRECTIONAL。在双向RNN中,在物理层之间传递的隐藏状态是正向和反向隐藏状态的串联。
inputMode
输入。指定第一层如何处理RNN模型的输入。当inputMode为MCDNN_LINEAR_INPUT时,inputSize的原始输入向量将乘以权重矩阵,以获得hiddenSize的向量。当inputMode为MCDNN_SKIP_INPUT时,第一层的原始输入向量将按原样使用,而不会乘以权重矩阵。
dataType
输入。为RNN权重/偏差以及输入和输出数据指定数据类型。
mathPrec
输入。此参数用于控制RNN模型中的数学精度。适用以下内容:
对于FP16的输入/输出,mathPrec参数可以是MCDNN_DATA_HALF或MCDNN_DATA_FLOAT。
对于FP32的输入/输出,mathPrec参数只能是MCDNN_DATA_FLOAT。
对于FP64和双精度类型的输入/输出,mathPrec参数只能是MCDNN_DATA_DOUBLE。
mathType
输入。设置使用MMA加速器的首选项。
当dataType为MCDNN_DATA_HALF时,mathType参数可以是MCDNN_DEFAULT_MATH或MCDNN_TENSOR_OP_MATH。
对于此数据类型,ALLOW_CONVERSION设置的处理方式与MCDNN_TENSOR_OP_MATH相同。
当dataType为MCDNN_DATA_FLOAT时,mathType参数可以是MCDNN_DEFAULT_MATH或MCDNN_TENSOR_OP_MATH_ALLOW_CONVERSION。
使用后一种设置时,原始权重和中间结果将向下转换为MCDNN_DATA_HALF,然后再用于另一个递归迭代。
当dataType为MCDNN_DATA_DOUBLE时,mathType参数可以是MCDNN_DEFAULT_MATH 。
此选项具有警告含义。例如,由于特定的GEMM维度限制,Tensor Core有时可能无法使用。
inputSize
输入。RNN模型中输入向量的大小。当inputMode=MCDNN_SKIP_INPUT,inputSize的值应与hiddenSize的值一致。
hiddenSize
输入。RNN模型中隐藏状态向量的大小。在所有RNN层中使用相同的隐藏大小。
projSize
输入。循环投影后LSTM单元输出的大小。该值不应大于hiddenSize。将projSize设置为hiddenSize是合法的,但是在这种情况下,将禁用循环投影功能。循环投影是LSTM单元中的一个附加矩阵乘法,用于将隐藏状态向量ht投影为较小的向量rt = Wrht,其中Wr是一个具有projSize行和hiddenSize列的矩形矩阵。启用循环投影时,LSTM单元的输出(到下一层且及时展开)为rt,而不是ht。只能为LSTM单元和MCDNN_RNN_ALGO_STANDARD启用循环投影。
numLayers
输入。深度RNN模型中堆叠的物理层数。当dirMode=MCDNN_BIDIRECTIONAL时,物理层由与正向和反向对应的两个伪层组成。
dropoutDesc
输入。已创建和初始化的丢弃描述符的句柄。丢弃操作将在物理层之间应用。单层网络不会应用任何丢弃操作。丢弃仅用于训练模式中。
auxFlags
输入。此参数用于传递不需要附加数值来配置相应功能的其他switch。在将来的mcDNN版本中,此参数将用于扩展RNN功能,而不添加新的API函数(适用的选项应为bitwise OR-ed)。当前,此参数用于启用或禁用填充输入/输出(MCDNN_RNN_PADDED_IO_DISABLED、MCDNN_RNN_PADDED_IO_ENABLED)。启用填充输入/输出时,RNN数据描述符中允许MCDNN_RNN_DATA_LAYOUT_SEQ_MAJOR_UNPACKED和MCDNN_RNN_DATA_LAYOUT_BATCH_MAJOR_UNPACKED布局。
返回值
MCDNN_STATUS_SUCCESS
RNN描述符配置成功。
MCDNN_STATUS_BAD_PARAM
检测到一个无效的输入变量。
MCDNN_STATUS_NOT_SUPPORTED
bias张量的维度是指与输出张量维度不兼容的数据量,或者两个张量描述符的dataType不同。
MCDNN_STATUS_EXECUTION_FAILED
检测到不兼容或不支持的输入参数组合。
6.2.1.50. mcdnnSetRNNMatrixMathType()
此函数保留API,不再单独实现。使用mcdnnSetRNNDescriptor_v8()代替mcdnnSetRNNMatrixMathType()。
mcdnnStatus_t mcdnnSetRNNMatrixMathType(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnMathType_t mType)
此函数用于设置使用MMA加速器的首选项。当mType参数为MCDNN_TENSOR_OP_MATH时,若权重/bias类型为MCDNN_DATA_HALF或MCDNN_DATA_FLOAT,RNN推理和训练API将尝试使用Tensor Core。当RNN权重/bias存储为MCDNN_DATA_FLOAT格式时,原始权重和中间结果将向下转换为MCDNN_DATA_HALF,然后再用于另一个递归迭代。
参数
rnnDesc
输入。已创建和初始化的RNN描述符。
mType
输入。执行RNN GEMM(通用矩阵乘法)时的首选计算选项。此选项具有警告含义。例如,由于特定的GEMM维度限制,Tensor Core有时可能无法使用。
返回值
MCDNN_STATUS_SUCCESS
已成功设置RNN网络的首选计算选项。
MCDNN_STATUS_BAD_PARAM
检测到一个无效的输入参数。
6.2.1.51. mcdnnSetRNNPaddingMode()
此函数保留API,不再单独实现。使用mcdnnSetRNNDescriptor_v8()代替mcdnnSetRNNPaddingMode()。
mcdnnStatus_t mcdnnSetRNNPaddingMode(
mcdnnRNNDescriptor_t rnnDesc,
mcdnnRNNPaddingMode_t paddingMode)
此函数启用或禁用已创建和初始化的RNN描述符的填充RNN输入/输出。在调用mcdnnGetRNNWorkspaceSize()和mcdnnGetRNNTrainingReserveSize()函数之前,需要此信息以确定是否需要其他工作空间和训练预留空间。默认情况下,不启用填充的RNN输入/输出。
参数
rnnDesc
输入/输出。已创建的RNN描述符。
paddingMode
输入。启用或禁用填充输入/输出。更多信息,参见mcdnnRNNPaddingMode_t。
返回值
MCDNN_STATUS_SUCCESS
paddingMode设置成功。
MCDNN_STATUS_BAD_PARAM
rnnDesc为NULL或paddingMode有一个无效的枚举值。
6.2.1.52. mcdnnSetRNNProjectionLayers()
此函数保留API,不再单独实现。使用mcdnnSetRNNDescriptor_v8()代替mcdnnSetRNNProjectionLayers()。
mcdnnStatus_t mcdnnSetRNNProjectionLayers(
mcdnnHandle_t handle,
mcdnnRNNDescriptor_t rnnDesc,
int recProjSize,
int outProjSize)
调用 mcdnnSetRNNProjectionLayers() 函数可以启用递归神经网络(recursive neural network)中的循环和/或输出投影。
循环投影是LSTM单元中的一个附加矩阵乘法,用于将隐藏状态向量 \(h_{t}\) 投影为较小的向量 \(r_{t}\ = \ W_{r}h_{t}\),其中 \(W_{r}\) 是一个包含 recProjSize 行和 hiddenSize 列的矩形矩阵。
启用循环投影时,LSTM单元的输出(到下一层且及时展开)为 \(r_{t}\),而不是 \(h_{t}\)。
与非线性函数结合使用的 \(i_{t}\)、\(f_{t}\)、\(o_{t}\)、\(c_{t}\) 向量的维度,与标准LSTM单元中保持一致。
为了实现这一点,LSTM公式(请参见 mcdnnRNNMode_t 类型)中的矩阵形状,例如隐藏RNN层中的 \(W_{i}\) 或整个网络中的 \(R_{i}\),在标准LSTM模式中变为矩形或正方形。
显然,\(R_{i}*W_{r}\) 的结果是一个方形矩阵,但它是秩亏缺,反映了LSTM输出的压缩。对于相同的 hiddenSize 值,当具有投影的RNN网络中独立(可调整)权重的数量比标准LSTM的少时,通常使用循环投影。
只能为LSTM单元和 MCDNN_RNN_ALGO_STANDARD 启用循环投影。recProjSize 参数应小于 hiddenSize 值。
设置 recProjSize 等于 hiddenSize 是合法的,但在这种情况下,循环投影功能是禁用的。
输出投影目前尚未实现。
参数
handle
输入。已创建的mcDNN库描述符的句柄。
rnnDesc
输入。已创建和初始化的RNN描述符。
recProjSize
输入。循环投影后LSTM单元输出的大小。该值不应大于hiddenSize。
outProjSize
输入。此参数应为零。
返回值
MCDNN_STATUS_SUCCESS
已成功设置RNN投影参数。
MCDNN_STATUS_BAD_PARAM
检测到无效的输入参数(例如,NULL句柄,投影参数为负值)。
MCDNN_STATUS_NOT_SUPPORTED
投影应用于MCDNN_RNN_ALGO_STANDARD以外的RNN算法,MCDNN_LSTM以外的单元类型,recProjSize大于hiddenSize。
6.2.1.53. mcdnnSetSeqDataDescriptor()
此函数用于初始化已创建的序列数据描述符对象。简言之,此描述符定义了四维张量的维度(dimA)和数据布局(axes)。
mcdnnStatus_t mcdnnSetSeqDataDescriptor(
mcdnnSeqDataDescriptor_t seqDataDesc,
mcdnnDataType_t dataType,
int nbDims,
const int dimA[],
const mcdnnSeqDataAxis_t axes[],
size_t seqLengthArraySize,
const int seqLengthArray[],
void *paddingFill);
序列数据描述符的四个维度都具有可用于索引dimA[]数组的唯一标识符:
MCDNN_SEQDATA_TIME_DIM
MCDNN_SEQDATA_BATCH_DIM
MCDNN_SEQDATA_BEAM_DIM
MCDNN_SEQDATA_VECT_DIM
例如,要表示序列数据缓冲区中向量的长度为五个元素,我们需要在dimA[]数组中指定dimA[MCDNN_SEQDATA_VECT_DIM]=5。 dimA[]和axes[]数组中的活动维数由nbDims参数定义。当前,此参数的值应为4。dimA[]和axes[]数组的实际大小应使用MCDNN_SEQDATA_DIM_COUNT宏进行声明。 mcdnnSeqDataDescriptor_t容器被视为一个向量的集合,这些向量是形成序列的具有固定长度的向量,类似于构造句子的单词(字符向量)。TIME维度涵盖序列长度。不同的序列会捆绑在一个batch中。一个batch可以是一组单独的序列或束。一个束是备选序列或候选序列的集群。我们可以把束考虑为从一种语言到另一种语言的翻译任务。在选择最佳译文之前,您可能需要保留并尝试使用原句的几个译文版本。保留的候选项数量是束宽。 即使在同一个束内,每个序列都可以有不同的长度,因此朝向序列末尾的向量可以只是填充向量。paddingFill参数指定如何在输出序列数据缓冲区中写入填充向量。paddingFill参数指向一个dataType的值,该值应复制到填充向量中的所有元素。目前,paddingFill唯一支持的值是NULL,即应该忽略此选项。在这种情况下,输出缓冲区中填充向量的元素将具有未定义的值。 假定非空序列始终从时间索引零开始。seqLengthArray[]必须指定容器中的所有序列长度,因此该数组的总大小应为dimA[MCDNN_SEQDATA_BATCH_DIM] * dimA[MCDNN_SEQDATA_BEAM_DIM]。seqLengthArray[]数组的每个元素都应有一个非负值,该值应小于或等于dimA[MCDNN_SEQDATA_TIME_DIM;最大序列长度。seqLengthArray[]中的元素始终按相同的批主序(batch-major order)排列,这意味着,考虑束和batch的维度时,当我们按地址的升序遍历数组,batch是外部或较慢变化的索引。 使用一个简单的示例,seqLengthArray[]数组应按以下顺序保存序列长度:
{batch_idx=0, beam_idx=0}
{batch_idx=0, beam_idx=1}
{batch_idx=1, beam_idx=0}
{batch_idx=1, beam_idx=1}
{batch_idx=2, beam_idx=0}
{batch_idx=2, beam_idx=1}
当dimA[MCDNN_SEQDATA_BATCH_DIM]=3和dimA[MCDNN_SEQDATA_BEAM_DIM]=2时。 存储在mcdnnSeqDataDescriptor_t容器中的数据必须符合以下条件:
所有数据都是完全压缩格式。单独的向量元素或连续向量之间没有未使用的空间或间隙。 容器的最内维度是向量。换言之,dimA[MCDNN_SEQDATA_VECT_DIM]元素的第一个连续组属于第一个向量,后面跟着第二个向量的元素,依此类推。 mcdnnSetSeqDataDescriptor()函数中的axes参数要复杂一些。此数组应与dimA[]具有相同的容量。axes[]数组指定GPU内存中的实际数据布局。在此函数中,布局描述如下:当我们通过增加元素指针从内存中的一个向量元素移动到另一个元素时,我们遇到的VECT、TIME、BATCH和BEAM维度的顺序是什么? 假设我们要定义以下数据布局:
对应于张量维度的mcdnnSetSeqDataDescriptor()的数据布局示例:
int dimA[MCDNN_SEQDATA_DIM_COUNT];
dimA[MCDNN_SEQDATA_TIME_DIM] = 4;
dimA[MCDNN_SEQDATA_BATCH_DIM] = 3;
dimA[MCDNN_SEQDATA_BEAM_DIM] = 2;
dimA[MCDNN_SEQDATA_VECT_DIM] = 5;
现在,我们初始化axes[]数组。请注意,最内维度由axes[]的最后一个活动元素描述。这里只有一个有效的配置,因为我们总是先遍历一个完整的向量。因此,我们需要在axes[]的最后一个活动元素中写入MCDNN_SEQDATA_VECT_DIM。 mcdnnSeqDataAxis_t axes[MCDNN_SEQDATA_DIM_COUNT];
axes[3] = MCDNN_SEQDATA_VECT_DIM; // 3 = nbDims-1
现在,我们来研究axes[]的其余三个元素。当我们到达第一个向量的末尾时,我们跳到下一个束,因此:
axes[2] = MCDNN_SEQDATA_BEAM_DIM;
当我们接近第二个向量的末尾时,我们将移到下一个batch,因此:
axes[1] = MCDNN_SEQDATA_BATCH_DIM;
最后一个(最外侧)维度为TIME:
axes[0] = MCDNN_SEQDATA_TIME_DIM;
axes[]数组的四个值完全描述了图中所示的数据布局。 序列数据描述符允许用户选择3!=6种不同的数据布局或BEAM、BATCH、TIME维度的排列。 多头注意力API支持所有六种布局。
参数
seqDataDesc
输出。指向已创建的序列数据描述符的指针。
dataType
输入。序列数据缓冲区的数据类型(MCDNN_DATA_HALF、MCDNN_DATA_FLOAT或MCDNN_DATA_DOUBLE)。
nbDims
输入。必须为4。dimA[]和axes[]数组中的活动维数。两个数组都应声明至少包含MCDNN_SEQDATA_DIM_COUNT个元素。
dimA[]
输入。包含序列数据维度的整数数组。使用mcdnnSeqDataAxis_t枚举类型以索引所有活动的dimA[]元素。
axes[]
输入。mcdnnSeqDataAxis_t数组,用于定义内存中序列数据的布局。axes[]的第一个nbDims元素应使用axes[0]的最外维度和axes[nbDims-1]的最内维度进行初始化。
seqLengthArraySize
输入。序列长度数组seqLengthArray[]中的元素数。
seqLengthArray[]
输入。整数数组,定义容器的所有序列长度。
paddingFill
输入。必须为NULL。指向一个dataType值的指针,该值用于填充超出每个序列有效长度的输出向量,或者指向NULL以忽略此设置。
返回值
MCDNN_STATUS_SUCCESS
所有输入参数均已验证,序列数据描述符已成功更新。
MCDNN_STATUS_BAD_PARAM
找到一个无效的输入参数。例如:
seqDataDesc=NULL
dateType不是有效的mcdnnDataType_t类型
nbDims为负值或零
seqLengthArraySize与期望的长度不匹配
seqLengthArray[]的某些元素无效
MCDNN_STATUS_NOT_SUPPORTED
输入参数不受支持。例如:
nbDims不等于4
paddingFill不为NULL
MCDNN_STATUS_ALLOC_FAILED
无法为序列数据描述符对象分配存储。