假设我有N个序列x [i],每个序列的长度为seqLength [i] 0 <= i <N.据我从cuDNN文档中了解,它们必须按序列长度排序,最长的是第一个,所以假设seqLength [i]> = seqLength [i + 1].假设它们具有特征尺寸D,因此x [i]是2D张量形状(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是一个数组.什么长度?MAX(seqLength)?如果是这样,我假设它描述了每个帧的一批特征,但是后面的一些帧将具有较少的序列.听起来像第一维中描述了每帧序列的数量.所以:
xDesc[t].shape[0] = len([i for i in range(N) if t < seqLength[i]])
Run Code Online (Sandbox Code Playgroud)
对于所有0 <= t <max(seqLength).即0 <= xDesc[t].shape[0]<= N.
每个xDesc [t]描述多少维度,即什么是len(xDesc [t] .shape)?我假设它是2,第二个维度是特征维度,即D,即:
xDesc[t].shape = (len(...), D)
Run Code Online (Sandbox Code Playgroud)
必须相应地设置步幅,尽管它也不完全清楚.如果x以行主顺序存储,那么
xDesc[0].strides[0] = D * xDesc[0].shape[0]
xDesc[0].strides[1] = 1
Run Code Online (Sandbox Code Playgroud)
但是cuDNN如何计算帧的偏移量t?我想它会跟踪并因此计算sum([xDesc[t2].strides[0] for t2 in range(t)]).
我见过的大多数示例代码都假设所有序列的长度都相同.它们都描述了每个xDesc [t]的3个维度,而不是2.为什么?第三个维度始终为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*/);
Run Code Online (Sandbox Code Playgroud)
在我找到的所有示例中,代码看起来非常相似.搜索cudnnSetTensorNdDescriptor或cudnnRNNForwardTraining.例如:
我找到了一个可以处理不同长度序列的例子.再次搜索cudnnSetTensorNdDescriptor:
这声称每个人必须有3个维度xDesc[t].它有评论:
这些维度是CUDNN所期望的:(小批量维度,数据维度和数字1(因为每个描述符描述一帧数据)
编辑:在此提交中,现在为PyTorch添加了对此的支持.
我错过了cuDNN文档中的内容吗?我真的没有在其中找到这些信息.
我的问题是根本,是我对如何设置参数的结论x,seqLength以及xDesc对cudnnRNNForwardInference/ cudnnRNNForwardTraining正确的,也是我的隐含假设,如果没有,我会怎样使用它,如何做内存布局的样子,等?
| 归档时间: |
|
| 查看次数: |
707 次 |
| 最近记录: |