Skip to content

Commit

Permalink
feat: Sync the formula implementation with the one used in the paper
Browse files Browse the repository at this point in the history
  • Loading branch information
gfieni committed Feb 18, 2020
1 parent e8917ff commit 324bfde
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 21 deletions.
31 changes: 21 additions & 10 deletions smartwatts/formula.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,19 +132,30 @@ def compute_power_estimation(self, events: Dict[str, int]) -> float:

return self.model.predict([self._extract_events_value(events)])[0]

@staticmethod
def cap_power_estimation(power_reference: float, global_power: float, target_power: float) -> (float, float):
def cap_power_estimation(self, raw_target_power: float, raw_global_power: float) -> (float, float):
"""
Cap the target power estimation to the reference power estimation.
:param power_reference: Reference power estimation (in Watt, usually RAPL)
:param global_power: Global power estimation from the power model (in Watt)
:param target_power: Target power estimation from the power model (in Watt)
Cap target's power estimation to the global power estimation.
:param raw_target_power: Target power estimation from the power model (in Watt)
:param raw_global_power: Global power estimation from the power model (in Watt)
:return: Capped power estimation (in Watt) with its ratio over global power consumption
"""
ratio = target_power / global_power if global_power > 0.0 else 0.0
power = power_reference * ratio
target_power = raw_target_power - self.model.intercept_
global_power = raw_global_power - self.model.intercept_

ratio = target_power / global_power if global_power > 0.0 and target_power > 0.0 else 0.0
power = global_power * ratio if ratio > 0.0 else 0.0
return power, ratio

def apply_intercept_share(self, target_power: float, target_ratio: float) -> float:
"""
Apply the target's share of intercept from its ratio from the global power consumption.
:param target_power: Target power estimation (in Watt)
:param target_ratio: Target ratio over the global power consumption
:return: Target power estimation including intercept (in Watt) and ratio over global power consumption
"""
intercept = target_ratio * self.model.intercept_
return target_power + intercept


class SmartWattsFormula:
"""
Expand Down Expand Up @@ -180,7 +191,7 @@ def _get_frequency_layer(self, frequency: float) -> int:

return last_layer_freq

def _compute_pkg_frequency(self, system_msr: Dict[str, int]) -> float:
def compute_pkg_frequency(self, system_msr: Dict[str, int]) -> float:
"""
Compute the average package frequency.
:param msr: MSR events group of System target
Expand All @@ -194,4 +205,4 @@ def get_power_model(self, system_core: Dict[str, int]) -> PowerModel:
:param system_core: Core events group of System target
:return: Power model to use for the current frequency
"""
return self.models[self._get_frequency_layer(self._compute_pkg_frequency(system_core))]
return self.models[self._get_frequency_layer(self.compute_pkg_frequency(system_core))]
25 changes: 14 additions & 11 deletions smartwatts/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def _gen_agg_core_report_from_running_targets(self, targets_report: Dict[str, HW

return agg_core_events_group

def _gen_power_report(self, timestamp: datetime, target: str, formula: str, power: float, ratio: float) -> PowerReport:
def _gen_power_report(self, timestamp: datetime, target: str, formula: str, raw_power: float, power: float, ratio: float) -> PowerReport:
"""
Generate a power report using the given parameters.
:param timestamp: Timestamp of the measurements
Expand All @@ -107,7 +107,8 @@ def _gen_power_report(self, timestamp: datetime, target: str, formula: str, powe
'scope': self.state.config.scope.value,
'socket': self.state.socket,
'formula': formula,
'ratio': ratio
'ratio': ratio,
'predict': raw_power,
}
return PowerReport(timestamp, self.state.sensor, target, power, metadata)

Expand All @@ -127,7 +128,8 @@ def _gen_formula_report(self, timestamp: datetime, pkg_frequency: float, model:
'pkg_frequency': pkg_frequency,
'samples': len(model.history),
'id': model.id,
'error': error
'error': error,
'intercept': model.model.intercept_
}
return FormulaReport(timestamp, self.state.sensor, model.hash, metadata)

Expand Down Expand Up @@ -155,16 +157,16 @@ def _process_oldest_tick(self) -> (List[PowerReport], List[FormulaReport]):

# compute RAPL power report
rapl_power = rapl[self.state.config.rapl_event]
power_reports.append(self._gen_power_report(timestamp, 'rapl', self.state.config.rapl_event, rapl_power, 1.0))
power_reports.append(self._gen_power_report(timestamp, 'rapl', self.state.config.rapl_event, rapl_power, rapl_power, 1.0))

# fetch power model to use
pkg_frequency = self.formula._compute_pkg_frequency(avg_msr)
pkg_frequency = self.formula.compute_pkg_frequency(avg_msr)
model = self.formula.get_power_model(avg_msr)

# compute Global target power report
try:
system_power = model.compute_power_estimation(global_core)
power_reports.append(self._gen_power_report(timestamp, 'global', model.hash, system_power, 1.0))
raw_global_power = model.compute_power_estimation(global_core)
power_reports.append(self._gen_power_report(timestamp, 'global', model.hash, raw_global_power, raw_global_power, 1.0))
except PowerModelNotInitializedException:
model.store_report_in_history(rapl_power, global_core)
model.learn_power_model()
Expand All @@ -173,12 +175,13 @@ def _process_oldest_tick(self) -> (List[PowerReport], List[FormulaReport]):
# compute per-target power report
for target_name, target_report in hwpc_reports.items():
target_core = self._gen_core_events_group(target_report)
target_power = model.compute_power_estimation(target_core)
target_power, target_ratio = model.cap_power_estimation(rapl_power, system_power, target_power)
power_reports.append(self._gen_power_report(timestamp, target_name, model.hash, target_power, target_ratio))
raw_target_power = model.compute_power_estimation(target_core)
target_power, target_ratio = model.cap_power_estimation(raw_target_power, raw_global_power)
target_power = model.apply_intercept_share(target_power, target_ratio)
power_reports.append(self._gen_power_report(timestamp, target_name, model.hash, raw_target_power, target_power, target_ratio))

# compute power model error from reference
model_error = fabs(rapl_power - system_power)
model_error = fabs(rapl_power - raw_global_power)

# store Global report if the power model error exceeds the error threshold
if model_error > self.state.config.error_threshold:
Expand Down

0 comments on commit 324bfde

Please sign in to comment.