xref: /libCEED/benchmarks/postprocess_plot.py (revision d13e9b485390d2a242cbc549de647bb7b44f1cad)
1*d13e9b48SJed Brown#!/usr/bin/env python3
2*d13e9b48SJed Brown# Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC.
3*d13e9b48SJed Brown# Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707.
4*d13e9b48SJed Brown# All Rights reserved. See files LICENSE and NOTICE for details.
5*d13e9b48SJed Brown#
6*d13e9b48SJed Brown# This file is part of CEED, a collection of benchmarks, miniapps, software
7*d13e9b48SJed Brown# libraries and APIs for efficient high-order finite element and spectral
8*d13e9b48SJed Brown# element discretizations for exascale applications. For more information and
9*d13e9b48SJed Brown# source code availability see http://github.com/ceed.
10*d13e9b48SJed Brown#
11*d13e9b48SJed Brown# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
12*d13e9b48SJed Brown# a collaborative effort of two U.S. Department of Energy organizations (Office
13*d13e9b48SJed Brown# of Science and the National Nuclear Security Administration) responsible for
14*d13e9b48SJed Brown# the planning and preparation of a capable exascale ecosystem, including
15*d13e9b48SJed Brown# software, applications, hardware, advanced system engineering and early
16*d13e9b48SJed Brown# testbed platforms, in support of the nation's exascale computing imperative.
17*d13e9b48SJed Brown
18*d13e9b48SJed Brown
19*d13e9b48SJed Brown#####   Adjustable plot parameters:
20*d13e9b48SJed Brownlog_y=0               # use log scale on the y-axis?
21*d13e9b48SJed Brownx_range=(1e1,4e6)     # plot range for the x-axis; comment out for auto
22*d13e9b48SJed Browny_range=(0,2e9)       # plot range for the y-axis; comment out for auto
23*d13e9b48SJed Browndraw_iter_lines=0     # draw the "iter/s" lines?
24*d13e9b48SJed Brownymin_iter_lines=3e5   # minimal y value for the "iter/s" lines
25*d13e9b48SJed Brownymax_iter_lines=8e8   # maximal y value for the "iter/s" lines
26*d13e9b48SJed Brownlegend_ncol=(2 if log_y else 1)   # number of columns in the legend
27*d13e9b48SJed Brownwrite_figures=1       # save the figures to files?
28*d13e9b48SJed Brownshow_figures=1        # display the figures on the screen?
29*d13e9b48SJed Brown
30*d13e9b48SJed Brown
31*d13e9b48SJed Brown#####   Load the data
32*d13e9b48SJed Brownimport pandas as pd
33*d13e9b48SJed Brownfrom postprocess_base import read_logs
34*d13e9b48SJed Brown
35*d13e9b48SJed Brownruns = read_logs()
36*d13e9b48SJed Brown
37*d13e9b48SJed Brown#####   Sample plot output
38*d13e9b48SJed Brownfrom matplotlib import use
39*d13e9b48SJed Brownif not show_figures:
40*d13e9b48SJed Brown   use('pdf')
41*d13e9b48SJed Brownfrom pylab import *
42*d13e9b48SJed Brown
43*d13e9b48SJed BrownrcParams['font.sans-serif'].insert(0,'Noto Sans')
44*d13e9b48SJed BrownrcParams['font.sans-serif'].insert(1,'Open Sans')
45*d13e9b48SJed BrownrcParams['figure.figsize']=[10, 8] # default: 8 x 6
46*d13e9b48SJed Brown
47*d13e9b48SJed Browncm_size=16
48*d13e9b48SJed Browncolors=['dimgrey','black','saddlebrown','firebrick','red','orange',
49*d13e9b48SJed Brown        'gold','lightgreen','green','cyan','teal','blue','navy',
50*d13e9b48SJed Brown        'purple','magenta','pink']
51*d13e9b48SJed Brown
52*d13e9b48SJed Brown##### Get test names
53*d13e9b48SJed Brownsel_runs=runs
54*d13e9b48SJed Browntests=list(sel_runs.test.unique())
55*d13e9b48SJed Browntest=tests[0]
56*d13e9b48SJed Brown
57*d13e9b48SJed Brown##### Run information
58*d13e9b48SJed Brownprint('Using test:', test)
59*d13e9b48SJed Brown
60*d13e9b48SJed Brownif 'CEED Benchmark Problem' in test:
61*d13e9b48SJed Brown   test_short = test.strip().split()[0] + ' BP' + test.strip().split()[-1]
62*d13e9b48SJed Brown
63*d13e9b48SJed Brown##### Plot same BP
64*d13e9b48SJed Brownsel_runs=sel_runs.loc[sel_runs['test'] == test]
65*d13e9b48SJed Brown
66*d13e9b48SJed Brown##### Plot same case (scalar vs vector)
67*d13e9b48SJed Browncases=list(sel_runs.case.unique())
68*d13e9b48SJed Browncase=cases[0]
69*d13e9b48SJed Brownvdim=1 if case=='scalar' else 3
70*d13e9b48SJed Brownprint('Using case:', case)
71*d13e9b48SJed Brownsel_runs=sel_runs.loc[sel_runs['case'] == case]
72*d13e9b48SJed Brown
73*d13e9b48SJed Brown##### Plot same 'code'
74*d13e9b48SJed Browncodes = list(sel_runs.code.unique())
75*d13e9b48SJed Browncode  = codes[0]
76*d13e9b48SJed Brownsel_runs=sel_runs.loc[sel_runs['code'] == code]
77*d13e9b48SJed Brown
78*d13e9b48SJed Brown##### Group plots by backend and number of processes
79*d13e9b48SJed Brownpl_set=sel_runs[['backend', 'backend_memtype', 'num_procs', 'num_procs_node']]
80*d13e9b48SJed Brownpl_set=pl_set.drop_duplicates()
81*d13e9b48SJed Brown
82*d13e9b48SJed Brown##### Plotting
83*d13e9b48SJed Brownfor index, row in pl_set.iterrows():
84*d13e9b48SJed Brown   backend=row['backend']
85*d13e9b48SJed Brown   backend_memtype=row['backend_memtype']
86*d13e9b48SJed Brown   num_procs=float(row['num_procs'])
87*d13e9b48SJed Brown   num_procs_node=float(row['num_procs_node'])
88*d13e9b48SJed Brown   num_nodes=num_procs/num_procs_node
89*d13e9b48SJed Brown   pl_runs=sel_runs[(sel_runs.backend==backend) |
90*d13e9b48SJed Brown                    (sel_runs.num_procs==num_procs) |
91*d13e9b48SJed Brown                    (sel_runs.num_procs_node==num_procs_node)]
92*d13e9b48SJed Brown   if len(pl_runs.index)==0:
93*d13e9b48SJed Brown      continue
94*d13e9b48SJed Brown
95*d13e9b48SJed Brown   print('backend: %s, compute nodes: %i, number of MPI tasks = %i'%(
96*d13e9b48SJed Brown      backend,num_nodes,num_procs))
97*d13e9b48SJed Brown
98*d13e9b48SJed Brown   figure()
99*d13e9b48SJed Brown   i=0
100*d13e9b48SJed Brown   sol_p_set=sel_runs['degree'].drop_duplicates()
101*d13e9b48SJed Brown   sol_p_set=sol_p_set.sort_values()
102*d13e9b48SJed Brown   ##### Iterate over P
103*d13e9b48SJed Brown   for sol_p in sol_p_set:
104*d13e9b48SJed Brown      qpts=sel_runs['quadrature_pts'].loc[pl_runs['degree']==sol_p]
105*d13e9b48SJed Brown      qpts=qpts.drop_duplicates().sort_values(ascending=False)
106*d13e9b48SJed Brown      qpts=qpts.reset_index(drop=True)
107*d13e9b48SJed Brown      print('Degree: %i, quadrature points:'%sol_p, qpts[0])
108*d13e9b48SJed Brown      # Generate plot data
109*d13e9b48SJed Brown      d=[[run['degree'],run['num_elem'],1.*run['num_unknowns']/num_nodes/vdim,
110*d13e9b48SJed Brown          run['cg_iteration_dps']/num_nodes]
111*d13e9b48SJed Brown         for index, run in
112*d13e9b48SJed Brown         pl_runs.loc[(pl_runs['degree']==sol_p) |
113*d13e9b48SJed Brown                     (pl_runs['quadrature_pts']==qpts[0])].iterrows()]
114*d13e9b48SJed Brown      d=[[e[2],e[3]] for e in d if e[0]==sol_p]
115*d13e9b48SJed Brown      # (DOFs/[sec/iter]/node)/(DOFs/node) = iter/sec
116*d13e9b48SJed Brown      d=[[nun,
117*d13e9b48SJed Brown          min([e[1] for e in d if e[0]==nun]),
118*d13e9b48SJed Brown          max([e[1] for e in d if e[0]==nun])]
119*d13e9b48SJed Brown         for nun in set([e[0] for e in d])]
120*d13e9b48SJed Brown      d=asarray(sorted(d))
121*d13e9b48SJed Brown      # Plot
122*d13e9b48SJed Brown      plot(d[:,0],d[:,2],'o-',color=colors[i%cm_size],
123*d13e9b48SJed Brown           label='p=%i'%sol_p)
124*d13e9b48SJed Brown      if list(d[:,1]) != list(d[:,2]):
125*d13e9b48SJed Brown         plot(d[:,0],d[:,1],'o-',color=colors[i])
126*d13e9b48SJed Brown         fill_between(d[:,0],d[:,1],d[:,2],facecolor=colors[i],alpha=0.2)
127*d13e9b48SJed Brown      # Continue if only 1 set of qpts
128*d13e9b48SJed Brown      if len(qpts)==1:
129*d13e9b48SJed Brown         i=i+1
130*d13e9b48SJed Brown         continue
131*d13e9b48SJed Brown      # Second set of qpts
132*d13e9b48SJed Brown      d=[[run['degree'],run['num_elem'],1.*run['num_unknowns']/num_nodes/vdim,
133*d13e9b48SJed Brown          run['cg_iteration_dps']/num_nodes]
134*d13e9b48SJed Brown         for index, run in
135*d13e9b48SJed Brown         pl_runs.loc[(pl_runs['degree']==sol_p) |
136*d13e9b48SJed Brown                     (pl_runs['quadrature_pts']==qpts[1])].iterrows()]
137*d13e9b48SJed Brown      d=[[e[2],e[3]] for e in d if e[0]==sol_p]
138*d13e9b48SJed Brown      if len(d)==0:
139*d13e9b48SJed Brown         i=i+1
140*d13e9b48SJed Brown         continue
141*d13e9b48SJed Brown      d=[[nun,
142*d13e9b48SJed Brown          min([e[1] for e in d if e[0]==nun]),
143*d13e9b48SJed Brown          max([e[1] for e in d if e[0]==nun])]
144*d13e9b48SJed Brown         for nun in set([e[0] for e in d])]
145*d13e9b48SJed Brown      d=asarray(sorted(d))
146*d13e9b48SJed Brown      plot(d[:,0],d[:,2],'s--',color=colors[i],
147*d13e9b48SJed Brown           label='p=%i'%sol_p)
148*d13e9b48SJed Brown      if list(d[:,1]) != list(d[:,2]):
149*d13e9b48SJed Brown         plot(d[:,0],d[:,1],'s--',color=colors[i])
150*d13e9b48SJed Brown      ##
151*d13e9b48SJed Brown      i=i+1
152*d13e9b48SJed Brown   ##
153*d13e9b48SJed Brown   if draw_iter_lines:
154*d13e9b48SJed Brown      y0,y1=ymin_iter_lines,ymax_iter_lines
155*d13e9b48SJed Brown      y=asarray([y0,y1]) if log_y else exp(linspace(log(y0), log(y1)))
156*d13e9b48SJed Brown      slope1=600.
157*d13e9b48SJed Brown      slope2=6000.
158*d13e9b48SJed Brown      plot(y/slope1,y,'k--',label='%g iter/s'%(slope1/vdim))
159*d13e9b48SJed Brown      plot(y/slope2,y,'k-',label='%g iter/s'%(slope2/vdim))
160*d13e9b48SJed Brown
161*d13e9b48SJed Brown   # Plot information
162*d13e9b48SJed Brown   title(r'%i node%s $\times$ %i ranks, %s, %s, %s'%(
163*d13e9b48SJed Brown         num_nodes,'' if num_nodes==1 else 's',
164*d13e9b48SJed Brown         num_procs_node,backend,backend_memtype,test_short),fontsize=16)
165*d13e9b48SJed Brown   xscale('log') # subsx=[2,4,6,8]
166*d13e9b48SJed Brown   if log_y:
167*d13e9b48SJed Brown      yscale('log')
168*d13e9b48SJed Brown   if 'x_range' in vars() and len(x_range)==2:
169*d13e9b48SJed Brown      xlim(x_range)
170*d13e9b48SJed Brown   if 'y_range' in vars() and len(y_range)==2:
171*d13e9b48SJed Brown      ylim(y_range)
172*d13e9b48SJed Brown   grid('on', color='gray', ls='dotted')
173*d13e9b48SJed Brown   grid('on', axis='both', which='minor', color='gray', ls='dotted')
174*d13e9b48SJed Brown   plt.tick_params(labelsize=14)
175*d13e9b48SJed Brown   exptext = gca().yaxis.get_offset_text()
176*d13e9b48SJed Brown   exptext.set_size(14)
177*d13e9b48SJed Brown   gca().set_axisbelow(True)
178*d13e9b48SJed Brown   xlabel('Points per compute node',fontsize=14)
179*d13e9b48SJed Brown   ylabel('[DOFs x CG iterations] / [compute nodes x seconds]',fontsize=14)
180*d13e9b48SJed Brown   legend(ncol=legend_ncol, loc='best',fontsize=13)
181*d13e9b48SJed Brown
182*d13e9b48SJed Brown   # Write
183*d13e9b48SJed Brown   if write_figures: # write .pdf file?
184*d13e9b48SJed Brown      short_backend=backend.replace('/','')
185*d13e9b48SJed Brown      test_short_save=test_short.replace(' ','')
186*d13e9b48SJed Brown      pdf_file='plot_%s_%s_%s_%s_N%03i_pn%i.pdf'%(
187*d13e9b48SJed Brown               code,test_short_save,short_backend,backend_memtype,num_nodes,num_procs_node)
188*d13e9b48SJed Brown      print('\nsaving figure --> %s'%pdf_file)
189*d13e9b48SJed Brown      savefig(pdf_file, format='pdf', bbox_inches='tight')
190*d13e9b48SJed Brown
191*d13e9b48SJed Brownif show_figures: # show the figures?
192*d13e9b48SJed Brown   print('\nShowing figures ...')
193*d13e9b48SJed Brown   show()
194