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