Commit 0c93ce6a authored by Kazutomo Yoshii's avatar Kazutomo Yoshii

added powercap APIs and testbench

parent 68784add
......@@ -9,10 +9,36 @@
import os, sys, re, time, getopt
import clr_nodeinfo
class rapl_reader:
dryrun = False
rapldir='/sys/devices/virtual/powercap/intel-rapl'
re_domain = re.compile('package-([0-9]+)(/\S+)?')
def readint(self, fn):
v = -1
for retry in range(0,10):
try:
f = open( fn )
v = int(f.readline())
f.close()
except:
continue
return v
def writeint(self, fn, v):
ret = False
try:
f = open(fn, 'w')
f.write('%d' % v)
f.close()
ret = True
except:
ret = False
return ret
#
# e.g.,
# intel-rapl:0/name
......@@ -69,8 +95,8 @@ class rapl_reader:
def shortenkey(self,str):
return str.replace('package-','p')
# for k in sorted(self.dirs.keys()):
# print k, self.max_energy_range_uj_d[k]
# for k in sorted(self.dirs.keys()):
# print k, self.max_energy_range_uj_d[k]
def readenergy(self):
......@@ -84,18 +110,16 @@ class rapl_reader:
return ret
for k in sorted(self.dirs.keys()):
fn = self.dirs[k] + "/energy_uj"
v = -1
for retry in range(0,10):
try:
f = open( fn )
v = int(f.readline())
f.close()
except:
continue
ret[k] = v
ret[k] = self.readint(fn)
return ret
def readpowerlimit(self):
# Read all possible power caps, except package 'short_term', which
# will be supported later. This function is designed to be called
# from a slow path. return a dict with long domain names as keys
# and a value contains a dict with 'curW', 'maxW', 'enabled'
def readpowerlimitall(self):
if not self.init:
return
......@@ -104,16 +128,18 @@ class rapl_reader:
ret['package-0'] = 100.0
return ret
for k in sorted(self.dirs.keys()):
fn = self.dirs[k] + '/constraint_0_power_limit_uw'
v = -1
for retry in range(0,10):
try:
f = open( fn )
v = int(f.readline())
f.close()
except:
continue
ret[k] = v / (1000.0 * 1000.0) # uw to w
dvals = {}
v = self.readint( self.dirs[k] + '/constraint_0_power_limit_uw' )
dvals['curW'] = v * 1e-6 # uw to w
v = self.readint( self.dirs[k] + '/constraint_0_max_power_uw' )
dvals['maxW'] = v * 1e-6 # uw to w
dvals['enabled'] = False
v = self.readint( self.dirs[k] + '/enabled' )
if v == 1:
dvals['enabled'] = True
ret[k] = dvals
return ret
def diffenergy(self,e1,e2): # e1 is prev and e2 is not
......@@ -188,7 +214,7 @@ class rapl_reader:
e = self.read_energy_acc()
self.stop_time = time.time()
def sample(self, accflag=False):
def sample_and_json(self, label = "", accflag = False, node = ""):
if not self.initialized():
return
......@@ -200,31 +226,55 @@ class rapl_reader:
if k != 'time':
if accflag:
self.totalenergy[k] += de[k]
self.lastpower[k] = de[k]/de['time']/1000.0/1000.0
self.lastpower[k] = de[k]/de['time']/1000.0/1000.0;
self.prev_e = e
ret = dict()
ret['energy'] = dict()
# constructing a json output
s = '{"sample":"energy","time":%.3f' % (e['time'])
if len(node) > 0:
s += ',"node":"%s"' % node
if len(label) > 0:
s += ',"label":"%s"' % label
s += ',"energy":{'
firstitem = True
for k in sorted(e.keys()):
if k != 'time':
ret['energy'][self.shortenkey(k)] = e[k]
if firstitem:
firstitem = False
else:
s+=','
s += '"%s":%d' % (self.shortenkey(k), e[k])
s += '},'
s += '"power":{'
ret['power'] = dict()
totalpower = 0.0
firstitem = True
for k in sorted(self.lastpower.keys()):
if k != 'time':
ret['power'][self.shortenkey(k)] = self.lastpower[k]
if firstitem:
firstitem = False
else:
s+=','
s += '"%s":%.1f' % (self.shortenkey(k), self.lastpower[k])
# this is a bit ad hoc way to calculate the total. needs to be fixed later
if k.find("core") == -1:
totalpower += self.lastpower[k]
ret['power']['total'] = totalpower
s += ',"total":%.1f' % (totalpower)
s += '},'
ret['powercap'] = dict()
rlimit = self.readpowerlimit()
s += '"powercap":{'
rlimit = self.readpowerlimitall()
firstitem = True
for k in sorted(rlimit.keys()):
ret['powercap'][self.shortenkey(k)] = rlimit[k]
if firstitem:
firstitem = False
else:
s+=','
s += '"%s":%.1f' % (self.shortenkey(k), rlimit[k]['curW'])
s += '}'
return ret
s += '}'
return s
def total_energy_json(self):
if not self.initialized():
......@@ -239,3 +289,140 @@ class rapl_reader:
s += ',"%s":%d' % (self.shortenkey(k), e[k])
s += '}'
return s
def conv_long2short(self, n):
m = self.re_domain.match(n)
sn = ''
if m:
pkgid = int(m.group(1))
sn = 'p%d' % (pkgid)
if m.group(2):
subname = m.group(2)[1:]
sn += subname
return sn
#
# APIs for power capping
#
def get_powerdomains(self):
return self.readpowerlimitall().keys
def get_powerlimits(self):
return self.readpowerlimitall()
def _set_powerlimit(self, rrdir, newval, id = 0):
fn = rrdir + '/constraint_%d_power_limit_uw' % id
uw = newval * 1e6
try:
f = open(fn, 'w')
except:
print 'Failed to update:', fn, '(root privilege is required)'
return
f.write('%d' % uw)
f.close()
def set_powerlimit(self, newval, dom):
l = self.dirs[dom]
self._set_powerlimit(l, newval)
def set_powerlimit_pkg(self, newval):
rlims = self.readpowerlimitall()
for k in rlims.keys():
if re.findall('package-[0-9]$', k):
self._set_powerlimit(self.dirs[k], newval)
# Implement the following method
# is_enabled_rapl(), enable_rapl(), disable_rapl()
# convshort2long
# pkgid2cpuids, cpuid2pkgid
def usage():
print 'clr_rapl.py [options]'
print ''
print '--show [pkgid]: show the current setting'
print '--limitp val: set the limit to all packages'
print ' [pkgid:]powerval e.g., 140, 1:120'
print ''
print 'If no option is specified, run the test pattern.'
print ''
def test_conv():
l = ['package-1', 'package-3/dram', 'package-2/core']
for s in l:
rr.conv_long2short(s)
def report_powerlimits():
l = rr.get_powerlimits()
for k in l.keys():
if l[k]['enabled']:
print k, 'curW:', l[k]['curW'], 'maxW:', l[k]['maxW']
def run_powercap_testbench():
# hard-coded for Haswell E5-2699v2 dual socket
print rr.get_powerdomains()
report_powerlimits()
w = 10
rr.set_powerlimit_pkg(120)
time.sleep(w)
rr.set_powerlimit_pkg(80)
time.sleep(w)
rr.set_powerlimit(130, 'package-1')
time.sleep(w)
rr.set_powerlimit_pkg(145)
if __name__ == '__main__':
rr = rapl_reader()
if not rr.initialized():
print 'Error: No intel rapl sysfs found'
sys.exit(1)
shortopt = "h"
longopt = ['getpd', 'getplim', 'setplim=', 'show', 'limitp=', 'testbench' ]
try:
opts, args = getopt.getopt(sys.argv[1:],
shortopt, longopt)
except getopt.GetoptError, err:
print err
usage()
sys.exit(1)
for o, a in opts:
if o in ('-h'):
usage()
sys.exit(0)
elif o in ("--testbench"):
print 'Start: testbench'
run_powercap_testbench()
print 'Stop: testbench'
sys.exit(0)
elif o in ("--getpd"):
print rr.get_powerdomains()
sys.exit(0)
elif o in ("--getplim", "--show"):
report_powerlimits()
sys.exit(0)
elif o in ("--setplim", "--limitp"):
v = float(a)
rr.set_powerlimit_pkg(v)
report_powerlimits()
sys.exit(0)
rr.start_energy_counter()
for i in range(0,3):
time.sleep(1)
s = rr.sample_and_json(accflag=True)
print s
rr.stop_energy_counter()
s = rr.total_energy_json()
print s
sys.exit(0)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment