xref: /petsc/src/benchmarks/benchmarkAssembly.py (revision d52bd9f3ee665b897a5f0dc75d2f9f8201159d66)
1#!/usr/bin/env python
2import os
3from benchmarkExample import PETScExample
4
5savedTiming = {'baconost': {'ElemAssembly': [(0.040919999999999998, 0.0), (0.1242, 0.0), (0.24410000000000001, 0.0), (0.374, 0.0), (0.56259999999999999, 0.0), (0.79049999999999998, 0.0), (1.0880000000000001, 0.0), (1.351, 0.0), (1.6930000000000001, 0.0), (2.0609999999999999, 0.0), (2.4820000000000002, 0.0), (3.0640000000000001, 0.0)],
6                            'MatCUSPSetValBch': [(0.0123, 0.0), (0.023429999999999999, 0.0), (0.043540000000000002, 0.0), (0.06608, 0.0), (0.09579, 0.0), (0.12920000000000001, 0.0), (0.17169999999999999, 0.0), (0.2172, 0.0), (0.27179999999999999, 0.0), (0.48309999999999997, 0.0), (0.44180000000000003, 0.0), (0.51529999999999998, 0.0)]}
7               }
8
9def calculateNonzeros(n):
10  num = 0
11  # corners
12  num += 2*3 + 2*4
13  # edges
14  num += 4*(n-2)*5
15  # interior
16  num += (n-2)*(n-2)*7
17  return num
18
19def processSummary(moduleName, times, events):
20  '''Process the Python log summary into plot data'''
21  m = __import__(moduleName)
22  reload(m)
23  # Total Time
24  times.append(m.Time[0])
25  # Common events
26  #   Add the time and flop rate
27  for stageName, eventName in [('GPU_Stage','MatCUSPSetValBch'), ('CPU_Stage','ElemAssembly')]:
28    s = getattr(m, stageName)
29    if not eventName in events:
30      events[eventName] = []
31    events[eventName].append((s.event[eventName].Time[0], s.event[eventName].Flops[0]/(s.event[eventName].Time[0] * 1e6)))
32  return
33
34def plotSummary(library, num, sizes, nonzeros, times, events):
35  from pylab import legend, plot, show, title, xlabel, ylabel, ylim
36  import numpy as np
37  showEventTime      = True
38  showTimePerRow     = False
39  showTimePerNonzero = True
40  print events
41  if showEventTime:
42    data  = []
43    names = []
44    for event, style in [('MatCUSPSetValBch', 'b-'), ('ElemAssembly', 'b:')]:
45      names.append(event)
46      data.append(sizes)
47      data.append(np.array(events[event])[:,0])
48      data.append(style)
49    plot(*data)
50    title('Performance on '+library+' Example '+str(num))
51    xlabel('Number of Dof')
52    ylabel('Time (s)')
53    legend(names, 'upper left', shadow = True)
54    show()
55  if showTimePerRow:
56    data  = []
57    names = []
58    for event, style in [('MatCUSPSetValBch', 'b-'), ('ElemAssembly', 'b:')]:
59      names.append(event)
60      data.append(sizes)
61      rows = np.sqrt(sizes)
62      data.append(np.array(events[event])[:,0]/rows/3)
63      data.append(style)
64    plot(*data)
65    title('Performance on '+library+' Example '+str(num))
66    xlabel('Number of Dof')
67    ylabel('Time/Row (s)')
68    legend(names, 'upper left', shadow = True)
69    show()
70  if showTimePerNonzero:
71    data  = []
72    names = []
73    for event, style in [('MatCUSPSetValBch', 'b-'), ('ElemAssembly', 'b:')]:
74      names.append(event)
75      data.append(sizes)
76      data.append(np.array(events[event])[:,0]/nonzeros * 10**9)
77      data.append(style)
78    plot(*data)
79    title('Performance on '+library+' Example '+str(num))
80    xlabel('Number of Dof')
81    ylabel('Time/Nonzero (ns)')
82    legend(names, 'center right', shadow = True)
83    show()
84  return
85
86if __name__ == '__main__':
87  import argparse
88
89  parser = argparse.ArgumentParser(description     = 'PETSc Benchmarking',
90                                   epilog          = 'This script runs src/<library>/examples/tutorials/ex<num>, For more information, visit http://www.mcs.anl.gov/petsc',
91                                   formatter_class = argparse.ArgumentDefaultsHelpFormatter)
92  parser.add_argument('--library', default='KSP',           help='The PETSc library used in this example')
93  parser.add_argument('--num',     type = int, default='4', help='The example number')
94  parser.add_argument('--module',  default='summary',       help='The module for timing output')
95  parser.add_argument('--saved',                            help='Name of saved data')
96  parser.add_argument('--scaling',                          help='Run parallel scaling test')
97  parser.add_argument('--small',   action='store_true', default=False, help='Use small sizes')
98  parser.add_argument('--batch',   action='store_true', default=False, help='Generate batch files for the runs instead')
99
100  args = parser.parse_args()
101  print(args)
102  ex       = PETScExample(args.library, args.num, log_summary_python = None if args.batch else args.module+'.py', preload='off')
103  sizes    = []
104  nonzeros = []
105  times    = []
106  if args.saved is None:
107    events   = {}
108    if args.scaling == 'strong':
109      procs  = [1, 2, 4, 8]
110      if args.small:
111        grid = [10]*len(procs)
112      else:
113        grid = [1250]*len(procs)
114    else:
115      if args.small:
116        grid = [100, 150, 200, 250, 300]
117      else:
118        grid = range(150, 1350, 100)
119      procs  = [1]*len(grid)
120    for n, p in zip(grid, procs):
121      ex.run(p, da_grid_x=n, da_grid_y=n, cusp_synchronize=1, batch=args.batch)
122      sizes.append(n*n)
123      nonzeros.append(calculateNonzeros(n))
124      if not args.batch:
125        processSummary(args.module, times, events)
126        os.remove(args.module+'.pyc')
127  else:
128    if args.batch: raise RuntimeException('Cannot use batch option with saved data')
129    if args.saved in savedTiming:
130      events = savedTiming[args.saved]
131    else:
132      # Process output to produce module
133      events       = {}
134      filenameBase = args.saved[:-7]
135      jobnumBase   = int(args.saved[-7:])
136      for i, n in enumerate(range(150, 1350, 100)):
137        filename = filenameBase+str(jobnumBase+i)
138        print 'Processing',filename
139        headerSeen = False
140        with file(filename) as f, file(args.module+'.py', 'w') as o:
141          for line in f.readlines():
142            if not headerSeen:
143              if not line[0] == '#': continue
144              headerSeen = True
145            if line[0] == '#' and line[-6:] == '=====\n': break
146            o.write(line)
147            #print line
148        processSummary(args.module, times, events)
149        # I can't believe that this is necessary
150        os.remove(args.module+'.pyc')
151    for n in range(150, 1350, 100):
152      sizes.append(n*n)
153      nonzeros.append(calculateNonzeros(n))
154  if not args.batch: plotSummary(args.library, args.num, sizes, nonzeros, times, events)
155