@@ -28,36 +28,47 @@ def __init__(
2828 state_vars : Iterable [str ],
2929 time : Optional [int ] = None ,
3030 batch_size : int = 1 ,
31+ device : str = "cpu" ,
3132 ):
3233 # language=rst
3334 """
3435 Constructs a ``Monitor`` object.
3536
3637 :param obj: An object to record state variables from during network simulation.
37- :param state_vars: Iterable of strings indicating names of state variables to
38- record.
38+ :param state_vars: Iterable of strings indicating names of state variables to record.
3939 :param time: If not ``None``, pre-allocate memory for state variable recording.
40+ :param device: Allow the monitor to be on different device separate from Network device
4041 """
4142 super ().__init__ ()
4243
4344 self .obj = obj
4445 self .state_vars = state_vars
4546 self .time = time
4647 self .batch_size = batch_size
48+ self .device = device
49+
50+ # if time is not specified the monitor variable accumulate the logs
51+ if self .time is None :
52+ self .device = "cpu"
4753
48- # Deal with time later, the same underlying list is used
49- self .recording = { v : [] for v in self . state_vars }
54+ self . recording = []
55+ self .reset_state_variables ()
5056
5157 def get (self , var : str ) -> torch .Tensor :
5258 # language=rst
5359 """
5460 Return recording to user.
5561
5662 :param var: State variable recording to return.
57- :return: Tensor of shape ``[time, n_1, ..., n_k]``, where ``[n_1, ..., n_k]`` is
58- the shape of the recorded state variable.
63+ :return: Tensor of shape ``[time, n_1, ..., n_k]``, where ``[n_1, ..., n_k]`` is the shape of the recorded state
64+ variable.
65+ Note, if time == `None`, get return the logs and empty the monitor variable
66+
5967 """
60- return torch .cat (self .recording [var ], 0 )
68+ return_logs = torch .cat (self .recording [var ], 0 )
69+ if self .time is None :
70+ self .recording [var ] = []
71+ return return_logs
6172
6273 def record (self ) -> None :
6374 # language=rst
@@ -66,20 +77,27 @@ def record(self) -> None:
6677 """
6778 for v in self .state_vars :
6879 data = getattr (self .obj , v ).unsqueeze (0 )
69- self .recording [v ].append (data .detach ().clone ())
70-
71- # remove the oldest element (first in the list)
72- if self .time is not None :
73- for v in self .state_vars :
74- if len (self .recording [v ]) > self .time :
75- self .recording [v ].pop (0 )
80+ # self.recording[v].append(data.detach().clone().to(self.device))
81+ self .recording [v ].append (
82+ torch .empty_like (data , device = self .device , requires_grad = False ).copy_ (
83+ data , non_blocking = True
84+ )
85+ )
86+ # remove the oldest element (first in the list)
87+ if self .time is not None :
88+ self .recording [v ].pop (0 )
7689
7790 def reset_state_variables (self ) -> None :
7891 # language=rst
7992 """
80- Resets recordings to empty ``torch.Tensor ``s.
93+ Resets recordings to empty ``List ``s.
8194 """
82- self .recording = {v : [] for v in self .state_vars }
95+ if self .time is None :
96+ self .recording = {v : [] for v in self .state_vars }
97+ else :
98+ self .recording = {
99+ v : [[] for i in range (self .time )] for v in self .state_vars
100+ }
83101
84102
85103class NetworkMonitor (AbstractMonitor ):
0 commit comments