Skip to content

Commit

Permalink
Merge branch 'release/3.2.0' into optimizer/graph_pruning
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasrothenberger authored Jan 24, 2024
2 parents c13792b + 6d10555 commit cbeccd4
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 63 deletions.
16 changes: 6 additions & 10 deletions discopop_library/ConfigProvider/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,14 @@
def parse_args() -> ConfigProviderArguments:
"""Parse the arguments passed to the discopop_config_provider"""
parser = ArgumentParser(description="DiscoPoP Config Provider")
# all flags that are not considered stable should be added to the experimental_parser
experimental_parser = parser.add_argument_group(
"EXPERIMENTAL",
"Arguments for experimental features. Experimental arguments may or may not be removed or changed in the future.",
)

# fmt: off
parser.add_argument("-b", "--dp-build-dir", action="store_true",
mutually_exclusive = parser.add_mutually_exclusive_group()
mutually_exclusive.add_argument("-b", "--dp-build-dir", action="store_true",
help="Return the path to the DiscoPoP build directory")
parser.add_argument("-s", "--dp-source-dir", action="store_true",
mutually_exclusive.add_argument("-s", "--dp-source-dir", action="store_true",
help="Return the path to the DiscoPoP source directory")
parser.add_argument("--llvm-bin-dir", action="store_true",
mutually_exclusive.add_argument("--llvm-bin-dir", action="store_true",
help="Return the path to the LLVM bin directory")
# EXPERIMENTAL FLAGS:
# fmt: on
Expand All @@ -39,10 +35,10 @@ def parse_args() -> ConfigProviderArguments:
)


def main() -> str:
def main() -> None:
arguments = parse_args()
retval = run(arguments)
return retval
print(retval)


if __name__ == "__main__":
Expand Down
7 changes: 3 additions & 4 deletions discopop_library/ConfigProvider/config_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
# the 3-Clause BSD License. See the LICENSE file in the package base
# directory for details.

from typing import cast
from discopop_library.ConfigProvider.ConfigProviderArguments import ConfigProviderArguments
from discopop_library.ConfigProvider.assets.build_config import DP_BUILD, DP_SOURCE, LLVM_BIN_DIR # type: ignore

Expand All @@ -15,10 +14,10 @@ def run(arguments: ConfigProviderArguments) -> str:
"""Returns the contents of the written build_config.txt"""

if arguments.return_dp_build_dir:
return cast(str, DP_BUILD) # type: ignore
return DP_BUILD # type: ignore
elif arguments.return_dp_source_dir:
return cast(str, DP_SOURCE) # type: ignore
return DP_SOURCE # type: ignore
elif arguments.return_llvm_bin_dir:
return cast(str, LLVM_BIN_DIR) # type: ignore
return LLVM_BIN_DIR # type: ignore
else:
raise ValueError("No valid operation for execution configuration: \n" + str(arguments))
2 changes: 2 additions & 0 deletions discopop_library/HostpotLoader/hostpot_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def run(arguments: HotspotLoaderArguments) -> Dict[HotspotType, List[Tuple[FILEI

if not os.path.exists(os.path.join(os.getcwd(), "hotspot_detection")):
return result_dict
if not os.path.exists(os.path.join(os.getcwd(), "hotspot_detection", "Hotspots.json")):
return result_dict
with open(os.path.join(os.getcwd(), "hotspot_detection", "Hotspots.json"), "r") as f:
hotspots = json.load(f)

Expand Down
16 changes: 7 additions & 9 deletions discopop_library/discopop_optimizer/OptimizerArguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,18 @@ class OptimizerArguments(object):

verbose: bool
interactive: bool
exhaustive: bool
evolutionary: Optional[List[str]]
doall_microbench_file: str
reduction_microbench_file: str
allow_nested_parallelism: bool
plot: bool
system_configuration_path: str
check_called_function_for_nested_parallelism: bool
profiling: bool
greedy: bool
optimization: bool
pruning_level: int
optimization_level: int
optimization_level_2_parameters: str

def __post_init__(self):
# fix correct optimization method
if not self.exhaustive:
if self.evolutionary == None:
self.greedy = True

self.__validate()

def __validate(self):
Expand All @@ -49,4 +42,9 @@ def __validate(self):
# check pruning level values
if self.pruning_level not in [0, 1, 2]:
raise ValueError("Unsupported pruning level: ", self.pruning_level)

# check optimization level
if self.optimization_level not in [0, 1, 2, 3]:
raise ValueError("Unknown optimization level requested: ", self.optimization_level)

pass
20 changes: 7 additions & 13 deletions discopop_library/discopop_optimizer/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,12 @@ def parse_args() -> OptimizerArguments:
# fmt: off
parser.add_argument("-v", "--verbose", action="store_true",
help="Enable verbose output.")
parser.add_argument("-x", "--exhaustive", action="store_true",
help="Enable exhaustive search. By default, a greedy search is performed.")
parser.add_argument("-e", "--evolutionary", type=str, default=None, nargs=2, metavar=("population_size", "generations"),
help="Enable evolutionary search. By default, a greedy search is performed.")
parser.add_argument("-g", "--greedy", action="store_true",
help="Enable greedy search. (Default)")
parser.add_argument("-o", "--optimize", action="store_true",
help="Enable optimization.")
parser.add_argument("-p", "--pruning-level", type=int, default=0,
help="Program path pruning aggressiveness. 0: no pruning. 1: prune to most likely path. 2: prune to paths that cover 80%% of observed decisions per path split.")
parser.add_argument("-o", type=int, default=0, help="Optimization level: 0 -> no optimization. 1 -> greedy. 2 -> evolutionary. 3 -> exhaustive")

parser.add_argument("-opt-2-params", type=str, default=None, nargs=2, metavar=("population_size", "generations"), help="Configure parameters of the evolutionary optimization (-o2). Default: 50 5")

parser.add_argument(
"--doall-microbench-file", type=str, default="None",
help="Do-All microbenchmark results"
Expand Down Expand Up @@ -65,18 +61,16 @@ def parse_args() -> OptimizerArguments:
return OptimizerArguments(
verbose=arguments.verbose,
interactive=arguments.interactive,
exhaustive=arguments.exhaustive,
evolutionary=arguments.evolutionary,
doall_microbench_file=arguments.doall_microbench_file,
reduction_microbench_file=arguments.reduction_microbench_file,
allow_nested_parallelism=arguments.allow_nested_parallelism,
plot=arguments.plot,
system_configuration_path=arguments.system_configuration,
check_called_function_for_nested_parallelism=arguments.check_called_function_for_nested_parallelism,
profiling=arguments.profiling,
greedy=arguments.greedy,
optimization=arguments.optimize,
profiling=arguments.profiling,
pruning_level=arguments.pruning_level,
optimization_level=arguments.o,
optimization_level_2_parameters=arguments.opt_2_params,
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ def perform_evolutionary_search(
arguments: OptimizerArguments,
optimizer_dir: str,
) -> Optional[OptimizerOutputPattern]:
if arguments.evolutionary is None:
raise ValueError("Invalid arguments for evolutionary search: " + str(arguments.evolutionary))
if arguments.optimization_level_2_parameters is None:
arguments.optimization_level_2_parameters = ["50", "5"]
### SETTINGS
population_size = int(arguments.evolutionary[0])
generations = int(arguments.evolutionary[1])
population_size = int(arguments.optimization_level_2_parameters[0])
generations = int(arguments.optimization_level_2_parameters[1])
selection_strength = 0.85 # 0.8 --> 80% of the population will be selected for the next generation
crossovers = int(population_size / 10)
mutations = int(population_size / 10)
Expand Down
42 changes: 22 additions & 20 deletions discopop_library/discopop_optimizer/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,41 +199,43 @@ def run(arguments: OptimizerArguments):
if node_id != node_data.node_id:
node_data.node_id = node_id

if arguments.optimization:
# get values for free symbols
initialize_free_symbol_ranges_and_distributions(experiment, arguments, system)
# get values for free symbols
initialize_free_symbol_ranges_and_distributions(experiment, arguments, system)

if arguments.verbose:
print("# SUBSTITUTIONS:")
for key in experiment.substitutions:
print("#", key, " ->", experiment.substitutions[key])
print()
if arguments.verbose:
print("# SUBSTITUTIONS:")
for key in experiment.substitutions:
print("#", key, " ->", experiment.substitutions[key])
print()

# apply optimization steps if requested
best_configuration = None
if arguments.optimization_level != 0:
# calculate options for easy access
available_decisions = get_available_decisions_for_functions(experiment.optimization_graph, arguments)

# calculate costs for all combinations of decisions
if arguments.exhaustive:
best_configuration = evaluate_all_decision_combinations(
experiment, available_decisions, arguments, optimizer_dir
)
elif arguments.greedy:
if arguments.optimization_level == 1:
best_configuration = greedy_search(experiment, available_decisions, arguments, optimizer_dir)
elif arguments.evolutionary != None:
elif arguments.optimization_level == 2:
# perform evolutionary search
best_configuration = perform_evolutionary_search(
experiment,
available_decisions,
arguments,
optimizer_dir,
)
# calculate costs for all combinations of decisions
elif arguments.optimization_level == 3:
best_configuration = evaluate_all_decision_combinations(
experiment, available_decisions, arguments, optimizer_dir
)
else:
raise ValueError("No optimization method specified!")
raise ValueError("No valid optimization method specified: " + str(arguments.optimization_level))

if best_configuration is not None:
best_configuration = optimize_updates(experiment, best_configuration, arguments)
# append the configuration to the list of patterns
experiment.detection_result.patterns.optimizer_output.append(best_configuration)
if best_configuration is not None:
best_configuration = optimize_updates(experiment, best_configuration, arguments)
# append the configuration to the list of patterns
experiment.detection_result.patterns.optimizer_output.append(best_configuration)

if arguments.profiling:
experiment.profile.disable() # type: ignore
Expand Down
2 changes: 1 addition & 1 deletion discopop_library/global_data/version/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.1
3.2.0
17 changes: 17 additions & 0 deletions scripts/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,20 @@ configure_file(CMAKE_wrapper.sh CMAKE_wrapper.sh COPYONLY)
configure_file(MPI_CC_wrapper.sh MPI_CC_wrapper.sh COPYONLY)
configure_file(MPI_CXX_wrapper.sh MPI_CXX_wrapper.sh COPYONLY)
configure_file(MPI_LINKER_wrapper.sh MPI_LINKER_wrapper.sh COPYONLY)

# create symlinks to files
set(DP_LOCAL_BIN_DIR "$ENV{HOME}/.local/bin")
if(EXISTS ${DP_LOCAL_BIN_DIR})
message(STATUS "Creating symlink ${DP_LOCAL_BIN_DIR}/discopop_cc to ${CMAKE_CURRENT_BINARY_DIR}/CC_wrapper.sh")
execute_process(COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/CC_wrapper.sh ${DP_LOCAL_BIN_DIR}/discopop_cc)

message(STATUS "Creating symlink ${DP_LOCAL_BIN_DIR}/discopop_cxx to ${CMAKE_CURRENT_BINARY_DIR}/CXX_wrapper.sh")
execute_process(COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/CXX_wrapper.sh ${DP_LOCAL_BIN_DIR}/discopop_cxx)

message(STATUS "Creating symlink ${DP_LOCAL_BIN_DIR}/discopop_cmake to ${CMAKE_CURRENT_BINARY_DIR}/CMAKE_wrapper.sh")
execute_process(COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/CMAKE_wrapper.sh ${DP_LOCAL_BIN_DIR}/discopop_cmake)
else()
message(WARNING "Creation of symlinks discopop_cc to ${CMAKE_CURRENT_BINARY_DIR}/CC_wrapper.sh not possible. Please create it manually.")
message(WARNING "Creation of symlinks discopop_cxx to ${CMAKE_CURRENT_BINARY_DIR}/CXX_wrapper.sh not possible. Please create it manually.")
message(WARNING "Creation of symlinks discopop_cmake to ${CMAKE_CURRENT_BINARY_DIR}/CMAKE_wrapper.sh not possible. Please create it manually.")
endif()
2 changes: 1 addition & 1 deletion test/optimizer/loop_collapse/negative/simple_1/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test(self):
# execute DiscoPoP analysis
os.chdir(".discopop")
os.system("discopop_explorer")
os.system("discopop_optimizer -x")
os.system("discopop_optimizer -o3")
os.chdir("..")
# validate results
self.validate_results(current_dir, src_dir)
Expand Down
2 changes: 1 addition & 1 deletion test/optimizer/loop_collapse/positive/simple_1/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test(self):
# execute DiscoPoP analysis
os.chdir(".discopop")
os.system("discopop_explorer")
os.system("discopop_optimizer -x")
os.system("discopop_optimizer -o3")
os.chdir("..")
# validate results
self.validate_results(current_dir, src_dir)
Expand Down

0 comments on commit cbeccd4

Please sign in to comment.