|
|
@@ -4,6 +4,361 @@ import re
|
|
|
import pandas as pd
|
|
|
import numpy as np
|
|
|
|
|
|
+class Document:
|
|
|
+ def __init__(self,runid,date):
|
|
|
+ self._runid = runid
|
|
|
+ self._date = date
|
|
|
+ self._sections = []
|
|
|
+
|
|
|
+ @property
|
|
|
+ def runid(self):
|
|
|
+ return(self._runid)
|
|
|
+
|
|
|
+ @property
|
|
|
+ def date(self):
|
|
|
+ return(self._date)
|
|
|
+
|
|
|
+ @property
|
|
|
+ def sections(self):
|
|
|
+ return(self._sections)
|
|
|
+
|
|
|
+ def addSection(self,section):
|
|
|
+ self._sections.append(section)
|
|
|
+
|
|
|
+ def accept(self, visitor):
|
|
|
+ visitor.visitDocument(self)
|
|
|
+ for element in self._sections:
|
|
|
+ element.accept(visitor)
|
|
|
+ visitor.leaveDocument(self)
|
|
|
+
|
|
|
+class Section:
|
|
|
+ def __init__(self,name):
|
|
|
+ self._name=name
|
|
|
+ self._subsections = []
|
|
|
+ self._tables = []
|
|
|
+
|
|
|
+ def addSection(self,section):
|
|
|
+ self._subsections.append(section)
|
|
|
+
|
|
|
+ def addTable(self,table):
|
|
|
+ self._tables.append(table)
|
|
|
+
|
|
|
+ @property
|
|
|
+ def hasChildren(self):
|
|
|
+ return(len(self._subsections)>0)
|
|
|
+
|
|
|
+ @property
|
|
|
+ def name(self):
|
|
|
+ return(self._name)
|
|
|
+
|
|
|
+ def accept(self, visitor):
|
|
|
+ visitor.visitSection(self)
|
|
|
+ for element in self._subsections:
|
|
|
+ element.accept(visitor)
|
|
|
+ for element in self._tables:
|
|
|
+ element.accept(visitor)
|
|
|
+ visitor.leaveSection(self)
|
|
|
+
|
|
|
+class Table:
|
|
|
+ def __init__(self,columns):
|
|
|
+ self._columns=columns
|
|
|
+ self._rows=[]
|
|
|
+
|
|
|
+ def addRow(self,row):
|
|
|
+ self._rows.append(row)
|
|
|
+
|
|
|
+ @property
|
|
|
+ def columns(self):
|
|
|
+ return(self._columns)
|
|
|
+
|
|
|
+ @property
|
|
|
+ def rows(self):
|
|
|
+ return(self._rows)
|
|
|
+
|
|
|
+ def accept(self, visitor):
|
|
|
+ visitor.visitTable(self)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class Markdown:
|
|
|
+ def __init__(self,output):
|
|
|
+ self._id=0
|
|
|
+ self._output = output
|
|
|
+
|
|
|
+ # Write columns in markdown format
|
|
|
+ def writeColumns(self,cols):
|
|
|
+ colStr = "".join(joinit(cols,"|"))
|
|
|
+ self._output.write("|")
|
|
|
+ self._output.write(colStr)
|
|
|
+ self._output.write("|\n")
|
|
|
+ sepStr="".join(joinit([":-:" for x in cols],"|"))
|
|
|
+ self._output.write("|")
|
|
|
+ self._output.write(sepStr)
|
|
|
+ self._output.write("|\n")
|
|
|
+
|
|
|
+ # Write row in markdown format
|
|
|
+ def writeRow(self,row):
|
|
|
+ row=[str(x) for x in row]
|
|
|
+ rowStr = "".join(joinit(row,"|"))
|
|
|
+ self._output.write("|")
|
|
|
+ self._output.write(rowStr)
|
|
|
+ self._output.write("|\n")
|
|
|
+
|
|
|
+ def visitTable(self,table):
|
|
|
+ self.writeColumns(table.columns)
|
|
|
+ for row in table.rows:
|
|
|
+ self.writeRow(row)
|
|
|
+
|
|
|
+ def visitSection(self,section):
|
|
|
+ self._id = self._id + 1
|
|
|
+ header = "".join(["#" for i in range(self._id)])
|
|
|
+ output.write("%s %s\n" % (header,section.name))
|
|
|
+
|
|
|
+ def leaveSection(self,section):
|
|
|
+ self._id = self._id - 1
|
|
|
+
|
|
|
+ def visitDocument(self,document):
|
|
|
+ self._output.write("Run number %d on %s\n" % (document.runid, str(document.date)))
|
|
|
+
|
|
|
+ def leaveDocument(self,document):
|
|
|
+ pass
|
|
|
+
|
|
|
+styleSheet="""
|
|
|
+<style type='text/css'>
|
|
|
+
|
|
|
+#TOC {
|
|
|
+ position: fixed;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ width: 250px;
|
|
|
+ height: 100%;
|
|
|
+ overflow:auto;
|
|
|
+}
|
|
|
+
|
|
|
+html {
|
|
|
+ font-size: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+html, body {
|
|
|
+ background-color: #f3f2ee;
|
|
|
+ font-family: "PT Serif", 'Times New Roman', Times, serif;
|
|
|
+ color: #1f0909;
|
|
|
+ line-height: 1.5em;
|
|
|
+
|
|
|
+ margin: auto;
|
|
|
+ margin-left:220px;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+table {
|
|
|
+ border-collapse: collapse;
|
|
|
+ border-spacing: 0;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+h1,
|
|
|
+h2,
|
|
|
+h3,
|
|
|
+h4,
|
|
|
+h5,
|
|
|
+h6 {
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+h1 {
|
|
|
+ font-size: 1.875em;
|
|
|
+ line-height: 1.6em;
|
|
|
+ margin-top: 1em;
|
|
|
+}
|
|
|
+h2,
|
|
|
+h3 {
|
|
|
+ font-size: 1.3125em;
|
|
|
+ line-height: 1.15;
|
|
|
+ margin-top: 2.285714em;
|
|
|
+ margin-bottom: 1.15em;
|
|
|
+}
|
|
|
+h4 {
|
|
|
+ font-size: 1.125em;
|
|
|
+ margin-top: 2.67em;
|
|
|
+}
|
|
|
+h5,
|
|
|
+h6 {
|
|
|
+ font-size: 1em;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+table {
|
|
|
+ margin-bottom: 1.5em;
|
|
|
+ /*24 / 16*/
|
|
|
+ font-size: 1em;
|
|
|
+ /* width: 100%; */
|
|
|
+}
|
|
|
+thead th,
|
|
|
+tfoot th {
|
|
|
+ padding: .25em .25em .25em .4em;
|
|
|
+ text-transform: uppercase;
|
|
|
+}
|
|
|
+th {
|
|
|
+ text-align: left;
|
|
|
+}
|
|
|
+td {
|
|
|
+ vertical-align: top;
|
|
|
+ padding: .25em .25em .25em .4em;
|
|
|
+}
|
|
|
+
|
|
|
+.ty-table-edit {
|
|
|
+ background-color: transparent;
|
|
|
+}
|
|
|
+thead {
|
|
|
+ background-color: #dadada;
|
|
|
+}
|
|
|
+tr:nth-child(even) {
|
|
|
+ background: #e8e7e7;
|
|
|
+}
|
|
|
+
|
|
|
+ul, #myUL {
|
|
|
+ list-style-type: none;
|
|
|
+ padding-inline-start:10px;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/* Remove margins and padding from the parent ul */
|
|
|
+#myUL {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* Style the caret/arrow */
|
|
|
+.caret {
|
|
|
+ cursor: pointer;
|
|
|
+ user-select: none; /* Prevent text selection */
|
|
|
+}
|
|
|
+
|
|
|
+/* Create the caret/arrow with a unicode, and style it */
|
|
|
+.caret::before {
|
|
|
+ content: "\\25B6";
|
|
|
+ color: black;
|
|
|
+ display: inline-block;
|
|
|
+ margin-right: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
|
|
|
+.caret-down::before {
|
|
|
+ transform: rotate(90deg);
|
|
|
+}
|
|
|
+
|
|
|
+/* Hide the nested list */
|
|
|
+.nested {
|
|
|
+ display: none;
|
|
|
+}
|
|
|
+
|
|
|
+/* Show the nested list when the user clicks on the caret/arrow (with JavaScript) */
|
|
|
+.active {
|
|
|
+ display: block;
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|
|
|
+"""
|
|
|
+
|
|
|
+script="""<script type="text/javascript">
|
|
|
+var toggler = document.getElementsByClassName("caret");
|
|
|
+var i;
|
|
|
+for (i = 0; i < toggler.length; i++) {
|
|
|
+ toggler[i].addEventListener("click", function() {
|
|
|
+ this.parentElement.querySelector(".nested").classList.toggle("active");
|
|
|
+ this.classList.toggle("caret-down");
|
|
|
+ });
|
|
|
+}</script>"""
|
|
|
+
|
|
|
+
|
|
|
+class HTMLToc:
|
|
|
+ def __init__(self,output):
|
|
|
+ self._id=0
|
|
|
+ self._sectionID = 0
|
|
|
+ self._output = output
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ def visitTable(self,table):
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+ def visitSection(self,section):
|
|
|
+ self._id = self._id + 1
|
|
|
+ self._sectionID = self._sectionID + 1
|
|
|
+ if section.hasChildren:
|
|
|
+ self._output.write("<li><span class=\"caret\"><a href=\"#section%d\">%s</a></span>\n" % (self._sectionID,section.name))
|
|
|
+ self._output.write("<ul class=\"nested\">\n")
|
|
|
+ else:
|
|
|
+ self._output.write("<li><span><a href=\"#section%d\">%s</a></span>\n" % (self._sectionID,section.name))
|
|
|
+
|
|
|
+ def leaveSection(self,section):
|
|
|
+ if section.hasChildren:
|
|
|
+ self._output.write("</ul></li>\n")
|
|
|
+
|
|
|
+ self._id = self._id - 1
|
|
|
+
|
|
|
+ def visitDocument(self,document):
|
|
|
+ self._output.write("<div id=\"TOC\"><h1>Table of content</h1><ul id=\"myUL\">\n")
|
|
|
+
|
|
|
+
|
|
|
+ def leaveDocument(self,document):
|
|
|
+ self._output.write("</ul></div>%s\n" % script)
|
|
|
+
|
|
|
+
|
|
|
+class HTML:
|
|
|
+ def __init__(self,output):
|
|
|
+ self._id=0
|
|
|
+ self._sectionID = 0
|
|
|
+ self._output = output
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ def visitTable(self,table):
|
|
|
+ output.write("<table>\n")
|
|
|
+ output.write("<thead>\n")
|
|
|
+ output.write("<tr>\n")
|
|
|
+ for col in table.columns:
|
|
|
+ output.write("<th>")
|
|
|
+ output.write(str(col))
|
|
|
+ output.write("</th>\n")
|
|
|
+ output.write("</tr>\n")
|
|
|
+ output.write("</thead>\n")
|
|
|
+ for row in table.rows:
|
|
|
+ output.write("<tr>\n")
|
|
|
+ for elem in row:
|
|
|
+ output.write("<td>")
|
|
|
+ output.write(str(elem))
|
|
|
+ output.write("</td>\n")
|
|
|
+ output.write("</tr>\n")
|
|
|
+ output.write("</table>\n")
|
|
|
+
|
|
|
+
|
|
|
+ def visitSection(self,section):
|
|
|
+ self._id = self._id + 1
|
|
|
+ self._sectionID = self._sectionID + 1
|
|
|
+ output.write("<h%d id=\"section%d\">%s</h%d>\n" % (self._id,self._sectionID,section.name,self._id))
|
|
|
+
|
|
|
+ def leaveSection(self,section):
|
|
|
+ self._id = self._id - 1
|
|
|
+
|
|
|
+ def visitDocument(self,document):
|
|
|
+ self._output.write("""<!doctype html>
|
|
|
+<html>
|
|
|
+<head>
|
|
|
+<meta charset='UTF-8'><meta name='viewport' content='width=device-width initial-scale=1'>
|
|
|
+<title>Benchmarks</title>%s</head><body>\n""" % styleSheet)
|
|
|
+ self._output.write("<p>Run number %d on %s</p>\n" % (document.runid, str(document.date)))
|
|
|
+
|
|
|
+ def leaveDocument(self,document):
|
|
|
+ document.accept(HTMLToc(self._output))
|
|
|
+
|
|
|
+ self._output.write("</body></html>\n")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
# Command to get last runid
|
|
|
lastID="""SELECT runid FROM RUN ORDER BY runid DESC LIMIT 1
|
|
|
"""
|
|
|
@@ -27,6 +382,7 @@ parser = argparse.ArgumentParser(description='Generate summary benchmarks')
|
|
|
parser.add_argument('-b', nargs='?',type = str, default="bench.db", help="Benchmark database")
|
|
|
parser.add_argument('-o', nargs='?',type = str, default="full.md", help="Full summary")
|
|
|
parser.add_argument('-r', action='store_true', help="Regression database")
|
|
|
+parser.add_argument('-t', nargs='?',type = str, default="md", help="md,html")
|
|
|
|
|
|
# For runid or runid range
|
|
|
parser.add_argument('others', nargs=argparse.REMAINDER)
|
|
|
@@ -203,28 +559,11 @@ def getColNamesAndData(benchTable,comp,typeid):
|
|
|
vals =np.array([list(x) for x in list(result)])
|
|
|
return(keepCols,vals)
|
|
|
|
|
|
-# Write columns in markdown format
|
|
|
-def writeColumns(f,cols):
|
|
|
- colStr = "".join(joinit(cols,"|"))
|
|
|
- f.write("|")
|
|
|
- f.write(colStr)
|
|
|
- f.write("|\n")
|
|
|
- sepStr="".join(joinit([":-:" for x in cols],"|"))
|
|
|
- f.write("|")
|
|
|
- f.write(sepStr)
|
|
|
- f.write("|\n")
|
|
|
-
|
|
|
-# Write row in markdown format
|
|
|
-def writeRow(f,row):
|
|
|
- row=[str(x) for x in row]
|
|
|
- rowStr = "".join(joinit(row,"|"))
|
|
|
- f.write("|")
|
|
|
- f.write(rowStr)
|
|
|
- f.write("|\n")
|
|
|
+
|
|
|
|
|
|
PARAMS=["NB","NumTaps", "NBA", "NBB", "Factor", "NumStages","VECDIM","NBR","NBC","NBI","IFFT", "BITREV"]
|
|
|
|
|
|
-def regressionTableFor(name,output,ref,toSort,indexCols,field):
|
|
|
+def regressionTableFor(name,section,ref,toSort,indexCols,field):
|
|
|
data=ref.pivot_table(index=indexCols, columns='core',
|
|
|
values=[field], aggfunc='first')
|
|
|
|
|
|
@@ -233,7 +572,9 @@ def regressionTableFor(name,output,ref,toSort,indexCols,field):
|
|
|
cores = [c[1] for c in list(data.columns)]
|
|
|
columns = diff(indexCols,['NAME']) + cores
|
|
|
|
|
|
- writeColumns(output,columns)
|
|
|
+ dataTable=Table(columns)
|
|
|
+ section.addTable(dataTable)
|
|
|
+
|
|
|
dataForFunc=data.loc[name]
|
|
|
if type(dataForFunc) is pd.DataFrame:
|
|
|
for row in dataForFunc.itertuples():
|
|
|
@@ -242,11 +583,11 @@ def regressionTableFor(name,output,ref,toSort,indexCols,field):
|
|
|
row=[row[0]] + row[1:]
|
|
|
else:
|
|
|
row=list(row[0]) + row[1:]
|
|
|
- writeRow(output,row)
|
|
|
+ dataTable.addRow(row)
|
|
|
else:
|
|
|
- writeRow(output,dataForFunc)
|
|
|
+ dataTable.addRow(dataForFunc)
|
|
|
|
|
|
-def formatTableByCore(output,testNames,cols,vals):
|
|
|
+def formatTableByCore(typeSection,testNames,cols,vals):
|
|
|
if vals.size != 0:
|
|
|
ref=pd.DataFrame(vals,columns=cols)
|
|
|
toSort=["NAME"]
|
|
|
@@ -272,16 +613,20 @@ def formatTableByCore(output,testNames,cols,vals):
|
|
|
|
|
|
for name in testNames:
|
|
|
if args.r:
|
|
|
- output.write("#### %s\n" % name)
|
|
|
+ testSection = Section(name)
|
|
|
+ typeSection.addSection(testSection)
|
|
|
|
|
|
- output.write("##### Regression\n" )
|
|
|
- regressionTableFor(name,output,ref,toSort,indexCols,'Regression')
|
|
|
+ regressionSection = Section("Regression")
|
|
|
+ testSection.addSection(regressionSection)
|
|
|
+ regressionTableFor(name,regressionSection,ref,toSort,indexCols,'Regression')
|
|
|
|
|
|
- output.write("##### Max cycles\n" )
|
|
|
- regressionTableFor(name,output,ref,toSort,indexCols,'MAX')
|
|
|
+ maxCyclesSection = Section("Max cycles")
|
|
|
+ testSection.addSection(maxCyclesSection)
|
|
|
+ regressionTableFor(name,maxCyclesSection,ref,toSort,indexCols,'MAX')
|
|
|
|
|
|
- output.write("##### Max Reg Coef\n" )
|
|
|
- regressionTableFor(name,output,ref,toSort,indexCols,'MAXREGCOEF')
|
|
|
+ maxRegCoefSection = Section("Max Reg Coef")
|
|
|
+ testSection.addSection(maxRegCoefSection)
|
|
|
+ regressionTableFor(name,maxRegCoefSection,ref,toSort,indexCols,'MAXREGCOEF')
|
|
|
|
|
|
else:
|
|
|
data=ref.pivot_table(index=indexCols, columns='core',
|
|
|
@@ -292,8 +637,12 @@ def formatTableByCore(output,testNames,cols,vals):
|
|
|
cores = [c[1] for c in list(data.columns)]
|
|
|
columns = diff(indexCols,['NAME']) + cores
|
|
|
|
|
|
- output.write("#### %s\n" % name)
|
|
|
- writeColumns(output,columns)
|
|
|
+ testSection = Section(name)
|
|
|
+ typeSection.addSection(testSection)
|
|
|
+
|
|
|
+ dataTable=Table(columns)
|
|
|
+ testSection.addTable(dataTable)
|
|
|
+
|
|
|
dataForFunc=data.loc[name]
|
|
|
if type(dataForFunc) is pd.DataFrame:
|
|
|
for row in dataForFunc.itertuples():
|
|
|
@@ -302,23 +651,25 @@ def formatTableByCore(output,testNames,cols,vals):
|
|
|
row=[row[0]] + row[1:]
|
|
|
else:
|
|
|
row=list(row[0]) + row[1:]
|
|
|
- writeRow(output,row)
|
|
|
+ dataTable.addRow(row)
|
|
|
else:
|
|
|
- writeRow(output,dataForFunc)
|
|
|
+ dataTable.addRow(dataForFunc)
|
|
|
|
|
|
# Add a report for each table
|
|
|
-def addReportFor(output,benchName):
|
|
|
+def addReportFor(document,benchName):
|
|
|
nbElems = getNbElemsInBenchCmd(benchName)
|
|
|
if nbElems > 0:
|
|
|
+ benchSection = Section(benchName)
|
|
|
+ document.addSection(benchSection)
|
|
|
print("Process %s\n" % benchName)
|
|
|
- output.write("# %s\n" % benchName)
|
|
|
allTypes = getExistingTypes(benchName)
|
|
|
# Add report for each type
|
|
|
for aTypeID in allTypes:
|
|
|
nbElems = getNbElemsInBenchAndTypeCmd(benchName,aTypeID)
|
|
|
if nbElems > 0:
|
|
|
typeName = getTypeName(aTypeID)
|
|
|
- output.write("## %s\n" % typeName)
|
|
|
+ typeSection = Section(typeName)
|
|
|
+ benchSection.addSection(typeSection)
|
|
|
## Add report for each compiler
|
|
|
allCompilers = getExistingCompiler(benchName,aTypeID)
|
|
|
for compiler in allCompilers:
|
|
|
@@ -326,23 +677,31 @@ def addReportFor(output,benchName):
|
|
|
nbElems = getNbElemsInBenchAndTypeAndCompilerCmd(benchName,compiler,aTypeID)
|
|
|
# Print test results for table, type, compiler
|
|
|
if nbElems > 0:
|
|
|
- output.write("### %s (%s)\n" % compiler)
|
|
|
+ compilerSection = Section("%s (%s)" % compiler)
|
|
|
+ typeSection.addSection(compilerSection)
|
|
|
cols,vals=getColNamesAndData(benchName,compiler,aTypeID)
|
|
|
names=getTestNames(benchName,compiler,aTypeID)
|
|
|
- formatTableByCore(output,names,cols,vals)
|
|
|
+ formatTableByCore(compilerSection,names,cols,vals)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
- with open(args.o,"w") as output:
|
|
|
benchtables=getBenchTables()
|
|
|
theDate = getrunIDDate(runid)
|
|
|
- output.write("Run number %d on %s\n" % (runid, str(theDate)))
|
|
|
+ document = Document(runid,theDate)
|
|
|
for bench in benchtables:
|
|
|
- addReportFor(output,bench)
|
|
|
+ addReportFor(document,bench)
|
|
|
+ with open(args.o,"w") as output:
|
|
|
+ if args.t=="md":
|
|
|
+ document.accept(Markdown(output))
|
|
|
+ if args.t=="html":
|
|
|
+ document.accept(HTML(output))
|
|
|
+
|
|
|
finally:
|
|
|
c.close()
|
|
|
|
|
|
+
|
|
|
+
|
|
|
|