Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add distinguished behavior to reduction and doall detector #651

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading