13428b40fSMatthew G Knepley#!/usr/bin/env python 23428b40fSMatthew G Knepleyimport os 3*19d5f70aSMatthew G Knepleyfrom benchmarkBatch import generateBatchScript 43428b40fSMatthew G Knepley 53428b40fSMatthew G Knepleyclass PETSc(object): 63428b40fSMatthew G Knepley def __init__(self): 73428b40fSMatthew G Knepley return 83428b40fSMatthew G Knepley 93428b40fSMatthew G Knepley def dir(self): 103428b40fSMatthew G Knepley '''Return the root directory for the PETSc tree (usually $PETSC_DIR)''' 113428b40fSMatthew G Knepley # This should search for a valid PETSc 123428b40fSMatthew G Knepley return os.environ['PETSC_DIR'] 133428b40fSMatthew G Knepley 143428b40fSMatthew G Knepley def arch(self): 153428b40fSMatthew G Knepley '''Return the PETSc build label (usually $PETSC_ARCH)''' 163428b40fSMatthew G Knepley # This should be configurable 173428b40fSMatthew G Knepley return os.environ['PETSC_ARCH'] 183428b40fSMatthew G Knepley 193428b40fSMatthew G Knepley def mpiexec(self): 203428b40fSMatthew G Knepley '''Return the path for the mpi launch executable''' 21e3da8a91SMatthew G Knepley mpiexec = os.path.join(self.dir(), self.arch(), 'bin', 'mpiexec') 226cbfa02cSMatthew G Knepley if not os.path.isfile(mpiexec): 23e3da8a91SMatthew G Knepley return None 24e3da8a91SMatthew G Knepley return mpiexec 253428b40fSMatthew G Knepley 263428b40fSMatthew G Knepley def example(self, num): 273428b40fSMatthew G Knepley '''Return the path to the executable for a given example number''' 283428b40fSMatthew G Knepley return os.path.join(self.dir(), self.arch(), 'lib', 'ex'+str(num)+'-obj', 'ex'+str(num)) 293428b40fSMatthew G Knepley 303428b40fSMatthew G Knepleyclass PETScExample(object): 313428b40fSMatthew G Knepley def __init__(self, library, num, **defaultOptions): 323428b40fSMatthew G Knepley self.petsc = PETSc() 333428b40fSMatthew G Knepley self.library = library 343428b40fSMatthew G Knepley self.num = num 353428b40fSMatthew G Knepley self.opts = defaultOptions 363428b40fSMatthew G Knepley return 373428b40fSMatthew G Knepley 383428b40fSMatthew G Knepley @staticmethod 393428b40fSMatthew G Knepley def runShellCommand(command, cwd = None): 403428b40fSMatthew G Knepley import subprocess 413428b40fSMatthew G Knepley 423428b40fSMatthew G Knepley Popen = subprocess.Popen 433428b40fSMatthew G Knepley PIPE = subprocess.PIPE 443428b40fSMatthew G Knepley print 'Executing: %s\n' % (command,) 453428b40fSMatthew G Knepley pipe = Popen(command, cwd=cwd, stdin=None, stdout=PIPE, stderr=PIPE, bufsize=-1, shell=True, universal_newlines=True) 463428b40fSMatthew G Knepley (out, err) = pipe.communicate() 473428b40fSMatthew G Knepley ret = pipe.returncode 483428b40fSMatthew G Knepley return (out, err, ret) 493428b40fSMatthew G Knepley 503428b40fSMatthew G Knepley def optionsToString(self, **opts): 513428b40fSMatthew G Knepley '''Convert a dictionary of options to a command line argument string''' 523428b40fSMatthew G Knepley a = [] 533428b40fSMatthew G Knepley for key,value in opts.iteritems(): 543428b40fSMatthew G Knepley if value is None: 553428b40fSMatthew G Knepley a.append('-'+key) 563428b40fSMatthew G Knepley else: 573428b40fSMatthew G Knepley a.append('-'+key+' '+str(value)) 583428b40fSMatthew G Knepley return ' '.join(a) 593428b40fSMatthew G Knepley 60*19d5f70aSMatthew G Knepley def run(self, numProcs = 1, **opts): 61e3da8a91SMatthew G Knepley if self.petsc.mpiexec() is None: 62e3da8a91SMatthew G Knepley cmd = self.petsc.example(self.num) 63e3da8a91SMatthew G Knepley else: 64*19d5f70aSMatthew G Knepley cmd = ' '.join([self.petsc.mpiexec(), '-n', str(numProcs), self.petsc.example(self.num)]) 65e3da8a91SMatthew G Knepley cmd += ' '+self.optionsToString(**self.opts)+' '+self.optionsToString(**opts) 66*19d5f70aSMatthew G Knepley if 'batch' in opts and opts['batch']: 67*19d5f70aSMatthew G Knepley del opts['batch'] 68*19d5f70aSMatthew G Knepley generateBatchScript(self.num, numProcs, 120, ' '+self.optionsToString(**self.opts)+' '+self.optionsToString(**opts)) 69*19d5f70aSMatthew G Knepley else: 703428b40fSMatthew G Knepley out, err, ret = self.runShellCommand(cmd) 713428b40fSMatthew G Knepley if ret: 723428b40fSMatthew G Knepley print err 733428b40fSMatthew G Knepley print out 743428b40fSMatthew G Knepley return 753428b40fSMatthew G Knepley 763428b40fSMatthew G Knepleydef processSummary(moduleName, times, events): 773428b40fSMatthew G Knepley '''Process the Python log summary into plot data''' 783428b40fSMatthew G Knepley m = __import__(moduleName) 793428b40fSMatthew G Knepley reload(m) 803428b40fSMatthew G Knepley # Total Time 813428b40fSMatthew G Knepley times.append(m.Time[0]) 823428b40fSMatthew G Knepley # Common events 833428b40fSMatthew G Knepley # VecMAXPY and VecMDot essentially give KSPGMRESOrthog 843428b40fSMatthew G Knepley # Add the time and flop rate 853428b40fSMatthew G Knepley for name in ['VecMDot', 'VecMAXPY', 'KSPGMRESOrthog', 'MatMult']: 863428b40fSMatthew G Knepley if not name in events: 873428b40fSMatthew G Knepley events[name] = [] 883428b40fSMatthew G Knepley events[name].append((m.Solve.event[name].Time[0], m.Solve.event[name].Flops[0]/(m.Solve.event[name].Time[0] * 1e6))) 893428b40fSMatthew G Knepley # Particular events 903428b40fSMatthew G Knepley for name in ['VecCUSPCopyTo', 'VecCUSPCopyFrom', 'MatCUSPCopyTo']: 913428b40fSMatthew G Knepley if name in m.Solve.event: 923428b40fSMatthew G Knepley if not name in events: 933428b40fSMatthew G Knepley events[name] = [] 943428b40fSMatthew G Knepley events[name].append((m.Solve.event[name].Time[0], m.Solve.event[name].Flops[0]/(m.Solve.event[name].Time[0] * 1e6))) 953428b40fSMatthew G Knepley return 963428b40fSMatthew G Knepley 97e3da8a91SMatthew G Knepleydef plotSummaryLine(library, num, sizes, times, events): 983428b40fSMatthew G Knepley from pylab import legend, plot, show, title, xlabel, ylabel 993428b40fSMatthew G Knepley import numpy as np 1003428b40fSMatthew G Knepley showTime = False 1013428b40fSMatthew G Knepley showEventTime = True 1023428b40fSMatthew G Knepley showEventFlops = True 1033428b40fSMatthew G Knepley arches = sizes.keys() 1043428b40fSMatthew G Knepley # Time 1053428b40fSMatthew G Knepley if showTime: 1063428b40fSMatthew G Knepley data = [] 1073428b40fSMatthew G Knepley for arch in arches: 1083428b40fSMatthew G Knepley data.append(sizes[arch]) 1093428b40fSMatthew G Knepley data.append(times[arch]) 1103428b40fSMatthew G Knepley plot(*data) 1113428b40fSMatthew G Knepley title('Performance on '+library+' Example '+str(num)) 1123428b40fSMatthew G Knepley xlabel('Number of Dof') 1133428b40fSMatthew G Knepley ylabel('Time (s)') 1143428b40fSMatthew G Knepley legend(arches, 'upper left', shadow = True) 1153428b40fSMatthew G Knepley show() 1163428b40fSMatthew G Knepley # Common event time 1173428b40fSMatthew G Knepley # We could make a stacked plot like Rio uses here 1183428b40fSMatthew G Knepley if showEventTime: 1193428b40fSMatthew G Knepley data = [] 1203428b40fSMatthew G Knepley names = [] 1213428b40fSMatthew G Knepley for event, color in [('VecMDot', 'b'), ('VecMAXPY', 'g'), ('MatMult', 'r')]: 1223428b40fSMatthew G Knepley for arch, style in zip(arches, ['-', ':']): 1233428b40fSMatthew G Knepley names.append(arch+' '+event) 1243428b40fSMatthew G Knepley data.append(sizes[arch]) 1253428b40fSMatthew G Knepley data.append(np.array(events[arch][event])[:,0]) 1263428b40fSMatthew G Knepley data.append(color+style) 1273428b40fSMatthew G Knepley plot(*data) 1283428b40fSMatthew G Knepley title('Performance on '+library+' Example '+str(num)) 1293428b40fSMatthew G Knepley xlabel('Number of Dof') 1303428b40fSMatthew G Knepley ylabel('Time (s)') 1313428b40fSMatthew G Knepley legend(names, 'upper left', shadow = True) 1323428b40fSMatthew G Knepley show() 1333428b40fSMatthew G Knepley # Common event flops 1343428b40fSMatthew G Knepley # We could make a stacked plot like Rio uses here 1353428b40fSMatthew G Knepley if showEventFlops: 1363428b40fSMatthew G Knepley data = [] 1373428b40fSMatthew G Knepley names = [] 1383428b40fSMatthew G Knepley for event, color in [('VecMDot', 'b'), ('VecMAXPY', 'g'), ('MatMult', 'r')]: 1393428b40fSMatthew G Knepley for arch, style in zip(arches, ['-', ':']): 1403428b40fSMatthew G Knepley names.append(arch+' '+event) 1413428b40fSMatthew G Knepley data.append(sizes[arch]) 1423428b40fSMatthew G Knepley data.append(np.array(events[arch][event])[:,1]) 1433428b40fSMatthew G Knepley data.append(color+style) 1443428b40fSMatthew G Knepley plot(*data) 1453428b40fSMatthew G Knepley title('Performance on '+library+' Example '+str(num)) 1463428b40fSMatthew G Knepley xlabel('Number of Dof') 1473428b40fSMatthew G Knepley ylabel('Computation Rate (MF/s)') 1483428b40fSMatthew G Knepley legend(names, 'upper left', shadow = True) 1493428b40fSMatthew G Knepley show() 1503428b40fSMatthew G Knepley return 1513428b40fSMatthew G Knepley 152e3da8a91SMatthew G Knepleydef plotSummaryBar(library, num, sizes, times, events): 153e3da8a91SMatthew G Knepley import numpy as np 154e3da8a91SMatthew G Knepley import matplotlib.pyplot as plt 155e3da8a91SMatthew G Knepley 156e3da8a91SMatthew G Knepley eventNames = ['VecMDot', 'VecMAXPY', 'MatMult'] 157e3da8a91SMatthew G Knepley eventColors = ['b', 'g', 'r'] 158e3da8a91SMatthew G Knepley arches = sizes.keys() 159e3da8a91SMatthew G Knepley names = [] 160e3da8a91SMatthew G Knepley N = len(sizes[arches[0]]) 161e3da8a91SMatthew G Knepley width = 0.2 162e3da8a91SMatthew G Knepley ind = np.arange(N) - 0.25 163e3da8a91SMatthew G Knepley bars = {} 164e3da8a91SMatthew G Knepley for arch in arches: 165e3da8a91SMatthew G Knepley bars[arch] = [] 166e3da8a91SMatthew G Knepley bottom = np.zeros(N) 167e3da8a91SMatthew G Knepley for event, color in zip(eventNames, eventColors): 168e3da8a91SMatthew G Knepley names.append(arch+' '+event) 169e3da8a91SMatthew G Knepley times = np.array(events[arch][event])[:,0] 170e3da8a91SMatthew G Knepley bars[arch].append(plt.bar(ind, times, width, color=color, bottom=bottom)) 171e3da8a91SMatthew G Knepley bottom += times 172e3da8a91SMatthew G Knepley ind += 0.3 173e3da8a91SMatthew G Knepley 174e3da8a91SMatthew G Knepley plt.xlabel('Number of Dof') 175e3da8a91SMatthew G Knepley plt.ylabel('Time (s)') 176e3da8a91SMatthew G Knepley plt.title('GPU vs. CPU Performance on '+library+' Example '+str(num)) 177e3da8a91SMatthew G Knepley plt.xticks(np.arange(N), map(str, sizes[arches[0]])) 178e3da8a91SMatthew G Knepley #plt.yticks(np.arange(0,81,10)) 179e3da8a91SMatthew G Knepley #plt.legend( (p1[0], p2[0]), ('Men', 'Women') ) 180e3da8a91SMatthew G Knepley plt.legend([bar[0] for bar in bars[arches[0]]], eventNames, 'upper right', shadow = True) 181e3da8a91SMatthew G Knepley 182e3da8a91SMatthew G Knepley plt.show() 183e3da8a91SMatthew G Knepley return 184e3da8a91SMatthew G Knepley 1853428b40fSMatthew G Knepleyif __name__ == '__main__': 1863428b40fSMatthew G Knepley library = 'SNES' 1873428b40fSMatthew G Knepley num = 19 1883428b40fSMatthew G Knepley ex = PETScExample(library, num, pc_type='none', dmmg_nlevels=1, log_summary='summary.dat', log_summary_python='summary.py', mat_no_inode=None, preload='off') 1893428b40fSMatthew G Knepley sizes = {} 1903428b40fSMatthew G Knepley times = {} 1913428b40fSMatthew G Knepley events = {} 1923428b40fSMatthew G Knepley for name, vecType, matType, opts in [('CPU', 'seq', 'seqaij', {}), ('GPU', 'seqcusp', 'seqaijcusp', {'cusp_synchronize': None})]: 1933428b40fSMatthew G Knepley sizes[name] = [] 1943428b40fSMatthew G Knepley times[name] = [] 1953428b40fSMatthew G Knepley events[name] = {} 1963428b40fSMatthew G Knepley #for n in [10, 20, 50, 100, 150, 200]: 1973428b40fSMatthew G Knepley for n in [10, 20]: 1983428b40fSMatthew G Knepley ex.run(da_grid_x=n, da_grid_y=n, da_vec_type=vecType, da_mat_type=matType, **opts) 1993428b40fSMatthew G Knepley sizes[name].append(n*n * 4) 2003428b40fSMatthew G Knepley processSummary('summary', times[name], events[name]) 201e3da8a91SMatthew G Knepley plotSummaryLine(library, num, sizes, times, events) 202