flatten_parameters()有什么作用?

flo*_*oyd 11 pytorch

我在RNN的前向功能中看到了许多使用flatten_parameters的Pytorch示例

self.rnn.flatten_parameters()

我看到了这个RNNBase并写了它

重置参数数据指针,以便它们可以使用更快的代码路径

那是什么意思?

And*_*uib 8

它可能不是您问题的完整答案。但是,如果您查看flatten_parameters源代码,您会注意到它调用_cudnn_rnn_flatten_weight

...
NoGradGuard no_grad;
torch::_cudnn_rnn_flatten_weight(...)
...
Run Code Online (Sandbox Code Playgroud)

是完成工作的功能。你会发现它实际上做的是将模型的权重复制到一个vector<Tensor>(检查params_arr声明)中:

  // Slice off views into weight_buf
  std::vector<Tensor> params_arr;
  size_t params_stride0;
  std::tie(params_arr, params_stride0) = get_parameters(handle, rnn, rnn_desc, x_desc, w_desc, weight_buf);

  MatrixRef<Tensor> weight{weight_arr, static_cast<size_t>(weight_stride0)},
                    params{params_arr, params_stride0};
Run Code Online (Sandbox Code Playgroud)

和权重复制

  // Copy weights
  _copyParams(weight, params);
Run Code Online (Sandbox Code Playgroud)

另请注意,他们通过执行就地操作(是他们对就地操作的表示法Resetweights使用 的新指针更新(或如他们在文档中明确指出的那样)的原始指针params.set__orig_param.set_(new_param.view_as(orig_param));

  // Update the storage
  for (size_t i = 0; i < weight.size(0); i++) {
    for (auto orig_param_it = weight[i].begin(), new_param_it = params[i].begin();
         orig_param_it != weight[i].end() && new_param_it != params[i].end();
         orig_param_it++, new_param_it++) {
      auto orig_param = *orig_param_it, new_param = *new_param_it;
      orig_param.set_(new_param.view_as(orig_param));
    }
  }
Run Code Online (Sandbox Code Playgroud)

并根据n2798(C++0x 草案)

©ISO/IECN3092

23.3.6 类模板向量

向量是支持随机访问迭代器的序列容器。此外,它支持(摊销)最后的常量时间插入和擦除操作;在中间插入和擦除需要线性时间。存储管理是自动处理的,但可以提供提示以提高效率。向量的元素是连续存储的,这意味着如果v是一个向量<T, Allocator>,其中T是 bool 以外的某种类型,那么它遵守identity&v[n] == &v[0] + nfor all 0 <= n < v.size()


在某些情况下

用户警告:RNN 模块权重不是单个连续内存块的一部分。这意味着它们需要在每次调用时被压缩,可能会大大增加内存使用量。再次调用压缩权重flatten_parameters()

他们在代码警告中明确建议人们拥有连续的内存块。