Skip to content

Commit

Permalink
expose power and price parameters in config
Browse files Browse the repository at this point in the history
  • Loading branch information
iliapietri committed May 21, 2015
1 parent ee70a8b commit c5ef97c
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 30 deletions.
10 changes: 7 additions & 3 deletions philharmonic/cloud/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,11 @@ def _utilisation_multicore(self, s, weights):
util = 0
for vm in self.alloc[s]:
vm_cores = vm.spec['#CPUs']
util += float(vm.beta) * vm_cores / active_cores
#gamma = float(vm.beta)
gamma = (weights[0] * float(vm.beta)
+ weights[1] * float(vm.beta)**2 + weights[2]) / float(weights[3])
util += gamma * vm_cores / active_cores
#util += float(vm.beta) * vm_cores / active_cores
return util

def utilisation(self, s, weights=None, method="basic"):
Expand All @@ -400,9 +404,9 @@ def utilisation(self, s, weights=None, method="basic"):
else:
raise ValueError("unknown utilisation calculation method")

def calculate_utilisations(self, method="basic"):
def calculate_utilisations(self, method="basic", weights=None):
"""Return dict server -> utilisation rate."""
return {server: self.utilisation(server, method=method) \
return {server: self.utilisation(server, weights, method) \
for server in self.servers}

def calculate_prices(self):
Expand Down
7 changes: 5 additions & 2 deletions philharmonic/cloud/tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,9 +570,12 @@ def test_utilisation_multicore():
vm = VM(2000, 1)
s = Server(20000, 10)
cloud = Cloud([s], [vm])
assert_equals(cloud.get_current().utilisation(s, method="multicore"), 0)
w = [-1.362, 2.798, 1.31, 2.8]
ut = cloud.get_current().utilisation(s, weights=w, method="multicore")
assert_true(0. <= ut < 0.1)
cloud.apply(Migration(vm, s))
assert_equals(cloud.get_current().utilisation(s, method="multicore"), 1.0)
ut = cloud.get_current().utilisation(s, weights=w, method="multicore")
assert_true(0.9 < ut <= 1.)

def test_utilisation_unknown():
cloud = Cloud([], [])
Expand Down
25 changes: 16 additions & 9 deletions philharmonic/scheduler/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def calculate_cloud_utilisation(cloud, environment, schedule,
#TODO: use more precise pandas methods for indexing (performance)
#TODO: maybe move some of this state iteration functionality into Cloud
#TODO: see where schedule window should be propagated - here or Scheduler?
initial_utilisations = cloud.get_current().calculate_utilisations(method)
initial_utilisations = cloud.get_current().calculate_utilisations(method, conf.utilisation_weights)
utilisations_list = [initial_utilisations]
times = [start]
for t in schedule.actions.index.unique():
Expand All @@ -67,7 +67,7 @@ def calculate_cloud_utilisation(cloud, environment, schedule,
action = schedule.actions[t]
cloud.apply(action)
state = cloud.get_current()
new_utilisations = state.calculate_utilisations(method)
new_utilisations = state.calculate_utilisations(method, conf.utilisation_weights)
utilisations_list.append(new_utilisations)
times.append(t)
if times[-1] < end:
Expand Down Expand Up @@ -123,7 +123,8 @@ def generate_cloud_power(util, freq=None, active_cores=None, max_cores=None,
# TODO: generate active_cores DataFrame
power = ph.calculate_power_multicore(
util, freq, active_cores, max_cores,
freq_abs_min=conf.freq_abs_min, freq_abs_delta=conf.freq_abs_delta
freq_abs_min=conf.freq_abs_min, freq_abs_delta=conf.freq_abs_delta,
power_weights=conf.power_weights
)
else:
raise ValueError("Power model {} not supported.".format(power_model))
Expand Down Expand Up @@ -490,7 +491,7 @@ def evaluate(cloud, environment, schedule,
#TODO: use more precise pandas methods for indexing (performance)
#TODO: maybe move some of this state iteration functionality into Cloud
#TODO: see where schedule window should be propagated - here or Scheduler?
initial_utilisations = cloud.get_current().calculate_utilisations()
initial_utilisations = cloud.get_current().calculate_utilisations(weights=conf.utilisation_weights)
utilisations_list = [initial_utilisations]
times = [start]

Expand Down Expand Up @@ -531,7 +532,7 @@ def evaluate(cloud, environment, schedule,
raise
cloud.apply(action, inplace=True)
state = cloud.get_current()
new_utilisations = state.calculate_utilisations()
new_utilisations = state.calculate_utilisations(weights=conf.utilisation_weights)
utilisations_list.append(new_utilisations)
times.append(t)

Expand Down Expand Up @@ -741,10 +742,16 @@ def calculate_service_profit(cloud, environment, schedule,
else:
considered_vms = cloud.get_current().vms

df_beta = pd.DataFrame(
[{vm : vm.beta for vm in considered_vms}], [start]
)
df_beta = df_beta.reindex(freq.index, method='pad')

if conf.pricing_model == "performance_pricing":
df_beta = 1.
elif conf.pricing_model == "perceived_perf_pricing":
df_beta = pd.DataFrame(
[{vm : vm.beta for vm in considered_vms}], [start]
)
df_beta = df_beta.reindex(freq.index, method='pad')
else:
raise ValueError("Unknown pricing model")
ram_size_base = 1 # 1000 # 1024
ram_index = 'RAM'
df_rel_ram = pd.DataFrame([{vm : vm.res[ram_index] / ram_size_base \
Expand Down
6 changes: 6 additions & 0 deletions philharmonic/scheduler/tests/test_bcffs_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,15 @@ def test_bcf_reevaluate_freq_scaling(mock_conf):
mock_conf.C_base = 0.0520278
mock_conf.C_dif_cpu = 0.018
mock_conf.C_dif_ram = 0.025
mock_conf.pricing_model = "perceived_perf_pricing"
mock_conf.freq_scale_max = 1.0
mock_conf.freq_scale_min = 0.7
mock_conf.freq_scale_delta = 0.1
mock_conf.freq_scale_digits = 1
mock_conf.power_freq_model = True
mock_conf.power_model = "freq"
mock_conf.utilisation_weights = None
mock_conf.power_weights = None
mock_conf.P_idle = 100
mock_conf.P_std = 5
mock_conf.P_dif = 15
Expand Down Expand Up @@ -110,12 +113,15 @@ def test_bcf_reevaluate_freq_scaling_beta_0(mock_conf):
mock_conf.C_base = 0.0520278
mock_conf.C_dif_cpu = 0.018
mock_conf.C_dif_ram = 0.025
mock_conf.pricing_model = "perceived_perf_pricing"
mock_conf.freq_scale_max = 1.0
mock_conf.freq_scale_min = 0.7
mock_conf.freq_scale_delta = 0.1
mock_conf.freq_scale_digits = 1
mock_conf.power_freq_model = True
mock_conf.power_model = "freq"
mock_conf.utilisation_weights = None
mock_conf.power_weights = None
mock_conf.P_idle = 100
mock_conf.P_std = 5
mock_conf.P_dif = 15
Expand Down
16 changes: 12 additions & 4 deletions philharmonic/scheduler/tests/test_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ def _configure(mock_conf):
mock_conf.C_base = 0.0520278
mock_conf.C_dif_cpu = 0.018
mock_conf.C_dif_ram = 0.025
mock_conf.pricing_model = "perceived_perf_pricing"
mock_conf.freq_scale_max = 1.0
mock_conf.freq_scale_min = 0.7
mock_conf.freq_scale_delta = 0.1
mock_conf.freq_scale_digits = 1
mock_conf.power_freq_model = True
mock_conf.power_model = "freq"
mock_conf.utilisation_weights = None
mock_conf.power_weights = None
mock_conf.P_idle = 100
mock_conf.P_std = 5
mock_conf.P_dif = 15
Expand Down Expand Up @@ -148,7 +151,11 @@ def test_generate_cloud_power():
precreate_synth_power(index[0], index[-1], ['s1'])
power = generate_cloud_power(util)

def test_generate_cloud_power_multicore():
@patch('philharmonic.scheduler.evaluator.conf')
def test_generate_cloud_power_multicore(mock_conf):
mock_conf = _configure(mock_conf)
mock_conf.power_model = "multicore"
mock_conf.power_weights = [1.318, 0.03559, 0.2243, -0.003184, 0.03137, 0.0004377, 0.007106]
index = pd.date_range('2013-01-01', periods=6, freq='H')
num = len(index)/2
util = pd.Series([0]*num + [0.5]*num, index)
Expand All @@ -158,9 +165,10 @@ def test_generate_cloud_power_multicore():
active_cores = pd.DataFrame({'s1': active_cores})
max_cores = pd.Series([4] * 2 * num, index)
max_cores = pd.DataFrame({'s1': max_cores})
power = generate_cloud_power(util, power_model="multicore",
active_cores=active_cores,
max_cores=max_cores)
power = generate_cloud_power(
util, power_model="multicore", active_cores=active_cores,
max_cores=max_cores
)

def test_calculate_cost():
s1 = Server(4000, 2, location='A')
Expand Down
25 changes: 25 additions & 0 deletions philharmonic/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,23 @@ def get_factory():
C_base = 0.027028 #0.0520278 # in future use C_base = 0.027028
C_dif_cpu = 0.018
C_dif_ram = 0.025

# VM pricing:
# - perceived_perf_pricing
# - performance_pricing
pricing_model = "perceived_perf_pricing"
cloud_provider = "elastic_hosts"

if cloud_provider == "elastic_hosts":
C_base = 0.027028
C_dif_cpu = 0.018
C_dif_ram = 0.025

if cloud_provider == "cloud_sigma":
C_base = 0.004529
C_dif_cpu = 0.001653
C_dif_ram = 0.003979

# CPU frequency parameters
f_max = 2600 # the maximum CPU frequency in MHz

Expand All @@ -247,6 +264,14 @@ def get_factory():
# - "multicore" - utilisation and frequency-based for multiple CPU cores
power_model = "freq"

if power_model == "multicore":
# last value of utilisation weights should be maximum power consumption of 1 core
utilisation_weights = [-1.362, 2.798, 1.31, 2.8] # p0, p1, p2 for gamma
power_weights = [1.318, 0.03559, 0.2243, -0.003184, 0.03137, 0.0004377, 0.007106]
#p00, p10, p01, p20, p11, p30, p21 in power model
else: #optional parameters only for multicore
utilisation_weights = None
power_weights = None
# deprecated, use power_model instead
power_freq_model = (power_model == "freq") # consider CPU frequency in the power model

Expand Down
15 changes: 5 additions & 10 deletions philharmonic/timeseries/calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,15 @@ def calculate_power_freq(ut, f=2000, P_idle=100, P_base=150,
# c = (active_cores * util_beta).sum(axis=1) / (active_cores.sum(axis=1))
# return c

def _calculate_peakpower_freq_multicore(
q, c, p00, p10, p01, p20, p11, p30, p21):
def _calculate_peakpower_freq_multicore(q, c, power_weights):
p00, p10, p01, p20, p11, p30, p21 = power_weights
P=p00+p10*q+p01*c+p20*(q**2)+p11*q*c+p30*(q**3)+p21*(q**2)*c
return P

# TODO: p00..p30 as some kind of dict or list
def calculate_power_multicore(
util, freq, active_cores, max_cores, max_capacity=8, freq_abs_min=1800,
freq_abs_delta=200, p00=2.34, p10=0.598, p01=0.058, p20=-0.16,
p11=-0.025, p30=0.012, p21=0.01):
freq_abs_delta=200, power_weights=None):
"""@param util: utilisation (multicore) based on per-core utilisations
@param freq: DataFrame of absolute frequencies for servers over time
@param max_capacity: maximum utilisation in Simon's unitless notation
Expand All @@ -94,13 +93,9 @@ def calculate_power_multicore(
c = active_cores
# peak power when a number of cores are active at a frequency assuming
# they are fully utilized
max_power = _calculate_peakpower_freq_multicore(
freq_discr, c, p00, p10, p01, p20, p11, p30, p21
)
max_power = _calculate_peakpower_freq_multicore(freq_discr, c, power_weights)
# from the model of Holmbacka et al extract the idle part of the power
idle_power = _calculate_peakpower_freq_multicore(
freq_discr, 0, p00, p10, p01, p20, p11, p30, p21
)
idle_power = _calculate_peakpower_freq_multicore(freq_discr, 0, power_weights)
# take into account the utilization of the active cores
total_power = idle_power + (max_power - idle_power) * util

Expand Down
6 changes: 4 additions & 2 deletions philharmonic/timeseries/tests/test_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,10 @@ def test_calculate_power_multicore():
active_cores = pd.DataFrame({'s1': active_cores, 's2': [0] * 2 * num})
max_cores = pd.Series([4]*2*num, index)
max_cores = pd.DataFrame({'s1': max_cores, 's2': [4] * 2 * num})

power = ph.calculate_power_multicore(freq, active_cores, max_cores, 0.5)
power = ph.calculate_power_multicore(
freq, active_cores, max_cores, 0.5,
power_weights=[1.318, 0.03559, 0.2243, -0.003184, 0.03137, 0.0004377, 0.007106]
)
#power = ph.calculate_power_multicore(util, f=2000, P_idle=100, P_base=150,
# P_dif=15, f_base=1000)
#assert_equals(list(power['s1'][:num]), [0] * num)
Expand Down

0 comments on commit c5ef97c

Please sign in to comment.