xref: /petsc/src/benchmarks/benchmarkExample.py (revision 3428b40f6ebb789a1e16b81e8174cce9085ea3e1)
1*3428b40fSMatthew G Knepley#!/usr/bin/env python
2*3428b40fSMatthew G Knepleyimport os
3*3428b40fSMatthew G Knepley
4*3428b40fSMatthew G Knepleyclass PETSc(object):
5*3428b40fSMatthew G Knepley  def __init__(self):
6*3428b40fSMatthew G Knepley    return
7*3428b40fSMatthew G Knepley
8*3428b40fSMatthew G Knepley  def dir(self):
9*3428b40fSMatthew G Knepley    '''Return the root directory for the PETSc tree (usually $PETSC_DIR)'''
10*3428b40fSMatthew G Knepley    # This should search for a valid PETSc
11*3428b40fSMatthew G Knepley    return os.environ['PETSC_DIR']
12*3428b40fSMatthew G Knepley
13*3428b40fSMatthew G Knepley  def arch(self):
14*3428b40fSMatthew G Knepley    '''Return the PETSc build label (usually $PETSC_ARCH)'''
15*3428b40fSMatthew G Knepley    # This should be configurable
16*3428b40fSMatthew G Knepley    return os.environ['PETSC_ARCH']
17*3428b40fSMatthew G Knepley
18*3428b40fSMatthew G Knepley  def mpiexec(self):
19*3428b40fSMatthew G Knepley    '''Return the path for the mpi launch executable'''
20*3428b40fSMatthew G Knepley    return os.path.join(self.dir(), self.arch(), 'bin', 'mpiexec')
21*3428b40fSMatthew G Knepley
22*3428b40fSMatthew G Knepley  def example(self, num):
23*3428b40fSMatthew G Knepley    '''Return the path to the executable for a given example number'''
24*3428b40fSMatthew G Knepley    return os.path.join(self.dir(), self.arch(), 'lib', 'ex'+str(num)+'-obj', 'ex'+str(num))
25*3428b40fSMatthew G Knepley
26*3428b40fSMatthew G Knepleyclass PETScExample(object):
27*3428b40fSMatthew G Knepley  def __init__(self, library, num, **defaultOptions):
28*3428b40fSMatthew G Knepley    self.petsc   = PETSc()
29*3428b40fSMatthew G Knepley    self.library = library
30*3428b40fSMatthew G Knepley    self.num     = num
31*3428b40fSMatthew G Knepley    self.opts    = defaultOptions
32*3428b40fSMatthew G Knepley    return
33*3428b40fSMatthew G Knepley
34*3428b40fSMatthew G Knepley  @staticmethod
35*3428b40fSMatthew G Knepley  def runShellCommand(command, cwd = None):
36*3428b40fSMatthew G Knepley    import subprocess
37*3428b40fSMatthew G Knepley
38*3428b40fSMatthew G Knepley    Popen = subprocess.Popen
39*3428b40fSMatthew G Knepley    PIPE  = subprocess.PIPE
40*3428b40fSMatthew G Knepley    print 'Executing: %s\n' % (command,)
41*3428b40fSMatthew G Knepley    pipe = Popen(command, cwd=cwd, stdin=None, stdout=PIPE, stderr=PIPE, bufsize=-1, shell=True, universal_newlines=True)
42*3428b40fSMatthew G Knepley    (out, err) = pipe.communicate()
43*3428b40fSMatthew G Knepley    ret = pipe.returncode
44*3428b40fSMatthew G Knepley    return (out, err, ret)
45*3428b40fSMatthew G Knepley
46*3428b40fSMatthew G Knepley  def optionsToString(self, **opts):
47*3428b40fSMatthew G Knepley    '''Convert a dictionary of options to a command line argument string'''
48*3428b40fSMatthew G Knepley    a = []
49*3428b40fSMatthew G Knepley    for key,value in opts.iteritems():
50*3428b40fSMatthew G Knepley      if value is None:
51*3428b40fSMatthew G Knepley        a.append('-'+key)
52*3428b40fSMatthew G Knepley      else:
53*3428b40fSMatthew G Knepley        a.append('-'+key+' '+str(value))
54*3428b40fSMatthew G Knepley    return ' '.join(a)
55*3428b40fSMatthew G Knepley
56*3428b40fSMatthew G Knepley  def run(self, **opts):
57*3428b40fSMatthew G Knepley    cmd = ' '.join([self.petsc.mpiexec(), '-n 1', self.petsc.example(self.num)])+' '+self.optionsToString(**self.opts)+' '+self.optionsToString(**opts)
58*3428b40fSMatthew G Knepley    out, err, ret = self.runShellCommand(cmd)
59*3428b40fSMatthew G Knepley    if ret:
60*3428b40fSMatthew G Knepley      print err
61*3428b40fSMatthew G Knepley      print out
62*3428b40fSMatthew G Knepley    return
63*3428b40fSMatthew G Knepley
64*3428b40fSMatthew G Knepleydef processSummary(moduleName, times, events):
65*3428b40fSMatthew G Knepley  '''Process the Python log summary into plot data'''
66*3428b40fSMatthew G Knepley  m = __import__(moduleName)
67*3428b40fSMatthew G Knepley  reload(m)
68*3428b40fSMatthew G Knepley  # Total Time
69*3428b40fSMatthew G Knepley  times.append(m.Time[0])
70*3428b40fSMatthew G Knepley  # Common events
71*3428b40fSMatthew G Knepley  #   VecMAXPY and VecMDot essentially give KSPGMRESOrthog
72*3428b40fSMatthew G Knepley  #   Add the time and flop rate
73*3428b40fSMatthew G Knepley  for name in ['VecMDot', 'VecMAXPY', 'KSPGMRESOrthog', 'MatMult']:
74*3428b40fSMatthew G Knepley    if not name in events:
75*3428b40fSMatthew G Knepley      events[name] = []
76*3428b40fSMatthew G Knepley    events[name].append((m.Solve.event[name].Time[0], m.Solve.event[name].Flops[0]/(m.Solve.event[name].Time[0] * 1e6)))
77*3428b40fSMatthew G Knepley  # Particular events
78*3428b40fSMatthew G Knepley  for name in ['VecCUSPCopyTo', 'VecCUSPCopyFrom', 'MatCUSPCopyTo']:
79*3428b40fSMatthew G Knepley    if name in m.Solve.event:
80*3428b40fSMatthew G Knepley      if not name in events:
81*3428b40fSMatthew G Knepley        events[name] = []
82*3428b40fSMatthew G Knepley      events[name].append((m.Solve.event[name].Time[0], m.Solve.event[name].Flops[0]/(m.Solve.event[name].Time[0] * 1e6)))
83*3428b40fSMatthew G Knepley  return
84*3428b40fSMatthew G Knepley
85*3428b40fSMatthew G Knepleydef plotSummary(library, num, sizes, times, events):
86*3428b40fSMatthew G Knepley  from pylab import legend, plot, show, title, xlabel, ylabel
87*3428b40fSMatthew G Knepley  import numpy as np
88*3428b40fSMatthew G Knepley  showTime       = False
89*3428b40fSMatthew G Knepley  showEventTime  = True
90*3428b40fSMatthew G Knepley  showEventFlops = True
91*3428b40fSMatthew G Knepley  arches         = sizes.keys()
92*3428b40fSMatthew G Knepley  # Time
93*3428b40fSMatthew G Knepley  if showTime:
94*3428b40fSMatthew G Knepley    data = []
95*3428b40fSMatthew G Knepley    for arch in arches:
96*3428b40fSMatthew G Knepley      data.append(sizes[arch])
97*3428b40fSMatthew G Knepley      data.append(times[arch])
98*3428b40fSMatthew G Knepley    plot(*data)
99*3428b40fSMatthew G Knepley    title('Performance on '+library+' Example '+str(num))
100*3428b40fSMatthew G Knepley    xlabel('Number of Dof')
101*3428b40fSMatthew G Knepley    ylabel('Time (s)')
102*3428b40fSMatthew G Knepley    legend(arches, 'upper left', shadow = True)
103*3428b40fSMatthew G Knepley    show()
104*3428b40fSMatthew G Knepley  # Common event time
105*3428b40fSMatthew G Knepley  #   We could make a stacked plot like Rio uses here
106*3428b40fSMatthew G Knepley  if showEventTime:
107*3428b40fSMatthew G Knepley    data  = []
108*3428b40fSMatthew G Knepley    names = []
109*3428b40fSMatthew G Knepley    for event, color in [('VecMDot', 'b'), ('VecMAXPY', 'g'), ('MatMult', 'r')]:
110*3428b40fSMatthew G Knepley      for arch, style in zip(arches, ['-', ':']):
111*3428b40fSMatthew G Knepley        names.append(arch+' '+event)
112*3428b40fSMatthew G Knepley        data.append(sizes[arch])
113*3428b40fSMatthew G Knepley        data.append(np.array(events[arch][event])[:,0])
114*3428b40fSMatthew G Knepley        data.append(color+style)
115*3428b40fSMatthew G Knepley    plot(*data)
116*3428b40fSMatthew G Knepley    title('Performance on '+library+' Example '+str(num))
117*3428b40fSMatthew G Knepley    xlabel('Number of Dof')
118*3428b40fSMatthew G Knepley    ylabel('Time (s)')
119*3428b40fSMatthew G Knepley    legend(names, 'upper left', shadow = True)
120*3428b40fSMatthew G Knepley    show()
121*3428b40fSMatthew G Knepley  # Common event flops
122*3428b40fSMatthew G Knepley  #   We could make a stacked plot like Rio uses here
123*3428b40fSMatthew G Knepley  if showEventFlops:
124*3428b40fSMatthew G Knepley    data  = []
125*3428b40fSMatthew G Knepley    names = []
126*3428b40fSMatthew G Knepley    for event, color in [('VecMDot', 'b'), ('VecMAXPY', 'g'), ('MatMult', 'r')]:
127*3428b40fSMatthew G Knepley      for arch, style in zip(arches, ['-', ':']):
128*3428b40fSMatthew G Knepley        names.append(arch+' '+event)
129*3428b40fSMatthew G Knepley        data.append(sizes[arch])
130*3428b40fSMatthew G Knepley        data.append(np.array(events[arch][event])[:,1])
131*3428b40fSMatthew G Knepley        data.append(color+style)
132*3428b40fSMatthew G Knepley    plot(*data)
133*3428b40fSMatthew G Knepley    title('Performance on '+library+' Example '+str(num))
134*3428b40fSMatthew G Knepley    xlabel('Number of Dof')
135*3428b40fSMatthew G Knepley    ylabel('Computation Rate (MF/s)')
136*3428b40fSMatthew G Knepley    legend(names, 'upper left', shadow = True)
137*3428b40fSMatthew G Knepley    show()
138*3428b40fSMatthew G Knepley  return
139*3428b40fSMatthew G Knepley
140*3428b40fSMatthew G Knepleyif __name__ == '__main__':
141*3428b40fSMatthew G Knepley  library = 'SNES'
142*3428b40fSMatthew G Knepley  num     = 19
143*3428b40fSMatthew 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')
144*3428b40fSMatthew G Knepley  sizes   = {}
145*3428b40fSMatthew G Knepley  times   = {}
146*3428b40fSMatthew G Knepley  events  = {}
147*3428b40fSMatthew G Knepley  for name, vecType, matType, opts in [('CPU', 'seq', 'seqaij', {}), ('GPU', 'seqcusp', 'seqaijcusp', {'cusp_synchronize': None})]:
148*3428b40fSMatthew G Knepley    sizes[name]  = []
149*3428b40fSMatthew G Knepley    times[name]  = []
150*3428b40fSMatthew G Knepley    events[name] = {}
151*3428b40fSMatthew G Knepley    #for n in [10, 20, 50, 100, 150, 200]:
152*3428b40fSMatthew G Knepley    for n in [10, 20]:
153*3428b40fSMatthew G Knepley      ex.run(da_grid_x=n, da_grid_y=n, da_vec_type=vecType, da_mat_type=matType, **opts)
154*3428b40fSMatthew G Knepley      sizes[name].append(n*n * 4)
155*3428b40fSMatthew G Knepley      processSummary('summary', times[name], events[name])
156*3428b40fSMatthew G Knepley  plotSummary(library, num, sizes, times, events)
157