diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3a15ba37..aca972912 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,11 +47,11 @@ jobs: - name: "Run MyPy Type Checker - DiscoPoP Library" run: python -m mypy --config-file=mypy.ini -p discopop_library - - name: "Run MyPy Type Checker - DiscoPoP Profiler - DEPRECATED" - run: python -m mypy --config-file=mypy.ini -p DEPRECATED_discopop_profiler - - - name: "Run MyPy Type Checker - DiscoPoP Wizard - DEPRECATED" - run: python -m mypy --config-file=mypy.ini -p DEPRECATED_discopop_wizard +# - name: "Run MyPy Type Checker - DiscoPoP Profiler - DEPRECATED" +# run: python -m mypy --config-file=mypy.ini -p DEPRECATED_discopop_profiler +# +# - name: "Run MyPy Type Checker - DiscoPoP Wizard - DEPRECATED" +# run: python -m mypy --config-file=mypy.ini -p DEPRECATED_discopop_wizard - name: "Check formatting of DiscoPoP Explorer" run: python -m black -l 120 --check discopop_explorer @@ -59,11 +59,11 @@ jobs: - name: "Check formatting of DiscoPoP Library" run: python -m black -l 120 --check discopop_library - - name: "Check formatting of DiscoPoP Profiler - DEPRECATED" - run: python -m black -l 120 --check DEPRECATED_discopop_profiler - - - name: "Check formatting of DiscoPoP Wizard - DEPRECATED" - run: python -m black -l 120 --check DEPRECATED_discopop_wizard +# - name: "Check formatting of DiscoPoP Profiler - DEPRECATED" +# run: python -m black -l 120 --check DEPRECATED_discopop_profiler +# +# - name: "Check formatting of DiscoPoP Wizard - DEPRECATED" +# run: python -m black -l 120 --check DEPRECATED_discopop_wizard execute_cxx_unit_tests: runs-on: ubuntu-20.04 diff --git a/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py b/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py index 7f05132ad..775be77e3 100644 --- a/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py +++ b/DEPRECATED_discopop_wizard/screens/widgets/ScrollableText.py @@ -37,7 +37,7 @@ def __init__(self, parent_frame): self.text_container["xscrollcommand"] = x_scrollbar.set self.text_container.config(state=tk.DISABLED) - def set_text(self, content: str): + def set_text(self, content: str) -> None: self.text_container.config(state=tk.NORMAL) self.text_container.delete("1.0", tk.END) self.text_container.insert("1.0", content) diff --git a/discopop_explorer/PEGraphX.py b/discopop_explorer/PEGraphX.py index c026a7da0..569250686 100644 --- a/discopop_explorer/PEGraphX.py +++ b/discopop_explorer/PEGraphX.py @@ -19,7 +19,8 @@ from alive_progress import alive_bar # type: ignore from lxml.objectify import ObjectifiedElement # type: ignore -from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType # type:ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type:ignore from .parser import LoopData, readlineToCUIdMap, writelineToCUIdMap, DependenceItem from .variable import Variable @@ -195,12 +196,12 @@ def __init__(self, node_id: NodeID): self.id = node_id self.file_id, self.node_id = parse_id(node_id) - @classmethod - def from_kwargs(cls, node_id: NodeID, **kwargs): - node = cls(node_id) - for key, value in kwargs.items(): - setattr(node, key, value) - return node + # @classmethod + # def from_kwargs(cls, node_id: NodeID, **kwargs) -> Node: + # node = cls(node_id) + # for key, value in kwargs.items(): + # setattr(node, key, value) + # return node def start_position(self) -> LineID: """Start position file_id:line @@ -219,7 +220,7 @@ def end_position(self) -> LineID: """ return LineID(f"{self.file_id}:{self.end_line}") - def contains_line(self, other_line) -> bool: + def contains_line(self, other_line: str) -> bool: if other_line == "GlobalVar" or other_line == "LineNotFound": return False if not ":" in other_line: @@ -380,7 +381,7 @@ def get_exit_cu_ids(self, pet: PEGraphX) -> Set[NodeID]: exit_cu_ids.add(child_cu_id) return exit_cu_ids - def calculate_reachability_pairs(self, pet: PEGraphX): + def calculate_reachability_pairs(self, pet: PEGraphX) -> Dict[NodeID, Set[NodeID]]: reachability_pairs: Dict[NodeID, Set[NodeID]] = dict() # create graph copy and remove all but successor edges copied_graph = pet.g.copy() @@ -614,7 +615,7 @@ class PEGraphX(object): main: Node pos: Dict[Any, Any] - def __init__(self, g: nx.MultiDiGraph, reduction_vars: List[Dict[str, str]], pos): + def __init__(self, g: nx.MultiDiGraph, reduction_vars: List[Dict[str, str]], pos: Dict[Any, Any]): self.g = g self.reduction_vars = reduction_vars for _, node in g.nodes(data="data"): @@ -629,7 +630,7 @@ def from_parsed_input( dependencies_list: List[DependenceItem], loop_data: Dict[str, LoopData], reduction_vars: List[Dict[str, str]], - ): + ) -> PEGraphX: """Constructor for making a PETGraphX from the output of parser.parse_inputs()""" g = nx.MultiDiGraph() print("\tCreating graph...") @@ -766,7 +767,11 @@ def map_static_and_dynamic_dependencies(self): print("Done.") - def calculateFunctionMetadata(self, hotspot_information=None, func_nodes=None) -> None: + def calculateFunctionMetadata( + self, + hotspot_information: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] = None, + func_nodes: Optional[List[FunctionNode]] = None, + ) -> None: # store id of parent function in each node # and store in each function node a list of all children ids if func_nodes is None: @@ -1088,7 +1093,7 @@ def subtree_of_type_rec(self, root, visited, type=Node): return res - def __cu_equal__(self, cu_1: Node, cu_2: Node): + def __cu_equal__(self, cu_1: Node, cu_2: Node) -> bool: """Alternative to CUNode.__eq__, bypasses the isinstance-check and relies on MyPy for type safety. :param cu_1: CUNode 1 :param cu_2: CUNode 2 @@ -1358,7 +1363,7 @@ def get_undefined_variables_inside_loop( return vars - def unused_is_first_written_in_loop(self, dep: Dependency, root_loop: Node): + def unused_is_first_written_in_loop(self, dep: Dependency, root_loop: Node) -> bool: """Checks whether a variable is first written inside the current node :param var: diff --git a/discopop_explorer/discopop_explorer.py b/discopop_explorer/discopop_explorer.py index bf62c48f0..69c4c390b 100644 --- a/discopop_explorer/discopop_explorer.py +++ b/discopop_explorer/discopop_explorer.py @@ -171,7 +171,7 @@ def __run( return res -def run(arguments: ExplorerArguments): +def run(arguments: ExplorerArguments) -> None: """Run the discopop_explorer with the given arguments""" logger = logging.getLogger("Explorer") diff --git a/discopop_explorer/generate_Data_CUInst.py b/discopop_explorer/generate_Data_CUInst.py index 96910cc1c..402138250 100644 --- a/discopop_explorer/generate_Data_CUInst.py +++ b/discopop_explorer/generate_Data_CUInst.py @@ -6,6 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from io import TextIOWrapper from typing import List, cast, TextIO from .PEGraphX import ( @@ -22,7 +23,7 @@ from .parser import parse_inputs -def __collect_children_ids(pet: PEGraphX, parent_id: NodeID, children_ids: List[NodeID]): +def __collect_children_ids(pet: PEGraphX, parent_id: NodeID, children_ids: List[NodeID]) -> List[NodeID]: if parent_id in children_ids: # this id has already been processed. No need to go through it again return children_ids @@ -104,7 +105,7 @@ def __output_dependencies_of_type( output_file: TextIO, dep_type: DepType, dep_identifier: str, -): +) -> None: """check for and output dependencies of the given type :param pet: PET Graph :param child_id: specific node id, taken from children_ids @@ -131,7 +132,7 @@ def __output_dependencies_of_type( ) -def __search_recursive_calls(pet: PEGraphX, output_file, node: Node): +def __search_recursive_calls(pet: PEGraphX, output_file: TextIOWrapper, node: Node) -> None: if not isinstance(node, CUNode): return for recursive_function_call in node.recursive_function_calls: @@ -165,7 +166,7 @@ def __search_recursive_calls(pet: PEGraphX, output_file, node: Node): output_file.write("\n") -def cu_instantiation_input_cpp(pet: PEGraphX, output_file: str): +def cu_instantiation_input_cpp(pet: PEGraphX, output_file: str) -> None: """translation of CUInstantiationInput.cpp, previously contained in discopop-analyzer/analyzer/src. Wrapper to gather information on recursive function calls for CU Instantiation. :param pet: PET Graph @@ -175,7 +176,7 @@ def cu_instantiation_input_cpp(pet: PEGraphX, output_file: str): __search_recursive_calls(pet, data_cu_inst_file, node) -def wrapper(cu_xml, dep_file, loop_counter_file, reduction_file, output_file): +def wrapper(cu_xml: str, dep_file: str, loop_counter_file: str, reduction_file: str, output_file: str) -> None: """Wrapper to generate the Data_CUInst.txt file, required for the generation of CUInstResult.txt""" # 1. generate PET Graph pet = PEGraphX.from_parsed_input(*parse_inputs(cu_xml, dep_file, loop_counter_file, reduction_file)) diff --git a/discopop_explorer/parser.py b/discopop_explorer/parser.py index 9bbcd9984..3ab39fcb6 100644 --- a/discopop_explorer/parser.py +++ b/discopop_explorer/parser.py @@ -6,6 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from io import TextIOWrapper import os import re import warnings @@ -110,7 +111,7 @@ def __map_dummy_nodes(cu_dict): return cu_dict -def __parse_dep_file(dep_fd, output_path: str) -> Tuple[List[DependenceItem], List[LoopData]]: +def __parse_dep_file(dep_fd: TextIOWrapper, output_path: str) -> Tuple[List[DependenceItem], List[LoopData]]: dependencies_list: List[DependenceItem] = [] loop_data_list: List[LoopData] = [] diff --git a/discopop_explorer/pattern_detection.py b/discopop_explorer/pattern_detection.py index a4a78e741..e2767d2de 100644 --- a/discopop_explorer/pattern_detection.py +++ b/discopop_explorer/pattern_detection.py @@ -8,7 +8,7 @@ import json import os import sys -from typing import cast +from typing import Dict, List, Optional, Tuple, cast from alive_progress import alive_bar # type: ignore @@ -16,6 +16,8 @@ build_preprocessed_graph_and_run_detection as detect_tp, ) from discopop_explorer.variable import Variable +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType from discopop_library.JSONHandler.JSONHandler import read_patterns_from_json_to_json from discopop_library.discopop_optimizer.OptimizationGraph import OptimizationGraph from discopop_library.discopop_optimizer.Variables.Experiment import Experiment @@ -43,7 +45,7 @@ def __init__(self, pet_graph: PEGraphX) -> None: """ self.pet = pet_graph - def __merge(self, loop_type: bool, remove_dummies: bool): + def __merge(self, loop_type: bool, remove_dummies: bool) -> None: """Removes dummy nodes :param loop_type: loops only @@ -63,20 +65,20 @@ def __merge(self, loop_type: bool, remove_dummies: bool): def detect_patterns( self, - project_path, - cu_dict, - dependencies, - loop_data, - reduction_vars, - file_mapping, - cu_inst_result_file, - llvm_cxxfilt_path, - discopop_build_path, - enable_patterns, - enable_task_pattern, - enable_detection_of_scheduling_clauses, - hotspots, - ): + project_path: str, + cu_dict: str, + dependencies: str, + loop_data: str, + reduction_vars: str, + file_mapping: Optional[str], + cu_inst_result_file: Optional[str], + llvm_cxxfilt_path: Optional[str], + discopop_build_path: Optional[str], + enable_patterns: str, + enable_task_pattern: bool, + enable_detection_of_scheduling_clauses: bool, + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + ) -> DetectionResult: """Runs pattern discovery on the CU graph""" self.__merge(False, True) self.pet.map_static_and_dynamic_dependencies() @@ -105,6 +107,10 @@ def detect_patterns( # check if task pattern should be enabled if enable_task_pattern: + if cu_inst_result_file is None: + raise ValueError("cu_inst_result_file not specified.") + if file_mapping is None: + raise ValueError("file_mapping not specified.") res.patterns.task = detect_tp( cu_dict, dependencies, diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py index 8d97fdd6b..b49df0244 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/CombinedGPURegions.py @@ -6,7 +6,7 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. import sys -from typing import List, Tuple, Dict, Set +from typing import List, Tuple, Dict, Set, cast from discopop_explorer.PEGraphX import EdgeType, CUNode, PEGraphX, NodeID, MemoryRegion from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo @@ -14,6 +14,7 @@ VarName, ) from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Dependency import Dependency +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.EntryPoint import EntryPoint from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Enums import ( ExitPointPositioning, EntryPointPositioning, @@ -21,6 +22,8 @@ EntryPointType, UpdateType, ) +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.ExitPoint import ExitPoint +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Update import Update from discopop_explorer.pattern_detectors.combined_gpu_patterns.prepare_metadata import ( get_dependencies_as_metadata, ) @@ -68,10 +71,10 @@ class CombinedGPURegion(PatternInfo): target_data_regions: Dict[str, List[Tuple[List[NodeID], NodeID, NodeID, str, str]]] # {var: ([contained cu_s], entry_cu, exit_after_cu, meta_entry_line_num, meta_exit_line_num) data_region_entry_points: List[ - Tuple[VarName, NodeID, EntryPointType, str, EntryPointPositioning] + Tuple[str, NodeID, NodeID, EntryPointType, str, EntryPointPositioning] ] # [(var, cu_id, entry_point_type, meta_line_num, positioning)] data_region_exit_points: List[ - Tuple[VarName, NodeID, ExitPointType, str, ExitPointPositioning] + Tuple[str, NodeID, NodeID, ExitPointType, str, ExitPointPositioning] ] # [(var, cu_id, exit_point_type, meta_line_num, positioning)] data_region_depend_in: List[Tuple[VarName, NodeID, str]] # [(var, cu_id, meta_line_num)] data_region_depend_out: List[Tuple[VarName, NodeID, str]] # [(var, cu_id, meta_line_num)] @@ -302,9 +305,9 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec ) # remove duplicates - updates = remove_duplicates(updates) - entry_points = remove_duplicates(entry_points) - exit_points = remove_duplicates(exit_points) + updates = cast(Set[Update], remove_duplicates(updates)) + entry_points = cast(Set[EntryPoint], remove_duplicates(entry_points)) + exit_points = cast(Set[ExitPoint], remove_duplicates(exit_points)) # join entries updates = join_elements(updates) @@ -354,7 +357,7 @@ def __init__(self, pet: PEGraphX, contained_regions: List[GPURegionInfo], projec def __str__(self): raise NotImplementedError() # used to identify necessity to call to_string() instead - def to_string(self, pet: PEGraphX): + def to_string(self, pet: PEGraphX) -> str: contained_regions_str = "\n" if len(self.contained_regions) > 0 else "" for region in self.contained_regions: region_str = region.to_string(pet) @@ -453,7 +456,7 @@ def find_combinations_within_function_body( def find_true_successor_combinations( - pet, intra_function_combinations: List[Tuple[CombinedGPURegion, CombinedGPURegion]] + pet: PEGraphX, intra_function_combinations: List[Tuple[CombinedGPURegion, CombinedGPURegion]] ) -> List[Tuple[CombinedGPURegion, CombinedGPURegion]]: """Check for combinations options without branching inbetween. As a result, both regions will always be executed in succession.""" @@ -462,7 +465,9 @@ def find_true_successor_combinations( # a true successor relation exists, if every successor path outgoing from any child of region_1 arrives at region_2 for region_1, region_2 in intra_function_combinations: true_successors = True - queue: List[CUNode] = pet.direct_children(pet.node_at(region_1.contained_regions[0].node_id)) + queue: List[CUNode] = cast( + List[CUNode], pet.direct_children(pet.node_at(region_1.contained_regions[0].node_id)) + ) visited: List[CUNode] = [] while queue: current_node: CUNode = queue.pop() @@ -479,7 +484,7 @@ def find_true_successor_combinations( else: # end of the function's body not yet reached, continue searching # add successors to queue - queue += [succ for succ in successors if succ not in visited] + queue += [cast(CUNode, succ) for succ in successors if succ not in visited] if true_successors: result.append((region_1, region_2)) return result diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py index 083f266f0..7ad1ed032 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/EntryPoint.py @@ -118,7 +118,9 @@ def join(self, other): self.memory_regions.update(other.memory_regions) self.dependencies.update(other.dependencies) - def get_as_metadata(self, pet: PEGraphX, project_folder_path: str): + def get_as_metadata( + self, pet: PEGraphX, project_folder_path: str + ) -> Tuple[str, NodeID, NodeID, EntryPointType, str, EntryPointPositioning]: # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.var_names: @@ -148,11 +150,11 @@ def get_as_metadata(self, pet: PEGraphX, project_folder_path: str): else: modified_var_names = [(vn + "[:]" if "**" in t else vn) for vn, t, s in var_names_types_and_sizes] - return [ + return ( ",".join(modified_var_names), self.source_cu_id, self.sink_cu_id, self.entry_point_type, self.pragma_line, self.entry_point_positioning, - ] + ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py index c2729672a..ed8388e9a 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/ExitPoint.py @@ -116,7 +116,9 @@ def join(self, other): self.memory_regions.update(other.memory_regions) self.dependencies.update(other.dependencies) - def get_as_metadata(self, pet: PEGraphX, project_folder_path: str): + def get_as_metadata( + self, pet: PEGraphX, project_folder_path: str + ) -> Tuple[str, NodeID, NodeID, ExitPointType, str, ExitPointPositioning]: # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.var_names: @@ -146,11 +148,11 @@ def get_as_metadata(self, pet: PEGraphX, project_folder_path: str): else: modified_var_names = [(vn + "[:]" if "**" in t else vn) for vn, t, s in var_names_types_and_sizes] - return [ + return ( ",".join(modified_var_names), self.source_cu_id, self.sink_cu_id, self.exit_point_type, self.pragma_line, self.exit_point_positioning, - ] + ) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py index 98bc650f9..d68561e59 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/classes/Update.py @@ -8,7 +8,7 @@ import os from typing import Set, Dict, cast, Optional, List, Tuple -from discopop_explorer.PEGraphX import PEGraphX, NodeID, MemoryRegion +from discopop_explorer.PEGraphX import LineID, PEGraphX, NodeID, MemoryRegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -141,28 +141,32 @@ def __hash__(self): ) ) - def get_position_identifier(self): + def get_position_identifier(self) -> Tuple[NodeID, NodeID, UpdateType]: # used to join multiple elements if self.asynchronous_possible: + if self.asynchronous_source_cu_id is None: + raise ValueError("Asynchronous_source_cu_id is None") return (self.sink_cu_id, self.asynchronous_source_cu_id, self.update_type) else: return (self.sink_cu_id, self.synchronous_source_cu_id, self.update_type) - def join(self, other): + def join(self, other: Update) -> None: self.variable_names.update(other.variable_names) self.memory_regions.update(other.memory_regions) self.dependencies.update(other.dependencies) - def get_as_metadata_using_memory_regions(self, pet: PEGraphX): - return [ + def get_as_metadata_using_memory_regions(self, pet: PEGraphX) -> Tuple[NodeID, NodeID, UpdateType, str, LineID]: + return ( self.synchronous_source_cu_id, self.sink_cu_id, self.update_type, str(self.memory_regions), pet.node_at(self.synchronous_source_cu_id).end_position(), - ] + ) - def get_as_metadata_using_variable_names(self, pet: PEGraphX, project_folder_path: str): + def get_as_metadata_using_variable_names( + self, pet: PEGraphX, project_folder_path: str + ) -> Tuple[NodeID, NodeID, UpdateType, str, LineID]: # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.variable_names: @@ -212,15 +216,17 @@ def get_as_metadata_using_variable_names(self, pet: PEGraphX, project_folder_pat # updating inbetween both CUs should be a safe fallback update_position = pet.node_at(self.sink_cu_id).start_position() - return [ + return ( self.synchronous_source_cu_id, self.sink_cu_id, self.update_type, ",".join(modified_var_names), update_position, - ] + ) - def get_as_metadata_using_variable_names_and_memory_regions(self, pet: PEGraphX, project_folder_path: str): + def get_as_metadata_using_variable_names_and_memory_regions( + self, pet: PEGraphX, project_folder_path: str + ) -> Tuple[NodeID, NodeID, UpdateType, str, LineID]: # get type of mapped variables var_names_types_and_sizes: List[Tuple[VarName, str, int]] = [] for var_name in self.variable_names: @@ -253,19 +259,19 @@ def get_as_metadata_using_variable_names_and_memory_regions(self, pet: PEGraphX, else: modified_var_names = [(vn + "[:]" if "**" in t else vn) for vn, t, s in var_names_types_and_sizes] - return [ + return ( self.synchronous_source_cu_id, self.sink_cu_id, self.update_type, str(modified_var_names) + "/" + str(self.memory_regions), pet.node_at(self.synchronous_source_cu_id).end_position(), - ] + ) def convert_memory_regions_to_variable_names( self, pet: PEGraphX, memory_regions_to_functions_and_variables: Dict[MemoryRegion, Dict[NodeID, Set[VarName]]], - ): + ) -> None: self.variable_names = set() parent_function_id = pet.get_parent_function(pet.node_at(self.synchronous_source_cu_id)).id diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py index 2bac17340..0137c5140 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/combined_gpu_pattern_detector.py @@ -13,9 +13,11 @@ from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import ( find_combined_gpu_regions, ) +from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import GPURegionInfo +from discopop_library.result_classes.DetectionResult import DetectionResult -def run_detection(pet: PEGraphX, res, project_folder_path: str) -> List[PatternInfo]: +def run_detection(pet: PEGraphX, res: DetectionResult, project_folder_path: str) -> List[PatternInfo]: """Search for combined gpu patterns :param pet: PET graph @@ -24,6 +26,8 @@ def run_detection(pet: PEGraphX, res, project_folder_path: str) -> List[PatternI """ # construct Combined GPU Regions - combined_gpu_regions = find_combined_gpu_regions(pet, res.simple_gpu, project_folder_path) + combined_gpu_regions = find_combined_gpu_regions( + pet, cast(List[GPURegionInfo], res.patterns.simple_gpu), project_folder_path + ) return cast(List[PatternInfo], combined_gpu_regions) diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py index 3d1a90132..8de5648e5 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_1.py @@ -6,16 +6,17 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from typing import Tuple, Dict, Set, cast +from typing import List, Tuple, Dict, Set, cast from discopop_explorer.PEGraphX import EdgeType, DepType, PEGraphX, NodeID, CUNode, MemoryRegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) +from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import GPURegionInfo def get_written_and_read_memory_regions_by_cu( - contained_regions, pet: PEGraphX + contained_regions: List[GPURegionInfo], pet: PEGraphX ) -> Tuple[Dict[NodeID, Set[MemoryRegion]], Dict[NodeID, Set[MemoryRegion]]]: all_function_cu_ids: Set[NodeID] = set() for region in contained_regions: @@ -67,7 +68,7 @@ def get_written_and_read_memory_regions_by_cu( def get_cu_and_varname_to_memory_regions( - contained_regions, pet: PEGraphX, written_memory_regions_by_cu: Dict[NodeID, Set[MemoryRegion]] + contained_regions: List[GPURegionInfo], pet: PEGraphX, written_memory_regions_by_cu: Dict[NodeID, Set[MemoryRegion]] ) -> Dict[NodeID, Dict[VarName, Set[MemoryRegion]]]: # dict -> {Cu_ID: {var_name: [memory regions]}} result_dict: Dict[NodeID, Dict[VarName, Set[MemoryRegion]]] = dict() diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py index b0e6d4dc5..0fd71f1b0 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_2.py @@ -21,6 +21,7 @@ Dependency, FunctionNode, ) +from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import ( VarName, ) @@ -30,7 +31,9 @@ ) -def populate_live_data(comb_gpu_reg, pet: PEGraphX, ignore_update_instructions=False) -> Dict[VarName, List[NodeID]]: +def populate_live_data( + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, ignore_update_instructions: bool = False +) -> Dict[VarName, List[NodeID]]: """calculate List of cu-id's in the combined region for each variable in which the respective data is live. The gathered information is used for the optimization / creation of data mapping instructions afterwards. """ @@ -56,13 +59,14 @@ def populate_live_data(comb_gpu_reg, pet: PEGraphX, ignore_update_instructions=F if not ignore_update_instructions: # populate liveness sets based on update instructions - for source_id, sink_id, update_type, var, meta_line_num in comb_gpu_reg.update_instructions: - if var not in liveness: - liveness[var] = [] + for source_id, sink_id, update_type, varname_str, meta_line_num in comb_gpu_reg.update_instructions: + varname: VarName = VarName(varname_str) + if varname not in liveness: + liveness[varname] = [] if update_type == UpdateType.TO_DEVICE: - liveness[var].append(sink_id) + liveness[varname].append(sink_id) elif update_type == UpdateType.FROM_DEVICE: - liveness[var].append(source_id) + liveness[varname].append(source_id) else: raise ValueError("Unsupported Update type: ", update_type) @@ -266,7 +270,7 @@ def extend_data_lifespan( def calculate_host_liveness( - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, ) -> Dict[VarName, List[Tuple[NodeID, Set[MemoryRegion]]]]: """ diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py index c99721207..8d29abef6 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_3.py @@ -9,6 +9,7 @@ from typing import Dict, List, Tuple, Set, Optional from discopop_explorer.PEGraphX import PEGraphX, EdgeType, NodeID, CUNode, MemoryRegion +from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion global_write_unique_id = 0 @@ -39,7 +40,7 @@ def initialize_writes( def propagate_writes( - comb_gpu_reg, pet: PEGraphX, writes: Dict[MemoryRegion, Set[Tuple[NodeID, Optional[int]]]] + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, writes: Dict[MemoryRegion, Set[Tuple[NodeID, Optional[int]]]] ) -> Dict[MemoryRegion, Set[Tuple[NodeID, Optional[int]]]]: """propagate writes to parents. propagate writes to successors and their children. diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py index 4ee2fc68a..22d646871 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_4.py @@ -23,6 +23,7 @@ Dependency, FunctionNode, ) +from discopop_explorer.pattern_detectors.combined_gpu_patterns.CombinedGPURegions import CombinedGPURegion from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Enums import UpdateType from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Update import Update @@ -131,7 +132,7 @@ def find_required_updates(self, pet: PEGraphX, new_device_id: int) -> Set[Tuple[ return required_updates - def synchronize_states(self, new_device_id: int): + def synchronize_states(self, new_device_id: int) -> None: overlapping_mem_reg = [ mem_reg for mem_reg in self.seen_writes_by_device[self.device_id] @@ -145,7 +146,9 @@ def synchronize_states(self, new_device_id: int): print("SYNCHRONIZED: ", mem_reg, (ident, origin), file=sys.stderr) self.seen_writes_by_device[new_device_id][mem_reg].add((ident, origin)) - def request_updates_from_other_devices(self, pet, new_device_id: int) -> Set[Tuple[MemoryRegion, int, int, NodeID]]: + def request_updates_from_other_devices( + self, pet: PEGraphX, new_device_id: int + ) -> Set[Tuple[MemoryRegion, int, int, NodeID]]: required_updates: Set[Tuple[MemoryRegion, int, int, NodeID]] = set() to_be_removed = set() for mem_reg in self.seen_writes_by_device[new_device_id]: @@ -198,7 +201,7 @@ def update_to( self, pet: PEGraphX, next_cu_id: NodeID, - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]], ) -> Set[Update]: print("UPDATE TO: ", next_cu_id, file=sys.stderr) @@ -287,14 +290,14 @@ def update_to( return required_updates -def get_device_id(comb_gpu_reg, cu_id: NodeID) -> int: +def get_device_id(comb_gpu_reg: CombinedGPURegion, cu_id: NodeID) -> int: if cu_id in comb_gpu_reg.device_cu_ids: return 1 return 0 -def __identify_merge_node(pet, successors: List[NodeID]) -> Optional[NodeID]: - def check_validity_of_potential_merge_node(node_id: NodeID): +def __identify_merge_node(pet: PEGraphX, successors: List[NodeID]) -> Optional[NodeID]: + def check_validity_of_potential_merge_node(node_id: NodeID) -> bool: # return True if the given node is a valid merge node. # return False otherwise. # do not allow return BB's as merge nodes, since this would be trivially true for every path split @@ -366,7 +369,7 @@ def check_validity_of_potential_merge_node(node_id: NodeID): def identify_updates( - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]], unrolled_function_graph: MultiDiGraph, @@ -435,7 +438,7 @@ def get_update_type(from_device_id: int, to_device_id: int) -> UpdateType: def __calculate_updates( pet: PEGraphX, - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, context: Context, cur_node_id: NodeID, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]], @@ -518,7 +521,7 @@ def __calculate_updates( return identified_updates -def create_circle_free_function_graphs(pet: PEGraphX, add_dummy_node=True): +def create_circle_free_function_graphs(pet: PEGraphX, add_dummy_node: bool = True) -> Dict[FunctionNode, MultiDiGraph]: """Remove loops from the CUGraph by unrolling loops in the successor graphs of each function.""" import networkx as nx @@ -728,7 +731,7 @@ def add_accesses_from_called_functions( def identify_updates_in_unrolled_function_graphs( - comb_gpu_reg, + comb_gpu_reg: CombinedGPURegion, pet: PEGraphX, writes_by_device: Dict[int, Dict[NodeID, Dict[MemoryRegion, Set[Optional[int]]]]], unrolled_function_graphs: Dict[FunctionNode, MultiDiGraph], diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py index 35d4b19b7..944b1b97d 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/step_6.py @@ -337,7 +337,9 @@ def extend_region_liveness_using_unrolled_functions( return liveness -def remove_duplicates(target_set: Union[Set[Update], Set[EntryPoint], Set[ExitPoint]]): +def remove_duplicates( + target_set: Union[Set[Update], Set[EntryPoint], Set[ExitPoint]] +) -> Union[Set[Update], Set[EntryPoint], Set[ExitPoint]]: to_be_removed = [] for element_1 in target_set: for element_2 in target_set: diff --git a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py index f1717b109..eac85d82d 100644 --- a/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py +++ b/discopop_explorer/pattern_detectors/combined_gpu_patterns/utilities.py @@ -47,7 +47,7 @@ def prepare_liveness_metadata( liveness: Dict[MemoryRegion, List[NodeID]], writes: Dict[MemoryRegion, Set[Tuple[NodeID, Optional[int]]]], meta_liveness: Dict[MemoryRegion, List[str]], -): +) -> Dict[MemoryRegion, List[str]]: for mem_reg in liveness: for cu_id in liveness[mem_reg]: if mem_reg not in meta_liveness: diff --git a/discopop_explorer/pattern_detectors/do_all_detector.py b/discopop_explorer/pattern_detectors/do_all_detector.py index 3e38fa573..2cf46a9c2 100644 --- a/discopop_explorer/pattern_detectors/do_all_detector.py +++ b/discopop_explorer/pattern_detectors/do_all_detector.py @@ -7,10 +7,11 @@ # directory for details. import sys from multiprocessing import Pool -from typing import List, Dict, Set, Tuple, cast +from typing import List, Dict, Optional, Set, Tuple, cast import warnings -from alive_progress import alive_bar # type: ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo from .reduction_detector import ReductionInfo @@ -71,7 +72,11 @@ def __str__(self): global_pet = None -def run_detection(pet: PEGraphX, hotspots, reduction_info: List[ReductionInfo]) -> List[DoAllInfo]: +def run_detection( + pet: PEGraphX, + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], + reduction_info: List[ReductionInfo], +) -> List[DoAllInfo]: """Search for do-all loop pattern :param pet: PET graph @@ -376,7 +381,7 @@ def __old_detect_do_all(pet: PEGraphX, root_loop: CUNode) -> bool: return True -def __calculate_nesting_level(pet: PEGraphX, root_loop: LoopNode, cu_node_id: str): +def __calculate_nesting_level(pet: PEGraphX, root_loop: LoopNode, cu_node_id: str) -> int: potential_parents = [(cu_node_id, -1)] # -1 to offset the initialization with cu_node_id while True: if len(potential_parents) == 0: @@ -391,7 +396,7 @@ def __calculate_nesting_level(pet: PEGraphX, root_loop: LoopNode, cu_node_id: st potential_parents.append((in_child_edge[0], nesting_level + 1)) -def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode): +def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: """duplicates exists: do_all_detector <-> reduction_detector !""" parents: List[NodeID] = [] queue = [root_loop.id] diff --git a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py index d02ab86f6..929d0b4b5 100644 --- a/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py +++ b/discopop_explorer/pattern_detectors/geometric_decomposition_detector.py @@ -10,7 +10,8 @@ import math from typing import Dict, List, Tuple, Optional, cast -from alive_progress import alive_bar # type: ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo from ..PEGraphX import FunctionNode, LoopNode, NodeID, PEGraphX, Node, EdgeType @@ -78,7 +79,9 @@ def __str__(self): global_pet = None -def run_detection(pet: PEGraphX, hotspots) -> List[GDInfo]: +def run_detection( + pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] +) -> List[GDInfo]: """Detects geometric decomposition :param pet: PET graph diff --git a/discopop_explorer/pattern_detectors/pipeline_detector.py b/discopop_explorer/pattern_detectors/pipeline_detector.py index de70de80f..e34ed388a 100644 --- a/discopop_explorer/pattern_detectors/pipeline_detector.py +++ b/discopop_explorer/pattern_detectors/pipeline_detector.py @@ -7,9 +7,10 @@ # directory for details. -from typing import List, Tuple, Dict, Set, cast +from typing import List, Optional, Tuple, Dict, Set, cast -from alive_progress import alive_bar # type: ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo from ..PEGraphX import ( @@ -29,7 +30,13 @@ class PipelineStage(object): - def __init__(self, pet: PEGraphX, node: Node, in_dep, out_dep): + def __init__( + self, + pet: PEGraphX, + node: Node, + in_dep: List[Tuple[NodeID, NodeID, Dependency]], + out_dep: List[Tuple[NodeID, NodeID, Dependency]], + ): self.node = node.id self.startsAtLine = node.start_position() self.endsAtLine = node.end_position() @@ -84,7 +91,7 @@ def __init__(self, pet: PEGraphX, node: Node): self.stages = [self.__output_stage(s) for s in self._stages] - def __in_dep(self, node: Node): + def __in_dep(self, node: Node) -> List[Tuple[NodeID, NodeID, Dependency]]: raw: List[Tuple[NodeID, NodeID, Dependency]] = [] for n in self._pet.subtree_of_type(node, CUNode): raw.extend((s, t, d) for s, t, d in self._pet.out_edges(n.id, EdgeType.DATA) if d.dtype == DepType.RAW) @@ -95,7 +102,7 @@ def __in_dep(self, node: Node): return [dep for dep in raw if dep[1] in [n.id for n in nodes_before]] - def __out_dep(self, node: Node): + def __out_dep(self, node: Node) -> List[Tuple[NodeID, NodeID, Dependency]]: raw: List[Tuple[NodeID, NodeID, Dependency]] = [] for n in self._pet.subtree_of_type(node, CUNode): raw.extend((s, t, d) for s, t, d in self._pet.in_edges(n.id, EdgeType.DATA) if d.dtype == DepType.RAW) @@ -148,7 +155,9 @@ def is_pipeline_subnode(root: Node, current: Node, children_start_lines: List[Li global_pet = None -def run_detection(pet: PEGraphX, hotspots) -> List[PipelineInfo]: +def run_detection( + pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] +) -> List[PipelineInfo]: """Search for pipeline pattern on all the loops in the graph except for doall loops @@ -162,8 +171,6 @@ def run_detection(pet: PEGraphX, hotspots) -> List[PipelineInfo]: global_pet = pet result: List[PipelineInfo] = [] - children_cache: Dict[Node, List[Node]] = dict() - dependency_cache: Dict[Tuple[Node, Node], Set[Node]] = dict() nodes = pet.all_nodes(LoopNode) nodes = cast(List[LoopNode], filter_for_hotspots(pet, cast(List[Node], nodes), hotspots)) @@ -202,13 +209,11 @@ def __check_node(param_tuple): return local_result -def __detect_pipeline(pet: PEGraphX, root: Node, children_cache=None, dep_cache=None) -> float: +def __detect_pipeline(pet: PEGraphX, root: Node) -> float: """Calculate pipeline value for node :param pet: PET graph :param root: current node - :param children_cache: used to cache intermediate children - :param dep_cache: used to cache intermediate dependencies :return: Pipeline scalar value """ diff --git a/discopop_explorer/pattern_detectors/reduction_detector.py b/discopop_explorer/pattern_detectors/reduction_detector.py index 3afc2494d..24535f357 100644 --- a/discopop_explorer/pattern_detectors/reduction_detector.py +++ b/discopop_explorer/pattern_detectors/reduction_detector.py @@ -8,10 +8,11 @@ from multiprocessing import Pool -from typing import List, cast, Set, Tuple +from typing import Dict, List, Optional, cast, Set, Tuple import warnings -from alive_progress import alive_bar # type: ignore +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType # type: ignore from .PatternInfo import PatternInfo from ..PEGraphX import ( @@ -66,7 +67,9 @@ def __str__(self): global_pet = None -def run_detection(pet: PEGraphX, hotspots) -> List[ReductionInfo]: +def run_detection( + pet: PEGraphX, hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]] +) -> List[ReductionInfo]: """Search for reduction pattern :param pet: PET graph @@ -141,7 +144,7 @@ def __detect_reduction(pet: PEGraphX, root: LoopNode) -> bool: if is_reduction_var(root.start_position(), v.name, pet.reduction_vars) # and "**" not in v.type --> replaced by check for array reduction ] - reduction_var_names = [v.name for v in reduction_vars] + reduction_var_names = cast(List[str], [v.name for v in reduction_vars]) fp, p, lp, s, r = classify_loop_variables(pet, root) # get parents of loop @@ -315,7 +318,7 @@ def __check_loop_dependencies( return False -def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode): +def __get_parent_loops(pet: PEGraphX, root_loop: LoopNode) -> List[LineID]: """duplicates exists: do_all_detector <-> reduction_detector !""" parents: List[NodeID] = [] queue = [root_loop.id] diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py index 900e38e44..0276e4d9b 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPULoop.py @@ -42,6 +42,7 @@ ) from discopop_explorer.variable import Variable from discopop_library.MemoryRegions.utils import get_sizes_of_memory_regions +from discopop_library.result_classes.DetectionResult import DetectionResult from .GPUMemory import getCalledFunctions, map_node """ @@ -180,8 +181,8 @@ def __init__( self, pet: PEGraphX, nodeID: NodeID, - startLine, - endLine, + startLine: LineID, + endLine: LineID, iterationCount: int, project_folder_path: str, reduction_vars: Optional[List[Variable]] = None, @@ -240,7 +241,7 @@ def to_string(self, pet: PEGraphX) -> str: f"OpenMP constructs: {construct_str}\n" ) - def save_omp_constructs(self, pet: PEGraphX, project_folder_path: str): + def save_omp_constructs(self, pet: PEGraphX, project_folder_path: str) -> None: """Save OpenMP constructs such that they are included in the exported JSON file.""" constructs = self.__get_constructs(pet, project_folder_path) self.constructs = constructs @@ -633,7 +634,7 @@ def getNextLoop(self, pet: PEGraphX, node_id: NodeID) -> None: if children.end_line > endLine: endLine = children.end_line - def setCollapseClause(self, pet: PEGraphX, node_id: NodeID, res): + def setCollapseClause(self, pet: PEGraphX, node_id: NodeID, res: DetectionResult) -> None: """ :param node_id: diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py index c6ca69482..077ceaf4d 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/GPURegions.py @@ -72,7 +72,7 @@ def __init__( def __str__(self): raise NotImplementedError() # used to identify necessity to call to_string() instead - def to_string(self, pet: PEGraphX): + def to_string(self, pet: PEGraphX) -> str: contained_loops_str = "\n" if len(self.contained_loops) > 0 else "" for loop in self.contained_loops: loop_str = loop.to_string(pet) @@ -346,8 +346,8 @@ def old_mapData(self) -> None: lastNodeID = self.cascadingLoopsInRegions[i][t] fn = map_node(self.pet, firstNodeID) ln = map_node(self.pet, lastNodeID) - start = fn.start_line - end = ln.end_line + start = fn.start_position() + end = ln.end_position() gpuRegionLoop = GPULoopPattern(self.pet, firstNodeID, start, end, 1000, self.project_folder_path) visitedVars: Set[Variable] = set() while t >= 0: diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py index 9abd89020..28edc22ea 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/gpu_pattern_detector.py @@ -10,7 +10,7 @@ from alive_progress import alive_bar # type: ignore -from discopop_explorer.PEGraphX import PEGraphX, LoopNode +from discopop_explorer.PEGraphX import LineID, PEGraphX, LoopNode from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPURegions import ( @@ -18,9 +18,10 @@ GPURegionInfo, ) from discopop_explorer.variable import Variable +from discopop_library.result_classes.DetectionResult import DetectionResult -def run_detection(pet: PEGraphX, res, project_folder_path: str) -> List[PatternInfo]: +def run_detection(pet: PEGraphX, res: DetectionResult, project_folder_path: str) -> List[PatternInfo]: """Search for do-all loop pattern :param pet: PET graph @@ -46,8 +47,8 @@ def run_detection(pet: PEGraphX, res, project_folder_path: str) -> List[PatternI gpulp = GPULoopPattern( pet, node.id, - node.start_line, - node.end_line, + LineID(str(node.file_id) + ":" + str(node.start_line)), + LineID(str(node.file_id) + ":" + str(node.end_line)), node.loop_iterations, project_folder_path, reduction_vars, diff --git a/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py b/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py index c837adf32..168651770 100644 --- a/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py +++ b/discopop_explorer/pattern_detectors/simple_gpu_patterns/utils.py @@ -6,10 +6,11 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from discopop_explorer.PEGraphX import NodeID from discopop_explorer.pattern_detectors.simple_gpu_patterns.GPULoop import GPULoopPattern -def sort_by_nodeID(e: GPULoopPattern): +def sort_by_nodeID(e: GPULoopPattern) -> NodeID: """used to sort a list of gpu patterns by their node ids :return: diff --git a/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py b/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py index 203a8348f..736796c80 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/alias_detection.py @@ -274,7 +274,7 @@ def __get_function_information(cu_xml: str) -> List[Dict[str, Any]]: return function_information -def __create_statements_file(file_mapping: str, output_file: str, application_path: str): +def __create_statements_file(file_mapping: str, output_file: str, application_path: str) -> None: """Wrapper to start getStatements application for each source code file in file_mapping :param file_mapping: path to file_mapping file :param output_file: path to output file diff --git a/discopop_explorer/pattern_detectors/task_parallelism/classes.py b/discopop_explorer/pattern_detectors/task_parallelism/classes.py index b2ad620a9..c1246c828 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/classes.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/classes.py @@ -9,7 +9,7 @@ from enum import Enum from typing import List, Optional -from discopop_explorer.PEGraphX import Node, MWType, PEGraphX +from discopop_explorer.PEGraphX import LineID, Node, MWType, PEGraphX from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo @@ -22,8 +22,8 @@ class Task(object): nodes: List[Node] child_tasks: List["Task"] - start_line: str - end_line: str + start_line: LineID + end_line: LineID def __init__(self, pet: PEGraphX, node: Node): self.node_id = node.id @@ -47,7 +47,7 @@ def __init__(self, pet: PEGraphX, node: Node): self.workload = 0 self.child_tasks = [] - def aggregate(self, other: "Task"): + def aggregate(self, other: "Task") -> None: """Aggregates given task into current task :param other: task to aggregate @@ -70,7 +70,16 @@ class TPIType(Enum): class TaskParallelismInfo(PatternInfo): """Class, that contains task parallelism detection result""" - def __init__(self, node: Node, type: TPIType, pragma, pragma_line, first_private, private, shared): + def __init__( + self, + node: Node, + type: TPIType, + pragma: List[str], + pragma_line: str, + first_private: List[str], + private: List[str], + shared: List[str], + ): """ :param node: node, where task parallelism was detected :param type: type of the suggestion (task, taskwait, taskloop) @@ -123,7 +132,7 @@ def __str__(self): class ParallelRegionInfo(PatternInfo): """Class, that contains parallel region info.""" - def __init__(self, node: Node, type: TPIType, region_start_line, region_end_line): + def __init__(self, node: Node, type: TPIType, region_start_line: LineID, region_end_line: LineID): PatternInfo.__init__(self, node) self.region_start_line = region_start_line self.region_end_line = region_end_line diff --git a/discopop_explorer/pattern_detectors/task_parallelism/filter.py b/discopop_explorer/pattern_detectors/task_parallelism/filter.py index bfdfea80d..eb795c54e 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/filter.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/filter.py @@ -8,7 +8,7 @@ from typing import List, Dict, cast, Optional, Union -from discopop_explorer.PEGraphX import CUNode, NodeType, EdgeType, Node, PEGraphX +from discopop_explorer.PEGraphX import CUNode, LineID, NodeType, EdgeType, Node, PEGraphX from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_explorer.pattern_detectors.task_parallelism.classes import ( TaskParallelismInfo, @@ -22,6 +22,7 @@ check_reachability, ) from discopop_explorer.utils import is_loop_index2 +from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot def filter_data_sharing_clauses( @@ -38,7 +39,9 @@ def filter_data_sharing_clauses( return suggestions -def __filter_data_sharing_clauses_suppress_shared_loop_index(pet: PEGraphX, suggestions: List[PatternInfo]): +def __filter_data_sharing_clauses_suppress_shared_loop_index( + pet: PEGraphX, suggestions: List[PatternInfo] +) -> List[PatternInfo]: """Removes clauses for shared loop indices. :param pet: PET graph :param suggestions: List[PatternInfo] @@ -120,7 +123,9 @@ def __filter_data_sharing_clauses_by_function( return suggestions -def __filter_shared_clauses(suggestion: TaskParallelismInfo, parent_function, var_def_line_dict: Dict[str, List[str]]): +def __filter_shared_clauses( + suggestion: TaskParallelismInfo, parent_function: Node, var_def_line_dict: Dict[str, List[str]] +) -> None: """helper function for filter_data_sharing_clauses_by_function. Filters shared clauses. :param suggestion: Suggestion to be checked @@ -153,7 +158,9 @@ def __filter_shared_clauses(suggestion: TaskParallelismInfo, parent_function, va suggestion.shared = [v for v in suggestion.shared if not v.replace(".addr", "") in to_be_removed] -def __filter_private_clauses(suggestion: TaskParallelismInfo, parent_function, var_def_line_dict: Dict[str, List[str]]): +def __filter_private_clauses( + suggestion: TaskParallelismInfo, parent_function: Node, var_def_line_dict: Dict[str, List[str]] +) -> None: """helper function for filter_data_sharing_clauses_by_function. Filters private clauses. :param suggestion: Suggestion to be checked @@ -191,8 +198,8 @@ def __filter_private_clauses(suggestion: TaskParallelismInfo, parent_function, v def __filter_firstprivate_clauses( - suggestion: TaskParallelismInfo, parent_function, var_def_line_dict: Dict[str, List[str]] -): + suggestion: TaskParallelismInfo, parent_function: Node, var_def_line_dict: Dict[str, List[str]] +) -> None: """helper function for filter_data_sharing_clauses_by_function. Filters firstprivate clauses. :param suggestion: Suggestion to be checked @@ -221,7 +228,9 @@ def __filter_firstprivate_clauses( suggestion.first_private = [v for v in suggestion.first_private if not v.replace(".addr", "") in to_be_removed] -def __reverse_reachable_w_o_breaker(pet: PEGraphX, root: Node, target: Node, breaker_cu: Node, visited: List[Node]): +def __reverse_reachable_w_o_breaker( + pet: PEGraphX, root: Node, target: Node, breaker_cu: Node, visited: List[Node] +) -> bool: """Helper function for filter_data_sharing_clauses_by_scope. Checks if target is reachable by traversing the successor graph in reverse, starting from root, without visiting breaker_cu. @@ -289,9 +298,9 @@ def __filter_sharing_clause( pet: PEGraphX, suggestion: TaskParallelismInfo, var_def_line_dict: Dict[str, List[str]], - parent_function_cu, + parent_function_cu: Node, target_clause_list: str, -): +) -> None: """Helper function for filter_data_sharing_clauses_by_scope. Filters a given suggestions private, firstprivate or shared variables list, depending on the specific value of target_clause_list. @@ -377,8 +386,8 @@ def remove_useless_barrier_suggestions( # remove suggested barriers which are no descendants of relevant functions result_suggestions += task_suggestions for tws in taskwait_suggestions: - tws_line_number = tws.pragma_line - tws_line_number = tws_line_number[tws_line_number.index(":") + 1 :] + tws_line_id = tws.pragma_line + tws_line_number = tws_line_id[tws_line_id.index(":") + 1 :] for rel_func_body in relevant_function_bodies.keys(): if check_reachability(pet, tws._node, rel_func_body, [EdgeType.CHILD]): # remove suggested barriers where line number smaller than diff --git a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py index 190490e30..d041fb8a2 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/preprocessor.py @@ -8,7 +8,7 @@ import copy import os -from typing import List +from typing import Any, List from lxml import objectify, etree # type: ignore @@ -347,7 +347,7 @@ def __add_parent_id_to_children(parsed_cu, parent): parent_function.childrenNodes._setText(parent_function.childrenNodes.text[1:]) -def __preprocessor_cu_contains_at_least_two_recursive_calls(node) -> bool: +def __preprocessor_cu_contains_at_least_two_recursive_calls(node: Any) -> bool: """Check if >= 2 recursive function calls are contained in a cu's code region. Returns True, if so. Returns False, else. @@ -383,7 +383,7 @@ def __preprocessor_cu_contains_at_least_two_recursive_calls(node) -> bool: return False -def check_loop_scopes(pet: PEGraphX): +def check_loop_scopes(pet: PEGraphX) -> None: """Checks if the scope of loop CUs matches these of their children. Corrects the scope of the loop CU (expand only) if necessary :param pet: PET graph""" diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py index e6c42a9b0..f25ef84a9 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/barriers.py @@ -228,7 +228,7 @@ def __count_adjacent_nodes( def __check_dependences_and_predecessors( pet: PEGraphX, out_dep_edges: List[Tuple[Any, Any, Any]], parent_task: Node, cur_cu: Node -): +) -> bool: """Checks if only dependences to self, parent omittable node or path to target task exists. Checks if node is a direct successor of an omittable node or a task node. :param pet: PET Graph @@ -266,7 +266,7 @@ def __split_suggestions( taskwait_suggestions: List[TaskParallelismInfo], task_suggestions: List[TaskParallelismInfo], omittable_suggestions: List[PatternInfo], -): +) -> None: """Split suggestions into taskwait, task and omittable suggestions. :param suggestions: list of suggestions to be split :param taskwait_suggestions: list to store taskwait suggestions diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py index 844b9dfe7..d03d5065a 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/dependency_clauses.py @@ -19,6 +19,7 @@ LineID, ) from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName from discopop_explorer.pattern_detectors.task_parallelism.alias_detection import ( get_alias_information as get_alias_detection_result, ) @@ -162,7 +163,9 @@ def get_dict_from_cu_inst_result_file( return res_dict -def get_alias_information(pet: PEGraphX, suggestions: List[PatternInfo], source_code_files: Dict[str, str]): +def get_alias_information( + pet: PEGraphX, suggestions: List[PatternInfo], source_code_files: Dict[str, str] +) -> Dict[TaskParallelismInfo, List[List[Tuple[str, str, LineID, LineID]]]]: """Generate and return alias information dictionary. :param pet: PET Graph :param suggestions: List[PatternInfo] @@ -554,10 +557,10 @@ def identify_dependencies_for_same_functions( break # 3. get R/W information for cf's parameters based on CUInstResult.txt called_function_name_1, call_line_1 = recursive_function_call_entry_1.split(",")[0].split(" ") - lower_line_num_1 = ts_1.pragma_line - if ":" in lower_line_num_1: - lower_line_num_1 = lower_line_num_1.split(":")[1] - lower_line_num_1 = int(lower_line_num_1) + lower_line_id_1 = ts_1.pragma_line + if ":" in lower_line_id_1: + lower_line_num_str_1 = lower_line_id_1.split(":")[1] + lower_line_num_1 = int(lower_line_num_str_1) ret_val_1 = get_function_call_parameter_rw_information( pet, call_line_1, @@ -588,10 +591,10 @@ def identify_dependencies_for_same_functions( continue # 5. get R/W Information for scf called_function_name_2, call_line_2 = recursive_function_call_entry_2.split(",")[0].split(" ") - lower_line_num_2 = ts_1.pragma_line - if ":" in lower_line_num_2: - lower_line_num_2 = lower_line_num_2.split(":")[1] - lower_line_num_2 = int(lower_line_num_2) + lower_line_id_2 = ts_1.pragma_line + if ":" in lower_line_id_2: + lower_line_num_str_2 = lower_line_id_2.split(":")[1] + lower_line_num_2 = int(lower_line_num_str_2) ret_val_2 = get_function_call_parameter_rw_information( pet, call_line_2, @@ -698,7 +701,7 @@ def get_alias_for_parameter_at_position( source_code_files: Dict[str, str], visited: List[Tuple[Node, int]], called_function_cache: Dict[Any, Any], -) -> List[Tuple[str, str, LineID, LineID]]: +) -> List[Tuple[VarName, str, LineID, LineID]]: """Returns alias information for a parameter at a specific position. :param pet: PET Graph :param function: CUNode of called function @@ -1137,7 +1140,8 @@ def get_function_call_parameter_rw_information_recursion_step( # if parameter alias entry for parent function exists: if called_function_cu.name in function_parameter_alias_dict: alias_entries = function_parameter_alias_dict[called_function_cu.name] - for var_name, alias_name in alias_entries: + for var_name_str, alias_name in alias_entries: + var_name_2: VarName = VarName(var_name_str) var_name_is_modified = False # check if alias_name occurs in any depencendy in any of called_function_cu's children, # recursively visits all children cu nodes in function body. @@ -1172,7 +1176,7 @@ def get_function_call_parameter_rw_information_recursion_step( if var_name_is_modified: # update RAW information for idx, (old_var_name, raw_info, _) in enumerate(called_function_args_raw_information): - if old_var_name == var_name: + if old_var_name == var_name_2: if not raw_info: called_function_args_raw_information[idx] = (old_var_name, True, True) # second True denotes the pessimistic nature of a potential created dependency diff --git a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py index f4bd4773b..05cf01877 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/suggesters/tasks.py @@ -160,7 +160,7 @@ def correct_task_suggestions_in_loop_body(pet: PEGraphX, suggestions: List[Patte # check if task suggestion inside do-all loop exists if line_contained_in_region(ts._node.start_position(), loop_cu.start_position(), loop_cu.end_position()): - def find_taskwaits(cu_node: Node, visited: List[Node]): + def find_taskwaits(cu_node: Node, visited: List[Node]) -> List[Node]: if cu_node.tp_contains_taskwait: return [cu_node] result = [] @@ -175,7 +175,7 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): return result # find successive taskwaits - successive_taskwait_cus = find_taskwaits(ts._node, []) + successive_taskwait_cus = cast(List[CUNode], find_taskwaits(ts._node, [])) for stws_cu in successive_taskwait_cus: if loop_cu.do_all: # check if stws is suggested at loop increment @@ -193,7 +193,10 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): for s in suggestions: if type(s) == TaskParallelismInfo: if s.type is TPIType.TASKWAIT and s._node == stws_cu: - s.pragma_line = int(loop_cu.end_position().split(":")[1]) + 1 + s.pragma_line = LineID( + str(loop_cu.file_id) + ":" + str(int(loop_cu.end_position().split(":")[1]) + 1) + ) + else: # Regular loop: task = loop body, move taskwait to the end of the loop body # protect RAW to shared with critical section around CU (general) or atomic (reduction) @@ -210,7 +213,7 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): for s in suggestions: if type(s) == TaskParallelismInfo: if s.type is TPIType.TASKWAIT and s._node == stws_cu: - s.pragma_line = int(loop_cu.end_position().split(":")[1]) + s.pragma_line = loop_cu.end_position() # move pragma task line to beginning of loop body (i.e. make the entire loop body a task) # set task region lines accordingly # if ts._node is a direct child of loop_cu @@ -221,9 +224,11 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): " to: ", int(loop_cu.start_position().split(":")[1]) + 1, ) - ts.pragma_line = int(loop_cu.start_position().split(":")[1]) + 1 + ts.pragma_line = LineID( + str(loop_cu.file_id) + ":" + str(int(loop_cu.start_position().split(":")[1]) + 1) + ) ts.region_start_line = str(ts.pragma_line) - ts.region_end_line = loop_cu.end_position().split(":")[1] + ts.region_end_line = loop_cu.end_position() # protect RAW-Writes to shared variables with critical section # i.e. find in-deps to shared variables and suggest critical section around CUs @@ -317,7 +322,7 @@ def find_taskwaits(cu_node: Node, visited: List[Node]): def __identify_atomic_or_critical_sections( pet: PEGraphX, ts: TaskParallelismInfo, found_cus: List[Node], selector: bool -): +) -> None: """Identifies and marks atomic or critical sections. :param pet: PET Graph :param ts: task suggestion diff --git a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py index 494cb444e..386740d49 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/task_parallelism_detector.py @@ -7,7 +7,7 @@ # directory for details. -from typing import List, Optional, cast +from typing import Dict, List, Optional, Tuple, cast from discopop_explorer.PEGraphX import DummyNode, PEGraphX, MWType from discopop_explorer.parser import parse_inputs @@ -15,6 +15,7 @@ from discopop_explorer.pattern_detectors.do_all_detector import run_detection as detect_do_all from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo, run_detection as detect_reduction from discopop_explorer.pattern_detectors.task_parallelism.classes import ( + Task, TaskParallelismInfo, TPIType, ) @@ -62,6 +63,8 @@ detect_mw_types, get_var_definition_line_dict, ) +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.HostpotLoader.HotspotType import HotspotType __global_llvm_cxxfilt_path: str = "" @@ -74,7 +77,7 @@ def build_preprocessed_graph_and_run_detection( cu_inst_result_file: str, llvm_cxxfilt_path: Optional[str], discopop_build_path: Optional[str], - hotspots, + hotspots: Optional[Dict[HotspotType, List[Tuple[int, int, HotspotNodeType, str]]]], reduction_info: List[ReductionInfo], ) -> List[PatternInfo]: """execute preprocessing of given cu xml file and construct a new cu graph. @@ -162,7 +165,9 @@ def run_detection( for fork in fs: if fork.child_tasks: - result.append(TaskParallelismInfo(fork.nodes[0], TPIType.DUMMY, ["dummy_fork"], [], [], [], [])) + result.append( + TaskParallelismInfo(fork.nodes[0], TPIType.DUMMY, ["dummy_fork"], fork.start_line, [], [], []) + ) # Preprocessing check_loop_scopes(pet) # Suggestion generation diff --git a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py index 84fdafa37..9039e83c6 100644 --- a/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py +++ b/discopop_explorer/pattern_detectors/task_parallelism/tp_utils.py @@ -188,7 +188,7 @@ def get_predecessor_nodes(pet: PEGraphX, root: Node, visited_nodes: List[Node]) return result, visited_nodes -def check_neighbours(first: Task, second: Task): +def check_neighbours(first: Task, second: Task) -> bool: """Checks if second task immediately follows first task :param first: predecessor task @@ -241,7 +241,7 @@ def check_neighbours(first: Task, second: Task): # pass -def create_task_tree(pet: PEGraphX, root: Node): +def create_task_tree(pet: PEGraphX, root: Node) -> None: """generates task tree data from root node :param pet: PET graph @@ -252,7 +252,7 @@ def create_task_tree(pet: PEGraphX, root: Node): create_task_tree_helper(pet, root, root_task, []) -def create_task_tree_helper(pet: PEGraphX, current: Node, root: Task, visited_func: List[Node]): +def create_task_tree_helper(pet: PEGraphX, current: Node, root: Task, visited_func: List[Node]) -> None: """generates task tree data recursively :param pet: PET graph @@ -521,7 +521,7 @@ def get_called_function_and_parameter_names_from_function_call( return cast(Optional[str], function_name), result_parameters -def set_global_llvm_cxxfilt_path(value: str): +def set_global_llvm_cxxfilt_path(value: str) -> None: """setter for __global_llvm_cxxfilt_path :param value: value to place in __global_llvm_cxxfilt_path""" global __global_llvm_cxxfilt_path @@ -566,7 +566,7 @@ def contains_reduction(pet: PEGraphX, node: Node) -> bool: return False -def detect_mw_types(pet: PEGraphX, main_node: Node): +def detect_mw_types(pet: PEGraphX, main_node: Node) -> None: """The mainNode we want to compute the Task Parallelism Pattern for it use Breadth First Search (BFS) to detect all barriers and workers. 1.) all child nodes become first worker if they are not marked as worker before diff --git a/discopop_explorer/plugins/pipeline.py b/discopop_explorer/plugins/pipeline.py index 2a1a07a18..919a3ef89 100644 --- a/discopop_explorer/plugins/pipeline.py +++ b/discopop_explorer/plugins/pipeline.py @@ -17,11 +17,11 @@ after: List[float] = [] -def run_before(pet: PEGraphX): +def run_before(pet: PEGraphX) -> PEGraphX: return pet -def run_after(pet: PEGraphX): +def run_after(pet: PEGraphX) -> PEGraphX: for node in pet.all_nodes(LoopNode): check_pipeline(pet, node) @@ -31,7 +31,7 @@ def run_after(pet: PEGraphX): return pet -def check_pipeline(pet: PEGraphX, root: Node): +def check_pipeline(pet: PEGraphX, root: Node) -> None: """Tries to optimize dependencies for pipeline detection 1. Deletes independent lines, that do not contribute to the pipeline 2. Deletes similar CU (that have same dependencies), as those can be one step in the pipeline diff --git a/discopop_explorer/utils.py b/discopop_explorer/utils.py index d3887b749..012b7c915 100644 --- a/discopop_explorer/utils.py +++ b/discopop_explorer/utils.py @@ -335,7 +335,7 @@ def is_func_arg(pet: PEGraphX, var: str, node: Node) -> bool: return False -def is_scalar_val(var) -> bool: +def is_scalar_val(var: Variable) -> bool: """Checks if variable is a scalar value :param var: variable @@ -419,7 +419,7 @@ def is_first_written_new( reverse_raw_deps: Set[Tuple[NodeID, NodeID, Dependency]], reverse_war_deps: Set[Tuple[NodeID, NodeID, Dependency]], tree: Sequence[Node], -): +) -> bool: """Checks whether a variable is first written inside the current node :param var: @@ -730,7 +730,7 @@ def classify_task_vars( type: str, in_deps: List[Tuple[NodeID, NodeID, Dependency]], out_deps: List[Tuple[NodeID, NodeID, Dependency]], - used_in_task_parallelism_detection=False, + used_in_task_parallelism_detection: bool = False, ) -> Tuple[ List[Variable], List[Variable], diff --git a/discopop_explorer/variable.py b/discopop_explorer/variable.py index 379cdb60b..fbd5de32a 100644 --- a/discopop_explorer/variable.py +++ b/discopop_explorer/variable.py @@ -7,13 +7,15 @@ # directory for details. from typing import Optional +from discopop_explorer.pattern_detectors.combined_gpu_patterns.classes.Aliases import VarName + class Variable(object): operation: Optional[str] def __init__(self, type, name, defLine, accessMode="", sizeInByte=0): self.type = type - self.name: str = name + self.name: VarName = name self.defLine = defLine self.operation = None self.accessMode = accessMode diff --git a/discopop_library/CodeGenerator/CodeGenerator.py b/discopop_library/CodeGenerator/CodeGenerator.py index c4d6f9efa..5bfd952e1 100644 --- a/discopop_library/CodeGenerator/CodeGenerator.py +++ b/discopop_library/CodeGenerator/CodeGenerator.py @@ -22,8 +22,8 @@ def from_pattern_info( patterns_by_type: Dict[str, List[PatternInfo]], skip_compilation_check: bool = False, compile_check_command: Optional[str] = None, - CC="clang", - CXX="clang++", + CC: str = "clang", + CXX: str = "clang++", ) -> Dict[int, str]: """Insert the given parallel patterns into the original source code. Returns a dictionary which maps the ID of every modified file to the updated contents of the file. @@ -51,8 +51,8 @@ def from_json_strings( pattern_json_strings_by_type: Dict[str, List[str]], skip_compilation_check: bool = False, compile_check_command: Optional[str] = None, - CC="clang", - CXX="clang++", + CC: str = "clang", + CXX: str = "clang++", ) -> Dict[int, str]: """Insert the parallel patterns described by the given json strings into the original source code. Returns a dictionary which maps the ID of every modified file to the updated contents of the file. @@ -124,9 +124,9 @@ def from_json_strings_with_mapping( pattern_json_strings_with_mapping_by_type: Dict[str, List[Tuple[str, DeviceID, Optional[DeviceTypeEnum]]]], skip_compilation_check: bool = False, compile_check_command: Optional[str] = None, - CC="clang", - CXX="clang++", - host_device_id=0, + CC: str = "clang", + CXX: str = "clang++", + host_device_id: int = 0, ) -> Dict[int, str]: """Insert the parallel patterns described by the given json strings into the original source code. Returns a dictionary which maps the ID of every modified file to the updated contents of the file. diff --git a/discopop_library/CodeGenerator/classes/ContentBuffer.py b/discopop_library/CodeGenerator/classes/ContentBuffer.py index 2da03f6e3..4a8f9e05f 100644 --- a/discopop_library/CodeGenerator/classes/ContentBuffer.py +++ b/discopop_library/CodeGenerator/classes/ContentBuffer.py @@ -27,7 +27,7 @@ class ContentBuffer(object): line_type: Any compile_result_buffer: str - def __init__(self, file_id: int, source_code_path: Path, tab_width: int = 4, line_type=Line): + def __init__(self, file_id: int, source_code_path: Path, tab_width: int = 4, line_type: Any = Line) -> None: self.line_type = line_type self.file_id = file_id self.lines = [] @@ -42,7 +42,7 @@ def __init__(self, file_id: int, source_code_path: Path, tab_width: int = 4, lin self.lines.append(line_obj) self.compile_result_buffer = "" - def print_lines(self): + def print_lines(self) -> None: for line in self.lines: print(line) @@ -59,7 +59,7 @@ def get_modified_source_code(self) -> str: result += line.content return result - def append_line_before(self, parent_line_num: int, line: Line, match_indentation: bool = True): + def append_line_before(self, parent_line_num: int, line: Line, match_indentation: bool = True) -> None: """Appends line before the specified parent_line_num""" for idx, potential_parent_line in enumerate(self.lines): if potential_parent_line.line_num == parent_line_num: @@ -68,7 +68,7 @@ def append_line_before(self, parent_line_num: int, line: Line, match_indentation self.lines.insert(idx, line) return - def append_line_after(self, parent_line_num: int, line: Line, match_indentation: bool = True): + def append_line_after(self, parent_line_num: int, line: Line, match_indentation: bool = True) -> None: """Appends line after the specified parent_line_num""" for idx, potential_parent_line in enumerate(self.lines): if potential_parent_line.line_num == parent_line_num: @@ -88,8 +88,8 @@ def add_pragma( add_as_comment: bool = False, skip_compilation_check: bool = False, compile_check_command: Optional[str] = None, - CC="clang", - CXX="clang++", + CC: str = "clang", + CXX: str = "clang++", match_indentation: bool = True, ) -> bool: """insert pragma into the maintained list of source code lines. diff --git a/discopop_library/CodeGenerator/classes/Line.py b/discopop_library/CodeGenerator/classes/Line.py index e43010033..448c75a5f 100644 --- a/discopop_library/CodeGenerator/classes/Line.py +++ b/discopop_library/CodeGenerator/classes/Line.py @@ -16,7 +16,7 @@ class Line(object): belongs_to_regions: List[int] belongs_to_original_line: int - def __init__(self, parent_line_num: int, line_num=None, content=""): + def __init__(self, parent_line_num: int, line_num: Optional[int] = None, content: str = ""): self.line_num = line_num self.content = content self.owns_region = None diff --git a/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py b/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py index 057bafed1..9eba29847 100644 --- a/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py +++ b/discopop_library/CodeGenerator/classes/UnpackedSuggestion.py @@ -34,7 +34,14 @@ class UnpackedSuggestion(object): device_type: Optional[DeviceTypeEnum] host_device_id: int - def __init__(self, type_str: str, values: Dict[str, Any], device_id=None, device_type=None, host_device_id=0): + def __init__( + self, + type_str: str, + values: Dict[str, Any], + device_id: Optional[DeviceID] = None, + device_type: Optional[DeviceTypeEnum] = None, + host_device_id: int = 0, + ): self.type = type_str self.values = values self.device_id = device_id @@ -234,16 +241,16 @@ def __get_pipeline_pragmas(self) -> List[Pragma]: def __get_simple_gpu_pragmas( self, - region_start, - region_end, - contained_loops, - map_to_vars, - map_from_vars, - map_to_from_vars, - map_alloc_vars, - map_delete_vars, - consumed_vars, - produced_vars, + region_start: Any, + region_end: Any, + contained_loops: Any, + map_to_vars: Any, + map_from_vars: Any, + map_to_from_vars: Any, + map_alloc_vars: Any, + map_delete_vars: Any, + consumed_vars: Any, + produced_vars: Any, indentation: int = 0, ignore_mapping_clauses: bool = False, ) -> List[Pragma]: @@ -309,7 +316,7 @@ def __get_simple_gpu_pragmas( pragmas.append(loop_pragma) return pragmas - def __get_update_pragmas(self, update_instructions) -> List[Pragma]: + def __get_update_pragmas(self, update_instructions: List[Tuple[str, str, UpdateType, str, str]]) -> List[Pragma]: pragmas = [] for source_cu_id, sink_cu_id, update_type, target_var, pragma_line in update_instructions: pragma = Pragma() @@ -338,7 +345,9 @@ def __get_update_pragmas(self, update_instructions) -> List[Pragma]: pragmas.append(pragma) return pragmas - def __get_data_region_dependencies(self, depend_in, depend_out) -> List[Pragma]: + def __get_data_region_dependencies( + self, depend_in: List[Tuple[str, str, str]], depend_out: List[Tuple[str, str, str]] + ) -> List[Pragma]: pragmas = [] for var_name, cu_id, pragma_line in depend_in: pragma = Pragma() @@ -362,7 +371,11 @@ def __get_data_region_dependencies(self, depend_in, depend_out) -> List[Pragma]: return pragmas - def __get_data_region_pragmas(self, entry_points, exit_points) -> List[Pragma]: + def __get_data_region_pragmas( + self, + entry_points: List[Tuple[str, str, str, EntryPointType, str, EntryPointPositioning]], + exit_points: List[Tuple[str, str, str, ExitPointType, str, ExitPointPositioning]], + ) -> List[Pragma]: pragmas = [] for ( var_name, diff --git a/discopop_library/GlobalLogger/setup.py b/discopop_library/GlobalLogger/setup.py index de054793c..90d60287a 100644 --- a/discopop_library/GlobalLogger/setup.py +++ b/discopop_library/GlobalLogger/setup.py @@ -11,7 +11,7 @@ from discopop_library.ArgumentClasses.GeneralArguments import GeneralArguments -def setup_logger(arguments: GeneralArguments): +def setup_logger(arguments: GeneralArguments) -> None: if arguments.write_log: logging.basicConfig(filename="log.txt", level=arguments.log_level) else: diff --git a/discopop_library/LineMapping/diff_modifications.py b/discopop_library/LineMapping/diff_modifications.py index f12cd51c2..3d9cf6583 100644 --- a/discopop_library/LineMapping/diff_modifications.py +++ b/discopop_library/LineMapping/diff_modifications.py @@ -13,7 +13,7 @@ from discopop_library.LineMapping.save import save_line_mapping -def apply_line_mapping_modifications_from_files(file_id: int, original_file: str, modified_file: str): +def apply_line_mapping_modifications_from_files(file_id: int, original_file: str, modified_file: str) -> None: """Calculates diff between original_file and modified_file and applied modifications from the diff to the line_mapping""" if not os.path.exists(original_file): raise FileNotFoundError(original_file) @@ -45,7 +45,7 @@ def apply_line_mapping_modifications_from_files(file_id: int, original_file: str apply_line_mapping_modifications_from_diff(file_id, diff) -def apply_line_mapping_modifications_from_diff(file_id: int, diff: str): +def apply_line_mapping_modifications_from_diff(file_id: int, diff: str) -> None: """parse diff, apply line num modifications according to c,a,d values""" # get cleaned diff cleaned_diff: List[str] = [] diff --git a/discopop_library/LineMapping/initialize.py b/discopop_library/LineMapping/initialize.py index ee18dad96..e00ffd680 100644 --- a/discopop_library/LineMapping/initialize.py +++ b/discopop_library/LineMapping/initialize.py @@ -18,7 +18,7 @@ def initialize_line_mapping( file_mapping: Dict[int, Path], discopop_path: str = ".discopop", -): +) -> None: """initializes the line mapping dictionary to track line shifts due to inserted pragmas. The Dictionary will be stored in .discopop/line_mapping.json. Line ids start with 1.""" diff --git a/discopop_library/LineMapping/save.py b/discopop_library/LineMapping/save.py index 8607d5f7d..bde72187f 100644 --- a/discopop_library/LineMapping/save.py +++ b/discopop_library/LineMapping/save.py @@ -10,7 +10,7 @@ from typing import Dict -def save_line_mapping(line_mapping_dict: Dict[str, Dict[str, int]], discopop_path: str = ""): +def save_line_mapping(line_mapping_dict: Dict[str, Dict[str, int]], discopop_path: str = "") -> None: """dumps line_mapping_dict to line_mapping.json""" # dump line mapping to json file with open(os.path.join(discopop_path, "line_mapping.json"), "w+") as f: diff --git a/discopop_library/PatchGenerator/from_json_patterns.py b/discopop_library/PatchGenerator/from_json_patterns.py index 3d1b2ab84..5748c5be9 100644 --- a/discopop_library/PatchGenerator/from_json_patterns.py +++ b/discopop_library/PatchGenerator/from_json_patterns.py @@ -25,7 +25,7 @@ def from_json_patterns( patterns_by_type: Dict[str, List[str]], file_mapping: Dict[int, Path], patch_generator_dir: str, -): +) -> None: # collect metadata max_pattern_id = 0 for suggestion_type in patterns_by_type: diff --git a/discopop_library/PatchGenerator/from_optimizer_output.py b/discopop_library/PatchGenerator/from_optimizer_output.py index 53d23db08..5ce309110 100644 --- a/discopop_library/PatchGenerator/from_optimizer_output.py +++ b/discopop_library/PatchGenerator/from_optimizer_output.py @@ -29,7 +29,7 @@ def from_optimizer_output( optimizer_output_json_str: str, arguments: PatchGeneratorArguments, patch_generator_dir: str, -): +) -> None: suggestion_strings_with_mapping: Dict[str, List[Tuple[str, DeviceID, Optional[DeviceTypeEnum]]]] = dict() if arguments.verbose: print("Loading optimizer output: ") diff --git a/discopop_library/PatchGenerator/patch_generator.py b/discopop_library/PatchGenerator/patch_generator.py index cfb222ff0..fa3492eb2 100644 --- a/discopop_library/PatchGenerator/patch_generator.py +++ b/discopop_library/PatchGenerator/patch_generator.py @@ -20,7 +20,7 @@ from discopop_library.PathManagement.PathManagement import load_file_mapping -def run(arguments: PatchGeneratorArguments): +def run(arguments: PatchGeneratorArguments) -> None: logger = logging.getLogger("PatchGenerator") if arguments.verbose: diff --git a/discopop_library/discopop_optimizer/CostModels/CostModel.py b/discopop_library/discopop_optimizer/CostModels/CostModel.py index c1e0a6bbf..395ba4300 100644 --- a/discopop_library/discopop_optimizer/CostModels/CostModel.py +++ b/discopop_library/discopop_optimizer/CostModels/CostModel.py @@ -5,6 +5,7 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations import random import sys from typing import List, Dict, Tuple, Optional @@ -36,9 +37,9 @@ def __init__( parallelizable_costs: Expr, sequential_costs: Expr, identifier: str = "None", - path_decisions=None, + path_decisions: Optional[List[int]] = None, symbol_value_suggestions: Optional[Dict[Symbol, Expr]] = None, - ): + ) -> None: if sequential_costs == sympy.nan: raise ValueError("NAN: ", sequential_costs) if path_decisions is None: @@ -64,7 +65,7 @@ def print(self, file=sys.stdout): print("\tSERIAL") print("\t", self.sequential_costs, file=file) - def parallelizable_plus_combine(self, other): + def parallelizable_plus_combine(self, other: CostModel) -> CostModel: """Combines both models in the following fashion: f(x,y) = ==> x.parallelizable_costs + y.parallelizable_costs @@ -220,7 +221,7 @@ def __lt__(self, other): else: return False - def __plot_weibull_distributions(self, alpha: float, beta: float): + def __plot_weibull_distributions(self, alpha: float, beta: float) -> None: """For Debug reasons. Plots the left and right side heavy weibull distributions using the given parameters.""" x = np.arange(1, 100.0) / 100.0 # normalized to [0,1] diff --git a/discopop_library/discopop_optimizer/CostModels/utilities.py b/discopop_library/discopop_optimizer/CostModels/utilities.py index e48b5b088..dfb27f5a9 100644 --- a/discopop_library/discopop_optimizer/CostModels/utilities.py +++ b/discopop_library/discopop_optimizer/CostModels/utilities.py @@ -114,7 +114,7 @@ def get_node_performance_models( do_not_allow_decisions: Optional[Set[int]] = None, get_single_random_model: bool = False, ignore_node_costs: Optional[List[int]] = None, - current_device_id=None, + current_device_id: Optional[int] = None, allow_sequential: bool = False, ) -> List[CostModel]: """Returns the performance models for the given node. @@ -392,7 +392,7 @@ def get_performance_models_for_children( return child_models -def print_introduced_symbols_per_node(graph: nx.DiGraph): +def print_introduced_symbols_per_node(graph: nx.DiGraph) -> None: print("Introduced Symbols:") for node_id in graph.nodes: print("NodeID: ", node_id) diff --git a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py index d1fe46299..4a942aba8 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/DataTransfers.py @@ -11,6 +11,7 @@ from discopop_explorer.PEGraphX import EdgeType, MemoryRegion from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode from discopop_library.discopop_optimizer.classes.nodes.DeviceSwitch import DeviceSwitch @@ -30,7 +31,7 @@ def calculate_data_transfers( - graph: nx.DiGraph, function_performance_models: Dict[FunctionRoot, List[CostModel]], experiment + graph: nx.DiGraph, function_performance_models: Dict[FunctionRoot, List[CostModel]], experiment: Experiment ) -> Dict[FunctionRoot, List[Tuple[CostModel, ContextObject]]]: """Calculate data transfers for each performance model and append the respective ContextObject to the result.""" result_dict: Dict[FunctionRoot, List[Tuple[CostModel, ContextObject]]] = dict() @@ -51,7 +52,7 @@ def get_path_context_iterative( graph: nx.DiGraph, model: CostModel, context: ContextObject, - experiment, + experiment: Experiment, top_level_call: bool = False, ) -> ContextObject: """passes the context Object along the path and returns the context once the end has been reached""" @@ -161,6 +162,8 @@ def get_path_context_iterative( if target in cu_nodes_in_function: continue # target outside the function. MemoryRegions qualifies for synchronization at the end of the function + if out_dep_edge[2].memory_region is None: + raise ValueError("Value is None!") filter.add(out_dep_edge[2].memory_region) # collect all write data accesses which might need synchronization @@ -193,7 +196,7 @@ def get_path_context_iterative( def get_path_context( - node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment + node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment: Experiment ) -> ContextObject: """passes the context Object along the path and returns the context once the end has been reached""" # push device id to stack if necessary @@ -271,7 +274,7 @@ def get_path_context( def __check_current_node( - node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment + node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment: Experiment ) -> ContextObject: """Check if the given node results in modifications to the given context. Return a modified version of the context which contains the required updates.""" @@ -344,7 +347,7 @@ def __check_current_node( def __check_children( - node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment + node_id: int, graph: nx.DiGraph, model: CostModel, context: ContextObject, experiment: Experiment ) -> ContextObject: # pass context to all children for child in get_children(graph, node_id): diff --git a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py index de1366327..8f1149ae5 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py +++ b/discopop_library/discopop_optimizer/DataTransfers/NewDataTransfers.py @@ -178,7 +178,7 @@ def perform_read(self, node_id: int, device_id: DeviceID, rda: ReadDataAccess) - return updates - def perform_write(self, node_id: int, device_id: DeviceID, wda: WriteDataAccess): + def perform_write(self, node_id: int, device_id: DeviceID, wda: WriteDataAccess) -> None: if device_id not in self.memory: self.memory[device_id] = dict() self.memory[device_id][wda.memory_region] = wda @@ -198,7 +198,7 @@ class DataFrame(object): def __init__(self): self.entered_data_regions_by_device = dict() - def parse_update(self, update: Update): + def parse_update(self, update: Update) -> None: if update.is_first_data_occurrence: if update.target_device_id not in self.entered_data_regions_by_device: self.entered_data_regions_by_device[update.target_device_id] = [] @@ -317,7 +317,7 @@ def log_state(self): def new_calculate_data_transfers( graph: nx.DiGraph, decisions: List[int], - experiment, + experiment: Experiment, targeted_functions: Optional[List[int]] = None, arguments: Optional[OptimizerArguments] = None, ) -> List[Update]: @@ -491,7 +491,7 @@ def new_calculate_data_transfers( def calculate_data_transfers_by_models( - graph: nx.DiGraph, function_performance_models: Dict[FunctionRoot, List[CostModel]], experiment + graph: nx.DiGraph, function_performance_models: Dict[FunctionRoot, List[CostModel]], experiment: Experiment ) -> Dict[FunctionRoot, List[Tuple[CostModel, ContextObject]]]: """Calculate data transfers for each performance model and append the respective ContextObject to the result.""" result_dict: Dict[FunctionRoot, List[Tuple[CostModel, ContextObject]]] = dict() diff --git a/discopop_library/discopop_optimizer/DataTransfers/calculate_configuration_data_movement.py b/discopop_library/discopop_optimizer/DataTransfers/calculate_configuration_data_movement.py index 84052a8c5..847a4279c 100644 --- a/discopop_library/discopop_optimizer/DataTransfers/calculate_configuration_data_movement.py +++ b/discopop_library/discopop_optimizer/DataTransfers/calculate_configuration_data_movement.py @@ -16,7 +16,7 @@ from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern -def calculate_data_movement(experiment: Experiment): +def calculate_data_movement(experiment: Experiment) -> None: """Calculate the necessary data movement for each suggestion created by the optimizer""" for idx, suggestion in enumerate(experiment.detection_result.patterns.optimizer_output): diff --git a/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py index ecea207d8..a590fdcfd 100644 --- a/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/DelaunayInterpolatedMicrobench.py @@ -44,27 +44,29 @@ def __init__( if removeOutliers: self.data.removeOutliers() - def removeZeroParameters(self): + def removeZeroParameters(self) -> None: self.data.removeZeroParameters() self.__isInterpolated = False - def clampValues(self, min: float = 0.0, max: float = float("inf")): + def clampValues(self, min: float = 0.0, max: float = float("inf")) -> None: self.data.clampValues() self.__isInterpolated = False - def removeOutliers(self): + def removeOutliers(self) -> None: self.data.removeOutliers() self.__isInterpolated = False - def useMedian(self): + def useMedian(self) -> None: self.data.useMedian() self.__isInterpolated = False - def useMean(self): + def useMean(self) -> None: self.data.useMean() self.__isInterpolated = False - def __getTuples(self, benchType: MicrobenchType, benchDim: MicrobenchDimension): + def __getTuples( + self, benchType: MicrobenchType, benchDim: MicrobenchDimension + ) -> List[Tuple[int, Union[int, float], int, float]]: tuples: List[Tuple[int, Union[int, float], int, float]] = [] for benchCoord, values in self.data[benchType][benchDim].items(): tuples.append((*benchCoord, np.median(values).item())) @@ -95,8 +97,8 @@ def evaluateInterpolation( benchType: MicrobenchType, benchDim: MicrobenchDimension, benchCoord: Union[MicrobenchCoordinate, Tuple[int, float, float]], - ): + ) -> float: if not self.__isInterpolated: self.__interpolate() self.__isInterpolated = True - return self.interpolator[benchType][benchDim](benchCoord) / 1000000.0 # convert microseconds to seconds + return float(self.interpolator[benchType][benchDim](benchCoord) / 1000000.0) # convert microseconds to seconds diff --git a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py index 960549456..6a190f2c7 100644 --- a/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/ExtrapInterpolatedMicrobench.py @@ -5,7 +5,8 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from typing import Dict, Tuple, Union +from typing import Dict, Tuple, Union, cast + import sympy from extrap.entities.callpath import Callpath # type: ignore @@ -55,14 +56,14 @@ def getFunctionString( self, benchType: MicrobenchType = MicrobenchType.DOALL, benchDim: MicrobenchDimension = MicrobenchDimension.OVERHEAD, - ): - return self.models[(Callpath(benchType), Metric(benchDim))].hypothesis.function.to_string() + ) -> str: + return str(self.models[(Callpath(benchType), Metric(benchDim))].hypothesis.function.to_string()) def getFunctionSympy( self, benchType: MicrobenchType = MicrobenchType.DOALL, benchDim: MicrobenchDimension = MicrobenchDimension.OVERHEAD, - ): + ) -> sympy.Expr: function_str = self.getFunctionString(benchType, benchDim) # NOTE: replacement order matters! "ab".replace("a","b").replace("b","a") --> "aa", NOT "ba" function_str = function_str.replace("^", "**") @@ -72,7 +73,7 @@ def getFunctionSympy( # define replacements to match representations used in extrap output function_mappings = {"log2": lambda x: sympy.log(x, 2)} expr = parse_expr(function_str, local_dict=function_mappings) - return expr + return cast(sympy.Expr, expr) def getMeasurements(self): raise NotImplementedError("TODO") # TODO @@ -85,5 +86,7 @@ def evaluateInterpolation( benchType: MicrobenchType, benchDim: MicrobenchDimension, benchCoord: Union[MicrobenchCoordinate, Tuple[int, float, float]], - ): - return self.models[(Callpath(benchType), Metric(benchDim))].hypothesis.function.evaluate([*benchCoord]) + ) -> float: + return cast( + float, self.models[(Callpath(benchType), Metric(benchDim))].hypothesis.function.evaluate([*benchCoord]) + ) diff --git a/discopop_library/discopop_optimizer/Microbench/Microbench.py b/discopop_library/discopop_optimizer/Microbench/Microbench.py index b25360e9b..429493621 100644 --- a/discopop_library/discopop_optimizer/Microbench/Microbench.py +++ b/discopop_library/discopop_optimizer/Microbench/Microbench.py @@ -73,10 +73,10 @@ def plotInterpolation( type: MicrobenchType, dim: MicrobenchDimension, iterations: int, - threads=range(1, 9), - workloads=range(0, 201), + threads: range = range(1, 9), + workloads: range = range(0, 201), file: Optional[Path] = None, - ): + ) -> None: logging.info("plotting interpolation to %s", str(file.absolute() if file else "")) # coords = list(self.getMeasurements()[type][dim].keys()) # minWorkload = coords[0].workload diff --git a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py index 545e49f78..0aa9f675f 100644 --- a/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py +++ b/discopop_library/discopop_optimizer/Microbench/PureDataMicrobench.py @@ -9,7 +9,7 @@ import json from dataclasses import dataclass -from typing import Dict, List, Tuple, TypeVar, Union, overload +from typing import Callable, Dict, List, Tuple, TypeVar, Union, overload import numpy as np @@ -23,7 +23,7 @@ T = TypeVar("T") -def __partition(pred, list: List[T]) -> Tuple[List[T], List[T]]: +def __partition(pred: Callable[[T], bool], list: List[T]) -> Tuple[List[T], List[T]]: trues: List[T] = [] falses: List[T] = [] for item in list: @@ -34,7 +34,7 @@ def __partition(pred, list: List[T]) -> Tuple[List[T], List[T]]: return trues, falses -def __remove_outliers_using_iqr(values: List[float], iqr_factor=1.5) -> List[float]: +def __remove_outliers_using_iqr(values: List[float], iqr_factor: float = 1.5) -> List[float]: values.sort() q1, q3 = np.percentile(values, [25, 75], method="linear") iqr = q3 - q1 @@ -153,7 +153,7 @@ def clampValues( ], min: float = float("-inf"), max: float = float("inf"), - ): + ) -> None: for type, dimMap in self.measurements.items(): for d in dim: if d in dimMap: @@ -162,7 +162,7 @@ def clampValues( v if v >= min and v <= max else (min if v < min else max) for v in values ] - def merge(self, other: PureDataMicrobench): + def merge(self, other: PureDataMicrobench) -> None: for type, dimMap in other.measurements.items(): if type not in self.measurements: self.measurements[type] = {} @@ -175,7 +175,7 @@ def merge(self, other: PureDataMicrobench): self.measurements[type][dim][coord].extend(values) # TODO check for duplicates? (but maybe we want them?) - def mergeAll(self, others: List[PureDataMicrobench]): + def mergeAll(self, others: List[PureDataMicrobench]) -> None: for other in others: self.merge(other) @@ -214,5 +214,5 @@ def evaluateInterpolation( benchType: MicrobenchType, benchDim: MicrobenchDimension, benchCoord: Union[MicrobenchCoordinate, Tuple[int, float, float]], - ): + ) -> float: raise TypeError("This class does not support interpolation.") diff --git a/discopop_library/discopop_optimizer/PETParser/PETParser.py b/discopop_library/discopop_optimizer/PETParser/PETParser.py index d88abbfd2..b7540bb9a 100644 --- a/discopop_library/discopop_optimizer/PETParser/PETParser.py +++ b/discopop_library/discopop_optimizer/PETParser/PETParser.py @@ -495,7 +495,7 @@ def __flatten_function_graphs(self): print("\tTimeout after: ", timeout, "s") self.invalid_functions.add(function) - def __fix_too_many_successors(self, node, dbg_function_node=None) -> bool: + def __fix_too_many_successors(self, node: int, dbg_function_node: Optional[FunctionRoot] = None) -> bool: """Return True if a graph modification has been applied. False otherwise.""" retval = False @@ -580,7 +580,7 @@ def __fix_too_many_successors(self, node, dbg_function_node=None) -> bool: retval = True return retval - def __fix_too_many_predecessors(self, node) -> Tuple[bool, List[int]]: + def __fix_too_many_predecessors(self, node: int) -> Tuple[bool, List[int]]: """Return True if a graph modification has been applied. False otherwise.""" retval = False modified_nodes: List[int] = [] @@ -857,7 +857,7 @@ def __fix_empty_branches( added_node_ids.append(dummy_node_id) return added_node_ids - def __insert_context_nodes(self, node_list: List[int]): + def __insert_context_nodes(self, node_list: List[int]) -> None: """flattens the graph via inserting context nodes""" modification_found = True from time import time diff --git a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py index 94f4a003a..f5434e5d0 100644 --- a/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py +++ b/discopop_library/discopop_optimizer/UpdateOptimization/RemoveDuplicatedUpdates.py @@ -13,7 +13,9 @@ from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern -def remove_duplicated_updates(configuration: OptimizerOutputPattern, arguments: OptimizerArguments): +def remove_duplicated_updates( + configuration: OptimizerOutputPattern, arguments: OptimizerArguments +) -> OptimizerOutputPattern: logger = logging.getLogger("Optimizer").getChild("RemoveDuplicatedUpdates") logger.setLevel(arguments.log_level) cleaned_updates: List[Update] = [] diff --git a/discopop_library/discopop_optimizer/Variables/Experiment.py b/discopop_library/discopop_optimizer/Variables/Experiment.py index 56db58eea..cefdb33c3 100644 --- a/discopop_library/discopop_optimizer/Variables/Experiment.py +++ b/discopop_library/discopop_optimizer/Variables/Experiment.py @@ -14,17 +14,18 @@ from sympy import Integer, Symbol, Expr, Float # type: ignore from discopop_explorer.PEGraphX import MemoryRegion -from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType from discopop_library.HostpotLoader.HotspotType import HotspotType from discopop_library.MemoryRegions.utils import get_sizes_of_memory_regions from discopop_library.PathManagement.PathManagement import load_file_mapping -from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.OptimizerArguments import OptimizerArguments -from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.enums.Distributions import FreeSymbolDistribution + +from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject +from discopop_library.HostpotLoader.HotspotNodeType import HotspotNodeType +from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot -from discopop_library.discopop_optimizer.classes.system.System import System from discopop_library.result_classes.DetectionResult import DetectionResult +from discopop_library.discopop_optimizer.classes.system.System import System class Experiment(object): @@ -131,7 +132,7 @@ def get_memory_region_size( else: return Integer(self.__memory_region_sizes[memory_region]), Integer(0) - def register_free_symbol(self, symbol: Symbol, value_suggestion: Optional[Expr] = None): + def register_free_symbol(self, symbol: Symbol, value_suggestion: Optional[Expr] = None) -> None: self.free_symbols.add(symbol) if value_suggestion is not None: self.suggested_values[symbol] = value_suggestion diff --git a/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py b/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py index 707dc62d0..4e144c728 100644 --- a/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py +++ b/discopop_library/discopop_optimizer/Variables/ExperimentUtils.py @@ -44,7 +44,7 @@ def show_function_models( parent_frame: tk.Frame, destroy_window_after_execution: bool, show_functions: Optional[List[FunctionRoot]] = None, -): +) -> None: considered_functions = show_functions if show_functions is not None else experiment.function_models # show function selection dialogue parent_frame.rowconfigure(0, weight=1) @@ -104,7 +104,7 @@ def __on_press(): def perform_headless_execution( experiment: Experiment, -): +) -> None: print("Headless execution...") for function in experiment.function_models: print("\t", function.name) @@ -128,7 +128,7 @@ def perform_headless_execution( experiment.function_models[function] = updated_options -def export_to_json(experiment: Experiment, export_path): +def export_to_json(experiment: Experiment, export_path: str) -> None: # convert functionRoot in function_models to node ids to_be_added = [] to_be_deleted = [] @@ -148,7 +148,7 @@ def export_to_json(experiment: Experiment, export_path): pickle.dump(experiment, open(experiment_dump_path, "wb")) -def export_patterns_to_json(experiment: Experiment, export_path): +def export_patterns_to_json(experiment: Experiment, export_path: str) -> None: detection_result_copy = copy.deepcopy(experiment.detection_result) # pet is not serializable and needs to be deleted del detection_result_copy.pet @@ -156,7 +156,7 @@ def export_patterns_to_json(experiment: Experiment, export_path): json.dump(detection_result_copy, f, indent=2, cls=PatternBaseSerializer) -def export_detection_result_to_json(experiment: Experiment, export_path): +def export_detection_result_to_json(experiment: Experiment, export_path: str) -> None: with open(export_path, "w+") as f: f.write(experiment.detection_result.dump_to_pickled_json()) f.flush() @@ -182,7 +182,7 @@ def restore_session(json_file: str) -> Experiment: return experiment -def create_optimization_graph(experiment: Experiment, arguments: OptimizerArguments): +def create_optimization_graph(experiment: Experiment, arguments: OptimizerArguments) -> None: if arguments.verbose: print("Creating optimization graph...", end="") pet_parser = PETParser(experiment) @@ -209,7 +209,7 @@ def get_sequential_cost_model(experiment: Experiment) -> Dict[FunctionRoot, List def initialize_free_symbol_ranges_and_distributions( experiment: Experiment, arguments: OptimizerArguments, system: System -): +) -> None: free_symbol_ranges: Dict[Symbol, Tuple[float, float]] = dict() free_symbol_distributions: Dict[Symbol, FreeSymbolDistribution] = dict() sorted_free_symbols = sorted(list(experiment.free_symbols), key=lambda x: x.name) diff --git a/discopop_library/discopop_optimizer/classes/context/ContextObject.py b/discopop_library/discopop_optimizer/classes/context/ContextObject.py index af339ed95..02804ab30 100644 --- a/discopop_library/discopop_optimizer/classes/context/ContextObject.py +++ b/discopop_library/discopop_optimizer/classes/context/ContextObject.py @@ -5,13 +5,19 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations from typing import Dict, Set, List, Optional import warnings + from sympy import Expr, Integer, Symbol # type: ignore import networkx as nx # type: ignore from discopop_explorer.PEGraphX import MemoryRegion +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.Update import Update from discopop_library.discopop_optimizer.classes.types.Aliases import DeviceID from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( @@ -46,9 +52,9 @@ def calculate_and_perform_necessary_updates( reading_device_id: int, reading_node_id: int, graph: nx.DiGraph, - experiment, + experiment: Experiment, updates_originated_from: Optional[int] = None, - ): + ) -> ContextObject: """checks if the specified list of ReadDataAccesses performed by the specified device id makes updates necessary. If so, the updates will get append to the list of updates of the current ContextObject. The list of seen writes by device of the ContextObject will be updated to reflect the identified data transfers. @@ -180,6 +186,8 @@ def calculate_and_perform_necessary_updates( self.initialize_seen_writes_by_device( update.target_device_id, update.write_data_access.memory_region ) + if update.target_device_id is None: + raise ValueError("Value is None") self.__add_seen_write( update.target_device_id, update.write_data_access.memory_region, update.write_data_access ) @@ -188,7 +196,7 @@ def calculate_and_perform_necessary_updates( return self - def add_writes(self, node_writes: Set[WriteDataAccess], writing_device_id: int): + def add_writes(self, node_writes: Set[WriteDataAccess], writing_device_id: int) -> ContextObject: """Add the specified writes to the list of seen writes of the given device and returns a reference to this ContextObject.""" # check if the device is known to the context @@ -203,7 +211,7 @@ def add_writes(self, node_writes: Set[WriteDataAccess], writing_device_id: int): self.__add_seen_write(writing_device_id, write.memory_region, write) return self - def set_last_visited_node_id(self, node_id: int): + def set_last_visited_node_id(self, node_id: int) -> None: self.last_visited_node_id = node_id def get_seen_writes_by_device(self, device_id: DeviceID) -> Dict[MemoryRegion, Set[WriteDataAccess]]: @@ -226,19 +234,19 @@ def get_seen_writes_by_device(self, device_id: DeviceID) -> Dict[MemoryRegion, S return seen_dict - def initialize_seen_writes_by_device(self, device_id: DeviceID, memory_region: MemoryRegion): + def initialize_seen_writes_by_device(self, device_id: DeviceID, memory_region: MemoryRegion) -> None: if device_id not in self.seen_writes_by_device: self.seen_writes_by_device[device_id] = dict() self.seen_writes_by_device[device_id][memory_region] = set() - def __add_seen_write(self, device_id, memory_region: MemoryRegion, write: WriteDataAccess): + def __add_seen_write(self, device_id: int, memory_region: MemoryRegion, write: WriteDataAccess) -> None: if device_id not in self.seen_writes_by_device: self.seen_writes_by_device[device_id] = dict() if memory_region not in self.seen_writes_by_device[device_id]: self.seen_writes_by_device[device_id][memory_region] = set() self.seen_writes_by_device[device_id][memory_region].add(write) - def __get_known_device_ids(self): + def __get_known_device_ids(self) -> Set[DeviceID]: seen_devices: Set[DeviceID] = set() for stack_entry in self.snapshot_stack: for device_id in stack_entry[0]: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextMerge.py b/discopop_library/discopop_optimizer/classes/nodes/ContextMerge.py index c63985d24..5ce59dc1a 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextMerge.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextMerge.py @@ -11,12 +11,13 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class ContextMerge(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextNode.py b/discopop_library/discopop_optimizer/classes/nodes/ContextNode.py index 4f8679e4f..42ff71378 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextNode.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextNode.py @@ -9,12 +9,13 @@ from sympy import Integer from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.Workload import Workload class ContextNode(Workload): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__( node_id, experiment, diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextRestore.py b/discopop_library/discopop_optimizer/classes/nodes/ContextRestore.py index fe35f2798..219f74184 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextRestore.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextRestore.py @@ -11,12 +11,13 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class ContextRestore(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextSave.py b/discopop_library/discopop_optimizer/classes/nodes/ContextSave.py index 35fe85d1c..5c3c742bd 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextSave.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextSave.py @@ -11,13 +11,14 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode from discopop_library.discopop_optimizer.utilities.MOGUtilities import show class ContextSave(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshot.py b/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshot.py index 3f2a83457..343f4e34f 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshot.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshot.py @@ -10,12 +10,13 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class ContextSnapshot(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshotPop.py b/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshotPop.py index 233845707..5f244d4dd 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshotPop.py +++ b/discopop_library/discopop_optimizer/classes/nodes/ContextSnapshotPop.py @@ -9,12 +9,13 @@ import networkx as nx # type: ignore from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.context.ContextObject import ContextObject from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class ContextSnapshotPop(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py b/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py index 549551eda..90d7a5016 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py +++ b/discopop_library/discopop_optimizer/classes/nodes/DeviceSwitch.py @@ -8,6 +8,7 @@ from typing import Optional, Set from sympy import Function, Symbol, Integer, Expr +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.types.DataAccessType import WriteDataAccess # type: ignore from discopop_explorer.PEGraphX import NodeID @@ -20,7 +21,7 @@ class DeviceSwitch(Workload): def __init__( self, node_id: int, - experiment, + experiment: Experiment, cu_id: Optional[NodeID], sequential_workload: Optional[Expr], parallelizable_workload: Optional[Expr], diff --git a/discopop_library/discopop_optimizer/classes/nodes/FunctionReturn.py b/discopop_library/discopop_optimizer/classes/nodes/FunctionReturn.py index 164fb81c0..a7358773a 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/FunctionReturn.py +++ b/discopop_library/discopop_optimizer/classes/nodes/FunctionReturn.py @@ -7,11 +7,12 @@ # directory for details. import networkx as nx # type: ignore +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.nodes.ContextNode import ContextNode class FunctionReturn(ContextNode): - def __init__(self, node_id: int, experiment): + def __init__(self, node_id: int, experiment: Experiment): super().__init__(node_id, experiment) def get_plot_label(self) -> str: diff --git a/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py b/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py index 9ebdea509..25963102f 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py +++ b/discopop_library/discopop_optimizer/classes/nodes/FunctionRoot.py @@ -5,13 +5,19 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from typing import Optional +from __future__ import annotations +from typing import Any, List, Optional from sympy import Function, Symbol, Integer, Expr # type: ignore from discopop_explorer.PEGraphX import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.nodes.Workload import Workload +from discopop_library.discopop_optimizer.classes.system.devices.Device import Device class FunctionRoot(Workload): @@ -20,7 +26,7 @@ class FunctionRoot(Workload): sequential_costs: Expr performance_model: CostModel - def __init__(self, node_id: int, experiment, cu_id: Optional[NodeID], name: str): + def __init__(self, node_id: int, experiment: Experiment, cu_id: Optional[NodeID], name: str): super().__init__( node_id, experiment, @@ -42,7 +48,9 @@ def __init__(self, node_id: int, experiment, cu_id: Optional[NodeID], name: str) def get_plot_label(self) -> str: return self.name - def get_cost_model(self, experiment, all_function_nodes, current_device) -> CostModel: + def get_cost_model( + self, experiment: Experiment, all_function_nodes: List[Any], current_device: Device + ) -> CostModel: """Model: Spawn overhead + children""" # todo this is only a dummy, not a finished model! diff --git a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py index fba64254a..0f77acbdf 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py +++ b/discopop_library/discopop_optimizer/classes/nodes/GenericNode.py @@ -5,12 +5,21 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations from typing import Optional, List, Set from sympy import Symbol, Function, Integer # type: ignore from discopop_explorer.PEGraphX import NodeID +from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + print("TYPE CHECKING") + from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot + from discopop_library.discopop_optimizer.Variables.Experiment import Experiment +from discopop_library.discopop_optimizer.classes.system.devices.Device import Device from discopop_library.discopop_optimizer.classes.types.Aliases import DeviceID from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( ReadDataAccess, @@ -28,13 +37,12 @@ class GenericNode(object): read_memory_regions: Set[ReadDataAccess] device_id: DeviceID execute_in_parallel: bool - branch_affiliation: List[int] def __init__( self, node_id: int, - experiment, + experiment: Experiment, cu_id: Optional[NodeID] = None, written_memory_regions: Optional[Set[WriteDataAccess]] = None, read_memory_regions: Optional[Set[ReadDataAccess]] = None, @@ -45,7 +53,7 @@ def __init__( self.original_cu_id = cu_id # used for the creation of update suggestions self.introduced_symbols = [] self.performance_model = CostModel(Integer(0), Integer(0)) - self.suggestion = None + self.suggestion: Optional[PatternInfo] = None self.suggestion_type: Optional[str] = None self.branch_affiliation = [] self.execute_in_parallel = False @@ -74,10 +82,14 @@ def get_plot_label(self) -> str: def get_hover_text(self) -> str: return "" - def get_cost_model(self, experiment, all_function_nodes, current_device) -> CostModel: + def get_cost_model( + self, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: raise NotImplementedError("Implementation needs to be provided by derived class: !", type(self)) - def register_child(self, other, experiment, all_function_nodes, current_device): + def register_child( + self, other: CostModel, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Registers a child node for the given model. Does not modify the stored model in self or other.""" raise NotImplementedError("Implementation needs to be provided by derived class: !", type(self)) diff --git a/discopop_library/discopop_optimizer/classes/nodes/Loop.py b/discopop_library/discopop_optimizer/classes/nodes/Loop.py index b3f3cf9a3..783c80167 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Loop.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Loop.py @@ -5,14 +5,16 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. -from typing import Optional +from typing import List, Optional from sympy import Symbol, Integer, Expr, Float # type: ignore from discopop_explorer.PEGraphX import NodeID from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.Variables.Experiment import Experiment +from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot from discopop_library.discopop_optimizer.classes.nodes.Workload import Workload +from discopop_library.discopop_optimizer.classes.system.devices.Device import Device class Loop(Workload): @@ -89,7 +91,9 @@ def get_hover_text(self) -> str: "Device ID: " + str(self.device_id) ) - def get_cost_model(self, experiment, all_function_nodes, current_device) -> CostModel: + def get_cost_model( + self, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Performance model of a workload consists of the workload itself. Individual Workloads are assumed to be not parallelizable. Workloads of Loop etc. are parallelizable.""" @@ -111,7 +115,9 @@ def get_cost_model(self, experiment, all_function_nodes, current_device) -> Cost return cm - def register_child(self, other, experiment, all_function_nodes, current_device): + def register_child( + self, other: CostModel, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Registers a child node for the given model. Does not modify the stored model in self or other.""" diff --git a/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py b/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py index a372c0c13..89c62621b 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py +++ b/discopop_library/discopop_optimizer/classes/nodes/SynchronizationTrigger.py @@ -8,6 +8,7 @@ from typing import Optional, Set from sympy import Function, Symbol, Integer, Expr +from discopop_library.discopop_optimizer.Variables.Experiment import Experiment from discopop_library.discopop_optimizer.classes.types.DataAccessType import WriteDataAccess # type: ignore from discopop_explorer.PEGraphX import NodeID @@ -20,7 +21,7 @@ class SynchronizationTrigger(Workload): def __init__( self, node_id: int, - experiment, + experiment: Experiment, cu_id: Optional[NodeID], sequential_workload: Optional[Expr], parallelizable_workload: Optional[Expr], diff --git a/discopop_library/discopop_optimizer/classes/nodes/Workload.py b/discopop_library/discopop_optimizer/classes/nodes/Workload.py index 9e24c093b..31ec9a0fb 100644 --- a/discopop_library/discopop_optimizer/classes/nodes/Workload.py +++ b/discopop_library/discopop_optimizer/classes/nodes/Workload.py @@ -5,13 +5,20 @@ # This software may be modified and distributed under the terms of # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. +from __future__ import annotations from typing import Optional, Set, List, cast from sympy import Integer, Expr # type: ignore from discopop_explorer.PEGraphX import NodeID, PEGraphX, EdgeType from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from discopop_library.discopop_optimizer.Variables.Experiment import Experiment + from discopop_library.discopop_optimizer.classes.nodes.FunctionRoot import FunctionRoot from discopop_library.discopop_optimizer.classes.nodes.GenericNode import GenericNode +from discopop_library.discopop_optimizer.classes.system.devices.Device import Device from discopop_library.discopop_optimizer.classes.types.DataAccessType import ( WriteDataAccess, ReadDataAccess, @@ -28,7 +35,7 @@ class Workload(GenericNode): def __init__( self, node_id: int, - experiment, + experiment: Experiment, cu_id: Optional[NodeID], sequential_workload: Optional[Expr], parallelizable_workload: Optional[Expr], @@ -67,7 +74,9 @@ def get_hover_text(self) -> str: "Device ID: " + str(self.device_id) ) - def get_cost_model(self, experiment, all_function_nodes, current_device) -> CostModel: + def get_cost_model( + self, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Performance model of a workload consists of the workload itself + the workload of called functions. Individual Workloads are assumed to be not parallelizable. Workloads of called functions are added as encountered. @@ -103,16 +112,15 @@ def get_cost_model(self, experiment, all_function_nodes, current_device) -> Cost return cm - def __get_costs_of_function_call(self, experiment, all_function_nodes, current_device) -> CostModel: + def __get_costs_of_function_call( + self, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Check if the node performs a function call and returns the total costs for these.""" total_costs = CostModel(Integer(0), Integer(0)) # get CUIDs of called functions if self.original_cu_id is not None: called_cu_ids: List[str] = [ - str(t) - for s, t, d in cast(PEGraphX, experiment.detection_result.pet).out_edges( - self.original_cu_id, EdgeType.CALLSNODE - ) + str(t) for s, t, d in experiment.detection_result.pet.out_edges(self.original_cu_id, EdgeType.CALLSNODE) ] # filter for called FunctionRoots called_function_nodes = [fr for fr in all_function_nodes if str(fr.original_cu_id) in called_cu_ids] @@ -126,7 +134,9 @@ def __get_costs_of_function_call(self, experiment, all_function_nodes, current_d return total_costs - def register_child(self, other, experiment, all_function_nodes, current_device): + def register_child( + self, other: CostModel, experiment: Experiment, all_function_nodes: List[FunctionRoot], current_device: Device + ) -> CostModel: """Registers a child node for the given model. Does not modify the stored model in self or other.""" # since workloads do not modify their children, the performance model of other is simply added to self. diff --git a/discopop_library/discopop_optimizer/classes/system/Network.py b/discopop_library/discopop_optimizer/classes/system/Network.py index a32423c93..485dd5928 100644 --- a/discopop_library/discopop_optimizer/classes/system/Network.py +++ b/discopop_library/discopop_optimizer/classes/system/Network.py @@ -23,15 +23,15 @@ def __init__(self): self.__transfer_speeds = dict() self.__transfer_initialization_costs = dict() - def add_connection(self, source: Device, target: Device, transfer_speed: Expr, initialization_delay: Expr): + def add_connection(self, source: Device, target: Device, transfer_speed: Expr, initialization_delay: Expr) -> None: if source == target: transfer_speed = Integer(10000 * 1000) # 10000 GB/s = 10000 * 1000 MB/s self.__transfer_speeds[(source, target)] = transfer_speed self.__transfer_initialization_costs[(source, target)] = initialization_delay - def get_transfer_speed(self, source: Device, target: Device): + def get_transfer_speed(self, source: Device, target: Device) -> Expr: if source == target: - return Integer(1000000) # 1000 GB/s + return cast(Expr, Integer(1000000)) # 1000 GB/s if (source, target) not in self.__transfer_speeds: if self.__host_device is None: raise ValueError("Host device of network unspecified!") @@ -40,15 +40,15 @@ def get_transfer_speed(self, source: Device, target: Device): return min(S_to_H_speed, H_to_T_speed) return self.__transfer_speeds[(source, target)] - def get_transfer_initialization_costs(self, source: Device, target: Device): + def get_transfer_initialization_costs(self, source: Device, target: Device) -> Expr: if source == target: - return Integer(0) + return cast(Expr, Integer(0)) if (source, target) not in self.__transfer_speeds: if self.__host_device is None: raise ValueError("Host device of network unspecified!") S_to_H_init_costs = self.__transfer_initialization_costs[(source, self.__host_device)] H_to_T_init_costs = self.__transfer_initialization_costs[(self.__host_device, target)] - return S_to_H_init_costs + H_to_T_init_costs + return cast(Expr, S_to_H_init_costs + H_to_T_init_costs) return self.__transfer_initialization_costs[(source, target)] def get_free_symbols(self) -> List[Tuple[Symbol, Optional[Expr]]]: @@ -59,5 +59,5 @@ def get_free_symbols(self) -> List[Tuple[Symbol, Optional[Expr]]]: result_list += [(cast(Symbol, s), None) for s in expr.free_symbols] return result_list - def set_host_device(self, host_device: Device): + def set_host_device(self, host_device: Device) -> None: self.__host_device = host_device diff --git a/discopop_library/discopop_optimizer/classes/system/System.py b/discopop_library/discopop_optimizer/classes/system/System.py index ae87aed1d..3f8917f47 100644 --- a/discopop_library/discopop_optimizer/classes/system/System.py +++ b/discopop_library/discopop_optimizer/classes/system/System.py @@ -9,7 +9,7 @@ import os import pathlib import warnings -from typing import Any, Dict, List, Tuple, Optional +from typing import Any, Dict, List, Tuple, Optional, cast from sympy import Float, Symbol, Expr, Integer from discopop_library.discopop_optimizer.classes.enums.Distributions import FreeSymbolDistribution @@ -52,7 +52,7 @@ def __init__(self, arguments: OptimizerArguments): # todo: support the replication of device ids (e.g. CPU-0 and GPU-0) - def __build_from_configuration_file(self, arguments: OptimizerArguments): + def __build_from_configuration_file(self, arguments: OptimizerArguments) -> None: with open(arguments.system_configuration_path, "r") as f: system_configuration = json.load(f) self.__host_device_id = system_configuration["host_device"] @@ -87,7 +87,7 @@ def __build_from_configuration_file(self, arguments: OptimizerArguments): # no transfer speed information exists pass - def __build_CPU(self, device_configuration: Dict[str, Any]): + def __build_CPU(self, device_configuration: Dict[str, Any]) -> None: cpu = CPU( frequency=Integer(device_configuration["frequency"]), thread_count=Integer(device_configuration["threads"]), @@ -98,7 +98,7 @@ def __build_CPU(self, device_configuration: Dict[str, Any]): ) self.add_device(cpu, device_configuration["device_id"]) - def __build_GPU(self, device_configuration: Dict[str, Any]): + def __build_GPU(self, device_configuration: Dict[str, Any]) -> None: gpu = GPU( frequency=Integer(device_configuration["frequency"]), thread_count=Integer(device_configuration["threads"]), @@ -109,17 +109,19 @@ def __build_GPU(self, device_configuration: Dict[str, Any]): ) self.add_device(gpu, device_configuration["device_id"]) - def set_device_doall_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments): + def set_device_doall_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments) -> None: if arguments.verbose: print("System: Set DOALL overhead model: ", model) self.__device_do_all_overhead_models[device] = model - def set_device_doall_shared_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments): + def set_device_doall_shared_overhead_model( + self, device: Device, model: Expr, arguments: OptimizerArguments + ) -> None: if arguments.verbose: print("System: Set DOALL SHARED overhead model: ", model) self.__device_do_all_shared_overhead_models[device] = model - def set_reduction_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments): + def set_reduction_overhead_model(self, device: Device, model: Expr, arguments: OptimizerArguments) -> None: if arguments.verbose: print("System: Set REDUCTION overhead model: ", model) self.__device_reduction_overhead_models[device] = model @@ -128,24 +130,24 @@ def get_device_doall_overhead_model(self, device: Device, arguments: OptimizerAr if device not in self.__device_do_all_overhead_models: if arguments.verbose: warnings.warn("No DOALL overhead model, assuming 0 for device: " + str(device)) - return Expr(Integer(0)) + return cast(Expr, Integer(0)) return self.__device_do_all_overhead_models[device] def get_device_doall_shared_overhead_model(self, device: Device, arguments: OptimizerArguments) -> Expr: if device not in self.__device_do_all_shared_overhead_models: if arguments.verbose: warnings.warn("No DOALL SHARED overhead model, assuming 0 for device: " + str(device)) - return Expr(Integer(0)) + return cast(Expr, Integer(0)) return self.__device_do_all_shared_overhead_models[device] def get_device_reduction_overhead_model(self, device: Device, arguments: OptimizerArguments) -> Expr: if device not in self.__device_reduction_overhead_models: if arguments.verbose: warnings.warn("No REDUCTION overhead model, assuming 0 for device: " + str(device)) - return Expr(Integer(0)) + return cast(Expr, Integer(0)) return self.__device_reduction_overhead_models[device] - def add_device(self, device: Device, device_id: int): + def add_device(self, device: Device, device_id: int) -> None: self.__devices[device_id] = device def get_device(self, device_id: Optional[int]) -> Device: diff --git a/discopop_library/discopop_optimizer/classes/system/devices/CPU.py b/discopop_library/discopop_optimizer/classes/system/devices/CPU.py index f11efedcc..c78f279cb 100644 --- a/discopop_library/discopop_optimizer/classes/system/devices/CPU.py +++ b/discopop_library/discopop_optimizer/classes/system/devices/CPU.py @@ -6,6 +6,8 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. from typing import Dict + +from sympy import Integer from discopop_library.discopop_optimizer.classes.system.devices.Device import Device from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum @@ -13,8 +15,8 @@ class CPU(Device): def __init__( self, - frequency, - thread_count, + frequency: Integer, + thread_count: Integer, openmp_device_id: int, device_specific_compiler_flags: str, speedup: float, diff --git a/discopop_library/discopop_optimizer/classes/system/devices/Device.py b/discopop_library/discopop_optimizer/classes/system/devices/Device.py index 9be7ec5af..fb350c898 100644 --- a/discopop_library/discopop_optimizer/classes/system/devices/Device.py +++ b/discopop_library/discopop_optimizer/classes/system/devices/Device.py @@ -60,7 +60,7 @@ def get_free_symbols(self) -> List[Tuple[Symbol, Optional[Expr]]]: def get_measured_speedup(self) -> Expr: return Float(self.__speedup) - def get_estimated_execution_time_in_micro_seconds(self, workload: Expr, is_sequential: bool): + def get_estimated_execution_time_in_micro_seconds(self, workload: Optional[Expr], is_sequential: bool) -> Expr: """execution time is estimated by: - convert workload to estimated amount of CPU instructions using a extra-p model - NOTE: use "perf stat ./ define functions to evaluate workloads on different devices. include these functions in the construction of the cost model for later evaluation instead of "manually" converting the workload to time values # todo: correctly set is_sequential argument @@ -91,7 +93,7 @@ def get_estimated_execution_time_in_micro_seconds(self, workload: Expr, is_seque execution_time_in_seconds = workload_in_instructions / instructions_per_second execution_time_in_micro_seconds = execution_time_in_seconds * 1000000 - return execution_time_in_micro_seconds + return Float(execution_time_in_micro_seconds) def get_device_type(self) -> DeviceTypeEnum: raise ValueError("This method need to be overwritten by subclasses!") diff --git a/discopop_library/discopop_optimizer/classes/system/devices/GPU.py b/discopop_library/discopop_optimizer/classes/system/devices/GPU.py index f515b2ed8..edd9fa5ee 100644 --- a/discopop_library/discopop_optimizer/classes/system/devices/GPU.py +++ b/discopop_library/discopop_optimizer/classes/system/devices/GPU.py @@ -7,6 +7,8 @@ # directory for details. from typing import Dict, Tuple +from sympy import Integer + from discopop_explorer.pattern_detectors.PatternInfo import PatternInfo from discopop_library.discopop_optimizer.classes.system.devices.Device import Device from discopop_library.discopop_optimizer.classes.system.devices.DeviceTypeEnum import DeviceTypeEnum @@ -15,10 +17,10 @@ class GPU(Device): def __init__( self, - frequency, - thread_count, - openmp_device_id, - device_specific_compiler_flags, + frequency: Integer, + thread_count: Integer, + openmp_device_id: int, + device_specific_compiler_flags: str, speedup: float, compute_init_delays: Dict[str, float], ): diff --git a/discopop_library/discopop_optimizer/classes/system/system_utils.py b/discopop_library/discopop_optimizer/classes/system/system_utils.py index fc76c9899..2baa629ed 100644 --- a/discopop_library/discopop_optimizer/classes/system/system_utils.py +++ b/discopop_library/discopop_optimizer/classes/system/system_utils.py @@ -17,7 +17,7 @@ from discopop_library.discopop_optimizer.classes.system.devices.GPU import GPU -def generate_default_system_configuration(file_path: str): +def generate_default_system_configuration(file_path: str) -> None: """Generates a system configuration file using the default values if none exists so far.""" if os.path.exists(file_path): return diff --git a/discopop_library/discopop_optimizer/gui/plotting/CostModels.py b/discopop_library/discopop_optimizer/gui/plotting/CostModels.py index 084fdaf6a..c17c21db7 100644 --- a/discopop_library/discopop_optimizer/gui/plotting/CostModels.py +++ b/discopop_library/discopop_optimizer/gui/plotting/CostModels.py @@ -21,14 +21,14 @@ def plot_CostModels( - experiment, + experiment: Experiment, models: List[CostModel], sorted_free_symbols: List[Symbol], free_symbol_ranges: Dict[Symbol, Tuple[float, float]], labels: Optional[List[str]] = None, title: Optional[str] = None, super_title: Optional[str] = None, -): +) -> None: local_sorted_free_symbols = copy.deepcopy(sorted_free_symbols) local_free_symbol_ranges = copy.deepcopy(free_symbol_ranges) for symbol in experiment.substitutions: @@ -112,7 +112,7 @@ def plot_CostModels_using_function_path_selections( labels: Optional[List[str]] = None, title: Optional[str] = None, super_title: Optional[str] = None, -): +) -> None: # apply selected substitutions # collect substitutions local_substitutions = copy.deepcopy(experiment.substitutions) @@ -188,7 +188,7 @@ def plot_CostModels_using_function_path_selections( print("Plotiting not supported for", len(local_sorted_free_symbols), "free symbols!") -def print_current_function_path_selections(experiment: Experiment): +def print_current_function_path_selections(experiment: Experiment) -> None: """Prints an overview of the currently selected paths for each function to the console""" print("###") print("SELECTIONS:") @@ -198,7 +198,7 @@ def print_current_function_path_selections(experiment: Experiment): print("###") -def print_current_substitutions(experiment: Experiment): +def print_current_substitutions(experiment: Experiment) -> None: """Prints an overview of the currently selected paths for each function to the console""" print("###") print("SUBSTITUTIONS:") @@ -216,7 +216,7 @@ def print_simplified_function( labels: Optional[List[str]] = None, title: Optional[str] = None, super_title: Optional[str] = None, -): +) -> None: """Prints an simplified mathematical function based on the current set of selections""" # todo: NOTE: copied from plot_CostModels_using_function_path_selections @@ -288,7 +288,7 @@ def __1d_plot( labels: Optional[List[str]] = None, title: Optional[str] = None, super_title: Optional[str] = None, -): +) -> None: global __unique_plot_id matplotlib.use("TkAgg") # Make a dataset from models: @@ -329,7 +329,7 @@ def __2d_plot( free_symbol_ranges: Dict[Symbol, Tuple[float, float]], labels: Optional[List[str]] = None, title: Optional[str] = None, -): +) -> None: matplotlib.use("TkAgg") combined_plot = None for idx, model in enumerate(models): @@ -375,7 +375,7 @@ def __3d_plot( free_symbol_ranges: Dict[Symbol, Tuple[float, float]], labels: Optional[List[str]] = None, title: Optional[str] = None, -): +) -> None: matplotlib.use("TkAgg") combined_plot = None for idx, model in enumerate(models): diff --git a/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py b/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py index 7f9b7398f..d17e80ec1 100644 --- a/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py +++ b/discopop_library/discopop_optimizer/gui/presentation/ChoiceDetails.py @@ -16,7 +16,7 @@ from DEPRECATED_discopop_wizard.screens.widgets.ScrollableText import ScrollableTextWidget -def display_choices_for_model(graph: nx.DiGraph, model: CostModel, window_title: Optional[str] = None): +def display_choices_for_model(graph: nx.DiGraph, model: CostModel, window_title: Optional[str] = None) -> None: root = Tk() if window_title is not None: root.configure() diff --git a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py index 19a7887df..0a642c4c0 100644 --- a/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py +++ b/discopop_library/discopop_optimizer/gui/presentation/OptionTable.py @@ -44,7 +44,7 @@ def show_options( function_root: FunctionRoot, parent_frame: tkinter.Frame, spawned_windows: List[tkinter.Toplevel], - window_title=None, + window_title: Optional[str] = None, ) -> List[Tuple[CostModel, ContextObject, str]]: """Shows a tkinter table to browse and plot models""" # root = tkinter.Toplevel() @@ -240,7 +240,7 @@ def __save_models( experiment: Experiment, function_root: FunctionRoot, options: List[Tuple[CostModel, ContextObject, str]], -): +) -> None: print("SAVE: ", function_root) print("\ttype; ", type(function_root)) experiment.function_models[function_root] = options @@ -259,7 +259,7 @@ def add_random_models( function_root: FunctionRoot, parent_frame: Optional[tkinter.Frame], spawned_windows: List[tkinter.Toplevel], - window_title=None, + window_title: Optional[str] = None, show_results: bool = True, ) -> List[Tuple[CostModel, ContextObject, str]]: if root is not None: diff --git a/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py b/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py index b68fe4626..6c9ced61a 100644 --- a/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py +++ b/discopop_library/discopop_optimizer/gui/widgets/ScrollableFrame.py @@ -35,7 +35,7 @@ def __init__(self, parent_frame): self.canvas.configure(yscrollcommand=self.scrollbar.set) - def finalize(self, row_count: int, row: int = 0, col: int = 0, rowspan: int = 1, columnspan: int = 1): + def finalize(self, row_count: int, row: int = 0, col: int = 0, rowspan: int = 1, columnspan: int = 1) -> None: if rowspan < 1: rowspan = 1 if columnspan < 1: diff --git a/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py b/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py index bec28f2c3..fbc0b2d21 100644 --- a/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py +++ b/discopop_library/discopop_optimizer/interactive/interactive_optimizer.py @@ -28,7 +28,7 @@ logger = logging.getLogger("Optimizer").getChild("Interactive") -def run_interactive_optimizer(arguments: OptimizerArguments): +def run_interactive_optimizer(arguments: OptimizerArguments) -> None: logger.setLevel(arguments.log_level) logger.info("Starting..") # check prerequisites @@ -62,7 +62,9 @@ def run_interactive_optimizer(arguments: OptimizerArguments): logger.info("Closing interactive optimizer..") -def parse_interactive_export(experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments): +def parse_interactive_export( + experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments +) -> None: parse_input( input="add " + arguments.interactive_export.replace(",", " "), experiment=experiment, @@ -72,7 +74,9 @@ def parse_interactive_export(experiment: Experiment, applied_suggestions: Set[in parse_input(input="export", experiment=experiment, applied_suggestions=applied_suggestions, arguments=arguments) -def parse_input(input: str, experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments): +def parse_input( + input: str, experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments +) -> bool: """Return True if the interactive session should be kept alive. Return False if the main loop should be exited.""" if input.startswith("list"): @@ -115,12 +119,12 @@ def parse_input(input: str, experiment: Experiment, applied_suggestions: Set[int return True -def show_configuration_diff(experiment: Experiment, applied_suggestions: Set[int]): +def show_configuration_diff(experiment: Experiment, applied_suggestions: Set[int]) -> None: logger.info("Creating and showing the diff for the current configuration..") logger.info("Not yet implemented") -def export_configuration(experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments): +def export_configuration(experiment: Experiment, applied_suggestions: Set[int], arguments: OptimizerArguments) -> None: logger.info("Exporting the current configuration..") configured_pattern = __create_optimizer_output_pattern(experiment, applied_suggestions) if configured_pattern is None: diff --git a/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py b/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py index 345e4cdf9..e6f05333e 100644 --- a/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py +++ b/discopop_library/discopop_optimizer/optimization/evaluate_all_decision_combinations.py @@ -10,7 +10,7 @@ import os from typing import Dict, List, Optional, Set, Tuple, cast -from sympy import Expr +from sympy import Expr, re import tqdm # type: ignore from discopop_explorer.PEGraphX import NodeID # type: ignore @@ -129,14 +129,14 @@ def evaluate_all_decision_combinations( def __initialize_worker( experiment: Experiment, arguments: OptimizerArguments, -): +) -> None: global global_experiment global global_arguments global_experiment = experiment global_arguments = arguments -def __evaluate_configuration(param_tuple): +def __evaluate_configuration(param_tuple: List[int]) -> Tuple[Tuple[int, ...], Expr, ContextObject]: global global_experiment global global_arguments if global_experiment is None: @@ -163,7 +163,7 @@ def __dump_result_to_file_using_pattern_ids( for pattern_id in experiment.suggestion_to_node_ids_dict: if entry in experiment.suggestion_to_node_ids_dict[pattern_id]: new_key.append(str(pattern_id) + "@" + str(data_at(experiment.optimization_graph, entry).device_id)) - dumpable_dict[str(new_key)] = str(int(float(str(costs_dict[key].evalf())))) + dumpable_dict[str(new_key)] = str(int(float(str(re(costs_dict[key].evalf()))))) dump_path: str = os.path.join(optimizer_dir, "exhaustive_results.json") with open(dump_path, "w") as fp: diff --git a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py index e96edfb92..bc4dbe250 100644 --- a/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py +++ b/discopop_library/discopop_optimizer/optimization/evolutionary_algorithm.py @@ -122,14 +122,14 @@ def __calculate_fitness( def __initialize_fitness_worker( experiment: Experiment, arguments: OptimizerArguments, -): +) -> None: global global_experiment global global_arguments global_experiment = experiment global_arguments = arguments -def __get_score(param_tuple) -> Tuple[List[int], int, ContextObject]: +def __get_score(param_tuple: List[int]) -> Tuple[List[int], int, ContextObject]: global global_experiment global global_arguments configuration = param_tuple @@ -151,7 +151,7 @@ def __print_population( population: List[List[int]], fitness: List[int], arguments: OptimizerArguments, -): +) -> None: sorted_fitness = sorted(enumerate(fitness), key=lambda x: x[1], reverse=True) print("# POPULATION") for fitness_idx, fitness_value in sorted_fitness: @@ -181,7 +181,7 @@ def __initialize_fill_worker( experiment: Experiment, available_decisions: Dict[FunctionRoot, List[List[int]]], arguments: OptimizerArguments, -): +) -> None: global global_experiment global global_arguments global global_available_decisions @@ -246,7 +246,7 @@ def __select( population: List[List[int]], fitness: List[int], new_population_size: int, -): +) -> List[List[int]]: """Performs a fitness-proportionate Selection""" # get Sum of scores score_sum = 0.0 @@ -276,7 +276,7 @@ def __crossover( arguments: OptimizerArguments, population: List[List[int]], crossovers: int, -): +) -> List[List[int]]: global global_experiment global global_arguments global global_population @@ -305,7 +305,9 @@ def __crossover( return population -def __initialize_crossover_worker(experiment: Experiment, arguments: OptimizerArguments, population: List[List[int]]): +def __initialize_crossover_worker( + experiment: Experiment, arguments: OptimizerArguments, population: List[List[int]] +) -> None: global global_experiment global global_arguments global global_population @@ -314,7 +316,9 @@ def __initialize_crossover_worker(experiment: Experiment, arguments: OptimizerAr global_population = population -def __parallel_crossover(param_tuple): +def __parallel_crossover( + param_tuple: None, +) -> Optional[Tuple[Tuple[List[int], List[int]], Tuple[List[int], List[int]]]]: global global_experiment global global_arguments global global_population @@ -378,7 +382,9 @@ def __mutate( return population -def __initialize_mutate_worker(experiment: Experiment, arguments: OptimizerArguments, population: List[List[int]]): +def __initialize_mutate_worker( + experiment: Experiment, arguments: OptimizerArguments, population: List[List[int]] +) -> None: global global_experiment global global_arguments global global_population @@ -490,7 +496,7 @@ def __get_random_configuration( experiment: Experiment, available_decisions: Dict[FunctionRoot, List[List[int]]], arguments: OptimizerArguments, -): +) -> List[int]: while True: random_configuration: List[int] = [] # fill configuration diff --git a/discopop_library/discopop_optimizer/optimization/greedy.py b/discopop_library/discopop_optimizer/optimization/greedy.py index c33882c2f..710c52f4e 100644 --- a/discopop_library/discopop_optimizer/optimization/greedy.py +++ b/discopop_library/discopop_optimizer/optimization/greedy.py @@ -169,14 +169,14 @@ def __get_dicision_list(decisions_dict): def __initialize_cost_caluclation_worker( experiment: Experiment, arguments: OptimizerArguments, -): +) -> None: global global_experiment global global_arguments global_experiment = experiment global_arguments = arguments -def __get_score(param_tuple) -> Tuple[Dict[int, List[List[int]]], int, ContextObject]: +def __get_score(param_tuple: Dict[int, List[List[int]]]) -> Tuple[Dict[int, List[List[int]]], int, ContextObject]: global global_experiment global global_arguments configuration = param_tuple diff --git a/discopop_library/discopop_optimizer/optimizer.py b/discopop_library/discopop_optimizer/optimizer.py index 243c739e8..adcb0b952 100644 --- a/discopop_library/discopop_optimizer/optimizer.py +++ b/discopop_library/discopop_optimizer/optimizer.py @@ -76,14 +76,14 @@ from ..HostpotLoader.hostpot_loader import run as load_hotspots -def run(arguments: OptimizerArguments): +def run(arguments: OptimizerArguments) -> None: if arguments.interactive: run_interactive_optimizer(arguments) else: run_passive_optimizer(arguments) -def run_passive_optimizer(arguments: OptimizerArguments): +def run_passive_optimizer(arguments: OptimizerArguments) -> None: logger = logging.getLogger("Optimizer") # check prerequisites and setup folder structure diff --git a/discopop_library/discopop_optimizer/scheduling/workload_delta.py b/discopop_library/discopop_optimizer/scheduling/workload_delta.py index dbc22f776..c28e6c21b 100644 --- a/discopop_library/discopop_optimizer/scheduling/workload_delta.py +++ b/discopop_library/discopop_optimizer/scheduling/workload_delta.py @@ -116,7 +116,7 @@ def aggregate(self): cur_elem = cur_elem[index] cur_elem[indices[-1]] = RegularCosts((min_wl, max_wl)) - def register_workload(self, min_wl: int, max_wl: int): + def register_workload(self, min_wl: int, max_wl: int) -> None: # get the innermost workload stack innermost_stack, _ = self.__get_innermost_workload_stack() innermost_stack.append(RegularCosts((min_wl, max_wl))) diff --git a/discopop_library/discopop_optimizer/suggestions/importers/do_all.py b/discopop_library/discopop_optimizer/suggestions/importers/do_all.py index 8b30e5715..c5b95fa26 100644 --- a/discopop_library/discopop_optimizer/suggestions/importers/do_all.py +++ b/discopop_library/discopop_optimizer/suggestions/importers/do_all.py @@ -7,7 +7,7 @@ # directory for details. import copy import logging -from typing import Set, cast, Tuple, List, Dict +from typing import Callable, Set, cast, Tuple, List, Dict import networkx as nx # type: ignore from sympy import Expr, Integer, Symbol, log, Float, init_printing @@ -35,7 +35,7 @@ def import_suggestion( - graph: nx.DiGraph, suggestion, get_next_free_node_id_function, environment: Experiment + graph: nx.DiGraph, suggestion: DoAllInfo, get_next_free_node_id_function: Callable[[], int], environment: Experiment ) -> nx.DiGraph: # find a node which belongs to the suggestion buffer = [n for n in graph.nodes] diff --git a/discopop_library/discopop_optimizer/suggestions/importers/reduction.py b/discopop_library/discopop_optimizer/suggestions/importers/reduction.py index 936093171..d76072494 100644 --- a/discopop_library/discopop_optimizer/suggestions/importers/reduction.py +++ b/discopop_library/discopop_optimizer/suggestions/importers/reduction.py @@ -6,11 +6,12 @@ # the 3-Clause BSD License. See the LICENSE file in the package base # directory for details. import copy -from typing import Set, cast, Tuple, List, Dict +from typing import Callable, Set, cast, Tuple, List, Dict import networkx as nx # type: ignore from sympy import Expr, Integer, Symbol, log, Float, init_printing # type: ignore +from discopop_explorer.pattern_detectors.reduction_detector import ReductionInfo from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel from discopop_library.discopop_optimizer.Microbench.utils import ( convert_discopop_to_microbench_workload, @@ -28,7 +29,10 @@ def import_suggestion( - graph: nx.DiGraph, suggestion, get_next_free_node_id_function, environment: Experiment + graph: nx.DiGraph, + suggestion: ReductionInfo, + get_next_free_node_id_function: Callable[[], int], + environment: Experiment, ) -> nx.DiGraph: # find a node which belongs to the suggestion buffer = [n for n in graph.nodes] diff --git a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py index 2d1bba9f5..c17cc47f3 100644 --- a/discopop_library/discopop_optimizer/utilities/MOGUtilities.py +++ b/discopop_library/discopop_optimizer/utilities/MOGUtilities.py @@ -129,7 +129,7 @@ def get_function_return_node(graph: nx.DiGraph, function: int) -> int: def show_decision_graph( graph: nx.DiGraph, decisions: List[int], show_dataflow: bool = True, show_mutex_edges: bool = False -): +) -> None: print("Decisions: ", decisions) contained_nodes: Set[int] = set() for function in get_all_function_nodes(graph): @@ -167,7 +167,9 @@ def show_decision_graph( show(graph.subgraph(contained_nodes), show_dataflow=show_dataflow, show_mutex_edges=show_mutex_edges) -def show_function(graph: nx.DiGraph, function: FunctionRoot, show_dataflow: bool = True, show_mutex_edges: bool = True): +def show_function( + graph: nx.DiGraph, function: FunctionRoot, show_dataflow: bool = True, show_mutex_edges: bool = True +) -> None: # get nodes in subtree of function contained_nodes: Set[int] = set() queue: List[int] = [function.node_id] @@ -181,7 +183,7 @@ def show_function(graph: nx.DiGraph, function: FunctionRoot, show_dataflow: bool show(graph.subgraph(contained_nodes), show_dataflow=show_dataflow, show_mutex_edges=show_mutex_edges) -def show(graph: nx.DiGraph, show_dataflow: bool = True, show_mutex_edges: bool = True): +def show(graph: nx.DiGraph, show_dataflow: bool = True, show_mutex_edges: bool = True) -> None: """Plots the graph :return: @@ -376,32 +378,32 @@ def hover(event): plt.show() -def add_successor_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_successor_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = SuccessorEdge() graph.add_edge(source_id, target_id, data=edge_data) -def add_child_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_child_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = ChildEdge() graph.add_edge(source_id, target_id, data=edge_data) -def add_call_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_call_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = CallEdge() graph.add_edge(source_id, target_id, data=edge_data) -def add_temporary_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_temporary_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = TemporaryEdge() graph.add_edge(source_id, target_id, data=edge_data) -def add_dataflow_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def add_dataflow_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: edge_data = DataFlowEdge() graph.add_edge(source_id, target_id, data=edge_data) -def delete_outgoing_temporary_edges(graph: nx.DiGraph, source_id: int): +def delete_outgoing_temporary_edges(graph: nx.DiGraph, source_id: int) -> None: to_be_deleted = set() for edge in graph.out_edges(source_id): edge_data = graph.edges[edge]["data"] @@ -417,17 +419,17 @@ def redirect_edge( new_source_id: int, old_target_id: int, new_target_id: int, -): +) -> None: edge_data = graph.edges[(old_source_id, old_target_id)]["data"] remove_edge(graph, old_source_id, old_target_id) graph.add_edge(new_source_id, new_target_id, data=edge_data) -def remove_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def remove_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: graph.remove_edge(source_id, target_id) -def convert_temporary_edges(graph: nx.DiGraph): +def convert_temporary_edges(graph: nx.DiGraph) -> None: """Convert temporary edges to Successor edges""" for edge in graph.edges: edge_data = graph.edges[edge]["data"] @@ -435,7 +437,7 @@ def convert_temporary_edges(graph: nx.DiGraph): graph.edges[edge]["data"] = edge_data.convert_to_successor_edge() -def convert_temporary_edge(graph: nx.DiGraph, source_id: int, target_id: int): +def convert_temporary_edge(graph: nx.DiGraph, source_id: int, target_id: int) -> None: """Converts a single temporary edge to a successor edge""" edge_data = graph.edges[(source_id, target_id)]["data"] if isinstance(edge_data, TemporaryEdge): @@ -611,7 +613,7 @@ def get_available_decisions_for_functions( return available_decisions -def __initialize_availability_worker(graph: nx.DiGraph, arguments: OptimizerArguments): +def __initialize_availability_worker(graph: nx.DiGraph, arguments: OptimizerArguments) -> None: global global_graph global global_arguments global_graph = graph @@ -622,7 +624,7 @@ def __parallel_get_decisions_from_node_recursive(function_node): global global_graph global global_arguments - def get_decisions_from_node_recursive(node_id, prev_decisions: List[int]) -> List[List[int]]: + def get_decisions_from_node_recursive(node_id: int, prev_decisions: List[int]) -> List[List[int]]: children_paths: List[List[int]] = [] # get decisions from children for child in get_children(global_graph, node_id): diff --git a/discopop_library/discopop_optimizer/utilities/insert_device_switch_nodes.py b/discopop_library/discopop_optimizer/utilities/insert_device_switch_nodes.py index ba9390231..626a13f45 100644 --- a/discopop_library/discopop_optimizer/utilities/insert_device_switch_nodes.py +++ b/discopop_library/discopop_optimizer/utilities/insert_device_switch_nodes.py @@ -102,7 +102,7 @@ def insert_device_switch_nodes(experiment: Experiment) -> nx.DiGraph: return experiment.optimization_graph -def __set_read_and_write_information(experiment: Experiment, device_switch_nodes: List[int]): +def __set_read_and_write_information(experiment: Experiment, device_switch_nodes: List[int]) -> None: """Collect and set read and write information for the device switch nodes""" for node in device_switch_nodes: # look ahead to next device switch along each path and collect the encountered reads and writes diff --git a/discopop_library/discopop_optimizer/utilities/optimization/GlobalOptimization/RandomSamples.py b/discopop_library/discopop_optimizer/utilities/optimization/GlobalOptimization/RandomSamples.py index 17a7b2189..04c26e4d2 100644 --- a/discopop_library/discopop_optimizer/utilities/optimization/GlobalOptimization/RandomSamples.py +++ b/discopop_library/discopop_optimizer/utilities/optimization/GlobalOptimization/RandomSamples.py @@ -30,7 +30,13 @@ def find_quasi_optimal_using_random_samples( free_symbol_ranges: Dict[Symbol, Tuple[float, float]], free_symbol_distributions: Dict[Symbol, FreeSymbolDistribution], verbose: bool = False, -): +) -> Tuple[ + Tuple[CostModel, ContextObject], + Tuple[CostModel, ContextObject], + Tuple[CostModel, ContextObject], + Tuple[CostModel, ContextObject], + Tuple[CostModel, ContextObject], +]: """Returns the identified minimum, maximum, median, 25% quartile and 75% quartile of the random_path_count samples. NOTE: The decisions should be treated as suggestions, not mathematically accurate decisions due to the used comparison method!""" diff --git a/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py b/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py index 2017eed2f..7e9f5ace2 100644 --- a/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py +++ b/discopop_library/discopop_optimizer/utilities/visualization/update_graph.py @@ -29,7 +29,7 @@ from discopop_library.result_classes.OptimizerOutputPattern import OptimizerOutputPattern # type: ignore -def show_update_graph(graph, configuration: OptimizerOutputPattern, experiment: Experiment): +def show_update_graph(graph: nx.DiGraph, configuration: OptimizerOutputPattern, experiment: Experiment) -> None: matplotlib.use("TkAgg") fig, ax = plt.subplots() try: diff --git a/discopop_library/result_classes/OptimizerOutputPattern.py b/discopop_library/result_classes/OptimizerOutputPattern.py index df75e6edd..0aabcdf24 100644 --- a/discopop_library/result_classes/OptimizerOutputPattern.py +++ b/discopop_library/result_classes/OptimizerOutputPattern.py @@ -35,7 +35,7 @@ def __init__(self, node: Node, decisions: List[int], host_device_id: int, experi self.host_device_id = host_device_id experiment.pattern_id_to_decisions_dict[self.pattern_id] = decisions - def reconstruct_from_file(self, file_path: str): # todo remove? + def reconstruct_from_file(self, file_path: str) -> None: # todo remove? with open(file_path, "r") as f: loaded_data = json.load(f) self.applied_patterns = loaded_data["applied_patterns"] @@ -45,7 +45,7 @@ def reconstruct_from_file(self, file_path: str): # todo remove? for values in loaded_data["data_movement"]: self.data_movement.append(construct_update_from_dict(values)) - def dump_to_file(self, file_path: str): # todo remove? + def dump_to_file(self, file_path: str) -> None: # todo remove? dumpable_dict: Dict[str, Any] = dict() dumpable_dict["applied_patterns"] = self.applied_patterns dumpable_dict["data_movement"] = [update.toDict() for update in self.data_movement] @@ -55,14 +55,14 @@ def dump_to_file(self, file_path: str): # todo remove? with open(file_path, "w") as f: json.dump(dumpable_dict, f) - def add_pattern(self, pattern_id: SuggestionId, target_device_id: DeviceID, device_type: DeviceTypeEnum): + def add_pattern(self, pattern_id: SuggestionId, target_device_id: DeviceID, device_type: DeviceTypeEnum) -> None: if self.pattern_id is None: # get a unique pattern_id self.pattern_id = get_unique_pattern_id() tmp_dict = {"pattern_id": pattern_id, "device_id": target_device_id, "device_type": device_type} self.applied_patterns.append(tmp_dict) - def add_data_movement(self, update: Update): + def add_data_movement(self, update: Update) -> None: self.data_movement.append(update) def get_contained_decisions(self, experiment: Experiment) -> List[int]: diff --git a/test/end_to_end/do_all/calls/complex/src/FileMapping.txt b/test/end_to_end/do_all/calls/complex/src/FileMapping.txt new file mode 100644 index 000000000..e77368562 --- /dev/null +++ b/test/end_to_end/do_all/calls/complex/src/FileMapping.txt @@ -0,0 +1 @@ +1 /home/lukas/git/discopop/test/end_to_end/do_all/calls/complex/src/code.cpp diff --git a/test/end_to_end/do_all/calls/complex/src/code.ll b/test/end_to_end/do_all/calls/complex/src/code.ll new file mode 100644 index 000000000..c6ad70045 --- /dev/null +++ b/test/end_to_end/do_all/calls/complex/src/code.ll @@ -0,0 +1,780 @@ +; ModuleID = 'code.cpp' +source_filename = "code.cpp" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@_ZZ4mainE1n = internal global i32 5000, align 4, !dbg !0 +@_ZZ4mainE1a = internal global double 2.000000e+00, align 8, !dbg !17 +@.str = private unnamed_addr constant [5 x i8] c"base\00", align 1 +@.str.1 = private unnamed_addr constant [9 x i8] c"offset_1\00", align 1 +@.str.2 = private unnamed_addr constant [9 x i8] c"offset_2\00", align 1 +@.str.3 = private unnamed_addr constant [6 x i8] c"index\00", align 1 +@.str.4 = private unnamed_addr constant [2 x i8] c"n\00", align 1 +@.str.5 = private unnamed_addr constant [10 x i8] c"1:19;1:20\00", align 1 +@.str.6 = private unnamed_addr constant [10 x i8] c"1:19;1:22\00", align 1 +@.str.7 = private unnamed_addr constant [10 x i8] c"1:24;1:25\00", align 1 +@.str.8 = private unnamed_addr constant [10 x i8] c"1:24;1:28\00", align 1 +@.str.9 = private unnamed_addr constant [10 x i8] c"1:30;1:31\00", align 1 +@.str.10 = private unnamed_addr constant [10 x i8] c"1:30;1:34\00", align 1 +@.str.11 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1n\00", align 1 +@.str.12 = private unnamed_addr constant [12 x i8] c"_ZZ4mainE1a\00", align 1 +@.str.13 = private unnamed_addr constant [5 x i8] c".str\00", align 1 +@.str.14 = private unnamed_addr constant [7 x i8] c".str.1\00", align 1 +@.str.15 = private unnamed_addr constant [7 x i8] c".str.2\00", align 1 +@.str.16 = private unnamed_addr constant [7 x i8] c".str.3\00", align 1 +@.str.17 = private unnamed_addr constant [7 x i8] c".str.4\00", align 1 +@.str.18 = private unnamed_addr constant [7 x i8] c".str.5\00", align 1 +@.str.19 = private unnamed_addr constant [7 x i8] c".str.6\00", align 1 +@.str.20 = private unnamed_addr constant [7 x i8] c".str.7\00", align 1 +@.str.21 = private unnamed_addr constant [7 x i8] c".str.8\00", align 1 +@.str.22 = private unnamed_addr constant [7 x i8] c".str.9\00", align 1 +@.str.23 = private unnamed_addr constant [7 x i8] c"retval\00", align 1 +@.str.24 = private unnamed_addr constant [5 x i8] c"argc\00", align 1 +@.str.25 = private unnamed_addr constant [5 x i8] c"argv\00", align 1 +@.str.26 = private unnamed_addr constant [2 x i8] c"x\00", align 1 +@.str.27 = private unnamed_addr constant [2 x i8] c"i\00", align 1 + +; Function Attrs: noinline nounwind optnone uwtable +define void @_Z19perform_calculationPdii(double* %base, i32 %offset_1, i32 %offset_2) #0 !dbg !265 { +entry: + call void @__dp_func_entry(i32 16388, i32 0) + %base.addr = alloca double*, align 8 + %0 = ptrtoint double** %base.addr to i64 + %offset_1.addr = alloca i32, align 4 + %1 = ptrtoint i32* %offset_1.addr to i64 + %offset_2.addr = alloca i32, align 4 + %2 = ptrtoint i32* %offset_2.addr to i64 + %3 = ptrtoint double** %base.addr to i64 + store double* %base, double** %base.addr, align 8 + call void @llvm.dbg.declare(metadata double** %base.addr, metadata !268, metadata !DIExpression()), !dbg !269 + %4 = ptrtoint i32* %offset_1.addr to i64 + store i32 %offset_1, i32* %offset_1.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %offset_1.addr, metadata !270, metadata !DIExpression()), !dbg !271 + %5 = ptrtoint i32* %offset_2.addr to i64 + store i32 %offset_2, i32* %offset_2.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %offset_2.addr, metadata !272, metadata !DIExpression()), !dbg !273 + %6 = ptrtoint double** %base.addr to i64 + %7 = load double*, double** %base.addr, align 8, !dbg !274 + %8 = ptrtoint i32* %offset_2.addr to i64 + %9 = load i32, i32* %offset_2.addr, align 4, !dbg !275 + %idxprom = sext i32 %9 to i64, !dbg !274 + %arrayidx = getelementptr inbounds double, double* %7, i64 %idxprom, !dbg !274 + %10 = ptrtoint double* %arrayidx to i64 + call void @__dp_read(i32 16388, i64 %10, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0)) + %11 = load double, double* %arrayidx, align 8, !dbg !274 + %add = fadd double 4.200000e+01, %11, !dbg !276 + %12 = ptrtoint double** %base.addr to i64 + %13 = load double*, double** %base.addr, align 8, !dbg !277 + %14 = ptrtoint i32* %offset_1.addr to i64 + %15 = load i32, i32* %offset_1.addr, align 4, !dbg !278 + %idxprom1 = sext i32 %15 to i64, !dbg !277 + %arrayidx2 = getelementptr inbounds double, double* %13, i64 %idxprom1, !dbg !277 + %16 = ptrtoint double* %arrayidx2 to i64 + call void @__dp_write(i32 16388, i64 %16, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0)) + store double %add, double* %arrayidx2, align 8, !dbg !279 + call void @__dp_report_bb(i32 0) + call void @__dp_func_exit(i32 16388, i32 0), !dbg !280 + ret void, !dbg !280 +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: noinline nounwind optnone uwtable +define void @_Z14doall_possiblePdi(double* %base, i32 %index) #0 !dbg !281 { +entry: + call void @__dp_func_entry(i32 16390, i32 0) + %base.addr = alloca double*, align 8 + %0 = ptrtoint double** %base.addr to i64 + %index.addr = alloca i32, align 4 + %1 = ptrtoint i32* %index.addr to i64 + %2 = ptrtoint double** %base.addr to i64 + store double* %base, double** %base.addr, align 8 + call void @llvm.dbg.declare(metadata double** %base.addr, metadata !284, metadata !DIExpression()), !dbg !285 + %3 = ptrtoint i32* %index.addr to i64 + store i32 %index, i32* %index.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %index.addr, metadata !286, metadata !DIExpression()), !dbg !287 + %4 = ptrtoint double** %base.addr to i64 + %5 = load double*, double** %base.addr, align 8, !dbg !288 + %6 = ptrtoint i32* %index.addr to i64 + %7 = load i32, i32* %index.addr, align 4, !dbg !289 + %8 = ptrtoint i32* %index.addr to i64 + %9 = load i32, i32* %index.addr, align 4, !dbg !290 + call void @__dp_call(i32 16390), !dbg !291 + call void @_Z19perform_calculationPdii(double* %5, i32 %7, i32 %9), !dbg !291 + call void @__dp_report_bb(i32 1) + call void @__dp_func_exit(i32 16390, i32 0), !dbg !292 + ret void, !dbg !292 +} + +; Function Attrs: noinline nounwind optnone uwtable +define void @_Z18doall_not_possiblePdii(double* %base, i32 %index, i32 %n) #0 !dbg !293 { +entry: + call void @__dp_func_entry(i32 16392, i32 0) + %base.addr = alloca double*, align 8 + %0 = ptrtoint double** %base.addr to i64 + %index.addr = alloca i32, align 4 + %1 = ptrtoint i32* %index.addr to i64 + %n.addr = alloca i32, align 4 + %2 = ptrtoint i32* %n.addr to i64 + %3 = ptrtoint double** %base.addr to i64 + store double* %base, double** %base.addr, align 8 + call void @llvm.dbg.declare(metadata double** %base.addr, metadata !294, metadata !DIExpression()), !dbg !295 + %4 = ptrtoint i32* %index.addr to i64 + store i32 %index, i32* %index.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %index.addr, metadata !296, metadata !DIExpression()), !dbg !297 + %5 = ptrtoint i32* %n.addr to i64 + store i32 %n, i32* %n.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %n.addr, metadata !298, metadata !DIExpression()), !dbg !299 + %6 = ptrtoint double** %base.addr to i64 + %7 = load double*, double** %base.addr, align 8, !dbg !300 + %8 = ptrtoint i32* %index.addr to i64 + %9 = load i32, i32* %index.addr, align 4, !dbg !301 + %10 = ptrtoint i32* %index.addr to i64 + %11 = load i32, i32* %index.addr, align 4, !dbg !302 + %12 = ptrtoint i32* %n.addr to i64 + %13 = load i32, i32* %n.addr, align 4, !dbg !303 + %rem = srem i32 422, %13, !dbg !304 + %add = add nsw i32 %11, %rem, !dbg !305 + call void @__dp_call(i32 16392), !dbg !306 + call void @_Z19perform_calculationPdii(double* %7, i32 %9, i32 %add), !dbg !306 + call void @__dp_report_bb(i32 2) + call void @__dp_func_exit(i32 16392, i32 0), !dbg !307 + ret void, !dbg !307 +} + +; Function Attrs: noinline norecurse nounwind optnone uwtable +define i32 @main(i32 %argc, i8** %argv) #2 !dbg !2 { +entry: + call void @__dp_func_entry(i32 16394, i32 1) + %__dp_bb16 = alloca i32, align 4 + store i32 0, i32* %__dp_bb16, align 4 + %__dp_bb15 = alloca i32, align 4 + store i32 0, i32* %__dp_bb15, align 4 + %__dp_bb = alloca i32, align 4 + store i32 0, i32* %__dp_bb, align 4 + %retval = alloca i32, align 4 + %0 = ptrtoint i32* %retval to i64 + %argc.addr = alloca i32, align 4 + %1 = ptrtoint i32* %argc.addr to i64 + %argv.addr = alloca i8**, align 8 + %2 = ptrtoint i8*** %argv.addr to i64 + %x = alloca double*, align 8 + %3 = ptrtoint double** %x to i64 + %i = alloca i32, align 4 + %4 = ptrtoint i32* %i to i64 + %i1 = alloca i32, align 4 + %5 = ptrtoint i32* %i1 to i64 + %i8 = alloca i32, align 4 + %6 = ptrtoint i32* %i8 to i64 + %7 = ptrtoint i32* %retval to i64 + store i32 0, i32* %retval, align 4 + %8 = ptrtoint i32* %argc.addr to i64 + store i32 %argc, i32* %argc.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %argc.addr, metadata !308, metadata !DIExpression()), !dbg !309 + %9 = ptrtoint i8*** %argv.addr to i64 + store i8** %argv, i8*** %argv.addr, align 8 + call void @llvm.dbg.declare(metadata i8*** %argv.addr, metadata !310, metadata !DIExpression()), !dbg !311 + call void @llvm.dbg.declare(metadata double** %x, metadata !312, metadata !DIExpression()), !dbg !313 + %10 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16397, i64 %10, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %11 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !314 + %conv = sext i32 %11 to i64, !dbg !314 + %mul = mul i64 %conv, 8, !dbg !315 + %call = call noalias i8* @malloc(i64 %mul) #4, !dbg !316 + %12 = ptrtoint i8* %call to i64 + call void @__dp_new(i32 16397, i64 %12, i64 %12, i64 %mul), !dbg !317 + %13 = bitcast i8* %call to double*, !dbg !317 + %14 = ptrtoint double** %x to i64 + store double* %13, double** %x, align 8, !dbg !313 + call void @llvm.dbg.declare(metadata i32* %i, metadata !318, metadata !DIExpression()), !dbg !320 + %15 = ptrtoint i32* %i to i64 + store i32 0, i32* %i, align 4, !dbg !320 + call void @__dp_report_bb(i32 3) + br label %for.cond, !dbg !321 + +for.cond: ; preds = %for.inc, %entry + call void @__dp_loop_entry(i32 16401, i32 0) + %16 = ptrtoint i32* %i to i64 + %17 = load i32, i32* %i, align 4, !dbg !322 + %18 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16401, i64 %18, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %19 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !324 + %cmp = icmp slt i32 %17, %19, !dbg !325 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.5, i32 0, i32 0), i1 %cmp, i32 1), !dbg !326 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0), i1 %cmp, i32 0), !dbg !326 + call void @__dp_report_bb(i32 4) + %20 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %20, i32 16) + br i1 %cmp, label %for.body, label %for.end, !dbg !326 + +for.body: ; preds = %for.cond + call void @__dp_loop_incr(i32 3) + %21 = ptrtoint double** %x to i64 + %22 = load double*, double** %x, align 8, !dbg !327 + %23 = ptrtoint i32* %i to i64 + %24 = load i32, i32* %i, align 4, !dbg !329 + %idxprom = sext i32 %24 to i64, !dbg !327 + %arrayidx = getelementptr inbounds double, double* %22, i64 %idxprom, !dbg !327 + %25 = ptrtoint double* %arrayidx to i64 + call void @__dp_write(i32 16402, i64 %25, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.26, i32 0, i32 0)) + store double 1.000000e+00, double* %arrayidx, align 8, !dbg !330 + call void @__dp_report_bb(i32 7) + %26 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %26, i32 18) + br label %for.inc, !dbg !331 + +for.inc: ; preds = %for.body + %27 = ptrtoint i32* %i to i64 + %28 = load i32, i32* %i, align 4, !dbg !332 + %inc = add nsw i32 %28, 1, !dbg !332 + %29 = ptrtoint i32* %i to i64 + store i32 %inc, i32* %i, align 4, !dbg !332 + call void @__dp_report_bb(i32 6) + %30 = load i32, i32* %__dp_bb, align 4 + call void @__dp_report_bb_pair(i32 %30, i32 17) + store i32 1, i32* %__dp_bb, align 4 + br label %for.cond, !dbg !333, !llvm.loop !334 + +for.end: ; preds = %for.cond + call void @__dp_loop_exit(i32 16406, i32 0) + call void @llvm.dbg.declare(metadata i32* %i1, metadata !336, metadata !DIExpression()), !dbg !338 + %31 = ptrtoint i32* %i1 to i64 + store i32 0, i32* %i1, align 4, !dbg !338 + call void @__dp_report_bb(i32 5) + br label %for.cond2, !dbg !339 + +for.cond2: ; preds = %for.inc5, %for.end + call void @__dp_loop_entry(i32 16406, i32 1) + %32 = ptrtoint i32* %i1 to i64 + %33 = load i32, i32* %i1, align 4, !dbg !340 + %34 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16406, i64 %34, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %35 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !342 + %cmp3 = icmp slt i32 %33, %35, !dbg !343 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.7, i32 0, i32 0), i1 %cmp3, i32 1), !dbg !344 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.8, i32 0, i32 0), i1 %cmp3, i32 0), !dbg !344 + call void @__dp_report_bb(i32 9) + %36 = load i32, i32* %__dp_bb15, align 4 + call void @__dp_report_bb_pair(i32 %36, i32 19) + br i1 %cmp3, label %for.body4, label %for.end7, !dbg !344 + +for.body4: ; preds = %for.cond2 + call void @__dp_loop_incr(i32 2) + %37 = ptrtoint double** %x to i64 + %38 = load double*, double** %x, align 8, !dbg !345 + %39 = ptrtoint i32* %i1 to i64 + %40 = load i32, i32* %i1, align 4, !dbg !347 + call void @__dp_call(i32 16407), !dbg !348 + call void @_Z14doall_possiblePdi(double* %38, i32 %40), !dbg !348 + call void @__dp_report_bb(i32 11) + %41 = load i32, i32* %__dp_bb15, align 4 + call void @__dp_report_bb_pair(i32 %41, i32 21) + br label %for.inc5, !dbg !349 + +for.inc5: ; preds = %for.body4 + %42 = ptrtoint i32* %i1 to i64 + %43 = load i32, i32* %i1, align 4, !dbg !350 + %inc6 = add nsw i32 %43, 1, !dbg !350 + %44 = ptrtoint i32* %i1 to i64 + store i32 %inc6, i32* %i1, align 4, !dbg !350 + call void @__dp_report_bb(i32 10) + %45 = load i32, i32* %__dp_bb15, align 4 + call void @__dp_report_bb_pair(i32 %45, i32 20) + store i32 1, i32* %__dp_bb15, align 4 + br label %for.cond2, !dbg !351, !llvm.loop !352 + +for.end7: ; preds = %for.cond2 + call void @__dp_loop_exit(i32 16411, i32 1) + call void @llvm.dbg.declare(metadata i32* %i8, metadata !354, metadata !DIExpression()), !dbg !356 + %46 = ptrtoint i32* %i8 to i64 + store i32 0, i32* %i8, align 4, !dbg !356 + call void @__dp_report_bb(i32 8) + br label %for.cond9, !dbg !357 + +for.cond9: ; preds = %for.inc12, %for.end7 + call void @__dp_loop_entry(i32 16411, i32 2) + %47 = ptrtoint i32* %i8 to i64 + %48 = load i32, i32* %i8, align 4, !dbg !358 + %49 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16411, i64 %49, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %50 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !360 + %cmp10 = icmp slt i32 %48, %50, !dbg !361 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9, i32 0, i32 0), i1 %cmp10, i32 1), !dbg !362 + call void @__dp_incr_taken_branch_counter(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.10, i32 0, i32 0), i1 %cmp10, i32 0), !dbg !362 + call void @__dp_report_bb(i32 13) + %51 = load i32, i32* %__dp_bb16, align 4 + call void @__dp_report_bb_pair(i32 %51, i32 22) + br i1 %cmp10, label %for.body11, label %for.end14, !dbg !362 + +for.body11: ; preds = %for.cond9 + call void @__dp_loop_incr(i32 1) + %52 = ptrtoint double** %x to i64 + %53 = load double*, double** %x, align 8, !dbg !363 + %54 = ptrtoint i32* %i8 to i64 + %55 = load i32, i32* %i8, align 4, !dbg !365 + %56 = ptrtoint i32* @_ZZ4mainE1n to i64 + call void @__dp_read(i32 16412, i64 %56, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.11, i32 0, i32 0)) + %57 = load i32, i32* @_ZZ4mainE1n, align 4, !dbg !366 + call void @__dp_call(i32 16412), !dbg !367 + call void @_Z18doall_not_possiblePdii(double* %53, i32 %55, i32 %57), !dbg !367 + call void @__dp_report_bb(i32 15) + %58 = load i32, i32* %__dp_bb16, align 4 + call void @__dp_report_bb_pair(i32 %58, i32 24) + br label %for.inc12, !dbg !368 + +for.inc12: ; preds = %for.body11 + %59 = ptrtoint i32* %i8 to i64 + %60 = load i32, i32* %i8, align 4, !dbg !369 + %inc13 = add nsw i32 %60, 1, !dbg !369 + %61 = ptrtoint i32* %i8 to i64 + store i32 %inc13, i32* %i8, align 4, !dbg !369 + call void @__dp_report_bb(i32 14) + %62 = load i32, i32* %__dp_bb16, align 4 + call void @__dp_report_bb_pair(i32 %62, i32 23) + store i32 1, i32* %__dp_bb16, align 4 + br label %for.cond9, !dbg !370, !llvm.loop !371 + +for.end14: ; preds = %for.cond9 + call void @__dp_loop_exit(i32 16415, i32 2) + %63 = ptrtoint double** %x to i64 + %64 = load double*, double** %x, align 8, !dbg !373 + %65 = bitcast double* %64 to i8*, !dbg !373 + call void @free(i8* %65) #4, !dbg !374 + %66 = ptrtoint i8* %65 to i64 + call void @__dp_delete(i32 16415, i64 %66), !dbg !375 + call void @__dp_report_bb(i32 12) + call void @__dp_finalize(i32 16417), !dbg !375 + call void @__dp_loop_output(), !dbg !375 + call void @__dp_taken_branch_counter_output(), !dbg !375 + ret i32 0, !dbg !375 +} + +; Function Attrs: nounwind +declare noalias i8* @malloc(i64) #3 + +; Function Attrs: nounwind +declare void @free(i8*) #3 + +declare void @__dp_init(i32, i32, i32) + +declare void @__dp_finalize(i32) + +declare void @__dp_read(i32, i64, i8*) + +declare void @__dp_write(i32, i64, i8*) + +declare void @__dp_alloca(i32, i8*, i64, i64, i64, i64) + +declare void @__dp_new(i32, i64, i64, i64) + +declare void @__dp_delete(i32, i64) + +declare void @__dp_call(i32) + +declare void @__dp_func_entry(i32, i32) + +declare void @__dp_func_exit(i32, i32) + +declare void @__dp_loop_entry(i32, i32) + +declare void @__dp_loop_exit(i32, i32) + +declare void @__dp_incr_taken_branch_counter(i8*, i32, i32) + +declare void @__dp_report_bb(i32) + +declare void @__dp_report_bb_pair(i32, i32) + +declare void @__dp_loop_incr(i32) + +declare void @__dp_loop_output() + +declare void @__dp_taken_branch_counter_output() + +attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable willreturn } +attributes #2 = { noinline norecurse nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!11} +!llvm.module.flags = !{!260, !261, !262, !263} +!llvm.ident = !{!264} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 11, type: !6, isLocal: true, isDefinition: true) +!2 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 10, type: !4, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!3 = !DIFile(filename: "code.cpp", directory: "/home/lukas/git/discopop/test/end_to_end/do_all/calls/complex/src") +!4 = !DISubroutineType(types: !5) +!5 = !{!6, !6, !7} +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) +!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64) +!9 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) +!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !12, retainedTypes: !13, globals: !16, imports: !19, splitDebugInlining: false, nameTableKind: None) +!12 = !{} +!13 = !{!14} +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64) +!15 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) +!16 = !{!0, !17} +!17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression()) +!18 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 12, type: !15, isLocal: true, isDefinition: true) +!19 = !{!20, !27, !31, !38, !42, !47, !49, !53, !57, !61, !75, !79, !83, !87, !91, !96, !100, !104, !108, !112, !120, !124, !128, !130, !134, !138, !143, !149, !153, !157, !159, !167, !171, !179, !181, !185, !189, !193, !197, !202, !207, !212, !213, !214, !215, !217, !218, !219, !220, !221, !222, !223, !225, !226, !227, !228, !229, !230, !231, !236, !237, !238, !239, !240, !241, !242, !243, !244, !245, !246, !247, !248, !249, !250, !251, !252, !253, !254, !255, !256, !257, !258, !259} +!20 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !22, file: !26, line: 52) +!21 = !DINamespace(name: "std", scope: null) +!22 = !DISubprogram(name: "abs", scope: !23, file: !23, line: 848, type: !24, flags: DIFlagPrototyped, spFlags: 0) +!23 = !DIFile(filename: "/usr/include/stdlib.h", directory: "") +!24 = !DISubroutineType(types: !25) +!25 = !{!6, !6} +!26 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/std_abs.h", directory: "") +!27 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !28, file: !30, line: 127) +!28 = !DIDerivedType(tag: DW_TAG_typedef, name: "div_t", file: !23, line: 63, baseType: !29) +!29 = !DICompositeType(tag: DW_TAG_structure_type, file: !23, line: 59, flags: DIFlagFwdDecl, identifier: "_ZTS5div_t") +!30 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/cstdlib", directory: "") +!31 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !32, file: !30, line: 128) +!32 = !DIDerivedType(tag: DW_TAG_typedef, name: "ldiv_t", file: !23, line: 71, baseType: !33) +!33 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !23, line: 67, size: 128, flags: DIFlagTypePassByValue, elements: !34, identifier: "_ZTS6ldiv_t") +!34 = !{!35, !37} +!35 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !33, file: !23, line: 69, baseType: !36, size: 64) +!36 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed) +!37 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !33, file: !23, line: 70, baseType: !36, size: 64, offset: 64) +!38 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !39, file: !30, line: 130) +!39 = !DISubprogram(name: "abort", scope: !23, file: !23, line: 598, type: !40, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!40 = !DISubroutineType(types: !41) +!41 = !{null} +!42 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !43, file: !30, line: 134) +!43 = !DISubprogram(name: "atexit", scope: !23, file: !23, line: 602, type: !44, flags: DIFlagPrototyped, spFlags: 0) +!44 = !DISubroutineType(types: !45) +!45 = !{!6, !46} +!46 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !40, size: 64) +!47 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !48, file: !30, line: 137) +!48 = !DISubprogram(name: "at_quick_exit", scope: !23, file: !23, line: 607, type: !44, flags: DIFlagPrototyped, spFlags: 0) +!49 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !50, file: !30, line: 140) +!50 = !DISubprogram(name: "atof", scope: !23, file: !23, line: 102, type: !51, flags: DIFlagPrototyped, spFlags: 0) +!51 = !DISubroutineType(types: !52) +!52 = !{!15, !8} +!53 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !54, file: !30, line: 141) +!54 = !DISubprogram(name: "atoi", scope: !23, file: !23, line: 105, type: !55, flags: DIFlagPrototyped, spFlags: 0) +!55 = !DISubroutineType(types: !56) +!56 = !{!6, !8} +!57 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !58, file: !30, line: 142) +!58 = !DISubprogram(name: "atol", scope: !23, file: !23, line: 108, type: !59, flags: DIFlagPrototyped, spFlags: 0) +!59 = !DISubroutineType(types: !60) +!60 = !{!36, !8} +!61 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !62, file: !30, line: 143) +!62 = !DISubprogram(name: "bsearch", scope: !23, file: !23, line: 828, type: !63, flags: DIFlagPrototyped, spFlags: 0) +!63 = !DISubroutineType(types: !64) +!64 = !{!65, !66, !66, !68, !68, !71} +!65 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!66 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !67, size: 64) +!67 = !DIDerivedType(tag: DW_TAG_const_type, baseType: null) +!68 = !DIDerivedType(tag: DW_TAG_typedef, name: "size_t", file: !69, line: 46, baseType: !70) +!69 = !DIFile(filename: "Software/llvm-11.1.0/lib/clang/11.1.0/include/stddef.h", directory: "/home/lukas") +!70 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!71 = !DIDerivedType(tag: DW_TAG_typedef, name: "__compar_fn_t", file: !23, line: 816, baseType: !72) +!72 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !73, size: 64) +!73 = !DISubroutineType(types: !74) +!74 = !{!6, !66, !66} +!75 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !76, file: !30, line: 144) +!76 = !DISubprogram(name: "calloc", scope: !23, file: !23, line: 543, type: !77, flags: DIFlagPrototyped, spFlags: 0) +!77 = !DISubroutineType(types: !78) +!78 = !{!65, !68, !68} +!79 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !80, file: !30, line: 145) +!80 = !DISubprogram(name: "div", scope: !23, file: !23, line: 860, type: !81, flags: DIFlagPrototyped, spFlags: 0) +!81 = !DISubroutineType(types: !82) +!82 = !{!28, !6, !6} +!83 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !84, file: !30, line: 146) +!84 = !DISubprogram(name: "exit", scope: !23, file: !23, line: 624, type: !85, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!85 = !DISubroutineType(types: !86) +!86 = !{null, !6} +!87 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !88, file: !30, line: 147) +!88 = !DISubprogram(name: "free", scope: !23, file: !23, line: 555, type: !89, flags: DIFlagPrototyped, spFlags: 0) +!89 = !DISubroutineType(types: !90) +!90 = !{null, !65} +!91 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !92, file: !30, line: 148) +!92 = !DISubprogram(name: "getenv", scope: !23, file: !23, line: 641, type: !93, flags: DIFlagPrototyped, spFlags: 0) +!93 = !DISubroutineType(types: !94) +!94 = !{!95, !8} +!95 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) +!96 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !97, file: !30, line: 149) +!97 = !DISubprogram(name: "labs", scope: !23, file: !23, line: 849, type: !98, flags: DIFlagPrototyped, spFlags: 0) +!98 = !DISubroutineType(types: !99) +!99 = !{!36, !36} +!100 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !101, file: !30, line: 150) +!101 = !DISubprogram(name: "ldiv", scope: !23, file: !23, line: 862, type: !102, flags: DIFlagPrototyped, spFlags: 0) +!102 = !DISubroutineType(types: !103) +!103 = !{!32, !36, !36} +!104 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !105, file: !30, line: 151) +!105 = !DISubprogram(name: "malloc", scope: !23, file: !23, line: 540, type: !106, flags: DIFlagPrototyped, spFlags: 0) +!106 = !DISubroutineType(types: !107) +!107 = !{!65, !68} +!108 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !109, file: !30, line: 153) +!109 = !DISubprogram(name: "mblen", scope: !23, file: !23, line: 930, type: !110, flags: DIFlagPrototyped, spFlags: 0) +!110 = !DISubroutineType(types: !111) +!111 = !{!6, !8, !68} +!112 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !113, file: !30, line: 154) +!113 = !DISubprogram(name: "mbstowcs", scope: !23, file: !23, line: 941, type: !114, flags: DIFlagPrototyped, spFlags: 0) +!114 = !DISubroutineType(types: !115) +!115 = !{!68, !116, !119, !68} +!116 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !117) +!117 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !118, size: 64) +!118 = !DIBasicType(name: "wchar_t", size: 32, encoding: DW_ATE_signed) +!119 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !8) +!120 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !121, file: !30, line: 155) +!121 = !DISubprogram(name: "mbtowc", scope: !23, file: !23, line: 933, type: !122, flags: DIFlagPrototyped, spFlags: 0) +!122 = !DISubroutineType(types: !123) +!123 = !{!6, !116, !119, !68} +!124 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !125, file: !30, line: 157) +!125 = !DISubprogram(name: "qsort", scope: !23, file: !23, line: 838, type: !126, flags: DIFlagPrototyped, spFlags: 0) +!126 = !DISubroutineType(types: !127) +!127 = !{null, !65, !68, !68, !71} +!128 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !129, file: !30, line: 160) +!129 = !DISubprogram(name: "quick_exit", scope: !23, file: !23, line: 630, type: !85, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!130 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !131, file: !30, line: 163) +!131 = !DISubprogram(name: "rand", scope: !23, file: !23, line: 454, type: !132, flags: DIFlagPrototyped, spFlags: 0) +!132 = !DISubroutineType(types: !133) +!133 = !{!6} +!134 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !135, file: !30, line: 164) +!135 = !DISubprogram(name: "realloc", scope: !23, file: !23, line: 551, type: !136, flags: DIFlagPrototyped, spFlags: 0) +!136 = !DISubroutineType(types: !137) +!137 = !{!65, !65, !68} +!138 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !139, file: !30, line: 165) +!139 = !DISubprogram(name: "srand", scope: !23, file: !23, line: 456, type: !140, flags: DIFlagPrototyped, spFlags: 0) +!140 = !DISubroutineType(types: !141) +!141 = !{null, !142} +!142 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!143 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !144, file: !30, line: 166) +!144 = !DISubprogram(name: "strtod", scope: !23, file: !23, line: 118, type: !145, flags: DIFlagPrototyped, spFlags: 0) +!145 = !DISubroutineType(types: !146) +!146 = !{!15, !119, !147} +!147 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !148) +!148 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !95, size: 64) +!149 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !150, file: !30, line: 167) +!150 = !DISubprogram(name: "strtol", scope: !23, file: !23, line: 177, type: !151, flags: DIFlagPrototyped, spFlags: 0) +!151 = !DISubroutineType(types: !152) +!152 = !{!36, !119, !147, !6} +!153 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !154, file: !30, line: 168) +!154 = !DISubprogram(name: "strtoul", scope: !23, file: !23, line: 181, type: !155, flags: DIFlagPrototyped, spFlags: 0) +!155 = !DISubroutineType(types: !156) +!156 = !{!70, !119, !147, !6} +!157 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !158, file: !30, line: 169) +!158 = !DISubprogram(name: "system", scope: !23, file: !23, line: 791, type: !55, flags: DIFlagPrototyped, spFlags: 0) +!159 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !160, file: !30, line: 171) +!160 = !DISubprogram(name: "wcstombs", scope: !23, file: !23, line: 945, type: !161, flags: DIFlagPrototyped, spFlags: 0) +!161 = !DISubroutineType(types: !162) +!162 = !{!68, !163, !164, !68} +!163 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !95) +!164 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !165) +!165 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !166, size: 64) +!166 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !118) +!167 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !168, file: !30, line: 172) +!168 = !DISubprogram(name: "wctomb", scope: !23, file: !23, line: 937, type: !169, flags: DIFlagPrototyped, spFlags: 0) +!169 = !DISubroutineType(types: !170) +!170 = !{!6, !95, !118} +!171 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !173, file: !30, line: 200) +!172 = !DINamespace(name: "__gnu_cxx", scope: null) +!173 = !DIDerivedType(tag: DW_TAG_typedef, name: "lldiv_t", file: !23, line: 81, baseType: !174) +!174 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !23, line: 77, size: 128, flags: DIFlagTypePassByValue, elements: !175, identifier: "_ZTS7lldiv_t") +!175 = !{!176, !178} +!176 = !DIDerivedType(tag: DW_TAG_member, name: "quot", scope: !174, file: !23, line: 79, baseType: !177, size: 64) +!177 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) +!178 = !DIDerivedType(tag: DW_TAG_member, name: "rem", scope: !174, file: !23, line: 80, baseType: !177, size: 64, offset: 64) +!179 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !180, file: !30, line: 206) +!180 = !DISubprogram(name: "_Exit", scope: !23, file: !23, line: 636, type: !85, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: 0) +!181 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !182, file: !30, line: 210) +!182 = !DISubprogram(name: "llabs", scope: !23, file: !23, line: 852, type: !183, flags: DIFlagPrototyped, spFlags: 0) +!183 = !DISubroutineType(types: !184) +!184 = !{!177, !177} +!185 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !186, file: !30, line: 216) +!186 = !DISubprogram(name: "lldiv", scope: !23, file: !23, line: 866, type: !187, flags: DIFlagPrototyped, spFlags: 0) +!187 = !DISubroutineType(types: !188) +!188 = !{!173, !177, !177} +!189 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !190, file: !30, line: 227) +!190 = !DISubprogram(name: "atoll", scope: !23, file: !23, line: 113, type: !191, flags: DIFlagPrototyped, spFlags: 0) +!191 = !DISubroutineType(types: !192) +!192 = !{!177, !8} +!193 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !194, file: !30, line: 228) +!194 = !DISubprogram(name: "strtoll", scope: !23, file: !23, line: 201, type: !195, flags: DIFlagPrototyped, spFlags: 0) +!195 = !DISubroutineType(types: !196) +!196 = !{!177, !119, !147, !6} +!197 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !198, file: !30, line: 229) +!198 = !DISubprogram(name: "strtoull", scope: !23, file: !23, line: 206, type: !199, flags: DIFlagPrototyped, spFlags: 0) +!199 = !DISubroutineType(types: !200) +!200 = !{!201, !119, !147, !6} +!201 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!202 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !203, file: !30, line: 231) +!203 = !DISubprogram(name: "strtof", scope: !23, file: !23, line: 124, type: !204, flags: DIFlagPrototyped, spFlags: 0) +!204 = !DISubroutineType(types: !205) +!205 = !{!206, !119, !147} +!206 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!207 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !172, entity: !208, file: !30, line: 232) +!208 = !DISubprogram(name: "strtold", scope: !23, file: !23, line: 127, type: !209, flags: DIFlagPrototyped, spFlags: 0) +!209 = !DISubroutineType(types: !210) +!210 = !{!211, !119, !147} +!211 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float) +!212 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !173, file: !30, line: 240) +!213 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !180, file: !30, line: 242) +!214 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !182, file: !30, line: 244) +!215 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !216, file: !30, line: 245) +!216 = !DISubprogram(name: "div", linkageName: "_ZN9__gnu_cxx3divExx", scope: !172, file: !30, line: 213, type: !187, flags: DIFlagPrototyped, spFlags: 0) +!217 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !186, file: !30, line: 246) +!218 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !190, file: !30, line: 248) +!219 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !203, file: !30, line: 249) +!220 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !194, file: !30, line: 250) +!221 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !198, file: !30, line: 251) +!222 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !21, entity: !208, file: !30, line: 252) +!223 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !39, file: !224, line: 38) +!224 = !DIFile(filename: "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/stdlib.h", directory: "") +!225 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !43, file: !224, line: 39) +!226 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !84, file: !224, line: 40) +!227 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !48, file: !224, line: 43) +!228 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !129, file: !224, line: 46) +!229 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !28, file: !224, line: 51) +!230 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !32, file: !224, line: 52) +!231 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !232, file: !224, line: 54) +!232 = !DISubprogram(name: "abs", linkageName: "_ZSt3absg", scope: !21, file: !26, line: 103, type: !233, flags: DIFlagPrototyped, spFlags: 0) +!233 = !DISubroutineType(types: !234) +!234 = !{!235, !235} +!235 = !DIBasicType(name: "__float128", size: 128, encoding: DW_ATE_float) +!236 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !50, file: !224, line: 55) +!237 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !54, file: !224, line: 56) +!238 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !58, file: !224, line: 57) +!239 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !62, file: !224, line: 58) +!240 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !76, file: !224, line: 59) +!241 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !216, file: !224, line: 60) +!242 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !88, file: !224, line: 61) +!243 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !92, file: !224, line: 62) +!244 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !97, file: !224, line: 63) +!245 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !101, file: !224, line: 64) +!246 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !105, file: !224, line: 65) +!247 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !109, file: !224, line: 67) +!248 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !113, file: !224, line: 68) +!249 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !121, file: !224, line: 69) +!250 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !125, file: !224, line: 71) +!251 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !131, file: !224, line: 72) +!252 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !135, file: !224, line: 73) +!253 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !139, file: !224, line: 74) +!254 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !144, file: !224, line: 75) +!255 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !150, file: !224, line: 76) +!256 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !154, file: !224, line: 77) +!257 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !158, file: !224, line: 78) +!258 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !160, file: !224, line: 80) +!259 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !11, entity: !168, file: !224, line: 81) +!260 = !{i32 7, !"Dwarf Version", i32 4} +!261 = !{i32 2, !"Debug Info Version", i32 3} +!262 = !{i32 1, !"wchar_size", i32 4} +!263 = !{i32 7, !"PIC Level", i32 2} +!264 = !{!"clang version 11.1.0 (https://github.com/llvm/llvm-project.git 7e99bddfeaab2713a8bb6ca538da25b66e6efc59)"} +!265 = distinct !DISubprogram(name: "perform_calculation", linkageName: "_Z19perform_calculationPdii", scope: !3, file: !3, line: 4, type: !266, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!266 = !DISubroutineType(types: !267) +!267 = !{null, !14, !6, !6} +!268 = !DILocalVariable(name: "base", arg: 1, scope: !265, file: !3, line: 4, type: !14) +!269 = !DILocation(line: 4, column: 34, scope: !265) +!270 = !DILocalVariable(name: "offset_1", arg: 2, scope: !265, file: !3, line: 4, type: !6) +!271 = !DILocation(line: 4, column: 44, scope: !265) +!272 = !DILocalVariable(name: "offset_2", arg: 3, scope: !265, file: !3, line: 4, type: !6) +!273 = !DILocation(line: 4, column: 58, scope: !265) +!274 = !DILocation(line: 4, column: 92, scope: !265) +!275 = !DILocation(line: 4, column: 97, scope: !265) +!276 = !DILocation(line: 4, column: 90, scope: !265) +!277 = !DILocation(line: 4, column: 70, scope: !265) +!278 = !DILocation(line: 4, column: 75, scope: !265) +!279 = !DILocation(line: 4, column: 85, scope: !265) +!280 = !DILocation(line: 4, column: 108, scope: !265) +!281 = distinct !DISubprogram(name: "doall_possible", linkageName: "_Z14doall_possiblePdi", scope: !3, file: !3, line: 6, type: !282, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!282 = !DISubroutineType(types: !283) +!283 = !{null, !14, !6} +!284 = !DILocalVariable(name: "base", arg: 1, scope: !281, file: !3, line: 6, type: !14) +!285 = !DILocation(line: 6, column: 29, scope: !281) +!286 = !DILocalVariable(name: "index", arg: 2, scope: !281, file: !3, line: 6, type: !6) +!287 = !DILocation(line: 6, column: 39, scope: !281) +!288 = !DILocation(line: 6, column: 68, scope: !281) +!289 = !DILocation(line: 6, column: 74, scope: !281) +!290 = !DILocation(line: 6, column: 81, scope: !281) +!291 = !DILocation(line: 6, column: 48, scope: !281) +!292 = !DILocation(line: 6, column: 89, scope: !281) +!293 = distinct !DISubprogram(name: "doall_not_possible", linkageName: "_Z18doall_not_possiblePdii", scope: !3, file: !3, line: 8, type: !266, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !12) +!294 = !DILocalVariable(name: "base", arg: 1, scope: !293, file: !3, line: 8, type: !14) +!295 = !DILocation(line: 8, column: 33, scope: !293) +!296 = !DILocalVariable(name: "index", arg: 2, scope: !293, file: !3, line: 8, type: !6) +!297 = !DILocation(line: 8, column: 43, scope: !293) +!298 = !DILocalVariable(name: "n", arg: 3, scope: !293, file: !3, line: 8, type: !6) +!299 = !DILocation(line: 8, column: 54, scope: !293) +!300 = !DILocation(line: 8, column: 79, scope: !293) +!301 = !DILocation(line: 8, column: 85, scope: !293) +!302 = !DILocation(line: 8, column: 93, scope: !293) +!303 = !DILocation(line: 8, column: 107, scope: !293) +!304 = !DILocation(line: 8, column: 105, scope: !293) +!305 = !DILocation(line: 8, column: 99, scope: !293) +!306 = !DILocation(line: 8, column: 59, scope: !293) +!307 = !DILocation(line: 8, column: 112, scope: !293) +!308 = !DILocalVariable(name: "argc", arg: 1, scope: !2, file: !3, line: 10, type: !6) +!309 = !DILocation(line: 10, column: 14, scope: !2) +!310 = !DILocalVariable(name: "argv", arg: 2, scope: !2, file: !3, line: 10, type: !7) +!311 = !DILocation(line: 10, column: 32, scope: !2) +!312 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 13, type: !14) +!313 = !DILocation(line: 13, column: 11, scope: !2) +!314 = !DILocation(line: 13, column: 32, scope: !2) +!315 = !DILocation(line: 13, column: 34, scope: !2) +!316 = !DILocation(line: 13, column: 25, scope: !2) +!317 = !DILocation(line: 13, column: 15, scope: !2) +!318 = !DILocalVariable(name: "i", scope: !319, file: !3, line: 17, type: !6) +!319 = distinct !DILexicalBlock(scope: !2, file: !3, line: 17, column: 3) +!320 = !DILocation(line: 17, column: 12, scope: !319) +!321 = !DILocation(line: 17, column: 8, scope: !319) +!322 = !DILocation(line: 17, column: 19, scope: !323) +!323 = distinct !DILexicalBlock(scope: !319, file: !3, line: 17, column: 3) +!324 = !DILocation(line: 17, column: 23, scope: !323) +!325 = !DILocation(line: 17, column: 21, scope: !323) +!326 = !DILocation(line: 17, column: 3, scope: !319) +!327 = !DILocation(line: 18, column: 5, scope: !328) +!328 = distinct !DILexicalBlock(scope: !323, file: !3, line: 17, column: 31) +!329 = !DILocation(line: 18, column: 7, scope: !328) +!330 = !DILocation(line: 18, column: 10, scope: !328) +!331 = !DILocation(line: 19, column: 3, scope: !328) +!332 = !DILocation(line: 17, column: 26, scope: !323) +!333 = !DILocation(line: 17, column: 3, scope: !323) +!334 = distinct !{!334, !326, !335} +!335 = !DILocation(line: 19, column: 3, scope: !319) +!336 = !DILocalVariable(name: "i", scope: !337, file: !3, line: 22, type: !6) +!337 = distinct !DILexicalBlock(scope: !2, file: !3, line: 22, column: 3) +!338 = !DILocation(line: 22, column: 12, scope: !337) +!339 = !DILocation(line: 22, column: 8, scope: !337) +!340 = !DILocation(line: 22, column: 19, scope: !341) +!341 = distinct !DILexicalBlock(scope: !337, file: !3, line: 22, column: 3) +!342 = !DILocation(line: 22, column: 23, scope: !341) +!343 = !DILocation(line: 22, column: 21, scope: !341) +!344 = !DILocation(line: 22, column: 3, scope: !337) +!345 = !DILocation(line: 23, column: 20, scope: !346) +!346 = distinct !DILexicalBlock(scope: !341, file: !3, line: 22, column: 31) +!347 = !DILocation(line: 23, column: 23, scope: !346) +!348 = !DILocation(line: 23, column: 5, scope: !346) +!349 = !DILocation(line: 24, column: 3, scope: !346) +!350 = !DILocation(line: 22, column: 27, scope: !341) +!351 = !DILocation(line: 22, column: 3, scope: !341) +!352 = distinct !{!352, !344, !353} +!353 = !DILocation(line: 24, column: 3, scope: !337) +!354 = !DILocalVariable(name: "i", scope: !355, file: !3, line: 27, type: !6) +!355 = distinct !DILexicalBlock(scope: !2, file: !3, line: 27, column: 3) +!356 = !DILocation(line: 27, column: 12, scope: !355) +!357 = !DILocation(line: 27, column: 8, scope: !355) +!358 = !DILocation(line: 27, column: 19, scope: !359) +!359 = distinct !DILexicalBlock(scope: !355, file: !3, line: 27, column: 3) +!360 = !DILocation(line: 27, column: 23, scope: !359) +!361 = !DILocation(line: 27, column: 21, scope: !359) +!362 = !DILocation(line: 27, column: 3, scope: !355) +!363 = !DILocation(line: 28, column: 24, scope: !364) +!364 = distinct !DILexicalBlock(scope: !359, file: !3, line: 27, column: 31) +!365 = !DILocation(line: 28, column: 27, scope: !364) +!366 = !DILocation(line: 28, column: 30, scope: !364) +!367 = !DILocation(line: 28, column: 5, scope: !364) +!368 = !DILocation(line: 29, column: 3, scope: !364) +!369 = !DILocation(line: 27, column: 27, scope: !359) +!370 = !DILocation(line: 27, column: 3, scope: !359) +!371 = distinct !{!371, !362, !372} +!372 = !DILocation(line: 29, column: 3, scope: !355) +!373 = !DILocation(line: 31, column: 8, scope: !2) +!374 = !DILocation(line: 31, column: 3, scope: !2) +!375 = !DILocation(line: 33, column: 3, scope: !2)