Closed lieral closed 1 year ago
@lieral ,
From error logs (the initial code I read from my email), it seems that some tensor was deleted 2 times (illegal). However, I couldn't see it here now and I am so confused about your code. What func ModelManager()
was used? and how it is related to func ModelPredict()
. Please provide a completed working code and error logs and even better if you could shared your testing model file so that I can try to reproduce. Thanks.
@sugarme Thanks for reply. I create a debug repository:https://github.com/lieral/debug_gotch.git You can run the code by "cd debug_gotch/bin;./server_mcd".
@lieral , I can reproduce the issue in a for loop. Forward loop seems to be unstable and might related to memory allocation and handling from Go to C. I will find my time to investigate more. My working code as below:
package main
import (
"fmt"
"github.com/sugarme/gotch/ts"
)
type Model struct {
m *ts.CModule
}
func LoadModel(modelFile string) (*Model, error) {
model, err := ts.ModuleLoad(modelFile)
if err != nil {
err = fmt.Errorf("LoadModel() failed: %w\n", err)
return nil, err
}
return &Model{
m: model,
}, nil
}
func (m *Model) Predict(input *ts.Tensor) ([]ts.Tensor, error) {
inputIVal := ts.NewIValue(*input)
out, err := m.m.ForwardIs([]ts.IValue{*inputIVal})
if err != nil {
return nil, err
}
return out.Value().([]ts.Tensor), nil
}
func main() {
modelFile := "../model/epoch_2500.pt"
model, err := LoadModel(modelFile)
if err != nil {
panic(err)
}
// If increase n, err occurs.
n := 1
for i := 0; i < n; i++ {
input := []float64{0.18, 0.32}
x := ts.MustOfSlice(input)
outs, err := model.Predict(x)
if err != nil {
panic(err)
}
for i, out := range outs {
fmt.Printf("out-%v: %v\n", i, out)
// x.MustDrop()
}
// x.MustDrop()
}
}
@lieral , I can reproduce the issue in a for loop. Forward loop seems to be unstable and might related to memory allocation and handling from Go to C. I will find my time to investigate more. My working code as below:
package main import ( "fmt" "github.com/sugarme/gotch/ts" ) type Model struct { m *ts.CModule } func LoadModel(modelFile string) (*Model, error) { model, err := ts.ModuleLoad(modelFile) if err != nil { err = fmt.Errorf("LoadModel() failed: %w\n", err) return nil, err } return &Model{ m: model, }, nil } func (m *Model) Predict(input *ts.Tensor) ([]ts.Tensor, error) { inputIVal := ts.NewIValue(*input) out, err := m.m.ForwardIs([]ts.IValue{*inputIVal}) if err != nil { return nil, err } return out.Value().([]ts.Tensor), nil } func main() { modelFile := "../model/epoch_2500.pt" model, err := LoadModel(modelFile) if err != nil { panic(err) } // If increase n, err occurs. n := 1 for i := 0; i < n; i++ { input := []float64{0.18, 0.32} x := ts.MustOfSlice(input) outs, err := model.Predict(x) if err != nil { panic(err) } for i, out := range outs { fmt.Printf("out-%v: %v\n", i, out) // x.MustDrop() } // x.MustDrop() } }
OK. And thanks for your work.This repository is very helpful
@lieral ,
Would it be able to share your Pytorch model code (Python?). I would like to see how output tensors are formed and returned.
@lieral ,
Would it be able to share your Pytorch model code (Python?). I would like to see how output tensors are formed and returned. @sugarme
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
# rely on https://github.com/ikostrikov/pytorch-a2c-ppo-acktr-gail.git
from a2c_ppo_acktr.distributions import Bernoulli, Categorical, DiagGaussian
from a2c_ppo_acktr.utils import init
class Flatten(nn.Module):
def forward(self, x):
return x.view(x.size(0), -1)
class Policy(nn.Module):
def __init__(self, obs_len, action_space):
super(Policy, self).__init__()
self.base = MLPBase(obs_len)
action_shape = np.shape(action_space)
self.dist = Categorical(self.base.output_size, action_shape[1])
def forward(self, inputs):
value, actor_features = self.base(inputs)
dist = self.dist(actor_features)
action_s = dist.sample()
action_m = dist.mode()
action_log_probs = dist.log_probs(action_s)
action_prob = dist.probs
actions = torch.cat([action_s, action_m], -1)
#return value, actions, action_log_probs
# for debug gotch
# it works with 3 output
#return action_prob, action_prob, action_prob
# 4 output may cause gotch forward loop crash
return action_prob, action_prob, action_prob, action_prob
def get_value(self, inputs, rnn_hxs):
value, _ = self.base(inputs, rnn_hxs)
return value
def evaluate_actions(self, inputs, action):
value, actor_features = self.base(inputs)
dist = self.dist(actor_features)
action_log_probs = dist.log_probs(action)
dist_entropy = dist.entropy().mean()
return value, action_log_probs, dist_entropy
class MLPBase(nn.Module):
def __init__(self, num_inputs, recurrent=False, hidden_size=64):
super(MLPBase, self).__init__()
self.hidden_size = hidden_size
init_ = lambda m: init(m, nn.init.orthogonal_, lambda x: nn.init.
constant_(x, 0), np.sqrt(2))
self.common = nn.Sequential(
init_(nn.Linear(num_inputs, hidden_size)), nn.Tanh(),
init_(nn.Linear(hidden_size, hidden_size)), nn.Tanh())
self.critic = nn.Sequential(
init_(nn.Linear(hidden_size, hidden_size)), nn.Tanh())
self.actor = nn.Sequential(
init_(nn.Linear(hidden_size, hidden_size)), nn.Tanh())
self.critic_linear = init_(nn.Linear(hidden_size, 1))
self.train()
@property
def output_size(self):
return self.hidden_size
def forward(self, inputs):
x = inputs
hid_common = self.common(x)
hid_critic = self.critic(hid_common)
hid_actor = self.actor(hid_common)
return self.critic_linear(hid_critic), hid_actor
close for now.
I used ForwardIs func to get my model forward results. And I had a loop to call it. It works well when my forward function of model only has 3 or lesser output. But the goroutine crashed when the forward function of sasved model has more than 3 output tensor. The forward function is like this, and I return same tensor to specify the num of output.
go code: