xref: /petsc/src/benchmarks/benchmarkExample.py (revision 6cbfa02c2e16fa342be1d9390e5b53eb3576447a)
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'''
20e3da8a91SMatthew G Knepley    mpiexec = os.path.join(self.dir(), self.arch(), 'bin', 'mpiexec')
21*6cbfa02cSMatthew G Knepley    if not os.path.isfile(mpiexec):
22e3da8a91SMatthew G Knepley      return None
23e3da8a91SMatthew 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):
60e3da8a91SMatthew G Knepley    if self.petsc.mpiexec() is None:
61e3da8a91SMatthew G Knepley      cmd = self.petsc.example(self.num)
62e3da8a91SMatthew G Knepley    else:
63e3da8a91SMatthew G Knepley      cmd = ' '.join([self.petsc.mpiexec(), '-n 1', self.petsc.example(self.num)])
64e3da8a91SMatthew 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
92e3da8a91SMatthew 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
147e3da8a91SMatthew G Knepleydef plotSummaryBar(library, num, sizes, times, events):
148e3da8a91SMatthew G Knepley  import numpy as np
149e3da8a91SMatthew G Knepley  import matplotlib.pyplot as plt
150e3da8a91SMatthew G Knepley
151e3da8a91SMatthew G Knepley  eventNames  = ['VecMDot', 'VecMAXPY', 'MatMult']
152e3da8a91SMatthew G Knepley  eventColors = ['b',       'g',        'r']
153e3da8a91SMatthew G Knepley  arches = sizes.keys()
154e3da8a91SMatthew G Knepley  names  = []
155e3da8a91SMatthew G Knepley  N      = len(sizes[arches[0]])
156e3da8a91SMatthew G Knepley  width  = 0.2
157e3da8a91SMatthew G Knepley  ind    = np.arange(N) - 0.25
158e3da8a91SMatthew G Knepley  bars   = {}
159e3da8a91SMatthew G Knepley  for arch in arches:
160e3da8a91SMatthew G Knepley    bars[arch] = []
161e3da8a91SMatthew G Knepley    bottom = np.zeros(N)
162e3da8a91SMatthew G Knepley    for event, color in zip(eventNames, eventColors):
163e3da8a91SMatthew G Knepley      names.append(arch+' '+event)
164e3da8a91SMatthew G Knepley      times = np.array(events[arch][event])[:,0]
165e3da8a91SMatthew G Knepley      bars[arch].append(plt.bar(ind, times, width, color=color, bottom=bottom))
166e3da8a91SMatthew G Knepley      bottom += times
167e3da8a91SMatthew G Knepley    ind += 0.3
168e3da8a91SMatthew G Knepley
169e3da8a91SMatthew G Knepley  plt.xlabel('Number of Dof')
170e3da8a91SMatthew G Knepley  plt.ylabel('Time (s)')
171e3da8a91SMatthew G Knepley  plt.title('GPU vs. CPU Performance on '+library+' Example '+str(num))
172e3da8a91SMatthew G Knepley  plt.xticks(np.arange(N), map(str, sizes[arches[0]]))
173e3da8a91SMatthew G Knepley  #plt.yticks(np.arange(0,81,10))
174e3da8a91SMatthew G Knepley  #plt.legend( (p1[0], p2[0]), ('Men', 'Women') )
175e3da8a91SMatthew G Knepley  plt.legend([bar[0] for bar in bars[arches[0]]], eventNames, 'upper right', shadow = True)
176e3da8a91SMatthew G Knepley
177e3da8a91SMatthew G Knepley  plt.show()
178e3da8a91SMatthew G Knepley  return
179e3da8a91SMatthew 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])
196e3da8a91SMatthew G Knepley  plotSummaryLine(library, num, sizes, times, events)
197