Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature(bitwatts-eurosys-2015): add scripts relating to the article
Adds the scripts used for processing and for generating charts displayed in the article.
- Loading branch information
Showing
7 changed files
with
275 additions
and
10 deletions.
There are no files selected for viewing
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
26 changes: 26 additions & 0 deletions
26
bitwatts-eurosys-2015/src/universal/scripts/figure10/figure10.gp
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Plot the data processed with the process.py script. | ||
# @author: Maxime Colmant | ||
|
||
set term postscript color eps enhanced 22 | ||
set output "figure10.eps" | ||
|
||
set ylabel "Power (W)" | ||
set xlabel "Time (sec)" | ||
|
||
set format x "%.0s" | ||
set format y "%.0s" | ||
|
||
set pointsize 0.75 | ||
set key below horizontal center | ||
|
||
mdblue = '#000066' | ||
hp1 = '#d7301f' | ||
hp2 = '#fc8d59' | ||
hpapi = '#fdcc8a' | ||
hidle = '#fef0d9' | ||
|
||
plot "results/data.csv" using 0:($4+$3+$2+$1) title 'x264' lc rgb hp1 lt 1 lw 4 with filledcurves x1, \ | ||
"results/data.csv" using 0:($4+$3+$2) title 'freqmine' lc rgb hp2 lt 3 lw 4 with filledcurves x1, \ | ||
"results/data.csv" using 0:($4+$3) title 'BitWatts' lc rgb hpapi lt 2 lw 4 with filledcurves x1, \ | ||
"results/data.csv" using 0:($4) title 'Idle power' lc rgb hidle lt 1 lw 4 with filledcurves x1, \ | ||
"results/data.csv" using 0:($5) title 'PowerSpy' lc rgb mdblue lt -1 lw 2 with lines |
105 changes: 105 additions & 0 deletions
105
bitwatts-eurosys-2015/src/universal/scripts/figure10/process.py
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# Script to process the data used for plotting the Figure 10. | ||
# The data come from the corresponding experiment in bitwatts-eurosys-2015. | ||
# @author: Maxime Colmant | ||
import os | ||
import glob | ||
import re | ||
import numpy as np | ||
import csv | ||
import itertools as it | ||
import shutil | ||
import argparse | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument("path", help="experiment data path.") | ||
parser.add_argument('idle', help = 'idle power of the machine.') | ||
args = parser.parse_args() | ||
|
||
separator = '=\n' | ||
powers_filename = 'output-external.dat' | ||
powerapi_filename = 'output-powerapi.dat' | ||
powerapi_p1_filename = 'output-powerapi-p1.dat' | ||
powerapi_p2_filename = 'output-powerapi-p2.dat' | ||
|
||
output_path = os.path.join('results') | ||
|
||
# Creates the output data directory | ||
if os.path.exists(output_path): | ||
shutil.rmtree(output_path) | ||
|
||
os.mkdir(output_path) | ||
|
||
# Cleans the result file | ||
if os.path.isfile('data.csv'): | ||
os.remove('data.csv') | ||
|
||
data = [] | ||
relative_errors = [] | ||
|
||
real_powers_f = open(os.path.join(args.path, powers_filename)) | ||
real_powers_l = real_powers_f.readlines() | ||
real_powers_f.close() | ||
|
||
papi_powers_f = open(os.path.join(args.path, powerapi_filename)) | ||
papi_powers_l = papi_powers_f.readlines() | ||
papi_powers_f.close() | ||
|
||
papi_p1_powers_f = open(os.path.join(args.path, powerapi_p1_filename)) | ||
papi_p1_powers_l = papi_p1_powers_f.readlines() | ||
papi_p1_powers_f.close() | ||
|
||
papi_p2_powers_f = open(os.path.join(args.path, powerapi_p2_filename)) | ||
papi_p2_powers_l = papi_p2_powers_f.readlines() | ||
papi_p2_powers_f.close() | ||
|
||
# First part | ||
sub1_real_powers_l = list(it.takewhile(lambda line: line != separator, real_powers_l)) | ||
sub1_real_powers_d = np.array([ float(re.search('power=([0-9]+\.[0-9]+)$', line, re.IGNORECASE).group(1)) for line in sub1_real_powers_l if line != '' and line != '\n' ]) | ||
real_powers_l = list(it.dropwhile(lambda line: line != separator, real_powers_l))[1:] | ||
|
||
sub1_papi_powers_l = list(it.takewhile(lambda line: line != separator, papi_powers_l)) | ||
sub1_papi_powers_d = np.array([ float(re.search('power=([0-9]+\.[0-9]+)$', line, re.IGNORECASE).group(1)) for line in sub1_papi_powers_l if line != '' and line != '\n' ]) | ||
papi_powers_l = list(it.dropwhile(lambda line: line != separator, papi_powers_l))[1:] | ||
|
||
sub1_papi_p1_powers_l = list(it.takewhile(lambda line: line != separator, papi_p1_powers_l)) | ||
sub1_papi_p1_powers_d = np.array([ float(re.search('power=([0-9]+\.[0-9]+)$', line, re.IGNORECASE).group(1)) for line in sub1_papi_p1_powers_l if line != '' and line != '\n' ]) | ||
papi_p1_powers_l = list(it.dropwhile(lambda line: line != separator, papi_p1_powers_l))[1:] | ||
|
||
## Sync. the data size | ||
min_l = min(len(sub1_real_powers_d), len(sub1_papi_powers_d), len(sub1_papi_p1_powers_d)) | ||
sub1_real_powers_d = sub1_real_powers_d[0:min_l] | ||
sub1_papi_powers_d = sub1_papi_powers_d[0:min_l] | ||
sub1_papi_p1_powers_d = sub1_papi_p1_powers_d[0:min_l] | ||
|
||
relative_errors.extend([ (real - (float(args.idle) + papi + p1)) / real for p1, papi, real in zip(sub1_papi_p1_powers_d, sub1_papi_powers_d, sub1_real_powers_d) if p1 > 0 ]) | ||
data.extend([ [0, p1, papi, float(args.idle), real] for p1, papi, real in zip(sub1_papi_p1_powers_d, sub1_papi_powers_d, sub1_real_powers_d) if p1 > 0 ]) | ||
|
||
# Second part | ||
sub2_real_powers_d = np.array([ float(re.search('power=([0-9]+\.[0-9]+)$', line, re.IGNORECASE).group(1)) for line in real_powers_l if line != '' and line != '\n' ]) | ||
sub2_papi_powers_d = np.array([ float(re.search('power=([0-9]+\.[0-9]+)$', line, re.IGNORECASE).group(1)) for line in papi_powers_l if line != '' and line != '\n' ]) | ||
sub2_papi_p1_powers_d = np.array([ float(re.search('power=([0-9]+\.[0-9]+)$', line, re.IGNORECASE).group(1)) for line in papi_p1_powers_l if line != '' and line != '\n' ]) | ||
sub2_papi_p2_powers_d = np.array([ float(re.search('power=([0-9]+\.[0-9]+)$', line, re.IGNORECASE).group(1)) for line in papi_p2_powers_l if line != '' and line != '\n' ]) | ||
|
||
## Sync. the data size | ||
min_l = min(len(sub2_real_powers_d), len(sub2_papi_powers_d), len(sub2_papi_p1_powers_d), len(sub2_papi_p2_powers_d)) | ||
sub2_real_powers_d = sub2_real_powers_d[0:min_l] | ||
sub2_papi_powers_d = sub2_papi_powers_d[0:min_l] | ||
sub2_papi_p1_powers_d = sub2_papi_p1_powers_d[0:min_l] | ||
sub2_papi_p2_powers_d = sub2_papi_p2_powers_d[0:min_l] | ||
|
||
relative_errors.extend([ (real - (float(args.idle) + papi + p1 + p2)) / real for p1, p2, papi, real in zip(sub2_papi_p1_powers_d, sub2_papi_p2_powers_d, sub2_papi_powers_d, sub2_real_powers_d) if p1 > 0 and p2 > 0 ]) | ||
data.extend([ [p2, p1, papi, float(args.idle), real] for p1, p2, papi, real in zip(sub2_papi_p1_powers_d, sub2_papi_p2_powers_d, sub2_papi_powers_d, sub2_real_powers_d) if p1 > 0 and p2 > 0 ]) | ||
|
||
# Writes the results in files | ||
with open('%s/data.csv' % (output_path), 'a') as csvfile: | ||
writer = csv.writer(csvfile, quotechar='', quoting=csv.QUOTE_NONE, delimiter=' ') | ||
writer.writerow(['#', 'x264', 'freqmine', 'idle', 'measured']) | ||
|
||
for line in data: | ||
writer.writerow(line) | ||
|
||
# Writes statistical informations about errors | ||
with open("%s/errors.txt" % output_path, 'a') as f: | ||
f.write("Avg. BitWatts: %fW\n" % (np.average(np.append(sub1_papi_powers_d, sub2_papi_powers_d)))) | ||
f.write("median relative error: %f%%, max relative error: %f%%\n" % ((np.median(relative_errors) * 100), (max(relative_errors) * 100))) | ||
|
38 changes: 38 additions & 0 deletions
38
bitwatts-eurosys-2015/src/universal/scripts/figure6/figure6.gp
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Plot the formulae written inside the formula.inc file. | ||
# Be careful of the curve names. | ||
# @author: Maxime Colmant | ||
set term postscript dashed color eps enhanced 22 | ||
set termoption dash | ||
set output "figure6.eps" | ||
|
||
load 'formulae.inc' | ||
|
||
mred = '#CC0000' | ||
mgreen = '#009900' | ||
mlblue = '#6699FF' | ||
mblack = '#000000' | ||
|
||
hp1 = '#d7301f' | ||
hp2 = '#fc8d59' | ||
hpapi = '#fdcc8a' | ||
hidle = '#fef0d9' | ||
|
||
set style line 1 lc rgb mred lw 4 | ||
set style line 2 dt 3 lc rgb mgreen lw 6 | ||
set style line 3 lc rgb "orange" lw 8 | ||
set style line 4 dt 4 lc rgb mblack lw 6 | ||
set style line 5 dt 3 lc rgb mlblue lw 8 | ||
|
||
set xlabel "# Unhalted cycles" | ||
set ylabel "Estimated Power (W)" | ||
|
||
set key bottom right spacing 1.2 | ||
set xrange [0:10e8] | ||
set xtics 1e8 | ||
set format x "%.0te^%01T" | ||
|
||
plot e(x) title '2.660 GHz' ls 1 with lines, \ | ||
d(x) title '2.527 GHz' ls 2 with lines, \ | ||
c(x) title '2.394 GHz' ls 3 with lines, \ | ||
b(x) title '2.261 GHz' ls 4 with lines, \ | ||
a(x) title '2.128 GHz' ls 5 with lines |
8 changes: 8 additions & 0 deletions
8
bitwatts-eurosys-2015/src/universal/scripts/figure6/formulae.inc
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Some of the formulae generated by the sampling (see the PowerAPI's repository). | ||
# @author: Maxime Colmant | ||
a(x) = 90.18100211772799 + (3.205474819910001E-8 * x - 1.5778886140222546E-17 * x * x) * 4 | ||
b(x) = 89.91678535950723 + (3.413907478079189E-8 * x - 1.6123712450486037E-17 * x * x) * 4 | ||
c(x) = 89.68970555443457 + (3.569634036989102E-8 * x - 1.5498817702512596E-17 * x * x) * 4 | ||
d(x) = 90.91658043271491 + (3.333663293066566E-8 * x - 1.3041444594382363E-17 * x * x) * 4 | ||
e(x) = 89.79126236117554 + (3.9985158977460974E-8 * x - 1.5370128810306314E-17 * x * x) * 4 |
29 changes: 29 additions & 0 deletions
29
bitwatts-eurosys-2015/src/universal/scripts/figure8-9/figure9.gp
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Plot the data processed with the process.py script. | ||
# @author: Maxime Colmant | ||
|
||
set term postscript color eps enhanced 22 | ||
set output "figure9.eps" | ||
set termoption dashed | ||
set style boxplot nooutliers | ||
set style data boxplot | ||
set style fill solid 0.8 border -1 | ||
set boxwidth 0.5 absolute | ||
set border 2 lt 1 lc rgb "black" | ||
set ylabel "Relative error" | ||
|
||
set xtics ("blackscholes" 1,"bodytrack" 2,"facesim" 3,"fluidanimate" 4,"freqmine" 5,"swaptions" 6,"vips" 7,"x264" 8) | ||
set xtics rotate by -45 nomirror font ",16" | ||
set format y "%.00f%%" | ||
|
||
unset key | ||
|
||
mred = '#CC0000' | ||
|
||
plot 0 lt 3 linecolor rgb "black",\ | ||
'errors-data/blackscholes/errors.csv' u (1):($2*100) lt 1 linecolor rgb mred,\ | ||
'errors-data/bodytrack/errors.csv' u (2):($2*100) lt 1 linecolor rgb mred,\ | ||
'errors-data/facesim/errors.csv' u (3):($2*100) lt 1 linecolor rgb mred,\ | ||
'errors-data/fluidanimate/errors.csv' u (4):($2*100) lt 1 linecolor rgb mred,\ | ||
'errors-data/freqmine/errors.csv' u (5):($2*100) lt 1 linecolor rgb mred,\ | ||
'errors-data/swaptions/errors.csv' u (6):($2*100) lt 1 linecolor rgb mred,\ | ||
'errors-data/vips/errors.csv' u (7):($2*100) lt 1 linecolor rgb mred |
62 changes: 62 additions & 0 deletions
62
bitwatts-eurosys-2015/src/universal/scripts/figure8-9/process.py
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Script to process the data used for plotting the Figure 9. | ||
# The data come from the corresponding experiment in bitwatts-eurosys-2015. | ||
# @author: Maxime Colmant | ||
import os | ||
import glob | ||
import re | ||
import numpy as np | ||
import csv | ||
import shutil | ||
import argparse | ||
|
||
parser = argparse.ArgumentParser() | ||
parser.add_argument("path", help="experiment data path.") | ||
parser.add_argument('idle', help = 'idle power of the machine.') | ||
args = parser.parse_args() | ||
|
||
powers_filename = 'output-external.dat' | ||
powerapi_filename = 'output-powerapi.dat' | ||
|
||
output_path = os.path.join('errors-data') | ||
|
||
# Creates the output data directory | ||
if os.path.exists(output_path): | ||
shutil.rmtree(output_path) | ||
|
||
os.mkdir(output_path) | ||
|
||
for benchmark in filter((lambda name: os.path.isdir(os.path.join(args.path, name))), os.listdir(args.path)): | ||
benchmark_path = os.path.join(args.path, benchmark) | ||
benchmark_output_path = os.path.join(output_path, benchmark) | ||
|
||
if os.path.exists(benchmark_output_path): | ||
shutil.rmtree(benchmark_output_path) | ||
|
||
# Creates the output data directory for the benchmark | ||
os.mkdir(benchmark_output_path) | ||
|
||
# Reads files and converts data into numpy arrays | ||
real_powers_f = open(os.path.join(benchmark_path, powers_filename)) | ||
real_powers_d = np.array([ float(re.search('power=([0-9]+\.[0-9]+)$', line, re.IGNORECASE).group(1)) for line in real_powers_f ]) | ||
real_powers_f.close() | ||
|
||
papi_powers_f = open(os.path.join(benchmark_path, powerapi_filename)) | ||
papi_powers_d = np.array([ float(re.search('power=([0-9]+\.[0-9]+)$', line, re.IGNORECASE).group(1)) for line in papi_powers_f ]) | ||
papi_powers_f.close() | ||
|
||
# Computes the errors | ||
absolute_errors = real_powers_d - (papi_powers_d + float(args.idle)) | ||
relative_errors = (real_powers_d - (papi_powers_d + float(args.idle))) / real_powers_d | ||
errors = zip(absolute_errors, relative_errors) | ||
|
||
# Writes errors for each benchmark for the gnuplot script | ||
with open("%s/errors.csv" % benchmark_output_path, 'a') as csvfile: | ||
writer = csv.writer(csvfile, quotechar='', quoting=csv.QUOTE_NONE, delimiter=' ') | ||
writer.writerow(['#', 'abs_error', 'rel_error']) | ||
|
||
for abs_error, rel_error in errors: | ||
writer.writerow([abs_error, rel_error]) | ||
|
||
# Writes statistical informations about errors | ||
with open("%s/global-errors.txt" % output_path, 'a') as f: | ||
f.write("%s => median relative error: %f%%, max relative error: %f%%\n" % (benchmark, (np.median(relative_errors) * 100), (max(relative_errors) * 100))) |