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 execution time threshold handling. #133

Merged
merged 4 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
5 changes: 4 additions & 1 deletion spot/Spot.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ def __init__(self, config_dir: str, aws_session):
self.ctx, aws_session, self.config.function_name
)
self.recommendation_engine = RecommendationEngine(
function_invoker, self.payload_file_path, self.config.mem_bounds
function_invoker,
self.payload_file_path,
self.config.mem_bounds,
self.config.execution_time_threshold,
)
self.benchmark_name = os.path.basename(config_dir)

Expand Down
3 changes: 3 additions & 0 deletions spot/benchmark_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def __init__(self, f=None):
self.mem_size: int
self.mem_bounds: list
self.nickname: str
self.execution_time_threshold: float

if f is not None:
self.deserialize(f)
Expand All @@ -29,6 +30,7 @@ def _set_properties(
region: str,
random_seed: int,
nickname: str,
execution_time_threshold: float = None,
mem_bounds: Optional[list] = None,
):
self.function_name = function_name
Expand All @@ -37,6 +39,7 @@ def _set_properties(
self.mem_bounds = DEFAULT_MEM_BOUNDS if mem_bounds is None else mem_bounds
self.random_seed = random_seed
self.nickname = nickname
self.execution_time_threshold = execution_time_threshold

def deserialize(self, f):
try:
Expand Down
2 changes: 2 additions & 0 deletions spot/exceptions/NoMemoryLeft.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class NoMemoryLeft(Exception):
pass
2 changes: 1 addition & 1 deletion spot/invocation/aws_lambda_invoker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import sys
import time

import botocore
import botocore.exceptions
import re
import pandas as pd
from concurrent.futures import ThreadPoolExecutor
Expand Down
2 changes: 1 addition & 1 deletion spot/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def main():
help="Return best memory configuration for lowest cost",
)
parser.add_argument(
"--force", "-f", action="store_true", help="Ignore the invokation cache"
"--force", "-f", action="store_true", help="Ignore the invocation cache"
)
parser.add_argument(
"--invoke", "-i", type=int, help="The number of times you invoke the function"
Expand Down
41 changes: 31 additions & 10 deletions spot/recommendation_engine/recommendation_engine.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import sys

import numpy as np
import pandas as pd

from spot.exceptions import NoMemoryLeft
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be

from spot.exceptions.NoMemoryLeft import NoMemoryLeft

I get this error when running the code:
Screenshot 2023-06-02 at 8 47 57 AM

from spot.recommendation_engine.objectives import *
from spot.recommendation_engine.utility import Utility
from spot.constants import *
Expand All @@ -14,13 +17,20 @@ def __init__(self, memory, billed_time):


class RecommendationEngine:
def __init__(self, invocator, payload_path, memory_range):
def __init__(
self,
invocator,
payload_path,
memory_range,
execution_time_threshold: float = None,
):
self.payload_path = payload_path
self.function_invocator = invocator
self.sampled_datapoints = []
self.fitted_function = None
self.function_parameters = {}
self.memory_range = memory_range
self.execution_time_threshold = execution_time_threshold
if OPTIMIZATION_OBJECTIVE == "normal":
self.objective = NormalObjective(self, self.memory_range)
elif OPTIMIZATION_OBJECTIVE == "fit_to_real_cost":
Expand Down Expand Up @@ -50,15 +60,26 @@ def run(self):
return self.report()

def report(self):
minimum_memory, minimum_cost = Utility.find_minimum_memory_cost(
self.fitted_function, self.function_parameters, self.memory_range
)
result = {
"Minimum Cost Memory": [minimum_memory],
"Expected Cost": [minimum_cost],
"Exploration Cost": [self.exploration_cost],
}
return pd.DataFrame.from_dict(result)
try:
minimum_memory, minimum_cost = Utility.find_minimum_memory_cost(
self.fitted_function,
self.function_parameters,
self.memory_range,
self.execution_time_threshold,
)
result = {
"Minimum Cost Memory": [minimum_memory],
"Expected Cost": [minimum_cost],
"Exploration Cost": [self.exploration_cost],
}
return pd.DataFrame.from_dict(result)

except NoMemoryLeft:
print(
"No memory configuration is possible. The execution time threshold is too low!",
file=sys.stderr,
)
exit(1)

def initial_sample(self):
# TODO: ensure initial memories are in the accepted memory range.
Expand Down
17 changes: 16 additions & 1 deletion spot/recommendation_engine/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,27 @@
import numpy as np
from scipy.optimize import curve_fit

from spot.exceptions.NoMemoryLeft import NoMemoryLeft


class Utility:
@staticmethod
def find_minimum_memory_cost(f, params, memory_range):
def find_minimum_memory_cost(
f, params, memory_range, execution_time_threshold: float = None
):
mems = np.arange(memory_range[0], memory_range[1] + 1, dtype=np.double)
costs = f(mems, *params)

# Handling execution threshold
if execution_time_threshold is not None:
execution_times = costs / mems
for i in range(len(execution_times)):
if execution_times[i] > execution_time_threshold:
mems = np.delete(mems, i)
costs = np.delete(costs, i)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a safe delete. An example:
Screenshot 2023-06-02 at 8 42 12 AM

if len(mems) == 0:
raise NoMemoryLeft()

min_index = np.argmin(costs)
return mems[min_index], costs[min_index]

Expand Down