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