Skip to content

Commit

Permalink
feat[optimizer-gui]: selected paths have transitive effects on cost m…
Browse files Browse the repository at this point in the history
…odels
  • Loading branch information
lukasrothenberger committed Sep 15, 2023
1 parent 7542ff4 commit 80b518a
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 4 deletions.
4 changes: 4 additions & 0 deletions discopop_library/discopop_optimizer/CostModels/CostModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class CostModel(object):
identifier: str
parallelizable_costs: Expr
sequential_costs: Expr
raw_parallelizable_costs: Optional[Expr]
raw_sequential_costs: Optional[Expr]
free_symbol_ranges: Dict[Symbol, Tuple[float, float]]
free_symbol_distributions: Dict[Symbol, FreeSymbolDistribution]
symbol_value_suggestions: Dict[Symbol, Expr]
Expand Down Expand Up @@ -51,6 +53,8 @@ def __init__(
self.identifier = identifier
self.parallelizable_costs = parallelizable_costs
self.sequential_costs = sequential_costs
self.raw_parallelizable_costs = None
self.raw_sequential_costs = None

def __str__(self):
return str(self.parallelizable_costs) + "\n" + str(self.sequential_costs)
Expand Down
30 changes: 29 additions & 1 deletion discopop_library/discopop_optimizer/OptimizationGraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ def __init__(
FreeSymbolDistribution, symbol_distribution
)

# save raw cost models for sequential functions
for function in sequential_complete_performance_models:
for model, ctx in sequential_complete_performance_models[function]:
if model.raw_sequential_costs is None:
model.raw_sequential_costs = model.sequential_costs
if model.raw_parallelizable_costs is None:
model.raw_parallelizable_costs = model.parallelizable_costs

# by default, select the sequential version of each function for substitution
for function in sequential_complete_performance_models:
experiment.selected_paths_per_function[
Expand All @@ -163,7 +171,12 @@ def __init__(
print("SUBSTITUTION LOOP")
modification_found = False
for idx, function in enumerate(sequential_complete_performance_models):
for midx, model in enumerate(sequential_complete_performance_models[function]):
for model, ctx in sequential_complete_performance_models[function]:
# save raw cost models
if model.raw_sequential_costs is None:
model.raw_sequential_costs = model.sequential_costs
if model.raw_parallelizable_costs is None:
model.raw_parallelizable_costs = model.parallelizable_costs
# apply substitution to parallelizable costs
tmp_model = model.parallelizable_costs.subs(substitutions)
if tmp_model != model.parallelizable_costs:
Expand Down Expand Up @@ -192,6 +205,11 @@ def __init__(
for idx, function in enumerate(sequential_complete_performance_models):
for midx, pair in enumerate(sequential_complete_performance_models[function]):
model, context = pair
# save raw cost models
if model.raw_sequential_costs is None:
model.raw_sequential_costs = model.sequential_costs
if model.raw_parallelizable_costs is None:
model.raw_parallelizable_costs = model.parallelizable_costs
# apply substitution to parallelizable costs
tmp_model = model.parallelizable_costs.subs(substitutions)
if tmp_model != model.parallelizable_costs:
Expand Down Expand Up @@ -242,6 +260,11 @@ def __init__(
for idx, function in enumerate(locally_optimized_models):
for midx, pair in enumerate(locally_optimized_models[function]):
model, context = pair
# save raw cost models
if model.raw_sequential_costs is None:
model.raw_sequential_costs = model.sequential_costs
if model.raw_parallelizable_costs is None:
model.raw_parallelizable_costs = model.parallelizable_costs
# apply substitution to parallelizable costs
tmp_model = model.parallelizable_costs.subs(substitutions)
if tmp_model != model.parallelizable_costs:
Expand All @@ -267,6 +290,11 @@ def __init__(
for idx, function in enumerate(exhaustive_performance_models):
for midx, pair in enumerate(exhaustive_performance_models[function]):
model, context = pair
# save raw cost models
if model.raw_sequential_costs is None:
model.raw_sequential_costs = model.sequential_costs
if model.raw_parallelizable_costs is None:
model.raw_parallelizable_costs = model.parallelizable_costs
# apply substitution to parallelizable costs
tmp_model = model.parallelizable_costs.subs(substitutions)
if tmp_model != model.parallelizable_costs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,11 @@ def get_cost_model(self, experiment, all_function_nodes) -> CostModel:
cm.parallelizable_costs = cm.parallelizable_costs.subs({Expr(Integer(0)): Integer(0)})
cm.sequential_costs = cm.sequential_costs.subs({Expr(Integer(0)): Integer(0)})

if cm.raw_parallelizable_costs is not None:
cm.raw_parallelizable_costs = cm.raw_parallelizable_costs.subs(
{Expr(Integer(0)): Integer(0)}
)
if cm.raw_sequential_costs is not None:
cm.raw_sequential_costs = cm.raw_sequential_costs.subs({Expr(Integer(0)): Integer(0)})

return cm
7 changes: 7 additions & 0 deletions discopop_library/discopop_optimizer/classes/nodes/Loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ def get_cost_model(self, experiment, all_function_nodes) -> CostModel:
cm.parallelizable_costs = cm.parallelizable_costs.subs({Expr(Integer(0)): Integer(0)})
cm.sequential_costs = cm.sequential_costs.subs({Expr(Integer(0)): Integer(0)})

if cm.raw_sequential_costs is not None:
cm.raw_sequential_costs = cm.raw_sequential_costs.subs({Expr(Integer(0)): Integer(0)})
if cm.raw_parallelizable_costs is not None:
cm.raw_parallelizable_costs = cm.raw_parallelizable_costs.subs(
{Expr(Integer(0)): Integer(0)}
)

return cm

def register_child(self, other, experiment, all_function_nodes):
Expand Down
7 changes: 7 additions & 0 deletions discopop_library/discopop_optimizer/classes/nodes/Workload.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ def get_cost_model(self, experiment, all_function_nodes) -> CostModel:
cm.parallelizable_costs = cm.parallelizable_costs.subs({Expr(Integer(0)): Integer(0)})
cm.sequential_costs = cm.sequential_costs.subs({Expr(Integer(0)): Integer(0)})

if cm.raw_sequential_costs is not None:
cm.raw_sequential_costs = cm.raw_sequential_costs.subs({Expr(Integer(0)): Integer(0)})
if cm.raw_parallelizable_costs is not None:
cm.raw_parallelizable_costs = cm.raw_parallelizable_costs.subs(
{Expr(Integer(0)): Integer(0)}
)

print("CM: ")
print(cm)

Expand Down
93 changes: 91 additions & 2 deletions discopop_library/discopop_optimizer/gui/plotting/CostModels.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@
# 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 List, Dict, Tuple, Optional
import copy
from typing import List, Dict, Tuple, Optional, cast

import numpy as np
from matplotlib import pyplot as plt # type: ignore
import matplotlib
from spb import plot3d, MB, plot # type: ignore
from sympy import Symbol
from sympy import Symbol, Expr
import sympy

from discopop_library.discopop_optimizer.CostModels.CostModel import CostModel
from discopop_library.discopop_optimizer.Variables.Experiment import Experiment


def plot_CostModels(
Expand Down Expand Up @@ -54,6 +56,93 @@ def plot_CostModels(
print("Plotiting not supported for", len(sorted_free_symbols), "free symbols!")


def plot_CostModels_using_function_path_selections(
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,
):
print("PLOTTING: ")
for m in models:
print(m.raw_sequential_costs)
print(m.raw_parallelizable_costs)
print()

# apply selected substitutions
# collect substitutions
local_substitutions = copy.deepcopy(experiment.substitutions)
for function in experiment.selected_paths_per_function:
# register substitution
local_substitutions[
cast(Symbol, function.sequential_costs)
] = experiment.selected_paths_per_function[function][0].sequential_costs
local_substitutions[
cast(Symbol, function.parallelizable_costs)
] = experiment.selected_paths_per_function[function][0].parallelizable_costs

print("LOCAL FUNCTION SUBSTITUTIONS", local_substitutions)

# prepare models by loading raw costs
for model in models:
model.sequential_costs = cast(Expr, model.raw_sequential_costs)
model.parallelizable_costs = cast(Expr, model.raw_parallelizable_costs)

# perform iterative substitutions
modification_found = True
while modification_found:
print("LOCAL SUBSTITUTION LOOP")
modification_found = False
for model in models:
# apply substitution to parallelizable costs
tmp_model = model.parallelizable_costs.subs(local_substitutions)
if tmp_model != model.parallelizable_costs:
modification_found = True
model.parallelizable_costs = tmp_model

# apply substitutions to sequential costs
tmp_model = model.sequential_costs.subs(local_substitutions)
if tmp_model != model.sequential_costs:
modification_found = True
model.sequential_costs = model.sequential_costs.subs(local_substitutions)

print("PLOTTING AFTER SUBSTITUTION: ")
for m in models:
print(m.sequential_costs)
print(m.parallelizable_costs)
print()

if len(sorted_free_symbols) == 2:
__3d_plot(
models,
sorted_free_symbols,
free_symbol_ranges,
labels=labels,
title=str(title) + str(super_title) if super_title is not None else title,
)
elif len(sorted_free_symbols) == 1:
__2d_plot(
models,
sorted_free_symbols,
free_symbol_ranges,
labels=labels,
title=str(title) + str(super_title) if super_title is not None else title,
)
elif len(sorted_free_symbols) == 0:
__1d_plot(
models,
sorted_free_symbols,
free_symbol_ranges,
labels=labels,
title=title,
super_title=super_title,
)
else:
print("Plotiting not supported for", len(sorted_free_symbols), "free symbols!")


__unique_plot_id = 0


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
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.nodes.FunctionRoot import FunctionRoot
from discopop_library.discopop_optimizer.gui.plotting.CostModels import plot_CostModels
from discopop_library.discopop_optimizer.gui.plotting.CostModels import (
plot_CostModels,
plot_CostModels_using_function_path_selections,
)
from discopop_library.discopop_optimizer.gui.presentation.ChoiceDetails import (
display_choices_for_model,
)
Expand Down Expand Up @@ -74,6 +77,21 @@ def show_options(
label2.insert(END, str(experiment.selected_paths_per_function[function_root][0].path_decisions))
label2.configure(state=DISABLED, disabledforeground="black")

plot_button = Button(
root,
text="Plot using selections",
command=lambda: plot_CostModels_using_function_path_selections( # type: ignore
experiment,
[experiment.selected_paths_per_function[function_root][0]], # type: ignore
sorted_free_symbols,
free_symbol_ranges,
[function_root.name],
title=function_root.name,
super_title=function_root.name,
),
)
plot_button.grid(row=1, column=2, sticky=NSEW)

Button(
root,
text="Plot All",
Expand Down Expand Up @@ -165,6 +183,9 @@ def show_options(
export_code_button.grid(row=0, column=2)

def __update_selection(cm, ctx):
# use raw models for selection updates
cm.parallelizable_costs = cm.raw_parallelizable_costs
cm.sequential_costs = cm.raw_sequential_costs
experiment.selected_paths_per_function[function_root] = (cm, ctx)
# update displayed value
label2.configure(state=NORMAL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ def find_quasi_optimal_using_random_samples(
print("\tApplying substitutions...")
print("\t" + str(substitutions))
for model, context in random_paths:
# save raw cost models
if model.raw_sequential_costs is None:
model.raw_sequential_costs = model.sequential_costs
if model.raw_parallelizable_costs is None:
model.raw_parallelizable_costs = model.parallelizable_costs
# apply substitutions iteratively
modification_found = True
while modification_found:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ def get_locally_optimized_models(
modification_found = False
for decision, pair in decision_models:
model, context = pair
# save raw cost models
if model.raw_sequential_costs is None:
model.raw_sequential_costs = model.sequential_costs
if model.raw_parallelizable_costs is None:
model.raw_parallelizable_costs = model.parallelizable_costs

# apply substitutions to parallelizable costs
tmp_model = model.parallelizable_costs.subs(substitutions)
if tmp_model != model.parallelizable_costs:
Expand Down

0 comments on commit 80b518a

Please sign in to comment.