# Libtorch 自动微分(2)

## 原型实现（python）

### 1. 数据结构

class MyArray(np.ndarray):
"""
Same with np.ndarray but __setattr__ fucntion.
"""
def __setattr__(self, __name, __value):
self.__dict__[__name] = __value

def make_array(input_list, requires_grad=False):
nparray = np.array(input_list)
myarray = MyArray(nparray.shape)
myarray[:] = nparray[:]
return myarray

### 2. 计算节点

class NodeBase:
def __init__(self):
self._edges = []
self._depends = 0
self._inputs = []
self._outputs = []

def __call__(self, *args, **kwds):
return self.forward(*args, **kwds)

def _save_inputs(self, *args):
for a in args:
self._inputs.append(a)
self._edges.append(a.fn)

def _save_outputs(self, *args):
for a in args:
self._outputs.append(a)

class MulOP(NodeBase):
def __init__(self):
super().__init__()

def forward(self, a, b):
self._save_inputs(a, b)
output = a * b
output.fn = self
self._save_outputs(output)
return output

def _backward(self):
self._inputs[1].grad += self._outputs[0].grad * self._inputs[0]

_forward 中还将当前节点的计算 function 给保存了下来，这一点是仿照的 PyTorch，形如注意 b 的输出，包含两项：

>>> a = torch.ones(2, requires_grad=True)
>>> b = a*a
>>> b
tensor([1., 1.], grad_fn=<MulBackward0>)

### 3. 计算引擎

class BackwardEngine:
def __init__(self, arr):
self._target_arr = arr
self._root = arr.fn
self.topo_queue = []
self._topological_sorting()

def _topological_sorting(self):
def _dfs(node):
for next_node in node._edges:
_dfs(next_node)
node._depends += 1
self.topo_queue.append(node)
_dfs(self._root)
self.root._depends = 0

while len(self.topo_queue):
n._depends -= 1

Service Mesh实战 -〔马若飞〕

React Hooks 核心原理与实战 -〔王沛〕

B端产品经理入门课 -〔董小圣〕