140681896Sopenharmony_ci#!/usr/bin/env python3 240681896Sopenharmony_ci# -*- coding: utf-8 -*- 340681896Sopenharmony_ci 440681896Sopenharmony_ci# Copyright (c) 2021 Huawei Device Co., Ltd. 540681896Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 640681896Sopenharmony_ci# you may not use this file except in compliance with the License. 740681896Sopenharmony_ci# You may obtain a copy of the License at 840681896Sopenharmony_ci# 940681896Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 1040681896Sopenharmony_ci# 1140681896Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 1240681896Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 1340681896Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1440681896Sopenharmony_ci# See the License for the specific language governing permissions and 1540681896Sopenharmony_ci# limitations under the License. 1640681896Sopenharmony_cifrom collections import OrderedDict 1740681896Sopenharmony_ci 1840681896Sopenharmony_cifrom log_exception import UPDATE_LOGGER 1940681896Sopenharmony_ci 2040681896Sopenharmony_ci# 50% of the data partition, in KB x 1024. 2140681896Sopenharmony_ciDATA_SIZE = 1374024 * 1024 2240681896Sopenharmony_ci 2340681896Sopenharmony_ci 2440681896Sopenharmony_ciclass GigraphProcess(object): 2540681896Sopenharmony_ci def __init__(self, actions_list, src_image, tgt_image): 2640681896Sopenharmony_ci self.actions_list = actions_list 2740681896Sopenharmony_ci if len(self.actions_list) == 0: 2840681896Sopenharmony_ci raise RuntimeError 2940681896Sopenharmony_ci self.size_of_source_list = 0 3040681896Sopenharmony_ci self.src_img_obj = src_image 3140681896Sopenharmony_ci self.tgt_img_obj = tgt_image 3240681896Sopenharmony_ci self.vertices = len(self.actions_list) 3340681896Sopenharmony_ci self.data_size = DATA_SIZE 3440681896Sopenharmony_ci 3540681896Sopenharmony_ci self.generate_digraph() 3640681896Sopenharmony_ci self.stash_process() 3740681896Sopenharmony_ci 3840681896Sopenharmony_ci def generate_digraph(self): 3940681896Sopenharmony_ci """ 4040681896Sopenharmony_ci Start correlation lookup. 4140681896Sopenharmony_ci """ 4240681896Sopenharmony_ci source_ranges = [] 4340681896Sopenharmony_ci source_ranges = \ 4440681896Sopenharmony_ci self.get_source_ranges(self.actions_list, source_ranges) 4540681896Sopenharmony_ci 4640681896Sopenharmony_ci self.get_intersections_dict(source_ranges) 4740681896Sopenharmony_ci # Start ordering. 4840681896Sopenharmony_ci topo_logical = TopoLogical(self) 4940681896Sopenharmony_ci action_stack = topo_logical.stack() 5040681896Sopenharmony_ci new_action_list = [] 5140681896Sopenharmony_ci for action in action_stack: 5240681896Sopenharmony_ci action.order = len(new_action_list) 5340681896Sopenharmony_ci new_action_list.append(action) 5440681896Sopenharmony_ci self.actions_list = new_action_list 5540681896Sopenharmony_ci 5640681896Sopenharmony_ci def get_intersections_dict(self, source_ranges): 5740681896Sopenharmony_ci """ 5840681896Sopenharmony_ci Get the intersections_dict. 5940681896Sopenharmony_ci :param source_ranges: source blocks 6040681896Sopenharmony_ci :return: 6140681896Sopenharmony_ci """ 6240681896Sopenharmony_ci for each_action in self.actions_list: 6340681896Sopenharmony_ci intersections = OrderedDict() 6440681896Sopenharmony_ci for start_value, end_value in each_action.tgt_block_set: 6540681896Sopenharmony_ci for i in range(start_value, end_value): 6640681896Sopenharmony_ci if i >= len(source_ranges): 6740681896Sopenharmony_ci break 6840681896Sopenharmony_ci if source_ranges[i] is not None: 6940681896Sopenharmony_ci for j in source_ranges[i]: 7040681896Sopenharmony_ci intersections[j] = None 7140681896Sopenharmony_ci 7240681896Sopenharmony_ci self.update_goes_before_and_after(each_action, intersections) 7340681896Sopenharmony_ci 7440681896Sopenharmony_ci @staticmethod 7540681896Sopenharmony_ci def update_goes_before_and_after(each_action, intersections): 7640681896Sopenharmony_ci """ 7740681896Sopenharmony_ci Update "goes before" and "goes after". 7840681896Sopenharmony_ci :param each_action: action to be processed 7940681896Sopenharmony_ci :param intersections: intersections dict 8040681896Sopenharmony_ci :return: 8140681896Sopenharmony_ci """ 8240681896Sopenharmony_ci for each_intersection in intersections: 8340681896Sopenharmony_ci if each_action is each_intersection: 8440681896Sopenharmony_ci continue 8540681896Sopenharmony_ci 8640681896Sopenharmony_ci intersect_range = \ 8740681896Sopenharmony_ci each_action.tgt_block_set.get_intersect_with_other( 8840681896Sopenharmony_ci each_intersection.src_block_set) 8940681896Sopenharmony_ci if intersect_range: 9040681896Sopenharmony_ci if each_intersection.src_name == "__ZERO": 9140681896Sopenharmony_ci size = 0 9240681896Sopenharmony_ci else: 9340681896Sopenharmony_ci size = intersect_range.size() 9440681896Sopenharmony_ci each_intersection.child[each_action] = size 9540681896Sopenharmony_ci each_action.parent[each_intersection] = size 9640681896Sopenharmony_ci 9740681896Sopenharmony_ci @staticmethod 9840681896Sopenharmony_ci def get_source_ranges(transfers, source_ranges): 9940681896Sopenharmony_ci """ 10040681896Sopenharmony_ci Update "goes before" and "goes after". 10140681896Sopenharmony_ci :param transfers: actions list 10240681896Sopenharmony_ci :param source_ranges: source blocks 10340681896Sopenharmony_ci :return: 10440681896Sopenharmony_ci """ 10540681896Sopenharmony_ci for each_action in transfers: 10640681896Sopenharmony_ci for start_value, end_value in each_action.src_block_set: 10740681896Sopenharmony_ci if end_value > len(source_ranges): 10840681896Sopenharmony_ci source_ranges.extend( 10940681896Sopenharmony_ci [None] * (end_value - len(source_ranges))) 11040681896Sopenharmony_ci for i in range(start_value, end_value): 11140681896Sopenharmony_ci if source_ranges[i] is None: 11240681896Sopenharmony_ci source_ranges[i] = \ 11340681896Sopenharmony_ci OrderedDict.fromkeys([each_action]) 11440681896Sopenharmony_ci else: 11540681896Sopenharmony_ci source_ranges[i][each_action] = None 11640681896Sopenharmony_ci return source_ranges 11740681896Sopenharmony_ci 11840681896Sopenharmony_ci def stash_process(self): 11940681896Sopenharmony_ci """ 12040681896Sopenharmony_ci Stash processing 12140681896Sopenharmony_ci """ 12240681896Sopenharmony_ci UPDATE_LOGGER.print_log("Reversing backward edges...") 12340681896Sopenharmony_ci stash_raw_id = 0 12440681896Sopenharmony_ci for each_action in self.actions_list: 12540681896Sopenharmony_ci each_child_dict = each_action.child.copy() 12640681896Sopenharmony_ci for each_before in each_child_dict: 12740681896Sopenharmony_ci if each_action.order >= each_before.order: 12840681896Sopenharmony_ci intersect_block_set = \ 12940681896Sopenharmony_ci each_action.src_block_set.get_intersect_with_other( 13040681896Sopenharmony_ci each_before.tgt_block_set) 13140681896Sopenharmony_ci 13240681896Sopenharmony_ci each_before.stash_before.append( 13340681896Sopenharmony_ci (stash_raw_id, intersect_block_set)) 13440681896Sopenharmony_ci each_action.use_stash.append( 13540681896Sopenharmony_ci (stash_raw_id, intersect_block_set)) 13640681896Sopenharmony_ci stash_raw_id += 1 13740681896Sopenharmony_ci each_action.child.pop(each_before) 13840681896Sopenharmony_ci each_before.parent.pop(each_action) 13940681896Sopenharmony_ci each_action.parent[each_before] = None 14040681896Sopenharmony_ci each_before.child[each_action] = None 14140681896Sopenharmony_ci UPDATE_LOGGER.print_log("Reversing backward edges completed!") 14240681896Sopenharmony_ci 14340681896Sopenharmony_ci 14440681896Sopenharmony_ciclass DirectedCycle(object): 14540681896Sopenharmony_ci def __init__(self, graph): 14640681896Sopenharmony_ci self.graph = graph 14740681896Sopenharmony_ci self.marked = [False for _ in range(self.graph.vertices)] 14840681896Sopenharmony_ci self.has_cycle = False 14940681896Sopenharmony_ci self.ontrack = [False for _ in range(self.graph.vertices)] 15040681896Sopenharmony_ci 15140681896Sopenharmony_ci 15240681896Sopenharmony_ciclass DepthFirstOrder: 15340681896Sopenharmony_ci def __init__(self, graph): 15440681896Sopenharmony_ci self.graph = graph 15540681896Sopenharmony_ci self.marked = {} 15640681896Sopenharmony_ci self.stack = [] 15740681896Sopenharmony_ci 15840681896Sopenharmony_ci for each_action in self.graph.actions_list: 15940681896Sopenharmony_ci self.marked[each_action] = False 16040681896Sopenharmony_ci 16140681896Sopenharmony_ci def dfs(self): 16240681896Sopenharmony_ci def dfs(index): 16340681896Sopenharmony_ci self.marked[index] = True 16440681896Sopenharmony_ci for each_child in index.child: 16540681896Sopenharmony_ci if not self.marked[each_child]: 16640681896Sopenharmony_ci dfs(each_child) 16740681896Sopenharmony_ci self.stack.insert(0, index) 16840681896Sopenharmony_ci 16940681896Sopenharmony_ci for each_action in self.graph.actions_list: 17040681896Sopenharmony_ci if not self.marked[each_action]: 17140681896Sopenharmony_ci dfs(each_action) 17240681896Sopenharmony_ci return self.stack 17340681896Sopenharmony_ci 17440681896Sopenharmony_ci def sort_vertices(self): 17540681896Sopenharmony_ci return self.dfs() 17640681896Sopenharmony_ci 17740681896Sopenharmony_ci 17840681896Sopenharmony_ciclass TopoLogical(object): 17940681896Sopenharmony_ci def __init__(self, graph): 18040681896Sopenharmony_ci self.order = None 18140681896Sopenharmony_ci self.cycle = DirectedCycle(graph) 18240681896Sopenharmony_ci if not self.cycle.has_cycle: 18340681896Sopenharmony_ci dfo = DepthFirstOrder(graph) 18440681896Sopenharmony_ci self.order = dfo.sort_vertices() 18540681896Sopenharmony_ci 18640681896Sopenharmony_ci def stack(self): 18740681896Sopenharmony_ci return self.order 188