xref: /libCEED/benchmarks/postprocess_base.py (revision 5cd6c1fb67d52eb6a42b887bb79c183682dd86ca)
1d13e9b48SJed Brown#!/usr/bin/env python3
2*5cd6c1fbSSebastian Grimberg
3d13e9b48SJed Brown# Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC.
4d13e9b48SJed Brown# Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707.
5d13e9b48SJed Brown# All Rights reserved. See files LICENSE and NOTICE for details.
6d13e9b48SJed Brown#
7d13e9b48SJed Brown# This file is part of CEED, a collection of benchmarks, miniapps, software
8d13e9b48SJed Brown# libraries and APIs for efficient high-order finite element and spectral
9d13e9b48SJed Brown# element discretizations for exascale applications. For more information and
103d8e8822SJeremy L Thompson# source code availability see http://github.com/ceed
11d13e9b48SJed Brown#
12d13e9b48SJed Brown# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
13d13e9b48SJed Brown# a collaborative effort of two U.S. Department of Energy organizations (Office
14d13e9b48SJed Brown# of Science and the National Nuclear Security Administration) responsible for
15d13e9b48SJed Brown# the planning and preparation of a capable exascale ecosystem, including
16d13e9b48SJed Brown# software, applications, hardware, advanced system engineering and early
17d13e9b48SJed Brown# testbed platforms, in support of the nation's exascale computing imperative.
18d13e9b48SJed Brown
19*5cd6c1fbSSebastian Grimberg# Read all input files specified on the command line, or stdin and parse
20*5cd6c1fbSSebastian Grimberg# the content, storing it as a pandas dataframe
21*5cd6c1fbSSebastian Grimberg
22d13e9b48SJed Brownimport pandas as pd
23d13e9b48SJed Brownimport fileinput
24d13e9b48SJed Brownimport pprint
25d13e9b48SJed Brown
26dec49e00SJed Brown
27d13e9b48SJed Browndef read_logs(files=None):
28aa2aa0aeSJed Brown    """Read all input files and return pandas DataFrame"""
29aa2aa0aeSJed Brown    data_default = dict(
30dd839fb7SJed Brown        file='unknown',
31dd839fb7SJed Brown        backend='unknown',
32aa2aa0aeSJed Brown        backend_memtype='unknown',
33aa2aa0aeSJed Brown        hostname='unknown',
34dd839fb7SJed Brown        test='unknown',
35dd839fb7SJed Brown        num_procs=0,
36dd839fb7SJed Brown        num_procs_node=0,
37dd839fb7SJed Brown        degree=0,
38dd839fb7SJed Brown        quadrature_pts=0,
39dd839fb7SJed Brown        code='libCEED',
40dd839fb7SJed Brown    )
41aa2aa0aeSJed Brown    data = data_default.copy()
42dd839fb7SJed Brown
43d13e9b48SJed Brown    runs = []
44aa2aa0aeSJed Brown    for line in fileinput.input(files):
45dec49e00SJed Brown        # Legacy header contains number of MPI tasks
46dd839fb7SJed Brown        if 'Running the tests using a total of' in line:
47aa2aa0aeSJed Brown            data = data_default.copy()
48dec49e00SJed Brown            data['num_procs'] = int(
49dec49e00SJed Brown                line.split(
50dec49e00SJed Brown                    'a total of ',
51dec49e00SJed Brown                    1)[1].split(
52dec49e00SJed Brown                    None,
53dec49e00SJed Brown                    1)[0])
54dec49e00SJed Brown        # MPI tasks per node
55d13e9b48SJed Brown        elif 'tasks per node' in line:
56dec49e00SJed Brown            data['num_procs_node'] = int(
57dec49e00SJed Brown                line.split(
58dec49e00SJed Brown                    ' tasks per',
59dec49e00SJed Brown                    1)[0].rsplit(
60dec49e00SJed Brown                    None,
61dec49e00SJed Brown                    1)[1])
62dec49e00SJed Brown        # New Benchmark Problem
63d13e9b48SJed Brown        elif "CEED Benchmark Problem" in line:
64dd839fb7SJed Brown            # Starting a new block
65dd839fb7SJed Brown            data = data.copy()
66dd839fb7SJed Brown            runs.append(data)
67dd839fb7SJed Brown            data['file'] = fileinput.filename()
68d13e9b48SJed Brown            data['test'] = line.split()[-2] + " " + line.split('-- ')[1]
69aa2aa0aeSJed Brown            data['bp'] = data['test'].rsplit()[-1]
70d13e9b48SJed Brown            data['case'] = 'scalar' if (('Problem 1' in line) or ('Problem 3' in line)
71d13e9b48SJed Brown                                        or ('Problem 5' in line)) else 'vector'
72dd839fb7SJed Brown        elif "Hostname" in line:
73dd839fb7SJed Brown            data['hostname'] = line.split(':')[1].strip()
74dd839fb7SJed Brown        elif "Total ranks" in line:
75dd839fb7SJed Brown            data['num_procs'] = int(line.split(':')[1].strip())
76aa2aa0aeSJed Brown        elif "Ranks per compute node" in line:
77dd839fb7SJed Brown            data['num_procs_node'] = int(line.split(':')[1].strip())
78dec49e00SJed Brown        # Backend
79d13e9b48SJed Brown        elif 'libCEED Backend MemType' in line:
80d13e9b48SJed Brown            data['backend_memtype'] = line.split(':')[1].strip()
81d13e9b48SJed Brown        elif 'libCEED Backend' in line:
82d13e9b48SJed Brown            data['backend'] = line.split(':')[1].strip()
83dec49e00SJed Brown        # P
84d13e9b48SJed Brown        elif 'Basis Nodes' in line:
85d13e9b48SJed Brown            data['degree'] = int(line.split(':')[1]) - 1
86dec49e00SJed Brown        # Q
87d13e9b48SJed Brown        elif 'Quadrature Points' in line:
88aa2aa0aeSJed Brown            data['quadrature_pts'] = int(line.split(':')[1])
89dec49e00SJed Brown        # Total DOFs
90d13e9b48SJed Brown        elif 'Global nodes' in line:
91d13e9b48SJed Brown            data['num_unknowns'] = int(line.split(':')[1])
92d13e9b48SJed Brown            if data['case'] == 'vector':
93d13e9b48SJed Brown                data['num_unknowns'] *= 3
94aa2aa0aeSJed Brown        elif 'Global DOFs' in line:  # Legacy
95aa2aa0aeSJed Brown            data['num_unknowns'] = int(line.split(':')[1])
96dec49e00SJed Brown        # Number of elements
97d13e9b48SJed Brown        elif 'Local Elements' in line:
98dec49e00SJed Brown            data['num_elem'] = int(
99dec49e00SJed Brown                line.split(':')[1].split()[0]) * data['num_procs']
100aa2aa0aeSJed Brown        elif 'DoF per node' in line:
101aa2aa0aeSJed Brown            data['dof_per_node'] = int(line.split(':')[1])
102dec49e00SJed Brown        # CG Solve Time
103d13e9b48SJed Brown        elif 'Total KSP Iterations' in line:
104d13e9b48SJed Brown            data['ksp_its'] = int(line.split(':')[1].split()[0])
105d13e9b48SJed Brown        elif 'CG Solve Time' in line:
106dec49e00SJed Brown            data['time_per_it'] = float(
107dec49e00SJed Brown                line.split(':')[1].split()[0]) / data['ksp_its']
108dec49e00SJed Brown        # CG DOFs/Sec
109aa2aa0aeSJed Brown        elif 'DoFs/Sec in CG' in line or 'DOFs/Sec in CG' in line:
110dec49e00SJed Brown            data['cg_iteration_dps'] = 1e6 * \
111dec49e00SJed Brown                float(line.split(':')[1].split()[0])
112dec49e00SJed Brown        # End of output
113d13e9b48SJed Brown
114d13e9b48SJed Brown    return pd.DataFrame(runs)
115d13e9b48SJed Brown
116dec49e00SJed Brown
117d13e9b48SJed Brownif __name__ == "__main__":
118d13e9b48SJed Brown    runs = read_logs()
119aa2aa0aeSJed Brown    print(runs)         # Print summary (about 10 lines)
120aa2aa0aeSJed Brown    print('First entry:\n', runs.iloc[0])
121aa2aa0aeSJed Brown    print('Last entry:\n', runs.iloc[-1])
122