Last active
December 28, 2018 15:11
-
-
Save linnaea/6ab06de2f2d3b44ace4684bcbbfcc9ec to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from os import listdir | |
from time import time, sleep | |
from math import log10, copysign | |
from typing import List | |
energy = dict() | |
si_prefix = 'M', 'k', '', 'm', 'u' | |
hsign = lambda x: copysign(0.5, x) | |
def stat_energy(domain: str, readout: int, rollover: int) -> int: | |
now = time() | |
if domain not in energy: | |
energy[domain] = readout, readout, now | |
return 0, readout | |
last_read, total, last_time = energy[domain] | |
diff = readout - last_read | |
if diff < 0: | |
diff += rollover | |
total += diff | |
power = diff / (now - last_time) | |
energy[domain] = readout, total, now | |
return power, total | |
def read_file(path: str) -> str: | |
with open(path) as file: | |
return file.read().strip() | |
def bool_enabled_disabled(v) -> str: | |
return "Enabled" if v else "Disabled" | |
def fmt_numeric(v_u: int, width: int=4) -> str: | |
if not v_u: | |
return '0.' + '0' * (width - 2) + ' ' | |
sii = len(si_prefix) - 1 | |
while log10(abs(v_u)) >= (width + hsign(v_u) - 0.5) and sii > 0: | |
v_u /= 1000 | |
sii -= 1 | |
v = str(int(v_u)) | |
decimals = width - 1 - len(v) | |
if decimals > 0: | |
v = str(round(v_u, decimals)) | |
while len(v) < width: | |
if decimals > 0: | |
v += '0' | |
else: | |
v = ' ' + v | |
return f"{v} {si_prefix[sii]}" | |
def print_rapl_dir(path: str, domain: List[str]): | |
indent = " " * max(0, len(domain) - 1) | |
dom_id = ":".join(domain) | |
dom_prefix = "intel-rapl:" + dom_id + (":" if dom_id else "") | |
entries = listdir(path) | |
if 'name' in entries: | |
dom_name = read_file(f"{path}/name") | |
dom_enabled = int(read_file(f"{path}/enabled")) | |
print(f"{indent}Domain #{dom_id} {dom_name}: {bool_enabled_disabled(dom_enabled)}") | |
energy_readout = int(read_file(f"{path}/energy_uj")) | |
energy_range = int(read_file(f"{path}/max_energy_range_uj")) | |
power, total = stat_energy(dom_id, energy_readout, energy_range) | |
print(f"{indent} Power Statistics:") | |
print(f"{indent} Average power: {fmt_numeric(power)}W") | |
print(f"{indent} Total consumption: {fmt_numeric(total / 3600)}Wh") | |
print(f"{indent} Counter rollover: {fmt_numeric(energy_range / 3600)}Wh") | |
print("") | |
for ent in entries: | |
if not ent.startswith('constraint_') or not ent.endswith('_name'): | |
continue | |
i = ent[11:-5] | |
const_name = read_file(f"{path}/constraint_{i}_name") | |
try: | |
max_power = int(read_file(f"{path}/constraint_{i}_max_power_uw")) | |
except OSError: | |
max_power = 0 | |
power_limit = int(read_file(f"{path}/constraint_{i}_power_limit_uw")) | |
if not max_power and not power_limit: | |
continue | |
time_window = int(read_file(f"{path}/constraint_{i}_time_window_us")) | |
print(f"{indent} Constraint {i}: {const_name}") | |
print(f"{indent} Power Limit: {fmt_numeric(power_limit)}W", end="") | |
if max_power and max_power != power_limit: | |
print(f" (max: {fmt_numeric(max_power)}W)", end="") | |
print("") | |
print(f"{indent} Sampling Window: {fmt_numeric(time_window)}s") | |
print("") | |
subdomains = sorted(ent[len(dom_prefix):] for ent in entries if ent.startswith(dom_prefix)) | |
if subdomains: | |
if 'name' in entries: | |
print(f"{indent} Sub-domains: {len(subdomains)}") | |
else: | |
print(f"Domains: {len(subdomains)}") | |
for subdomain in subdomains: | |
print_rapl_dir(f"{path}/{dom_prefix}{subdomain}", domain + [subdomain]) | |
while True: | |
print('\033c', end="") | |
print_rapl_dir("/sys/devices/virtual/powercap/intel-rapl", []) | |
sleep(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment