energia/wrappers/PowerGadget.py

120 строки
4.2 KiB
Python

import sys
import platform
import shutil
import os
import multiprocessing
import pandas
import re
import tempfile
sys.path.append("..")
from wrapper import Wrapper
from pandas import DataFrame
get_long_path = lambda x: x
try:
import win32api
get_long_path= win32api.GetLongPathName
except:
pass
class PowerGadget(Wrapper):
_osx_exec = "PowerLog"
_win_exec = "PowerLog.exe"
_lin_exec = "power_gadget"
def __init__(self, args):
super().__init__(args)
self._fields = ["Processor Joules", "Processor Watt", "IA Joules", "IA Watt", "GT Joules", "GT Watt"]
self._system = platform.system()
if self._args.path:
if os.path.exists(self._args.path) and os.access(self._args.path, os.X_OK):
self._tool = self._args.path
else:
raise Exception("Intel Power Gadget executable not found")
elif self._system == "Darwin":
if shutil.which(PowerGadget._osx_exec):
self._tool = PowerGadget._osx_exec
else:
raise Exception("Intel Power Gadget executable not found")
elif self._system == "Linux":
if shutil.which(PowerGadget._lin_exec):
self._tool = PowerGadget._lin_exec
else:
raise Exception("Intel Power Gadget executable not found")
elif self._system == "Windows":
if shutil.which(PowerGadget._win_exec):
self._tool = PowerGadget._win_exec
else:
raise Exception("Intel Power Gadget executable not found")
else:
raise Exception("Platform is not supported.")
def start(self):
directory = get_long_path(tempfile.mkdtemp())
self._logfile = os.path.join(directory, "PowerLog.ipg")
self._log_process = multiprocessing.Process(target=self._start)
self._log_process.start()
def _start(self):
resolution = self._args.resolution
duration = self._args.duration
if self._system == "Darwin":
os.system("{} -resolution {} -duration {} -file {} > /dev/null".format(
self._tool, str(resolution), str(duration), self._logfile))
elif self._system == "Linux":
os.system("{} -e {} -d {} > {}".format(self._tool, str(resolution),
str(duration), self._logfile))
else:
os.system("{} -resolution {} -duration {} -file {} > NUL 2>&1".format(
self._tool, str(resolution), str(duration), self._logfile))
def join(self):
self._log_process.join()
return self._parse()
def _parse(self):
summary = {"Processor Watt" : 0,
"Processor Joules": 0,
"IA Watt": float('nan'),
"IA Joules": float('nan'),
"GT Watt": float('nan'),
"GT Joules": float('nan')}
regexps = {"Processor Watt" : re.compile(".* Processor Power_0 \(Watt\) = (.*)"),
"Processor Joules": re.compile(".* Processor Energy_0 \(Joules\) = (.*)"),
"IA Joules": re.compile(".* IA Energy_0 \(Joules\) = (.*)"),
"IA Watt": re.compile(".* IA Power_0 \(Watt\) = (.*)"),
"GT Joules": re.compile(".* GT Energy_0 \(Joules\) = (.*)"),
"GT Watt": re.compile(".* GT Power_0 \(Watt\) = (.*)")}
try:
with open(self._logfile) as f:
lines = f.readlines()
# split in data and metadata
for iteration, line in enumerate(lines):
if line == "\n":
data = lines[:iteration]
metadata = lines[iteration + 1:]
break
for line in metadata:
for key, regexp in regexps.items():
m = re.match(regexp, line)
if m:
summary[key] = float(m.group(1))
except FileNotFoundError:
raise Exception("PowerLog failed to generate a valid logfile")
return sys.exit(-1)
assert(summary['Processor Watt'] > 0)
#TODO
shutil.rmtree(os.path.split(self._logfile)[0])
return summary