xref: /libCEED/benchmarks/postprocess_base.py (revision 9ba83ac0e4b1fca39d6fa6737a318a9f0cbc172d)
1d13e9b48SJed Brown#!/usr/bin/env python3
25cd6c1fbSSebastian Grimberg
3*9ba83ac0SJeremy L Thompson# Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC and other CEED contributors.
45aed82e4SJeremy L Thompson# All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
5d13e9b48SJed Brown#
65aed82e4SJeremy L Thompson# SPDX-License-Identifier: BSD-2-Clause
7d13e9b48SJed Brown#
85aed82e4SJeremy L Thompson# This file is part of CEED:  http://github.com/ceed
9d13e9b48SJed Brown
105cd6c1fbSSebastian Grimberg# Read all input files specified on the command line, or stdin and parse
115cd6c1fbSSebastian Grimberg# the content, storing it as a pandas dataframe
125cd6c1fbSSebastian Grimberg
13d13e9b48SJed Brownimport pandas as pd
14d13e9b48SJed Brownimport fileinput
15d13e9b48SJed Brownimport pprint
16d13e9b48SJed Brown
17dec49e00SJed Brown
18d13e9b48SJed Browndef read_logs(files=None):
19aa2aa0aeSJed Brown    """Read all input files and return pandas DataFrame"""
20aa2aa0aeSJed Brown    data_default = dict(
21dd839fb7SJed Brown        file='unknown',
22dd839fb7SJed Brown        backend='unknown',
23aa2aa0aeSJed Brown        backend_memtype='unknown',
24aa2aa0aeSJed Brown        hostname='unknown',
25dd839fb7SJed Brown        test='unknown',
26dd839fb7SJed Brown        num_procs=0,
27dd839fb7SJed Brown        num_procs_node=0,
28dd839fb7SJed Brown        degree=0,
29dd839fb7SJed Brown        quadrature_pts=0,
30dd839fb7SJed Brown        code='libCEED',
31dd839fb7SJed Brown    )
32aa2aa0aeSJed Brown    data = data_default.copy()
33dd839fb7SJed Brown
34d13e9b48SJed Brown    runs = []
35aa2aa0aeSJed Brown    for line in fileinput.input(files):
36dec49e00SJed Brown        # Legacy header contains number of MPI tasks
37dd839fb7SJed Brown        if 'Running the tests using a total of' in line:
38aa2aa0aeSJed Brown            data = data_default.copy()
39dec49e00SJed Brown            data['num_procs'] = int(
40dec49e00SJed Brown                line.split(
41dec49e00SJed Brown                    'a total of ',
42dec49e00SJed Brown                    1)[1].split(
43dec49e00SJed Brown                    None,
44dec49e00SJed Brown                    1)[0])
45dec49e00SJed Brown        # MPI tasks per node
46d13e9b48SJed Brown        elif 'tasks per node' in line:
47dec49e00SJed Brown            data['num_procs_node'] = int(
48dec49e00SJed Brown                line.split(
49dec49e00SJed Brown                    ' tasks per',
50dec49e00SJed Brown                    1)[0].rsplit(
51dec49e00SJed Brown                    None,
52dec49e00SJed Brown                    1)[1])
53dec49e00SJed Brown        # New Benchmark Problem
54d13e9b48SJed Brown        elif "CEED Benchmark Problem" in line:
55dd839fb7SJed Brown            # Starting a new block
56dd839fb7SJed Brown            data = data.copy()
57dd839fb7SJed Brown            runs.append(data)
58dd839fb7SJed Brown            data['file'] = fileinput.filename()
59d13e9b48SJed Brown            data['test'] = line.split()[-2] + " " + line.split('-- ')[1]
60aa2aa0aeSJed Brown            data['bp'] = data['test'].rsplit()[-1]
61d13e9b48SJed Brown            data['case'] = 'scalar' if (('Problem 1' in line) or ('Problem 3' in line)
62d13e9b48SJed Brown                                        or ('Problem 5' in line)) else 'vector'
63dd839fb7SJed Brown        elif "Hostname" in line:
64dd839fb7SJed Brown            data['hostname'] = line.split(':')[1].strip()
65dd839fb7SJed Brown        elif "Total ranks" in line:
66dd839fb7SJed Brown            data['num_procs'] = int(line.split(':')[1].strip())
67aa2aa0aeSJed Brown        elif "Ranks per compute node" in line:
68dd839fb7SJed Brown            data['num_procs_node'] = int(line.split(':')[1].strip())
69dec49e00SJed Brown        # Backend
70d13e9b48SJed Brown        elif 'libCEED Backend MemType' in line:
71d13e9b48SJed Brown            data['backend_memtype'] = line.split(':')[1].strip()
72d13e9b48SJed Brown        elif 'libCEED Backend' in line:
73d13e9b48SJed Brown            data['backend'] = line.split(':')[1].strip()
74dec49e00SJed Brown        # P
75d13e9b48SJed Brown        elif 'Basis Nodes' in line:
76d13e9b48SJed Brown            data['degree'] = int(line.split(':')[1]) - 1
77dec49e00SJed Brown        # Q
78d13e9b48SJed Brown        elif 'Quadrature Points' in line:
79aa2aa0aeSJed Brown            data['quadrature_pts'] = int(line.split(':')[1])
80dec49e00SJed Brown        # Total DOFs
81d13e9b48SJed Brown        elif 'Global nodes' in line:
82d13e9b48SJed Brown            data['num_unknowns'] = int(line.split(':')[1])
83d13e9b48SJed Brown            if data['case'] == 'vector':
84d13e9b48SJed Brown                data['num_unknowns'] *= 3
85aa2aa0aeSJed Brown        elif 'Global DOFs' in line:  # Legacy
86aa2aa0aeSJed Brown            data['num_unknowns'] = int(line.split(':')[1])
87dec49e00SJed Brown        # Number of elements
88d13e9b48SJed Brown        elif 'Local Elements' in line:
89dec49e00SJed Brown            data['num_elem'] = int(
90dec49e00SJed Brown                line.split(':')[1].split()[0]) * data['num_procs']
91aa2aa0aeSJed Brown        elif 'DoF per node' in line:
92aa2aa0aeSJed Brown            data['dof_per_node'] = int(line.split(':')[1])
93dec49e00SJed Brown        # CG Solve Time
94d13e9b48SJed Brown        elif 'Total KSP Iterations' in line:
95d13e9b48SJed Brown            data['ksp_its'] = int(line.split(':')[1].split()[0])
96d13e9b48SJed Brown        elif 'CG Solve Time' in line:
97dec49e00SJed Brown            data['time_per_it'] = float(
98dec49e00SJed Brown                line.split(':')[1].split()[0]) / data['ksp_its']
99dec49e00SJed Brown        # CG DOFs/Sec
100aa2aa0aeSJed Brown        elif 'DoFs/Sec in CG' in line or 'DOFs/Sec in CG' in line:
101dec49e00SJed Brown            data['cg_iteration_dps'] = 1e6 * \
102dec49e00SJed Brown                float(line.split(':')[1].split()[0])
103dec49e00SJed Brown        # End of output
104d13e9b48SJed Brown
105d13e9b48SJed Brown    return pd.DataFrame(runs)
106d13e9b48SJed Brown
107dec49e00SJed Brown
108d13e9b48SJed Brownif __name__ == "__main__":
109d13e9b48SJed Brown    runs = read_logs()
110aa2aa0aeSJed Brown    print(runs)         # Print summary (about 10 lines)
111aa2aa0aeSJed Brown    print('First entry:\n', runs.iloc[0])
112aa2aa0aeSJed Brown    print('Last entry:\n', runs.iloc[-1])
113