假设我有 N 个序列 x[i],每个序列的长度 seqLength[i] 为 0 <= i < N。据我从 cuDNN 文档中了解到,它们必须按序列长度排序,最长的在前,所以假设 seqLength[i] >= seqLength[i+1]。假设它们具有特征维度 D,因此 x[i] 是形状 (seqLength[i], D) 的二维张量。据我了解,我应该准备一个张量x
,其中所有 x[i] 都是连续的,即它的形状为 (sum(seqLength), D)。
根据 cuDNN 文档,函数cudnnRNNForwardInference
/cudnnRNNForwardTraining
获取参数int seqLength
和cudnnTensorDescriptor_t* xDesc
,其中:
seqLength
:要展开的迭代次数。
xDesc
:张量描述符数组。每个必须具有相同的第二维。第一个维度可能会从元素 n 减少到元素 n + 1,但可能不会增加。
我不确定我是否正确理解这一点。是seqLength
我的最大值(seqLength)吗?
并且xDesc
是一个数组。多长?最大(序列长度)?如果是这样,我假设它为每一帧描述了一批特征,但后面的一些帧中的序列会更少。听起来每帧的序列数是在第一维中描述的。所以:
xDesc[t].shape[0] = len([i for i in range(N) if t < seqLength[i]])
对于所有 0 <= t < max(seqLength)。即 0 <= xDesc[t].shape[0]
<= N。
每个xDesc[t] 描述了多少维度,即len(xDesc[t].shape) 是什么?我假设它是2,第二维是特征维度,即D,即:
xDesc[t].shape = (len(...), D)
必须相应地设置步幅,尽管也不是很清楚。如果x
以行优先顺序存储,则
xDesc[0].strides[0] = D * xDesc[0].shape[0]
xDesc[0].strides[1] = 1
但是 cuDNN 如何计算 frame 的偏移量t
?我猜它会跟踪并因此计算sum([xDesc[t2].strides[0] for t2 in range(t)])
.
我见过的大多数示例代码都假设所有序列的长度相同。此外,它们都描述了每个 xDesc[t] 的 3 个维度,而不是 2 个。这是为什么呢?第三维始终为 1,第二维和第三维的步幅始终为 1,第一维的步幅为 N。因此假设张量x
是行主序且形状为 (max(seqLength), N , D)。代码实际上有点奇怪。例如来自 TensorFlow:
int dims[] = {batch_size, data_size, 1};
int strides[] = {dims[1] * dims[2], dims[2], 1};
cudnnSetTensorNdDescriptor(
...,
sizeof(dims) / sizeof(dims[0]) /*nbDims*/, dims /*dimA*/,
strides /*strideA*/);
在我找到的所有示例中,代码看起来都非常相似。搜索cudnnSetTensorNdDescriptor
或cudnnRNNForwardTraining
。例如:
我找到了一个可以处理不同长度序列的示例。再次搜索cudnnSetTensorNdDescriptor
:
这声称每个xDesc[t]
. 它有评论:
这些维度是 CUDNN 所期望的:(小批量维度、数据维度和数字 1(因为每个描述符描述一帧数据)
编辑:在 2018 年底,在此提交中为 PyTorch 添加了对此的支持。
我是否遗漏了 cuDNN 文档中的某些内容?我真的没有在其中找到该信息。
我的问题基本上是,我的结论是关于如何设置参数x
,for / correct,seqLength
以及我的隐含假设,或者如果没有,我将如何使用它,内存布局如何,等等?xDesc
cudnnRNNForwardInference
cudnnRNNForwardTraining