xref: /petsc/src/benchmarks/benchmarkExample.py (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
13428b40fSMatthew G Knepley#!/usr/bin/env python
2*5b6bfdb9SJed Brownfrom __future__ import print_function
3eda8839fSMatthew G Knepleyimport os,sys
4683aebbfSMatthew G Knepleysys.path.append(os.path.join(os.environ['PETSC_DIR'], 'config'))
590dfb094SAndy R. Terrelsys.path.append(os.getcwd())
6683aebbfSMatthew G Knepleyfrom builder2 import buildExample
719d5f70aSMatthew G Knepleyfrom benchmarkBatch import generateBatchScript
83428b40fSMatthew G Knepley
93428b40fSMatthew G Knepleyclass PETSc(object):
103428b40fSMatthew G Knepley  def __init__(self):
113428b40fSMatthew G Knepley    return
123428b40fSMatthew G Knepley
133428b40fSMatthew G Knepley  def dir(self):
143428b40fSMatthew G Knepley    '''Return the root directory for the PETSc tree (usually $PETSC_DIR)'''
153428b40fSMatthew G Knepley    # This should search for a valid PETSc
163428b40fSMatthew G Knepley    return os.environ['PETSC_DIR']
173428b40fSMatthew G Knepley
183428b40fSMatthew G Knepley  def arch(self):
193428b40fSMatthew G Knepley    '''Return the PETSc build label (usually $PETSC_ARCH)'''
203428b40fSMatthew G Knepley    # This should be configurable
213428b40fSMatthew G Knepley    return os.environ['PETSC_ARCH']
223428b40fSMatthew G Knepley
233428b40fSMatthew G Knepley  def mpiexec(self):
243428b40fSMatthew G Knepley    '''Return the path for the mpi launch executable'''
25e3da8a91SMatthew G Knepley    mpiexec = os.path.join(self.dir(), self.arch(), 'bin', 'mpiexec')
266cbfa02cSMatthew G Knepley    if not os.path.isfile(mpiexec):
27e3da8a91SMatthew G Knepley      return None
28e3da8a91SMatthew G Knepley    return mpiexec
293428b40fSMatthew G Knepley
30d37947eaSMatthew G. Knepley  def example(self, library, num):
313428b40fSMatthew G Knepley    '''Return the path to the executable for a given example number'''
32d37947eaSMatthew G. Knepley    return os.path.join(self.dir(), self.arch(), 'lib', library.lower(), 'ex'+str(num))
333428b40fSMatthew G Knepley
343973d8daSKarl Rupp  def source(self, library, num, filenametail):
350790b1abSMatthew G Knepley    '''Return the path to the sources for a given example number'''
360790b1abSMatthew G Knepley    d = os.path.join(self.dir(), 'src', library.lower(), 'examples', 'tutorials')
370790b1abSMatthew G Knepley    name = 'ex'+str(num)
380790b1abSMatthew G Knepley    sources = []
390790b1abSMatthew G Knepley    for f in os.listdir(d):
400790b1abSMatthew G Knepley      if f == name+'.c':
412642ea08SMatthew G Knepley        sources.insert(0, f)
423973d8daSKarl Rupp      elif f.startswith(name) and f.endswith(filenametail):
430790b1abSMatthew G Knepley        sources.append(f)
440790b1abSMatthew G Knepley    return map(lambda f: os.path.join(d, f), sources)
450790b1abSMatthew G Knepley
463428b40fSMatthew G Knepleyclass PETScExample(object):
473428b40fSMatthew G Knepley  def __init__(self, library, num, **defaultOptions):
483428b40fSMatthew G Knepley    self.petsc   = PETSc()
493428b40fSMatthew G Knepley    self.library = library
503428b40fSMatthew G Knepley    self.num     = num
513428b40fSMatthew G Knepley    self.opts    = defaultOptions
523428b40fSMatthew G Knepley    return
533428b40fSMatthew G Knepley
543428b40fSMatthew G Knepley  @staticmethod
55d006b754SMatthew G Knepley  def runShellCommand(command, cwd = None, log = True):
563428b40fSMatthew G Knepley    import subprocess
573428b40fSMatthew G Knepley
583428b40fSMatthew G Knepley    Popen = subprocess.Popen
593428b40fSMatthew G Knepley    PIPE  = subprocess.PIPE
60*5b6bfdb9SJed Brown    if log: print('Executing: %s\n' % (command,))
613428b40fSMatthew G Knepley    pipe = Popen(command, cwd=cwd, stdin=None, stdout=PIPE, stderr=PIPE, bufsize=-1, shell=True, universal_newlines=True)
623428b40fSMatthew G Knepley    (out, err) = pipe.communicate()
633428b40fSMatthew G Knepley    ret = pipe.returncode
643428b40fSMatthew G Knepley    return (out, err, ret)
653428b40fSMatthew G Knepley
663428b40fSMatthew G Knepley  def optionsToString(self, **opts):
673428b40fSMatthew G Knepley    '''Convert a dictionary of options to a command line argument string'''
683428b40fSMatthew G Knepley    a = []
693428b40fSMatthew G Knepley    for key,value in opts.iteritems():
703428b40fSMatthew G Knepley      if value is None:
713428b40fSMatthew G Knepley        a.append('-'+key)
723428b40fSMatthew G Knepley      else:
733428b40fSMatthew G Knepley        a.append('-'+key+' '+str(value))
743428b40fSMatthew G Knepley    return ' '.join(a)
753428b40fSMatthew G Knepley
76d37947eaSMatthew G. Knepley  def build(self, log = True):
77d37947eaSMatthew G. Knepley    sdir = os.path.join(self.petsc.dir(), 'src', self.library.lower(), 'examples', 'tutorials')
78d37947eaSMatthew G. Knepley    odir = os.getcwd()
79d37947eaSMatthew G. Knepley    os.chdir(sdir)
80d37947eaSMatthew G. Knepley    cmd = 'make ex'+str(self.num)
81d37947eaSMatthew G. Knepley    out, err, ret = self.runShellCommand(cmd, cwd = sdir, log = log)
82d37947eaSMatthew G. Knepley    if err:
83d37947eaSMatthew G. Knepley      raise RuntimeError('Unable to build example:\n'+err+out)
84d37947eaSMatthew G. Knepley    os.chdir(odir)
85d37947eaSMatthew G. Knepley    bdir = os.path.dirname(self.petsc.example(self.library, self.num))
86d37947eaSMatthew G. Knepley    try:
87d37947eaSMatthew G. Knepley      os.makedirs(bdir)
88d37947eaSMatthew G. Knepley    except OSError:
89d37947eaSMatthew G. Knepley      if not os.path.isdir(bdir):
90d37947eaSMatthew G. Knepley        raise
91d37947eaSMatthew G. Knepley    cmd = 'mv '+os.path.join(sdir, 'ex'+str(self.num))+' '+self.petsc.example(self.library, self.num)
92d37947eaSMatthew G. Knepley    out, err, ret = self.runShellCommand(cmd, log = log)
93d37947eaSMatthew G. Knepley    if ret:
94*5b6bfdb9SJed Brown      print(err)
95*5b6bfdb9SJed Brown      print(out)
96d37947eaSMatthew G. Knepley    return
97d37947eaSMatthew G. Knepley
98d006b754SMatthew G Knepley  def run(self, numProcs = 1, log = True, **opts):
99b3efd4cdSAndy R. Terrel    cmd = ''
100b3efd4cdSAndy R. Terrel    if self.petsc.mpiexec() is not None:
101b3efd4cdSAndy R. Terrel      cmd += self.petsc.mpiexec() + ' '
102b3efd4cdSAndy R. Terrel      numProcs = os.environ.get('NUM_RANKS', numProcs)
103b3efd4cdSAndy R. Terrel      cmd += ' -n ' + str(numProcs) + ' '
104*5b6bfdb9SJed Brown      if 'PE_HOSTFILE' in os.environ:
105b3efd4cdSAndy R. Terrel        cmd += ' -hostfile hostfile '
106d37947eaSMatthew G. Knepley    cmd += ' '.join([self.petsc.example(self.library, self.num), self.optionsToString(**self.opts), self.optionsToString(**opts)])
10719d5f70aSMatthew G Knepley    if 'batch' in opts and opts['batch']:
10819d5f70aSMatthew G Knepley      del opts['batch']
1093849a283SMatthew G Knepley      filename = generateBatchScript(self.num, numProcs, 120, ' '+self.optionsToString(**self.opts)+' '+self.optionsToString(**opts))
1103849a283SMatthew G Knepley      # Submit job
111d006b754SMatthew G Knepley      out, err, ret = self.runShellCommand('qsub -q gpu '+filename, log = log)
1123849a283SMatthew G Knepley      if ret:
113*5b6bfdb9SJed Brown        print(err)
114*5b6bfdb9SJed Brown        print(out)
11519d5f70aSMatthew G Knepley    else:
116d006b754SMatthew G Knepley      out, err, ret = self.runShellCommand(cmd, log = log)
1173428b40fSMatthew G Knepley      if ret:
118*5b6bfdb9SJed Brown        print(err)
119*5b6bfdb9SJed Brown        print(out)
1200790b1abSMatthew G Knepley    return out
1213428b40fSMatthew G Knepley
122eda8839fSMatthew G Knepleydef processSummary(moduleName, defaultStage, eventNames, times, events):
1233428b40fSMatthew G Knepley  '''Process the Python log summary into plot data'''
1243428b40fSMatthew G Knepley  m = __import__(moduleName)
1253428b40fSMatthew G Knepley  reload(m)
1263428b40fSMatthew G Knepley  # Total Time
1273428b40fSMatthew G Knepley  times.append(m.Time[0])
1283428b40fSMatthew G Knepley  # Particular events
129eda8839fSMatthew G Knepley  for name in eventNames:
130eda8839fSMatthew G Knepley    if name.find(':') >= 0:
131eda8839fSMatthew G Knepley      stageName, name = name.split(':', 1)
132eda8839fSMatthew G Knepley      stage = getattr(m, stageName)
133eda8839fSMatthew G Knepley    else:
134eda8839fSMatthew G Knepley      stage = getattr(m, defaultStage)
135eda8839fSMatthew G Knepley    if name in stage.event:
1363428b40fSMatthew G Knepley      if not name in events:
1373428b40fSMatthew G Knepley        events[name] = []
138df494a56SMatthew G Knepley      try:
1390bc2d6fdSMatthew G. Knepley        events[name].append((max(stage.event[name].Time), sum(stage.event[name].Flops)/(max(stage.event[name].Time) * 1e6)))
140df494a56SMatthew G Knepley      except ZeroDivisionError:
1410bc2d6fdSMatthew G. Knepley        events[name].append((max(stage.event[name].Time), 0))
1423428b40fSMatthew G Knepley  return
1433428b40fSMatthew G Knepley
1446e25a272SMatthew G Knepleydef plotTime(library, num, eventNames, sizes, times, events):
1456e25a272SMatthew G Knepley  from pylab import legend, plot, show, title, xlabel, ylabel
1466e25a272SMatthew G Knepley  import numpy as np
1476e25a272SMatthew G Knepley
1486e25a272SMatthew G Knepley  arches = sizes.keys()
1496e25a272SMatthew G Knepley  data   = []
1506e25a272SMatthew G Knepley  for arch in arches:
1516e25a272SMatthew G Knepley    data.append(sizes[arch])
1526e25a272SMatthew G Knepley    data.append(times[arch])
1536e25a272SMatthew G Knepley  plot(*data)
1546e25a272SMatthew G Knepley  title('Performance on '+library+' Example '+str(num))
1556e25a272SMatthew G Knepley  xlabel('Number of Dof')
1566e25a272SMatthew G Knepley  ylabel('Time (s)')
1576e25a272SMatthew G Knepley  legend(arches, 'upper left', shadow = True)
1586e25a272SMatthew G Knepley  show()
1596e25a272SMatthew G Knepley  return
1606e25a272SMatthew G Knepley
1616e25a272SMatthew G Knepleydef plotEventTime(library, num, eventNames, sizes, times, events, filename = None):
1626e25a272SMatthew G Knepley  from pylab import close, legend, plot, savefig, show, title, xlabel, ylabel
1636e25a272SMatthew G Knepley  import numpy as np
1646e25a272SMatthew G Knepley
1656e25a272SMatthew G Knepley  close()
1666e25a272SMatthew G Knepley  arches = sizes.keys()
1676e25a272SMatthew G Knepley  bs     = events[arches[0]].keys()[0]
1686e25a272SMatthew G Knepley  data   = []
1696e25a272SMatthew G Knepley  names  = []
1706e25a272SMatthew G Knepley  for event, color in zip(eventNames, ['b', 'g', 'r', 'y']):
1716e25a272SMatthew G Knepley    for arch, style in zip(arches, ['-', ':']):
1726e25a272SMatthew G Knepley      if event in events[arch][bs]:
1736e25a272SMatthew G Knepley        names.append(arch+'-'+str(bs)+' '+event)
1746e25a272SMatthew G Knepley        data.append(sizes[arch][bs])
1756e25a272SMatthew G Knepley        data.append(np.array(events[arch][bs][event])[:,0])
1766e25a272SMatthew G Knepley        data.append(color+style)
1776e25a272SMatthew G Knepley      else:
178*5b6bfdb9SJed Brown        print('Could not find %s in %s-%d events' % (event, arch, bs))
179*5b6bfdb9SJed Brown  print(data)
1806e25a272SMatthew G Knepley  plot(*data)
1816e25a272SMatthew G Knepley  title('Performance on '+library+' Example '+str(num))
1826e25a272SMatthew G Knepley  xlabel('Number of Dof')
1836e25a272SMatthew G Knepley  ylabel('Time (s)')
1846e25a272SMatthew G Knepley  legend(names, 'upper left', shadow = True)
1856e25a272SMatthew G Knepley  if filename is None:
1866e25a272SMatthew G Knepley    show()
1876e25a272SMatthew G Knepley  else:
1886e25a272SMatthew G Knepley    savefig(filename)
1896e25a272SMatthew G Knepley  return
1906e25a272SMatthew G Knepley
1916e25a272SMatthew G Knepleydef plotEventFlop(library, num, eventNames, sizes, times, events, filename = None):
1926e25a272SMatthew G Knepley  from pylab import legend, plot, savefig, semilogy, show, title, xlabel, ylabel
1936e25a272SMatthew G Knepley  import numpy as np
1946e25a272SMatthew G Knepley
1956e25a272SMatthew G Knepley  arches = sizes.keys()
1966e25a272SMatthew G Knepley  bs     = events[arches[0]].keys()[0]
1976e25a272SMatthew G Knepley  data   = []
1986e25a272SMatthew G Knepley  names  = []
1996e25a272SMatthew G Knepley  for event, color in zip(eventNames, ['b', 'g', 'r', 'y']):
2006e25a272SMatthew G Knepley    for arch, style in zip(arches, ['-', ':']):
2016e25a272SMatthew G Knepley      if event in events[arch][bs]:
2026e25a272SMatthew G Knepley        names.append(arch+'-'+str(bs)+' '+event)
2036e25a272SMatthew G Knepley        data.append(sizes[arch][bs])
2046e25a272SMatthew G Knepley        data.append(1e-3*np.array(events[arch][bs][event])[:,1])
2056e25a272SMatthew G Knepley        data.append(color+style)
2066e25a272SMatthew G Knepley      else:
207*5b6bfdb9SJed Brown        print('Could not find %s in %s-%d events' % (event, arch, bs))
2086e25a272SMatthew G Knepley  semilogy(*data)
2096e25a272SMatthew G Knepley  title('Performance on '+library+' Example '+str(num))
2106e25a272SMatthew G Knepley  xlabel('Number of Dof')
2116e25a272SMatthew G Knepley  ylabel('Computation Rate (GF/s)')
2126e25a272SMatthew G Knepley  legend(names, 'upper left', shadow = True)
2136e25a272SMatthew G Knepley  if filename is None:
2146e25a272SMatthew G Knepley    show()
2156e25a272SMatthew G Knepley  else:
2166e25a272SMatthew G Knepley    savefig(filename)
2176e25a272SMatthew G Knepley  return
2186e25a272SMatthew G Knepley
219929aa6beSMatthew G. Knepleydef plotEventScaling(library, num, eventNames, procs, events, filename = None):
220929aa6beSMatthew G. Knepley  from pylab import legend, plot, savefig, semilogy, show, title, xlabel, ylabel
221929aa6beSMatthew G. Knepley  import numpy as np
222929aa6beSMatthew G. Knepley
223929aa6beSMatthew G. Knepley  arches = procs.keys()
224929aa6beSMatthew G. Knepley  bs     = events[arches[0]].keys()[0]
225929aa6beSMatthew G. Knepley  data   = []
226929aa6beSMatthew G. Knepley  names  = []
227929aa6beSMatthew G. Knepley  for arch, style in zip(arches, ['-', ':']):
228929aa6beSMatthew G. Knepley    for event, color in zip(eventNames, ['b', 'g', 'r', 'y']):
229929aa6beSMatthew G. Knepley      if event in events[arch][bs]:
230929aa6beSMatthew G. Knepley        names.append(arch+'-'+str(bs)+' '+event)
231929aa6beSMatthew G. Knepley        data.append(procs[arch][bs])
232929aa6beSMatthew G. Knepley        data.append(1e-3*np.array(events[arch][bs][event])[:,1])
233929aa6beSMatthew G. Knepley        data.append(color+style)
234929aa6beSMatthew G. Knepley      else:
235*5b6bfdb9SJed Brown        print('Could not find %s in %s-%d events' % (event, arch, bs))
236929aa6beSMatthew G. Knepley  plot(*data)
237929aa6beSMatthew G. Knepley  title('Performance on '+library+' Example '+str(num))
238929aa6beSMatthew G. Knepley  xlabel('Number of Processors')
239929aa6beSMatthew G. Knepley  ylabel('Computation Rate (GF/s)')
240929aa6beSMatthew G. Knepley  legend(names, 'upper left', shadow = True)
241929aa6beSMatthew G. Knepley  if filename is None:
242929aa6beSMatthew G. Knepley    show()
243929aa6beSMatthew G. Knepley  else:
244929aa6beSMatthew G. Knepley    savefig(filename)
245929aa6beSMatthew G. Knepley  return
246929aa6beSMatthew G. Knepley
247303b7b21SMatthew G Knepleydef plotSummaryLine(library, num, eventNames, sizes, times, events):
2483428b40fSMatthew G Knepley  from pylab import legend, plot, show, title, xlabel, ylabel
2493428b40fSMatthew G Knepley  import numpy as np
2503428b40fSMatthew G Knepley  showTime       = False
2513428b40fSMatthew G Knepley  showEventTime  = True
2523428b40fSMatthew G Knepley  showEventFlops = True
2533428b40fSMatthew G Knepley  arches         = sizes.keys()
2543428b40fSMatthew G Knepley  # Time
2553428b40fSMatthew G Knepley  if showTime:
2563428b40fSMatthew G Knepley    data = []
2573428b40fSMatthew G Knepley    for arch in arches:
2583428b40fSMatthew G Knepley      data.append(sizes[arch])
2593428b40fSMatthew G Knepley      data.append(times[arch])
2603428b40fSMatthew G Knepley    plot(*data)
2613428b40fSMatthew G Knepley    title('Performance on '+library+' Example '+str(num))
2623428b40fSMatthew G Knepley    xlabel('Number of Dof')
2633428b40fSMatthew G Knepley    ylabel('Time (s)')
2643428b40fSMatthew G Knepley    legend(arches, 'upper left', shadow = True)
2653428b40fSMatthew G Knepley    show()
2663428b40fSMatthew G Knepley  # Common event time
2673428b40fSMatthew G Knepley  #   We could make a stacked plot like Rio uses here
2683428b40fSMatthew G Knepley  if showEventTime:
269df494a56SMatthew G Knepley    bs    = events[arches[0]].keys()[0]
2703428b40fSMatthew G Knepley    data  = []
2713428b40fSMatthew G Knepley    names = []
272df494a56SMatthew G Knepley    for event, color in zip(eventNames, ['b', 'g', 'r', 'y']):
2733428b40fSMatthew G Knepley      for arch, style in zip(arches, ['-', ':']):
274df494a56SMatthew G Knepley        if event in events[arch][bs]:
275df494a56SMatthew G Knepley          names.append(arch+'-'+str(bs)+' '+event)
276df494a56SMatthew G Knepley          data.append(sizes[arch][bs])
277df494a56SMatthew G Knepley          data.append(np.array(events[arch][bs][event])[:,0])
2783428b40fSMatthew G Knepley          data.append(color+style)
279df494a56SMatthew G Knepley        else:
280*5b6bfdb9SJed Brown          print('Could not find %s in %s-%d events' % (event, arch, bs))
281*5b6bfdb9SJed Brown    print(data)
2823428b40fSMatthew G Knepley    plot(*data)
2833428b40fSMatthew G Knepley    title('Performance on '+library+' Example '+str(num))
2843428b40fSMatthew G Knepley    xlabel('Number of Dof')
2853428b40fSMatthew G Knepley    ylabel('Time (s)')
2863428b40fSMatthew G Knepley    legend(names, 'upper left', shadow = True)
2873428b40fSMatthew G Knepley    show()
2883428b40fSMatthew G Knepley  # Common event flops
2893428b40fSMatthew G Knepley  #   We could make a stacked plot like Rio uses here
2903428b40fSMatthew G Knepley  if showEventFlops:
291df494a56SMatthew G Knepley    bs    = events[arches[0]].keys()[0]
2923428b40fSMatthew G Knepley    data  = []
2933428b40fSMatthew G Knepley    names = []
294df494a56SMatthew G Knepley    for event, color in zip(eventNames, ['b', 'g', 'r', 'y']):
2953428b40fSMatthew G Knepley      for arch, style in zip(arches, ['-', ':']):
296df494a56SMatthew G Knepley        if event in events[arch][bs]:
297df494a56SMatthew G Knepley          names.append(arch+'-'+str(bs)+' '+event)
298df494a56SMatthew G Knepley          data.append(sizes[arch][bs])
299df494a56SMatthew G Knepley          data.append(np.array(events[arch][bs][event])[:,1])
3003428b40fSMatthew G Knepley          data.append(color+style)
301df494a56SMatthew G Knepley        else:
302*5b6bfdb9SJed Brown          print('Could not find %s in %s-%d events' % (event, arch, bs))
3033428b40fSMatthew G Knepley    plot(*data)
3043428b40fSMatthew G Knepley    title('Performance on '+library+' Example '+str(num))
3053428b40fSMatthew G Knepley    xlabel('Number of Dof')
3063428b40fSMatthew G Knepley    ylabel('Computation Rate (MF/s)')
3073428b40fSMatthew G Knepley    legend(names, 'upper left', shadow = True)
3083428b40fSMatthew G Knepley    show()
3093428b40fSMatthew G Knepley  return
3103428b40fSMatthew G Knepley
311303b7b21SMatthew G Knepleydef plotSummaryBar(library, num, eventNames, sizes, times, events):
312e3da8a91SMatthew G Knepley  import numpy as np
313e3da8a91SMatthew G Knepley  import matplotlib.pyplot as plt
314e3da8a91SMatthew G Knepley
315303b7b21SMatthew G Knepley  eventColors = ['b', 'g', 'r', 'y']
316e3da8a91SMatthew G Knepley  arches = sizes.keys()
317e3da8a91SMatthew G Knepley  names  = []
318e3da8a91SMatthew G Knepley  N      = len(sizes[arches[0]])
319e3da8a91SMatthew G Knepley  width  = 0.2
320e3da8a91SMatthew G Knepley  ind    = np.arange(N) - 0.25
321e3da8a91SMatthew G Knepley  bars   = {}
322e3da8a91SMatthew G Knepley  for arch in arches:
323e3da8a91SMatthew G Knepley    bars[arch] = []
324e3da8a91SMatthew G Knepley    bottom = np.zeros(N)
325e3da8a91SMatthew G Knepley    for event, color in zip(eventNames, eventColors):
326e3da8a91SMatthew G Knepley      names.append(arch+' '+event)
327e3da8a91SMatthew G Knepley      times = np.array(events[arch][event])[:,0]
328e3da8a91SMatthew G Knepley      bars[arch].append(plt.bar(ind, times, width, color=color, bottom=bottom))
329e3da8a91SMatthew G Knepley      bottom += times
330e3da8a91SMatthew G Knepley    ind += 0.3
331e3da8a91SMatthew G Knepley
332e3da8a91SMatthew G Knepley  plt.xlabel('Number of Dof')
333e3da8a91SMatthew G Knepley  plt.ylabel('Time (s)')
334e3da8a91SMatthew G Knepley  plt.title('GPU vs. CPU Performance on '+library+' Example '+str(num))
335e3da8a91SMatthew G Knepley  plt.xticks(np.arange(N), map(str, sizes[arches[0]]))
336e3da8a91SMatthew G Knepley  #plt.yticks(np.arange(0,81,10))
337e3da8a91SMatthew G Knepley  #plt.legend( (p1[0], p2[0]), ('Men', 'Women') )
338e3da8a91SMatthew G Knepley  plt.legend([bar[0] for bar in bars[arches[0]]], eventNames, 'upper right', shadow = True)
339e3da8a91SMatthew G Knepley
340e3da8a91SMatthew G Knepley  plt.show()
341e3da8a91SMatthew G Knepley  return
342e3da8a91SMatthew G Knepley
343df494a56SMatthew G Knepleydef getDMComplexSize(dim, out):
3440a2738abSAndy R. Terrel  '''Retrieves the number of cells from -dm_view output'''
345683aebbfSMatthew G Knepley  size = 0
346683aebbfSMatthew G Knepley  for line in out.split('\n'):
347683aebbfSMatthew G Knepley    if line.strip().startswith(str(dim)+'-cells: '):
3480a2738abSAndy R. Terrel      sizes = line.strip()[9:].split()
3490a2738abSAndy R. Terrel      size  = sum(map(int, sizes))
350683aebbfSMatthew G Knepley      break
351683aebbfSMatthew G Knepley  return size
352683aebbfSMatthew G Knepley
353d006b754SMatthew G Knepleydef run_DMDA(ex, name, opts, args, sizes, times, events, log=True):
354683aebbfSMatthew G Knepley  for n in map(int, args.size):
355d006b754SMatthew G Knepley    ex.run(log=log, da_grid_x=n, da_grid_y=n, **opts)
356683aebbfSMatthew G Knepley    sizes[name].append(n*n * args.comp)
357683aebbfSMatthew G Knepley    processSummary('summary', args.stage, args.events, times[name], events[name])
358683aebbfSMatthew G Knepley  return
359683aebbfSMatthew G Knepley
360d006b754SMatthew G Knepleydef run_DMComplex(ex, name, opts, args, sizes, times, events, log=True):
361683aebbfSMatthew G Knepley  # This should eventually be replaced by a direct FFC/Ignition interface
362683aebbfSMatthew G Knepley  if args.operator == 'laplacian':
363683aebbfSMatthew G Knepley    numComp  = 1
364683aebbfSMatthew G Knepley  elif args.operator == 'elasticity':
365683aebbfSMatthew G Knepley    numComp  = args.dim
366683aebbfSMatthew G Knepley  else:
367683aebbfSMatthew G Knepley    raise RuntimeError('Unknown operator: %s' % args.operator)
368683aebbfSMatthew G Knepley
369683aebbfSMatthew G Knepley  for numBlock in [2**i for i in map(int, args.blockExp)]:
370683aebbfSMatthew G Knepley    opts['gpu_blocks'] = numBlock
371683aebbfSMatthew G Knepley    args.files = ['['+','.join(source)+']']
372683aebbfSMatthew G Knepley    buildExample(args)
373683aebbfSMatthew G Knepley    sizes[name][numBlock]  = []
374683aebbfSMatthew G Knepley    times[name][numBlock]  = []
375683aebbfSMatthew G Knepley    events[name][numBlock] = {}
376683aebbfSMatthew G Knepley    for r in map(float, args.refine):
377d006b754SMatthew G Knepley      out = ex.run(log=log, refinement_limit=r, **opts)
378df494a56SMatthew G Knepley      sizes[name][numBlock].append(getDMComplexSize(args.dim, out))
379683aebbfSMatthew G Knepley      processSummary('summary', args.stage, args.events, times[name][numBlock], events[name][numBlock])
380683aebbfSMatthew G Knepley  return
381683aebbfSMatthew G Knepley
382d006b754SMatthew G Knepleydef outputData(sizes, times, events, name = 'output.py'):
383d006b754SMatthew G Knepley  if os.path.exists(name):
384d006b754SMatthew G Knepley    base, ext = os.path.splitext(name)
385d006b754SMatthew G Knepley    num = 1
386d006b754SMatthew G Knepley    while os.path.exists(base+str(num)+ext):
387d006b754SMatthew G Knepley      num += 1
388d006b754SMatthew G Knepley    name = base+str(num)+ext
389d006b754SMatthew G Knepley  with file(name, 'w') as f:
390d006b754SMatthew G Knepley    f.write('#PETSC_ARCH='+os.environ['PETSC_ARCH']+' '+' '.join(sys.argv)+'\n')
391d006b754SMatthew G Knepley    f.write('sizes  = '+repr(sizes)+'\n')
392d006b754SMatthew G Knepley    f.write('times  = '+repr(times)+'\n')
393d006b754SMatthew G Knepley    f.write('events = '+repr(events)+'\n')
394d006b754SMatthew G Knepley  return
395d006b754SMatthew G Knepley
3963428b40fSMatthew G Knepleyif __name__ == '__main__':
397eda8839fSMatthew G Knepley  import argparse
398eda8839fSMatthew G Knepley
399eda8839fSMatthew G Knepley  parser = argparse.ArgumentParser(description     = 'PETSc Benchmarking',
400eda8839fSMatthew G Knepley                                   epilog          = 'This script runs src/<library>/examples/tutorials/ex<num>, For more information, visit http://www.mcs.anl.gov/petsc',
401eda8839fSMatthew G Knepley                                   formatter_class = argparse.ArgumentDefaultsHelpFormatter)
402eda8839fSMatthew G Knepley  parser.add_argument('--library', default='SNES',                     help='The PETSc library used in this example')
403eda8839fSMatthew G Knepley  parser.add_argument('--num',     type = int, default='5',            help='The example number')
404eda8839fSMatthew G Knepley  parser.add_argument('--module',  default='summary',                  help='The module for timing output')
405eda8839fSMatthew G Knepley  parser.add_argument('--stage',   default='Main_Stage',               help='The default logging stage')
406eda8839fSMatthew G Knepley  parser.add_argument('--events',  nargs='+',                          help='Events to process')
407eda8839fSMatthew G Knepley  parser.add_argument('--batch',   action='store_true', default=False, help='Generate batch files for the runs instead')
408d006b754SMatthew G Knepley  parser.add_argument('--daemon',  action='store_true', default=False, help='Run as a daemon')
4093973d8daSKarl Rupp  parser.add_argument('--gpulang', default='OpenCL',                   help='GPU Language to use: Either CUDA or OpenCL (default)')
410683aebbfSMatthew G Knepley  subparsers = parser.add_subparsers(help='DM types')
411eda8839fSMatthew G Knepley
412683aebbfSMatthew G Knepley  parser_dmda = subparsers.add_parser('DMDA', help='Use a DMDA for the problem geometry')
413683aebbfSMatthew G Knepley  parser_dmda.add_argument('--size', nargs='+',  default=['10'], help='Grid size (implementation dependent)')
414683aebbfSMatthew G Knepley  parser_dmda.add_argument('--comp', type = int, default='1',    help='Number of field components')
415683aebbfSMatthew G Knepley  parser_dmda.add_argument('runs',   nargs='*',                  help='Run descriptions: <name>=<args>')
416683aebbfSMatthew G Knepley
417df494a56SMatthew G Knepley  parser_dmmesh = subparsers.add_parser('DMComplex', help='Use a DMComplex for the problem geometry')
418683aebbfSMatthew G Knepley  parser_dmmesh.add_argument('--dim',      type = int, default='2',        help='Spatial dimension')
419683aebbfSMatthew G Knepley  parser_dmmesh.add_argument('--refine',   nargs='+',  default=['0.0'],    help='List of refinement limits')
420683aebbfSMatthew G Knepley  parser_dmmesh.add_argument('--order',    type = int, default='1',        help='Order of the finite element')
421683aebbfSMatthew G Knepley  parser_dmmesh.add_argument('--operator', default='laplacian',            help='The operator name')
422683aebbfSMatthew G Knepley  parser_dmmesh.add_argument('--blockExp', nargs='+', default=range(0, 5), help='List of block exponents j, block size is 2^j')
423683aebbfSMatthew G Knepley  parser_dmmesh.add_argument('runs',       nargs='*',                      help='Run descriptions: <name>=<args>')
424eda8839fSMatthew G Knepley
425eda8839fSMatthew G Knepley  args = parser.parse_args()
426eda8839fSMatthew G Knepley  print(args)
427683aebbfSMatthew G Knepley  if hasattr(args, 'comp'):
428683aebbfSMatthew G Knepley    args.dmType = 'DMDA'
429683aebbfSMatthew G Knepley  else:
430df494a56SMatthew G Knepley    args.dmType = 'DMComplex'
431683aebbfSMatthew G Knepley
432eda8839fSMatthew 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')
4333973d8daSKarl Rupp  if args.gpulang == 'CUDA':
4343973d8daSKarl Rupp    source = ex.petsc.source(args.library, args.num, '.cu')
4353973d8daSKarl Rupp  else:
4363973d8daSKarl Rupp    source = ex.petsc.source(args.library, args.num, 'OpenCL.c')  # Using the convention of OpenCL code residing in source files ending in 'OpenCL.c' (at least for snes/ex52)
4373428b40fSMatthew G Knepley  sizes  = {}
4383428b40fSMatthew G Knepley  times  = {}
4393428b40fSMatthew G Knepley  events = {}
440d006b754SMatthew G Knepley  log    = not args.daemon
441d006b754SMatthew G Knepley
442d006b754SMatthew G Knepley  if args.daemon:
443d006b754SMatthew G Knepley    import daemon
444*5b6bfdb9SJed Brown    print('Starting daemon')
445d006b754SMatthew G Knepley    daemon.createDaemon('.')
446683aebbfSMatthew G Knepley
447eda8839fSMatthew G Knepley  for run in args.runs:
448eda8839fSMatthew G Knepley    name, stropts = run.split('=', 1)
449eda8839fSMatthew G Knepley    opts = dict([t if len(t) == 2 else (t[0], None) for t in [arg.split('=', 1) for arg in stropts.split(' ')]])
450683aebbfSMatthew G Knepley    if args.dmType == 'DMDA':
4513428b40fSMatthew G Knepley      sizes[name]  = []
4523428b40fSMatthew G Knepley      times[name]  = []
4533428b40fSMatthew G Knepley      events[name] = {}
454d006b754SMatthew G Knepley      run_DMDA(ex, name, opts, args, sizes, times, events, log=log)
455df494a56SMatthew G Knepley    elif args.dmType == 'DMComplex':
456683aebbfSMatthew G Knepley      sizes[name]  = {}
457683aebbfSMatthew G Knepley      times[name]  = {}
458683aebbfSMatthew G Knepley      events[name] = {}
459d006b754SMatthew G Knepley      run_DMComplex(ex, name, opts, args, sizes, times, events, log=log)
460d006b754SMatthew G Knepley  outputData(sizes, times, events)
461d006b754SMatthew G Knepley  if not args.batch and log: plotSummaryLine(args.library, args.num, args.events, sizes, times, events)
462683aebbfSMatthew G Knepley# Benchmark for ex50
463683aebbfSMatthew G Knepley# ./src/benchmarks/benchmarkExample.py --events VecMDot VecMAXPY KSPGMRESOrthog MatMult VecCUSPCopyTo VecCUSPCopyFrom MatCUSPCopyTo --num 50 DMDA --size 10 20 50 100 --comp 4 CPU='pc_type=none mat_no_inode dm_vec_type=seq dm_mat_type=seqaij' GPU='pc_type=none mat_no_inode dm_vec_type=seqcusp dm_mat_type=seqaijcusp cusp_synchronize'
464683aebbfSMatthew G Knepley# Benchmark for ex52
465fd49fd63SMatthew G Knepley# ./src/benchmarks/benchmarkExample.py --events IntegBatchCPU IntegBatchGPU IntegGPUOnly --num 52 DMComplex --refine 0.0625 0.00625 0.000625 0.0000625 --blockExp 4 --order=1 CPU='dm_view show_residual=0 compute_function batch' GPU='dm_view show_residual=0 compute_function batch gpu gpu_batches=8'
466fd49fd63SMatthew G Knepley# ./src/benchmarks/benchmarkExample.py --events IntegBatchCPU IntegBatchGPU IntegGPUOnly --num 52 DMComplex --refine 0.0625 0.00625 0.000625 0.0000625 --blockExp 4 --order=1 --operator=elasticity CPU='dm_view op_type=elasticity show_residual=0 compute_function batch' GPU='dm_view op_type=elasticity show_residual=0 compute_function batch gpu gpu_batches=8'
467fd49fd63SMatthew G Knepley# ./src/benchmarks/benchmarkExample.py --events IntegBatchCPU IntegBatchGPU IntegGPUOnly --num 52 DMComplex --dim=3 --refine 0.0625 0.00625 0.000625 0.0000625 --blockExp 4 --order=1 CPU='dim=3 dm_view show_residual=0 compute_function batch' GPU='dim=3 dm_view show_residual=0 compute_function batch gpu gpu_batches=8'
468