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