I have an tensor with type caffe2::TypeMeta
, and I need to get its value as a regular std::vector
object. I know how to convert a Torch::Tensor
object with a regular type to a std::vector
object, but the same procedure does not work for tensors with type caffe2::TypeMeta
. I found an expensive way to do that, it needs to iterate over every single parameter on the caffe2:TypeMeta
object which can be very expensive.
I faced these tensors with type caffe2:TypeMeta
in the state of the optimizer, where I need to get the state value of different optimizer and modify them based on a given algorithm.
Below is the piece of the code which gets the tensors of caffe2:TypeMeta
.
I appreciate any comment on this.
void get_state(torch::optim::Optimizer *optimizer){
for (auto& group : optimizer->param_groups()) {
for (auto &p : group.params()) {
if (!p.grad().defined()) {
continue;
}
auto grad = p.grad();
TORCH_CHECK(!grad.is_sparse(),
"Adam does not support sparse gradients"/*, please consider SparseAdam instead*/);
ska::flat_hash_map<std::string, std::unique_ptr<torch::optim::OptimizerParamState>>& state_ = optimizer->state();
auto param_state = state_.find(c10::guts::to_string(p.unsafeGetTensorImpl()));
auto& state = static_cast<torch::optim::AdamParamState&>(*state_[c10::guts::to_string(p.unsafeGetTensorImpl())]);
auto& exp_avg = state.exp_avg();
auto& exp_avg_sq = state.exp_avg_sq();
auto& max_exp_avg_sq = state.max_exp_avg_sq();
auto step_counter = state.step();
// This works, but can be very expensive since I need to iterate over all the element for each of the tensors in the optimizer state
if (exp_avg.dim() > 1) {
auto tmp_v2 = exp_avg[10][3].item().toDouble();
std::cout << tmp_v2 << std::endl;
tmp_v2 = exp_avg_sq[10][3].item().toDouble();
std::cout << tmp_v2 << std::endl;
}
else
{
auto tmp_v2 = exp_avg[10].item().toDouble();
std::cout << tmp_v2 << std::endl;
tmp_v2 = exp_avg_sq[10].item().toDouble();
std::cout << tmp_v2 << std::endl;
}
state.exp_avg(torch::ones_like(exp_avg));
if (exp_avg.dim() > 1) {
auto tmp_v2 = exp_avg[10][3].item().toDouble();
std::cout << tmp_v2 << std::endl;
tmp_v2 = exp_avg_sq[10][3].item().toDouble();
std::cout << tmp_v2 << std::endl;
}
else
{
auto tmp_v2 = exp_avg[10].item().toDouble();
std::cout << tmp_v2 << std::endl;
tmp_v2 = exp_avg_sq[10].item().toDouble();
std::cout << tmp_v2 << std::endl;
}
// This does not work, it returns a memory segmentation fault error at the second line:
auto g = torch::reshape(exp_avg, {-1,}).to(at::kDouble);
auto v = std::vector<double>(g.data_ptr<double>(), g.data_ptr<double>() + g.numel());
}
}
}