blob: 13595bd936efbdfc3236309803dff4df020099bb [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
96# Command to get test names for specific compiler
97# and type
98benchNames="""select distinct NAME from %s
99 INNER JOIN COMPILER USING(compilerid)
100 INNER JOIN COMPILERKIND USING(compilerkindid)
101 INNER JOIN TYPE USING(typeid)
102 WHERE compiler=? AND VERSION=? AND typeid = ? AND runid = ?
103 """
104
105# Command to get columns for specific table
106benchCmdColumns="""select * from %s
107 INNER JOIN CATEGORY USING(categoryid)
108 INNER JOIN PLATFORM USING(platformid)
109 INNER JOIN CORE USING(coreid)
110 INNER JOIN COMPILER USING(compilerid)
111 INNER JOIN COMPILERKIND USING(compilerkindid)
112 INNER JOIN TYPE USING(typeid)
113 """
114
115def joinit(iterable, delimiter):
116 it = iter(iterable)
117 yield next(it)
118 for x in it:
119 yield delimiter
120 yield x
121
122# Is not a column name finishing by id
123# (often primary key for thetable)
124def isNotIDColumn(col):
125 if re.match(r'^.*id$',col):
126 return(False)
127 else:
128 return(True)
129
130# Get test names
131# for specific typeid and compiler (for the data)
132def getTestNames(benchTable,comp,typeid):
133 vals=(comp[0],comp[1],typeid,runid)
134 result=c.execute(benchNames % benchTable,vals).fetchall()
135 return([x[0] for x in list(result)])
136
137# Get names of columns and data for a table
138# for specific typeid and compiler (for the data)
139def getColNamesAndData(benchTable,comp,typeid):
140 cursor=c.cursor()
141 result=cursor.execute(benchCmdColumns % (benchTable))
142 cols= [member[0] for member in cursor.description]
143 keepCols = ['NAME'] + [c for c in diff(cols , REMOVECOLUMNS) if isNotIDColumn(c)]
144 keepColsStr = "".join(joinit(keepCols,","))
145 vals=(comp[0],comp[1],typeid,runid)
146 result=cursor.execute(benchCmd % (keepColsStr,benchTable),vals)
147 vals =np.array([list(x) for x in list(result)])
148 return(keepCols,vals)
149
150# Write columns in markdown format
151def writeColumns(f,cols):
152 colStr = "".join(joinit(cols,"|"))
153 f.write("|")
154 f.write(colStr)
155 f.write("|\n")
156 sepStr="".join(joinit([":-:" for x in cols],"|"))
157 f.write("|")
158 f.write(sepStr)
159 f.write("|\n")
160
161# Write row in markdown format
162def writeRow(f,row):
163 row=[str(x) for x in row]
164 rowStr = "".join(joinit(row,"|"))
165 f.write("|")
166 f.write(rowStr)
167 f.write("|\n")
168
169PARAMS=["NB","NumTaps", "NBA", "NBB", "Factor", "NumStages","VECDIM","NBR","NBC","NBI","IFFT", "BITREV"]
170
171def regressionTableFor(name,output,ref,toSort,indexCols,field):
172 data=ref.pivot_table(index=indexCols, columns='core',
173 values=[field], aggfunc='first')
174
175 data=data.sort_values(toSort)
176
177 cores = [c[1] for c in list(data.columns)]
178 columns = diff(indexCols,['NAME']) + cores
179
180 writeColumns(output,columns)
181 dataForFunc=data.loc[name]
182 if type(dataForFunc) is pd.DataFrame:
183 for row in dataForFunc.itertuples():
184 row=list(row)
185 if type(row[0]) is int:
186 row=[row[0]] + row[1:]
187 else:
188 row=list(row[0]) + row[1:]
189 writeRow(output,row)
190 else:
191 writeRow(output,dataForFunc)
192
193def formatTableByCore(output,testNames,cols,vals):
194 if vals.size != 0:
195 ref=pd.DataFrame(vals,columns=cols)
196 toSort=["NAME"]
197
198 for param in PARAMS:
199 if param in ref.columns:
200 ref[param]=pd.to_numeric(ref[param])
201 toSort.append(param)
202 if args.r:
203 # Regression table
204 ref['MAX']=pd.to_numeric(ref['MAX'])
205 ref['MAXREGCOEF']=pd.to_numeric(ref['MAXREGCOEF'])
206
207 indexCols=diff(cols,['core','Regression','MAXREGCOEF','MAX','version','compiler'])
208 valList = ['Regression']
209 else:
210 ref['CYCLES']=pd.to_numeric(ref['CYCLES'])
211
212 indexCols=diff(cols,['core','CYCLES','version','compiler'])
213 valList = ['CYCLES']
214
215
216
217 for name in testNames:
218 if args.r:
219 output.write("#### %s\n" % name)
220
221 output.write("##### Regression\n" )
222 regressionTableFor(name,output,ref,toSort,indexCols,'Regression')
223
224 output.write("##### Max cycles\n" )
225 regressionTableFor(name,output,ref,toSort,indexCols,'MAX')
226
227 output.write("##### Max Reg Coef\n" )
228 regressionTableFor(name,output,ref,toSort,indexCols,'MAXREGCOEF')
229
230 else:
231 data=ref.pivot_table(index=indexCols, columns='core',
232 values=valList, aggfunc='first')
233
234 data=data.sort_values(toSort)
235
236 cores = [c[1] for c in list(data.columns)]
237 columns = diff(indexCols,['NAME']) + cores
238
239 output.write("#### %s\n" % name)
240 writeColumns(output,columns)
241 dataForFunc=data.loc[name]
242 if type(dataForFunc) is pd.DataFrame:
243 for row in dataForFunc.itertuples():
244 row=list(row)
245 if type(row[0]) is int:
246 row=[row[0]] + row[1:]
247 else:
248 row=list(row[0]) + row[1:]
249 writeRow(output,row)
250 else:
251 writeRow(output,dataForFunc)
252
253# Add a report for each table
254def addReportFor(output,benchName):
255 print("Process %s\n" % benchName)
256 output.write("# %s\n" % benchName)
257 allTypes = getExistingTypes(benchName)
258 # Add report for each type
259 for aTypeID in allTypes:
260 typeName = getTypeName(aTypeID)
261 output.write("## %s\n" % typeName)
262 ## Add report for each compiler
263 allCompilers = getExistingCompiler(benchName,aTypeID)
264 for compiler in allCompilers:
265 #print(compiler)
266 output.write("### %s (%s)\n" % compiler)
267 cols,vals=getColNamesAndData(benchName,compiler,aTypeID)
268 names=getTestNames(benchName,compiler,aTypeID)
269 formatTableByCore(output,names,cols,vals)
270
271
272
273
274
275try:
276 with open(args.o,"w") as output:
277 benchtables=getBenchTables()
278 for bench in benchtables:
279 addReportFor(output,bench)
280finally:
281 c.close()
282
283