Network Block Builder will cut your graph into small blocks(subgraphs) Each block will have exact 1 input operation and 1 output operation. Besides, there is a parameter 'limit' to control the size of each block.
| 189 | |
| 190 | |
| 191 | class BlockBuilder: |
| 192 | """ |
| 193 | Network Block Builder will cut your graph into small blocks(subgraphs) |
| 194 | Each block will have exact 1 input operation and 1 output operation. |
| 195 | |
| 196 | Besides, there is a parameter 'limit' to control the size of each block. |
| 197 | """ |
| 198 | def __init__(self, graph: BaseGraph, topo_order: List[Operation]) -> None: |
| 199 | self.graph = graph |
| 200 | self.op_orders = topo_order |
| 201 | self.depth = {} |
| 202 | self.search_engine = SearchableGraph(self.graph) |
| 203 | self.initialize_depth() |
| 204 | |
| 205 | def create_block(self, sp: Operation, ep: Operation) -> TrainableBlock: |
| 206 | if sp == ep: return TrainableBlock(sp=sp, ep=ep, rps=[sp]) |
| 207 | rps = self.search_engine.opset_matching( |
| 208 | sp_expr = lambda x: x == sp, |
| 209 | rp_expr = lambda x, y: True, |
| 210 | ep_expr = lambda x: x == ep, |
| 211 | direction='down') |
| 212 | rps = [(self.op_orders.index(op), op) for op in rps] |
| 213 | rps = sorted(rps) |
| 214 | return TrainableBlock(sp=sp, ep=ep, rps=[op for _, op in rps]) |
| 215 | |
| 216 | def build(self, op: Operation, limit: int) -> TrainableBlock: |
| 217 | """子图分割算法, 这个算法将从指定节点出发, 构造一个满足定义的子图结构 Solving best block from given |
| 218 | operation. |
| 219 | |
| 220 | Block definition:(子图定义) |
| 221 | A Block is a triple contains S, E, M, |
| 222 | where S is the input node of block |
| 223 | where E is the output node of block |
| 224 | where M contains all nodes inside block |
| 225 | |
| 226 | Property:(子图性质) |
| 227 | 1. Minimal TrainableBlock start from p is {p, p, {p}}, |
| 228 | this block have only one node as both input and output. |
| 229 | 2. When S != E, |
| 230 | E must on every path from S to graph output. |
| 231 | S must on every path from graph input to E. |
| 232 | 3. M contains and only contains nodes on all paths from S to E. |
| 233 | |
| 234 | Lemma:(算法引理) |
| 235 | 1. 如果 s 的后继节点只有一个 e, 且 e 的输入只有一个,那么 {s, e, {s, e}} 构成满足定义的子图,从 s 寻找子图的任务可以递归由 e 完成 |
| 236 | 2. 如果 s 的后继存在多个节点,则只存在两种情况: |
| 237 | 2.1 从 s 出发,最大子图即为 {s, s, {s}}。 |
| 238 | 2.2 从 s 出发,可以构成子图 {s, e, R} (e!=s), 那么R中必须含有一个节点接收多个输入。(可用反证法证明,略) |
| 239 | |
| 240 | Algorithm:(算法) |
| 241 | Build(s, d): |
| 242 | 如果区块长度大于所需,则返回现有内容 |
| 243 | 从 s 出发,如果 s 的后继节点只有一个e,则判断e的输入节点个数: |
| 244 | 1. 如果 e 是单输入节点,执行Build(e, d-1),并将其结果与 {s, e, {s, e}} 合并 |
| 245 | 2. 如果 e 是多输入节点,算法立即停机,返回 {s, s, {s}} |
| 246 | |
| 247 | 如果 s 的后继节点存在多个,找出距离 s 拓扑序最近的多输入的节点 k1,判断 s 到输出的路径是否能够被 k1 阻断 |
| 248 | 如果 k 成功阻断所有输出,执行Build(k1, d-1),并将其结果与 {s, k1, F(s, k1)} 合并 |
no outgoing calls
no test coverage detected