aten/src/ATen/native/cudnn/RNN.cpp
// NB: does inplace update into TensorList
// It would be a relatively simple matter to refactor this into multiple
// functions, only one of which does an inplace update, but we leave this
// for future work
does inplace update into TensorList
It would be a relatively simple matter to refactor this into multiple
functions, only one of which does an inplace update, but we leave this
for future work
does inplace update into TensorList It would be a relatively simple matter to refactor this into multiple functions only one of which does an inplace update but we leave this for future work
Tensor _cudnn_rnn_flatten_weight(
    TensorList weight_arr, int64_t weight_stride0,
    int64_t input_size,
    int64_t fn_mode, int64_t fn_hidden_size,
    int64_t fn_num_layers, bool batch_first,
    bool fn_bidirectional
    ) {
  if (weight_arr.size() == 0) {
    throw std::runtime_error("_cudnn_rnn_flatten_weight_: cannot flatten empty weight list");
  }
  auto any_param = weight_arr[0];
  RNNDescriptorParams rnn;
  rnn.set(fn_mode, fn_hidden_size, fn_num_layers, fn_bidirectional, getCudnnDataType(any_param));
  auto handle = getCudnnHandle();
  RNNDescriptor rnn_desc = rnn.descriptor(handle);
  TensorGeometry x_geom({1, input_size});
  TensorDescriptor x_desc;
  x_desc.set(getCudnnDataType(any_param), x_geom.sizes(), x_geom.strides(), 5);
  auto num_weights = get_num_weights(handle, rnn_desc, x_desc, rnn.datatype);
  auto weight_buf = any_param.type().tensor(num_weights).zero_();
  FilterDescriptor w_desc;
  w_desc.set(weight_buf, 3);
  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};
  _copyParams(weight, params);
  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));
    }
  }
  return weight_buf;
}
Tensor _cudnn_rnn_flatten_weight ( TensorList weight_arr , int64_t weight_stride0 , int64_t input_size , int64_t fn_mode , int64_t fn_hidden_size , int64_t fn_num_layers , bool batch_first , bool fn_bidirectional ) { if ( weight_arr . size ( ) == 0 ) { throw std :: runtime_error ( " " ) ; } auto any_param = weight_arr [ 0 ] ; RNNDescriptorParams rnn ; rnn . set ( fn_mode , fn_hidden_size , fn_num_layers , fn_bidirectional , getCudnnDataType ( any_param ) ) ; auto handle = getCudnnHandle ( ) ; RNNDescriptor rnn_desc = rnn . descriptor ( handle ) ; TensorGeometry x_geom ( { 1 , input_size } ) ; TensorDescriptor x_desc ; x_desc . set ( getCudnnDataType ( any_param ) , x_geom . sizes ( ) , x_geom . strides ( ) , 5 ) ; auto num_weights = get_num_weights ( handle , rnn_desc , x_desc , rnn . datatype ) ; auto weight_buf = any_param . type ( ) . tensor ( num_weights ) . zero_ ( ) ; FilterDescriptor w_desc ; w_desc . set ( weight_buf , 3 ) ; 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 } ; _copyParams ( weight , params ) ; 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 ) ) ; } } return weight_buf ; }
NB: does inplace update into TensorList
It would be a relatively simple matter to refactor this into multiple
functions, only one of which does an inplace update, but we leave this
for future work
NB : does inplace update into TensorList It would be a relatively simple matter to refactor this into multiple functions only one of which does an inplace update but we leave this for future work
// Slice off views into weight_buf // Copy weights // Update the storage