7

假设我有 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 seqLengthcudnnTensorDescriptor_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*/);

在我找到的所有示例中,代码看起来都非常相似。搜索cudnnSetTensorNdDescriptorcudnnRNNForwardTraining。例如:

我找到了一个可以处理不同长度序列的示例。再次搜索cudnnSetTensorNdDescriptor

这声称每个xDesc[t]. 它有评论:

这些维度是 CUDNN 所期望的:(小批量维度、数据维度和数字 1(因为每个描述符描述一帧数据)

编辑:在 2018 年底,在此提交中为 PyTorch 添加了对此的支持。

我是否遗漏了 cuDNN 文档中的某些内容?我真的没有在其中找到该信息。

我的问题基本上是,我的结论是关于如何设置参数x,for / correct,seqLength以及我的隐含假设,或者如果没有,我将如何使用它,内存布局如何,等等?xDesccudnnRNNForwardInferencecudnnRNNForwardTraining

4

0 回答 0