13428b40fSMatthew G Knepley#!/usr/bin/env python 2*eda8839fSMatthew G Knepleyimport os,sys 319d5f70aSMatthew 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 300790b1abSMatthew G Knepley def source(self, library, num): 310790b1abSMatthew G Knepley '''Return the path to the sources for a given example number''' 320790b1abSMatthew G Knepley d = os.path.join(self.dir(), 'src', library.lower(), 'examples', 'tutorials') 330790b1abSMatthew G Knepley name = 'ex'+str(num) 340790b1abSMatthew G Knepley sources = [] 350790b1abSMatthew G Knepley for f in os.listdir(d): 360790b1abSMatthew G Knepley if f == name+'.c': 370790b1abSMatthew G Knepley sources.append(f) 380790b1abSMatthew G Knepley elif f.startswith(name) and f.endswith('.cu'): 390790b1abSMatthew G Knepley sources.append(f) 400790b1abSMatthew G Knepley return map(lambda f: os.path.join(d, f), sources) 410790b1abSMatthew G Knepley 423428b40fSMatthew G Knepleyclass PETScExample(object): 433428b40fSMatthew G Knepley def __init__(self, library, num, **defaultOptions): 443428b40fSMatthew G Knepley self.petsc = PETSc() 453428b40fSMatthew G Knepley self.library = library 463428b40fSMatthew G Knepley self.num = num 473428b40fSMatthew G Knepley self.opts = defaultOptions 483428b40fSMatthew G Knepley return 493428b40fSMatthew G Knepley 503428b40fSMatthew G Knepley @staticmethod 513428b40fSMatthew G Knepley def runShellCommand(command, cwd = None): 523428b40fSMatthew G Knepley import subprocess 533428b40fSMatthew G Knepley 543428b40fSMatthew G Knepley Popen = subprocess.Popen 553428b40fSMatthew G Knepley PIPE = subprocess.PIPE 563428b40fSMatthew G Knepley print 'Executing: %s\n' % (command,) 573428b40fSMatthew G Knepley pipe = Popen(command, cwd=cwd, stdin=None, stdout=PIPE, stderr=PIPE, bufsize=-1, shell=True, universal_newlines=True) 583428b40fSMatthew G Knepley (out, err) = pipe.communicate() 593428b40fSMatthew G Knepley ret = pipe.returncode 603428b40fSMatthew G Knepley return (out, err, ret) 613428b40fSMatthew G Knepley 623428b40fSMatthew G Knepley def optionsToString(self, **opts): 633428b40fSMatthew G Knepley '''Convert a dictionary of options to a command line argument string''' 643428b40fSMatthew G Knepley a = [] 653428b40fSMatthew G Knepley for key,value in opts.iteritems(): 663428b40fSMatthew G Knepley if value is None: 673428b40fSMatthew G Knepley a.append('-'+key) 683428b40fSMatthew G Knepley else: 693428b40fSMatthew G Knepley a.append('-'+key+' '+str(value)) 703428b40fSMatthew G Knepley return ' '.join(a) 713428b40fSMatthew G Knepley 7219d5f70aSMatthew G Knepley def run(self, numProcs = 1, **opts): 73e3da8a91SMatthew G Knepley if self.petsc.mpiexec() is None: 74e3da8a91SMatthew G Knepley cmd = self.petsc.example(self.num) 75e3da8a91SMatthew G Knepley else: 7619d5f70aSMatthew G Knepley cmd = ' '.join([self.petsc.mpiexec(), '-n', str(numProcs), self.petsc.example(self.num)]) 77e3da8a91SMatthew G Knepley cmd += ' '+self.optionsToString(**self.opts)+' '+self.optionsToString(**opts) 7819d5f70aSMatthew G Knepley if 'batch' in opts and opts['batch']: 7919d5f70aSMatthew G Knepley del opts['batch'] 803849a283SMatthew G Knepley filename = generateBatchScript(self.num, numProcs, 120, ' '+self.optionsToString(**self.opts)+' '+self.optionsToString(**opts)) 813849a283SMatthew G Knepley # Submit job 823849a283SMatthew G Knepley out, err, ret = self.runShellCommand('qsub -q gpu '+filename) 833849a283SMatthew G Knepley if ret: 843849a283SMatthew G Knepley print err 853849a283SMatthew G Knepley print out 8619d5f70aSMatthew G Knepley else: 873428b40fSMatthew G Knepley out, err, ret = self.runShellCommand(cmd) 883428b40fSMatthew G Knepley if ret: 893428b40fSMatthew G Knepley print err 903428b40fSMatthew G Knepley print out 910790b1abSMatthew G Knepley return out 923428b40fSMatthew G Knepley 93*eda8839fSMatthew G Knepleydef processSummary(moduleName, defaultStage, eventNames, times, events): 943428b40fSMatthew G Knepley '''Process the Python log summary into plot data''' 953428b40fSMatthew G Knepley m = __import__(moduleName) 963428b40fSMatthew G Knepley reload(m) 973428b40fSMatthew G Knepley # Total Time 983428b40fSMatthew G Knepley times.append(m.Time[0]) 993428b40fSMatthew G Knepley # Particular events 100*eda8839fSMatthew G Knepley for name in eventNames: 101*eda8839fSMatthew G Knepley if name.find(':') >= 0: 102*eda8839fSMatthew G Knepley stageName, name = name.split(':', 1) 103*eda8839fSMatthew G Knepley stage = getattr(m, stageName) 104*eda8839fSMatthew G Knepley else: 105*eda8839fSMatthew G Knepley stage = getattr(m, defaultStage) 106*eda8839fSMatthew G Knepley if name in stage.event: 1073428b40fSMatthew G Knepley if not name in events: 1083428b40fSMatthew G Knepley events[name] = [] 109*eda8839fSMatthew G Knepley events[name].append((stage.event[name].Time[0], stage.event[name].Flops[0]/(stage.event[name].Time[0] * 1e6))) 1103428b40fSMatthew G Knepley return 1113428b40fSMatthew G Knepley 112e3da8a91SMatthew G Knepleydef plotSummaryLine(library, num, sizes, times, events): 1133428b40fSMatthew G Knepley from pylab import legend, plot, show, title, xlabel, ylabel 1143428b40fSMatthew G Knepley import numpy as np 1153428b40fSMatthew G Knepley showTime = False 1163428b40fSMatthew G Knepley showEventTime = True 1173428b40fSMatthew G Knepley showEventFlops = True 1183428b40fSMatthew G Knepley arches = sizes.keys() 1193428b40fSMatthew G Knepley # Time 1203428b40fSMatthew G Knepley if showTime: 1213428b40fSMatthew G Knepley data = [] 1223428b40fSMatthew G Knepley for arch in arches: 1233428b40fSMatthew G Knepley data.append(sizes[arch]) 1243428b40fSMatthew G Knepley data.append(times[arch]) 1253428b40fSMatthew G Knepley plot(*data) 1263428b40fSMatthew G Knepley title('Performance on '+library+' Example '+str(num)) 1273428b40fSMatthew G Knepley xlabel('Number of Dof') 1283428b40fSMatthew G Knepley ylabel('Time (s)') 1293428b40fSMatthew G Knepley legend(arches, 'upper left', shadow = True) 1303428b40fSMatthew G Knepley show() 1313428b40fSMatthew G Knepley # Common event time 1323428b40fSMatthew G Knepley # We could make a stacked plot like Rio uses here 1333428b40fSMatthew G Knepley if showEventTime: 1343428b40fSMatthew G Knepley data = [] 1353428b40fSMatthew G Knepley names = [] 1363428b40fSMatthew G Knepley for event, color in [('VecMDot', 'b'), ('VecMAXPY', 'g'), ('MatMult', 'r')]: 1373428b40fSMatthew G Knepley for arch, style in zip(arches, ['-', ':']): 1383428b40fSMatthew G Knepley names.append(arch+' '+event) 1393428b40fSMatthew G Knepley data.append(sizes[arch]) 1403428b40fSMatthew G Knepley data.append(np.array(events[arch][event])[:,0]) 1413428b40fSMatthew G Knepley data.append(color+style) 1423428b40fSMatthew G Knepley plot(*data) 1433428b40fSMatthew G Knepley title('Performance on '+library+' Example '+str(num)) 1443428b40fSMatthew G Knepley xlabel('Number of Dof') 1453428b40fSMatthew G Knepley ylabel('Time (s)') 1463428b40fSMatthew G Knepley legend(names, 'upper left', shadow = True) 1473428b40fSMatthew G Knepley show() 1483428b40fSMatthew G Knepley # Common event flops 1493428b40fSMatthew G Knepley # We could make a stacked plot like Rio uses here 1503428b40fSMatthew G Knepley if showEventFlops: 1513428b40fSMatthew G Knepley data = [] 1523428b40fSMatthew G Knepley names = [] 1533428b40fSMatthew G Knepley for event, color in [('VecMDot', 'b'), ('VecMAXPY', 'g'), ('MatMult', 'r')]: 1543428b40fSMatthew G Knepley for arch, style in zip(arches, ['-', ':']): 1553428b40fSMatthew G Knepley names.append(arch+' '+event) 1563428b40fSMatthew G Knepley data.append(sizes[arch]) 1573428b40fSMatthew G Knepley data.append(np.array(events[arch][event])[:,1]) 1583428b40fSMatthew G Knepley data.append(color+style) 1593428b40fSMatthew G Knepley plot(*data) 1603428b40fSMatthew G Knepley title('Performance on '+library+' Example '+str(num)) 1613428b40fSMatthew G Knepley xlabel('Number of Dof') 1623428b40fSMatthew G Knepley ylabel('Computation Rate (MF/s)') 1633428b40fSMatthew G Knepley legend(names, 'upper left', shadow = True) 1643428b40fSMatthew G Knepley show() 1653428b40fSMatthew G Knepley return 1663428b40fSMatthew G Knepley 167e3da8a91SMatthew G Knepleydef plotSummaryBar(library, num, sizes, times, events): 168e3da8a91SMatthew G Knepley import numpy as np 169e3da8a91SMatthew G Knepley import matplotlib.pyplot as plt 170e3da8a91SMatthew G Knepley 171e3da8a91SMatthew G Knepley eventNames = ['VecMDot', 'VecMAXPY', 'MatMult'] 172e3da8a91SMatthew G Knepley eventColors = ['b', 'g', 'r'] 173e3da8a91SMatthew G Knepley arches = sizes.keys() 174e3da8a91SMatthew G Knepley names = [] 175e3da8a91SMatthew G Knepley N = len(sizes[arches[0]]) 176e3da8a91SMatthew G Knepley width = 0.2 177e3da8a91SMatthew G Knepley ind = np.arange(N) - 0.25 178e3da8a91SMatthew G Knepley bars = {} 179e3da8a91SMatthew G Knepley for arch in arches: 180e3da8a91SMatthew G Knepley bars[arch] = [] 181e3da8a91SMatthew G Knepley bottom = np.zeros(N) 182e3da8a91SMatthew G Knepley for event, color in zip(eventNames, eventColors): 183e3da8a91SMatthew G Knepley names.append(arch+' '+event) 184e3da8a91SMatthew G Knepley times = np.array(events[arch][event])[:,0] 185e3da8a91SMatthew G Knepley bars[arch].append(plt.bar(ind, times, width, color=color, bottom=bottom)) 186e3da8a91SMatthew G Knepley bottom += times 187e3da8a91SMatthew G Knepley ind += 0.3 188e3da8a91SMatthew G Knepley 189e3da8a91SMatthew G Knepley plt.xlabel('Number of Dof') 190e3da8a91SMatthew G Knepley plt.ylabel('Time (s)') 191e3da8a91SMatthew G Knepley plt.title('GPU vs. CPU Performance on '+library+' Example '+str(num)) 192e3da8a91SMatthew G Knepley plt.xticks(np.arange(N), map(str, sizes[arches[0]])) 193e3da8a91SMatthew G Knepley #plt.yticks(np.arange(0,81,10)) 194e3da8a91SMatthew G Knepley #plt.legend( (p1[0], p2[0]), ('Men', 'Women') ) 195e3da8a91SMatthew G Knepley plt.legend([bar[0] for bar in bars[arches[0]]], eventNames, 'upper right', shadow = True) 196e3da8a91SMatthew G Knepley 197e3da8a91SMatthew G Knepley plt.show() 198e3da8a91SMatthew G Knepley return 199e3da8a91SMatthew G Knepley 2003428b40fSMatthew G Knepleyif __name__ == '__main__': 201*eda8839fSMatthew G Knepley import argparse 202*eda8839fSMatthew G Knepley 203*eda8839fSMatthew G Knepley parser = argparse.ArgumentParser(description = 'PETSc Benchmarking', 204*eda8839fSMatthew G Knepley epilog = 'This script runs src/<library>/examples/tutorials/ex<num>, For more information, visit http://www.mcs.anl.gov/petsc', 205*eda8839fSMatthew G Knepley formatter_class = argparse.ArgumentDefaultsHelpFormatter) 206*eda8839fSMatthew G Knepley parser.add_argument('--library', default='SNES', help='The PETSc library used in this example') 207*eda8839fSMatthew G Knepley parser.add_argument('--num', type = int, default='5', help='The example number') 208*eda8839fSMatthew G Knepley parser.add_argument('--module', default='summary', help='The module for timing output') 209*eda8839fSMatthew G Knepley parser.add_argument('--scaling', help='Run parallel scaling test') 210*eda8839fSMatthew G Knepley parser.add_argument('--size', nargs='+', default=['10'], help='Grid size (implementation dependent)') 211*eda8839fSMatthew G Knepley parser.add_argument('--comp', type = int, default='1', help='Number of field components') 212*eda8839fSMatthew G Knepley parser.add_argument('runs', nargs='*', help='Run descriptions: <name>=<args>') 213*eda8839fSMatthew G Knepley parser.add_argument('--stage', default='Main_Stage', help='The default logging stage') 214*eda8839fSMatthew G Knepley parser.add_argument('--events', nargs='+', help='Events to process') 215*eda8839fSMatthew G Knepley parser.add_argument('--batch', action='store_true', default=False, help='Generate batch files for the runs instead') 216*eda8839fSMatthew G Knepley 217*eda8839fSMatthew G Knepley # Options for ex19: pc_type='none', dmmg_nlevels=1, mat_no_inode=None 218*eda8839fSMatthew G Knepley 219*eda8839fSMatthew G Knepley args = parser.parse_args() 220*eda8839fSMatthew G Knepley print(args) 221*eda8839fSMatthew G Knepley ex = PETScExample(args.library, args.num, log_summary='summary.dat', log_summary_python = None if args.batch else args.module+'.py', preload='off') 2223428b40fSMatthew G Knepley sizes = {} 2233428b40fSMatthew G Knepley times = {} 2243428b40fSMatthew G Knepley events = {} 225*eda8839fSMatthew G Knepley for run in args.runs: 226*eda8839fSMatthew G Knepley name, stropts = run.split('=', 1) 227*eda8839fSMatthew G Knepley opts = dict([t if len(t) == 2 else (t[0], None) for t in [arg.split('=', 1) for arg in stropts.split(' ')]]) 2283428b40fSMatthew G Knepley sizes[name] = [] 2293428b40fSMatthew G Knepley times[name] = [] 2303428b40fSMatthew G Knepley events[name] = {} 231*eda8839fSMatthew G Knepley # DMDA implementation 232*eda8839fSMatthew G Knepley # Need a good way to get the DMDA info 233*eda8839fSMatthew G Knepley for n in map(int, args.size): 234*eda8839fSMatthew G Knepley print(name,opts) 235*eda8839fSMatthew G Knepley ex.run(da_grid_x=n, da_grid_y=n, **opts) 236*eda8839fSMatthew G Knepley sizes[name].append(n*n * args.comp) 237*eda8839fSMatthew G Knepley processSummary('summary', args.stage, args.events, times[name], events[name]) 238*eda8839fSMatthew G Knepley print sizes 239*eda8839fSMatthew G Knepley print times 240*eda8839fSMatthew G Knepley print events 241*eda8839fSMatthew G Knepley if not args.batch: plotSummaryLine(args.library, args.num, sizes, times, events) 242*eda8839fSMatthew G Knepley# --num 19 --comp 4 --size 10 20 50 100 --events VecMDot VecMAXPY KSPGMRESOrthog MatMult VecCUSPCopyTo VecCUSPCopyFrom MatCUSPCopyTo --stage Solve CPU='da_vec_type=seq da_mat_type=seqaij' GPU='da_vec_type=seqcusp da_mat_type=seqaijcusp cusp_synchronize' 243