blob: eadc0289becc96e075fd059e7f49e9c200db0093 [file] [log] [blame]
Christophe Favergeon8cb37302020-05-13 13:06:58 +02001import argparse
2import sqlite3
3import re
4import pandas as pd
5import numpy as np
6
7# Command to get last runid
8lastID="""SELECT runid FROM RUN ORDER BY runid DESC LIMIT 1
9"""
10
11def getLastRunID():
12 r=c.execute(lastID)
13 return(int(r.fetchone()[0]))
14
15
16runid = 1
17
18parser = argparse.ArgumentParser(description='Generate summary benchmarks')
19
20parser.add_argument('-b', nargs='?',type = str, default="bench.db", help="Benchmark database")
21parser.add_argument('-o', nargs='?',type = str, default="full.md", help="Full summary")
22parser.add_argument('-r', action='store_true', help="Regression database")
23
24# For runid or runid range
25parser.add_argument('others', nargs=argparse.REMAINDER)
26
27args = parser.parse_args()
28
29c = sqlite3.connect(args.b)
30
31if args.others:
32 runid=int(args.others[0])
33else:
34 runid=getLastRunID()
35
36# We extract data only from data tables
37# Those tables below are used for descriptions
38REMOVETABLES=['RUN','CORE', 'PLATFORM', 'COMPILERKIND', 'COMPILER', 'TYPE', 'CATEGORY', 'CONFIG']
39
40# This is assuming the database is generated by the regression script
41# So platform is the same for all benchmarks.
42# Category and type is coming from the test name in the yaml
43# So no need to add this information here
44# Name is removed here because it is added at the beginning
45REMOVECOLUMNS=['runid','NAME','type','platform','category','coredef','OPTIMIZED','HARDFP','FASTMATH','NEON','HELIUM','UNROLL','ROUNDING','DATE','compilerkindid','date','categoryid', 'ID', 'platformid', 'coreid', 'compilerid', 'typeid']
46
47# Get existing benchmark tables
48def getBenchTables():
49 r=c.execute("SELECT name FROM sqlite_master WHERE type='table'")
50 benchtables=[]
51 for table in r:
52 if not table[0] in REMOVETABLES:
53 benchtables.append(table[0])
54 return(benchtables)
55
56# get existing types in a table
57def getExistingTypes(benchTable):
58 r=c.execute("select distinct typeid from %s" % benchTable).fetchall()
59 result=[x[0] for x in r]
60 return(result)
61
62# Get compilers from specific type and table
63versioncompiler="""select distinct compiler,version from %s
64 INNER JOIN COMPILER USING(compilerid)
65 INNER JOIN COMPILERKIND USING(compilerkindid) WHERE typeid=?"""
66
67# Get existing compiler in a table for a specific type
68# (In case report is structured by types)
69def getExistingCompiler(benchTable,typeid):
70 r=c.execute(versioncompiler % benchTable,(typeid,)).fetchall()
71 return(r)
72
73# Get type name from type id
74def getTypeName(typeid):
75 r=c.execute("select type from TYPE where typeid=?",(typeid,)).fetchone()
76 return(r[0])
77
78# Diff of 2 lists
79def diff(first, second):
80 second = set(second)
81 return [item for item in first if item not in second]
82
83
84# Command to get data for specific compiler
85# and type
86benchCmd="""select %s from %s
87 INNER JOIN CATEGORY USING(categoryid)
88 INNER JOIN PLATFORM USING(platformid)
89 INNER JOIN CORE USING(coreid)
90 INNER JOIN COMPILER USING(compilerid)
91 INNER JOIN COMPILERKIND USING(compilerkindid)
92 INNER JOIN TYPE USING(typeid)
93 WHERE compiler=? AND VERSION=? AND typeid = ? AND runid = ?
94 """
95
Christophe Favergeon4f750702020-05-13 15:56:15 +020096# Command to get data for specific compiler
97# and type
98nbElemsCmd="""select count(*) from %s
99 INNER JOIN CATEGORY USING(categoryid)
100 INNER JOIN PLATFORM USING(platformid)
101 INNER JOIN CORE USING(coreid)
102 INNER JOIN COMPILER USING(compilerid)
103 INNER JOIN COMPILERKIND USING(compilerkindid)
104 INNER JOIN TYPE USING(typeid)
105 WHERE compiler=? AND VERSION=? AND typeid = ? AND runid = ?
106 """
107
Christophe Favergeon8cb37302020-05-13 13:06:58 +0200108# Command to get test names for specific compiler
109# and type
110benchNames="""select distinct NAME from %s
111 INNER JOIN COMPILER USING(compilerid)
112 INNER JOIN COMPILERKIND USING(compilerkindid)
113 INNER JOIN TYPE USING(typeid)
114 WHERE compiler=? AND VERSION=? AND typeid = ? AND runid = ?
115 """
116
117# Command to get columns for specific table
118benchCmdColumns="""select * from %s
119 INNER JOIN CATEGORY USING(categoryid)
120 INNER JOIN PLATFORM USING(platformid)
121 INNER JOIN CORE USING(coreid)
122 INNER JOIN COMPILER USING(compilerid)
123 INNER JOIN COMPILERKIND USING(compilerkindid)
124 INNER JOIN TYPE USING(typeid)
125 """
126
127def joinit(iterable, delimiter):
128 it = iter(iterable)
129 yield next(it)
130 for x in it:
131 yield delimiter
132 yield x
133
134# Is not a column name finishing by id
135# (often primary key for thetable)
136def isNotIDColumn(col):
137 if re.match(r'^.*id$',col):
138 return(False)
139 else:
140 return(True)
141
142# Get test names
143# for specific typeid and compiler (for the data)
144def getTestNames(benchTable,comp,typeid):
145 vals=(comp[0],comp[1],typeid,runid)
146 result=c.execute(benchNames % benchTable,vals).fetchall()
147 return([x[0] for x in list(result)])
148
Christophe Favergeon4f750702020-05-13 15:56:15 +0200149# Get nb elems in a table
150def getNbElems(benchTable,comp,typeid):
151 vals=(comp[0],comp[1],typeid,runid)
152 result=c.execute(nbElemsCmd % benchTable,vals).fetchone()
153 return(result[0])
154
Christophe Favergeon8cb37302020-05-13 13:06:58 +0200155# Get names of columns and data for a table
156# for specific typeid and compiler (for the data)
157def getColNamesAndData(benchTable,comp,typeid):
158 cursor=c.cursor()
159 result=cursor.execute(benchCmdColumns % (benchTable))
160 cols= [member[0] for member in cursor.description]
161 keepCols = ['NAME'] + [c for c in diff(cols , REMOVECOLUMNS) if isNotIDColumn(c)]
162 keepColsStr = "".join(joinit(keepCols,","))
163 vals=(comp[0],comp[1],typeid,runid)
164 result=cursor.execute(benchCmd % (keepColsStr,benchTable),vals)
165 vals =np.array([list(x) for x in list(result)])
166 return(keepCols,vals)
167
168# Write columns in markdown format
169def writeColumns(f,cols):
170 colStr = "".join(joinit(cols,"|"))
171 f.write("|")
172 f.write(colStr)
173 f.write("|\n")
174 sepStr="".join(joinit([":-:" for x in cols],"|"))
175 f.write("|")
176 f.write(sepStr)
177 f.write("|\n")
178
179# Write row in markdown format
180def writeRow(f,row):
181 row=[str(x) for x in row]
182 rowStr = "".join(joinit(row,"|"))
183 f.write("|")
184 f.write(rowStr)
185 f.write("|\n")
186
187PARAMS=["NB","NumTaps", "NBA", "NBB", "Factor", "NumStages","VECDIM","NBR","NBC","NBI","IFFT", "BITREV"]
188
189def regressionTableFor(name,output,ref,toSort,indexCols,field):
190 data=ref.pivot_table(index=indexCols, columns='core',
191 values=[field], aggfunc='first')
192
193 data=data.sort_values(toSort)
194
195 cores = [c[1] for c in list(data.columns)]
196 columns = diff(indexCols,['NAME']) + cores
197
198 writeColumns(output,columns)
199 dataForFunc=data.loc[name]
200 if type(dataForFunc) is pd.DataFrame:
201 for row in dataForFunc.itertuples():
202 row=list(row)
203 if type(row[0]) is int:
204 row=[row[0]] + row[1:]
205 else:
206 row=list(row[0]) + row[1:]
207 writeRow(output,row)
208 else:
209 writeRow(output,dataForFunc)
210
211def formatTableByCore(output,testNames,cols,vals):
212 if vals.size != 0:
213 ref=pd.DataFrame(vals,columns=cols)
214 toSort=["NAME"]
215
216 for param in PARAMS:
217 if param in ref.columns:
218 ref[param]=pd.to_numeric(ref[param])
219 toSort.append(param)
220 if args.r:
221 # Regression table
222 ref['MAX']=pd.to_numeric(ref['MAX'])
223 ref['MAXREGCOEF']=pd.to_numeric(ref['MAXREGCOEF'])
224
225 indexCols=diff(cols,['core','Regression','MAXREGCOEF','MAX','version','compiler'])
226 valList = ['Regression']
227 else:
228 ref['CYCLES']=pd.to_numeric(ref['CYCLES'])
229
230 indexCols=diff(cols,['core','CYCLES','version','compiler'])
231 valList = ['CYCLES']
232
233
234
235 for name in testNames:
236 if args.r:
237 output.write("#### %s\n" % name)
238
239 output.write("##### Regression\n" )
240 regressionTableFor(name,output,ref,toSort,indexCols,'Regression')
241
242 output.write("##### Max cycles\n" )
243 regressionTableFor(name,output,ref,toSort,indexCols,'MAX')
244
245 output.write("##### Max Reg Coef\n" )
246 regressionTableFor(name,output,ref,toSort,indexCols,'MAXREGCOEF')
247
248 else:
249 data=ref.pivot_table(index=indexCols, columns='core',
250 values=valList, aggfunc='first')
251
252 data=data.sort_values(toSort)
253
254 cores = [c[1] for c in list(data.columns)]
255 columns = diff(indexCols,['NAME']) + cores
256
257 output.write("#### %s\n" % name)
258 writeColumns(output,columns)
259 dataForFunc=data.loc[name]
260 if type(dataForFunc) is pd.DataFrame:
261 for row in dataForFunc.itertuples():
262 row=list(row)
263 if type(row[0]) is int:
264 row=[row[0]] + row[1:]
265 else:
266 row=list(row[0]) + row[1:]
267 writeRow(output,row)
268 else:
269 writeRow(output,dataForFunc)
270
271# Add a report for each table
272def addReportFor(output,benchName):
273 print("Process %s\n" % benchName)
274 output.write("# %s\n" % benchName)
275 allTypes = getExistingTypes(benchName)
276 # Add report for each type
277 for aTypeID in allTypes:
278 typeName = getTypeName(aTypeID)
279 output.write("## %s\n" % typeName)
280 ## Add report for each compiler
281 allCompilers = getExistingCompiler(benchName,aTypeID)
282 for compiler in allCompilers:
283 #print(compiler)
Christophe Favergeon4f750702020-05-13 15:56:15 +0200284 nbElems = getNbElems(benchName,compiler,aTypeID)
285 # Print test results for table, type, compiler
286 if nbElems > 0:
287 output.write("### %s (%s)\n" % compiler)
288 cols,vals=getColNamesAndData(benchName,compiler,aTypeID)
289 names=getTestNames(benchName,compiler,aTypeID)
290 formatTableByCore(output,names,cols,vals)
Christophe Favergeon8cb37302020-05-13 13:06:58 +0200291
292
293
294
295
296try:
297 with open(args.o,"w") as output:
298 benchtables=getBenchTables()
299 for bench in benchtables:
300 addReportFor(output,bench)
301finally:
302 c.close()
303
304