cudnnRNNForwardTraining seqLength / xDesc usage

时间:2017-01-04 10:33:07

标签: cuda cudnn

假设我有N个序列x [i],每个序列的长度为seqLength [i],0 <= i&lt; N.据我所知,从cuDNN文档中,它们必须按序列长度排序,最长的第一个,所以假设seqLength [i]> = seqLength [i + 1]。假设它们具有特征尺寸D,因此x [i]是2D张量形状(seqLength [i],D)。据我所知,我应该准备一个张量x,其中所有x [i]都是相邻的,即形状(sum(seqLength),D)。

根据cuDNN文档,函数cudnnRNNForwardInference / cudnnRNNForwardTraining获取参数int seqLengthcudnnTensorDescriptor_t* xDesc,其中:

seqLength:展开的迭代次数。

xDesc:张量描述符数组。每个必须具有相同的第二维度。第一维可以从元素n减少到元素n + 1,但可以不增加。

我不确定我是否正确理解这一点。 seqLength我的最大值(seqLength)?

xDesc是一个数组。什么长度? MAX(seqLength)?如果是这样,我假设它描述了每个帧的一批特征,但是后面的一些帧将具有较少的序列。听起来像第一维中描述了每帧序列的数量。 所以:

xDesc[t].shape[0] = len([i for i in range(N) if t < seqLength[i]])

对于所有0&lt; = t&lt; MAX(seqLength)。即0&lt; = xDesc[t].shape[0]&lt; = 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如何计算帧t的偏移量?我想它会跟踪并计算sum([xDesc[t2].strides[0] for t2 in range(t)])

我见过的大多数示例代码都假设所有序列的长度都相同。它们都描述了每个xDesc [t]的3个维度,而不是2.为什么?第三个维度始终为1,以及第二维和第三维的步幅,第一个维度的步幅为N.因此,这假设张量x是行主要有序和形状(最大) (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。 E.g:

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

声称每xDesc[t]个必须有3个维度。它有评论:

  

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

编辑:现在在this commit中为PyTorch添加了对此的支持。

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

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

0 个答案:

没有答案