Skip to content

Commit

Permalink
feat: add distinguished behavior to reduction and doall detector
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasrothenberger committed Aug 12, 2024
1 parent 0d95c2b commit b50c3ab
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 127 deletions.
12 changes: 6 additions & 6 deletions discopop_explorer/classes/PEGraph/Dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ class Dependency:
sink_line: Optional[LineID] = None
intra_iteration: bool = False
intra_iteration_level: int = -1
metadata_intra_iteration_dep: List[LineID]
metadata_inter_iteration_dep: List[LineID]
metadata_intra_call_dep: List[LineID]
metadata_inter_call_dep: List[LineID]
metadata_sink_ancestors: List[LineID]
metadata_source_ancestors: List[LineID]
metadata_intra_iteration_dep: Optional[List[LineID]]
metadata_inter_iteration_dep: Optional[List[LineID]]
metadata_intra_call_dep: Optional[List[LineID]]
metadata_inter_call_dep: Optional[List[LineID]]
metadata_sink_ancestors: Optional[List[LineID]]
metadata_source_ancestors: Optional[List[LineID]]

def __init__(self, type: EdgeType):
self.etype = type
Expand Down
153 changes: 91 additions & 62 deletions discopop_explorer/pattern_detectors/do_all_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ def run_detection(
result: List[DoAllInfo] = []
nodes = all_nodes(pet, LoopNode)

warnings.warn("DOALL DETECTION CURRENTLY ASSUMES THE EXISTENCE OF DEPENDENCY METADATA!")

# remove reduction loops
print("ASDF: ", [r.node_id for r in reduction_info])
print("Nodes: ", [n.start_position() for n in nodes])
Expand Down Expand Up @@ -283,81 +281,112 @@ def __check_loop_dependencies(
if is_loop_index(pet, dep.var_name, loop_start_lines, root_children_cus):
continue

# ignore dependencies where either source or sink do not lie within root_loop
if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0:
if not (
(root_loop.start_position() in dep.metadata_sink_ancestors)
and root_loop.start_position() in dep.metadata_source_ancestors
):
tmp = root_loop.start_position()
continue
# if metadata exists, ignore dependencies where either source or sink do not lie within root_loop
if dep.metadata_source_ancestors is not None and dep.metadata_sink_ancestors is not None:
if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0:
if not (
(root_loop.start_position() in dep.metadata_sink_ancestors)
and root_loop.start_position() in dep.metadata_source_ancestors
):
tmp = root_loop.start_position()
continue

# targeted variable is not read-only
if dep.dtype == DepType.INIT:
continue
elif dep.dtype == DepType.RAW:
# check RAW dependencies
# RAW problematic, if it is not an intra-iteration RAW
cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in (
dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []
)
cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0
cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0
if cond_1 or cond_2 or cond_3:
return True
# if it is an intra iteration dependency, it is problematic if it belongs to a parent loop
else:
if dep.intra_iteration_level <= max_considered_intra_iteration_dep_level:
if pet.node_at(source) in root_children_cus and pet.node_at(target) in root_children_cus:
pass
else:
# check if metadata exists
if dep.metadata_intra_iteration_dep is not None:
for t in dep.metadata_intra_iteration_dep:
if t in parent_loops:
return True
return False
if (
dep.metadata_intra_iteration_dep is None
or dep.metadata_inter_iteration_dep is None
or dep.metadata_intra_call_dep is None
or dep.metadata_inter_call_dep is None
):
# no metadata created
if not dep.intra_iteration:
return True
else:
if dep.intra_iteration_level <= max_considered_intra_iteration_dep_level:
if pet.node_at(source) in root_children_cus and pet.node_at(target) in root_children_cus:
pass
else:
return True
else:
# metadata exists
cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in (
dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []
)
cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0
cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0
if cond_1 or cond_2 or cond_3:
return True
# if it is an intra iteration dependency, it is problematic if it belongs to a parent loop
else:
if dep.intra_iteration_level <= max_considered_intra_iteration_dep_level:
if pet.node_at(source) in root_children_cus and pet.node_at(target) in root_children_cus:
pass
else:
# check if metadata exists
if dep.metadata_intra_iteration_dep is not None:
for t in dep.metadata_intra_iteration_dep:
if t in parent_loops:
return True
return False
else:
return True

elif dep.dtype == DepType.WAR:
# check WAR dependencies
# WAR problematic, if it is not an intra-iteration WAR and the variable is not private or firstprivate
if (
not dep.intra_iteration
and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0)
and parent_function_lineid
in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [])
) or (
(
False
if dep.metadata_inter_call_dep is None
else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0)
)
and (
False
if dep.metadata_inter_iteration_dep is None
else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0)
)
):
if dep.var_name not in [v.name for v in first_privates + privates + last_privates]:
# check if variable is defined inside loop
if dep.memory_region not in memory_regions_defined_in_loop:
return True
# check if the definitions of the accessed variable originates from a function call
if __check_for_problematic_function_argument_access(pet, source, target, dep):
return True
# if it is an intra iteration dependency, it is problematic if it belongs to a parent loop
elif dep.intra_iteration_level > root_loop.get_nesting_level(pet):
tmp_nesting_level = root_loop.get_nesting_level(pet)
# check if metadata exists
if len(dep.metadata_intra_iteration_dep) != 0:
for t in dep.metadata_intra_iteration_dep:
if t in parent_loops:
if dep.metadata_intra_iteration_dep is None:
# no metadata created
if not dep.intra_iteration:
if dep.var_name not in [v.name for v in first_privates + privates + last_privates]:
# check if variable is defined inside loop
if dep.memory_region not in memory_regions_defined_in_loop:
return True
return False
else:
# if it is an intra iteration dependency, it is problematic if it belongs to a parent loop
elif dep.intra_iteration_level > root_loop.get_nesting_level(pet):
return True

else:
# metadata exists
if (
not dep.intra_iteration
and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0)
and parent_function_lineid
in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [])
) or (
(
False
if dep.metadata_inter_call_dep is None
else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0)
)
and (
False
if dep.metadata_inter_iteration_dep is None
else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0)
)
):
if dep.var_name not in [v.name for v in first_privates + privates + last_privates]:
# check if variable is defined inside loop
if dep.memory_region not in memory_regions_defined_in_loop:
return True
# check if the definitions of the accessed variable originates from a function call
if __check_for_problematic_function_argument_access(pet, source, target, dep):
return True
# if it is an intra iteration dependency, it is problematic if it belongs to a parent loop
elif dep.intra_iteration_level > root_loop.get_nesting_level(pet):
tmp_nesting_level = root_loop.get_nesting_level(pet)
# check if metadata exists
if len(dep.metadata_intra_iteration_dep) != 0:
for t in dep.metadata_intra_iteration_dep:
if t in parent_loops:
return True
return False
else:
return True
elif dep.dtype == DepType.WAW:
# check WAW dependencies
# handled by variable classification
Expand Down
100 changes: 58 additions & 42 deletions discopop_explorer/pattern_detectors/reduction_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ def run_detection(

nodes = cast(List[LoopNode], filter_for_hotspots(pet, cast(List[Node], nodes), hotspots))

warnings.warn("REDUCTION DETECTION CURRENTLY ASSUMES THE EXISTENCE OF DEPENDENCY METADATA!")

param_list = [(node) for node in nodes]
with Pool(initializer=__initialize_worker, initargs=(pet,)) as pool:
tmp_result = list(tqdm.tqdm(pool.imap_unordered(__check_node, param_list), total=len(param_list)))
Expand Down Expand Up @@ -243,14 +241,15 @@ def __check_loop_dependencies(
if is_loop_index(pet, dep.var_name, loop_start_lines, root_children_cus):
continue

# ignore dependencies where either source or sink do not lie within root_loop
if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0:
if not (
(root_loop.start_position() in dep.metadata_sink_ancestors)
and root_loop.start_position() in dep.metadata_source_ancestors
):
tmp = root_loop.start_position()
continue
# if metadata exists, ignore dependencies where either source or sink do not lie within root_loop
if dep.metadata_source_ancestors is not None and dep.metadata_sink_ancestors is not None:
if len(dep.metadata_source_ancestors) > 0 and len(dep.metadata_sink_ancestors) > 0:
if not (
(root_loop.start_position() in dep.metadata_sink_ancestors)
and root_loop.start_position() in dep.metadata_source_ancestors
):
tmp = root_loop.start_position()
continue

# targeted variable is not read-only
if dep.dtype == DepType.INIT:
Expand All @@ -269,42 +268,59 @@ def __check_loop_dependencies(
else:
# RAW does not target a reduction variable.
# RAW problematic, if it is not an intra-iteration RAW.
cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in (
dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []
)
cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0
cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0
if cond_1 or cond_2 or cond_3:
return True
# check for
if (
dep.metadata_intra_iteration_dep is None
or dep.metadata_inter_iteration_dep is None
or dep.metadata_intra_call_dep is None
or dep.metadata_inter_call_dep is None
):
# no metadata generated
if not dep.intra_iteration:
return True
else:
# metadata exist
cond_1 = (len(dep.metadata_intra_iteration_dep) == 0) and parent_function_lineid in (
dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else []
)
cond_2 = len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0
cond_3 = len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0
if cond_1 or cond_2 or cond_3:
return True
elif dep.dtype == DepType.WAR:
# check WAR dependencies
# WAR problematic, if it is not an intra-iteration WAR and the variable is not private or firstprivate
if (
not dep.intra_iteration
and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0)
and parent_function_lineid
in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [])
) or (
(
False
if dep.metadata_inter_call_dep is None
else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0)
)
and (
False
if dep.metadata_inter_iteration_dep is None
else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0)
)
):
if dep.var_name not in [v.name for v in first_privates + privates + last_privates]:
# check if variable is defined inside loop
if dep.memory_region not in memory_regions_defined_in_loop:
return True
# check if the definitions of the accessed variable originates from a function call
if __check_for_problematic_function_argument_access(pet, source, target, dep):
pass
if dep.metadata_intra_iteration_dep is None:
# no metadata generated
if not dep.intra_iteration:
if dep.var_name not in [v.name for v in first_privates + privates + last_privates]:
return True
else:
# metadata exists
if (
not dep.intra_iteration
and (dep.metadata_intra_iteration_dep is None or len(dep.metadata_intra_iteration_dep) == 0)
and parent_function_lineid
in (dep.metadata_intra_call_dep if dep.metadata_intra_call_dep is not None else [])
) or (
(
False
if dep.metadata_inter_call_dep is None
else (len([cf for cf in called_functions_lineids if cf in dep.metadata_inter_call_dep]) > 0)
)
and (
False
if dep.metadata_inter_iteration_dep is None
else (len([t for t in parent_loops if t in dep.metadata_inter_iteration_dep]) > 0)
)
):
if dep.var_name not in [v.name for v in first_privates + privates + last_privates]:
# check if variable is defined inside loop
if dep.memory_region not in memory_regions_defined_in_loop:
return True
# check if the definitions of the accessed variable originates from a function call
if __check_for_problematic_function_argument_access(pet, source, target, dep):
pass
return True
elif dep.dtype == DepType.WAW:
# check WAW dependencies
# handled by variable classification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

from __future__ import annotations

from typing import Union
from typing import List, Union, cast

from lxml.objectify import ObjectifiedElement # type: ignore

from discopop_explorer.aliases.LineID import LineID
from discopop_explorer.classes.PEGraph.CUNode import CUNode

from discopop_explorer.classes.PEGraph.Dependency import Dependency
Expand Down Expand Up @@ -41,7 +42,16 @@ def parse_dependency(dep: DependenceItem) -> Dependency:
d.dtype = DepType[dep.type]
d.var_name = dep.var_name
d.memory_region = dep.memory_region

# parse metadata
if dep.metadata is None:
d.metadata_intra_iteration_dep = None
d.metadata_inter_iteration_dep = None
d.metadata_intra_call_dep = None
d.metadata_inter_call_dep = None
d.metadata_sink_ancestors = None
d.metadata_source_ancestors = None
return d
if len(dep.metadata) > 0:
for md in dep.metadata.split(" "):
if len(md) == 0:
Expand All @@ -50,6 +60,18 @@ def parse_dependency(dep: DependenceItem) -> Dependency:
md_type = md[: md.index("[")]
md_raw_values = md[md.index("[") + 1 : -1]
md_values = [tmp for tmp in md_raw_values.split(",") if len(tmp) > 0]

# ensure validity and type correctness
if (
d.metadata_intra_iteration_dep is None
or d.metadata_inter_iteration_dep is None
or d.metadata_intra_call_dep is None
or d.metadata_inter_call_dep is None
or d.metadata_sink_ancestors is None
or d.metadata_source_ancestors is None
):
raise ValueError("Invalid data found!")

# store metadata
if md_type == "IAI":
d.metadata_intra_iteration_dep += md_values
Expand Down
Loading

0 comments on commit b50c3ab

Please sign in to comment.