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