From 64865cff1d57f09ad2a92d8229b1131981b8a7ae Mon Sep 17 00:00:00 2001 From: Vanessasaurus <814322+vsoch@users.noreply.github.com> Date: Fri, 24 Nov 2023 22:26:47 -0700 Subject: [PATCH] add mpitrace output python parser (#81) * add mpitrace python parser Signed-off-by: vsoch --- examples/addons/mpitrace-lammps/README.md | 3 +- examples/python/addon-mpitrace/README.md | 20 + examples/python/addon-mpitrace/metrics.json | 1111 +++++++++++++++++ .../python/addon-mpitrace/parse-metric.py | 59 + .../python/addon-mpitrace/requirements.txt | 1 + sdk/python/v1alpha2/CHANGELOG.md | 1 + .../metricsoperator/metrics/__init__.py | 3 + .../metricsoperator/metrics/addon/__init__.py | 1 + .../metricsoperator/metrics/addon/mpitrace.py | 163 +++ sdk/python/v1alpha2/setup.py | 2 +- setup.cfg | 1 + 11 files changed, 1363 insertions(+), 2 deletions(-) create mode 100644 examples/python/addon-mpitrace/README.md create mode 100644 examples/python/addon-mpitrace/metrics.json create mode 100644 examples/python/addon-mpitrace/parse-metric.py create mode 100644 examples/python/addon-mpitrace/requirements.txt create mode 100644 sdk/python/v1alpha2/metricsoperator/metrics/addon/__init__.py create mode 100644 sdk/python/v1alpha2/metricsoperator/metrics/addon/mpitrace.py diff --git a/examples/addons/mpitrace-lammps/README.md b/examples/addons/mpitrace-lammps/README.md index 07e557c..88a7b40 100644 --- a/examples/addons/mpitrace-lammps/README.md +++ b/examples/addons/mpitrace-lammps/README.md @@ -14,10 +14,11 @@ VERSION=v0.2.0 kubectl apply --server-side -f https://github.com/kubernetes-sigs/jobset/releases/download/$VERSION/manifests.yaml ``` -Install the operator (from the development manifest here): +Install the operator (from the development manifest here) or the production release: ```bash kubectl apply -f ../../dist/metrics-operator-dev.yaml +kubectl apply -f https://raw.githubusercontent.com/converged-computing/metrics-operator/main/examples/dist/metrics-operator.yaml ``` How to see metrics operator logs: diff --git a/examples/python/addon-mpitrace/README.md b/examples/python/addon-mpitrace/README.md new file mode 100644 index 0000000..0ba0c27 --- /dev/null +++ b/examples/python/addon-mpitrace/README.md @@ -0,0 +1,20 @@ +# Addon MPITrace + +MPI Trace can be added to an app and then used to generate files to parse with the library here. +This addon is a bit different in that it doesn't expect output in logs, but rather provided on the local +system (saved via kubectl or via the [ORAS Operator](https://github.com/converged-computing/oras-operator)). +For this example, you should first run the example in the [addon-mpitrace](../../addons/mpitrace-lammps) directory +and generate the output files: + +```bash + ls ../../addons/mpitrace-lammps/mpi_profile.114.* -l +-rw-rw-r-- 1 vanessa vanessa 5636 Oct 22 18:52 ../../addons/mpitrace-lammps/mpi_profile.114.0 +-rw-rw-r-- 1 vanessa vanessa 4684 Oct 22 18:52 ../../addons/mpitrace-lammps/mpi_profile.114.1 +-rw-rw-r-- 1 vanessa vanessa 4623 Oct 22 18:52 ../../addons/mpitrace-lammps/mpi_profile.114.2 +``` + +Then run the script, and target the files: + +```bash +$ python parse-metric.py ../../addons/mpitrace-lammps/ --prefix mpi_profile +``` \ No newline at end of file diff --git a/examples/python/addon-mpitrace/metrics.json b/examples/python/addon-mpitrace/metrics.json new file mode 100644 index 0000000..169150b --- /dev/null +++ b/examples/python/addon-mpitrace/metrics.json @@ -0,0 +1,1111 @@ +[ + { + "rank": 2, + "total_ranks": 4, + "times_mpi_init_to_mpi_finalize": [ + [ + "mpi_routine", + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + "MPI_Comm_rank", + 10, + 0.0, + 0.0 + ], + [ + "MPI_Comm_size", + 4, + 0.0, + 0.0 + ], + [ + "MPI_Send", + 20560, + 9785.9, + 0.017 + ], + [ + "MPI_Irecv", + 20560, + 9786.9, + 0.004 + ], + [ + "MPI_Sendrecv", + 36, + 8.0, + 0.0 + ], + [ + "MPI_Wait", + 20560, + 0.0, + 0.056 + ], + [ + "MPI_Bcast", + 129, + 1044.8, + 0.001 + ], + [ + "MPI_Barrier", + 7, + 0.0, + 0.0 + ], + [ + "MPI_Reduce", + 4, + 7.0, + 0.0 + ], + [ + "MPI_Allreduce", + 5167, + 8.1, + 0.006 + ], + [ + "MPI_Allgather", + 1, + 4.0, + 0.0 + ], + [ + "MPI_Allgatherv", + 1, + 7488.0, + 0.0 + ] + ], + "communication_time_description": "MPI task 2 of 4 had the minimum communication time.", + "total communication time": "0.085 seconds.", + "total elapsed time": "14.510 seconds.", + "user cpu time": "14.454 seconds.", + "system time": "0.055 seconds.", + "max resident set size": "129.863 MiB.", + "message_size_distributions": { + "MPI_Send": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 9, + 0.0, + 0.0 + ], + [ + 1, + 176.0, + 0.0 + ], + [ + 1, + 352.0, + 0.0 + ], + [ + 1, + 704.0, + 0.0 + ], + [ + 9870, + 2529.1, + 0.003 + ], + [ + 392, + 7585.4, + 0.0 + ], + [ + 9870, + 15547.8, + 0.012 + ], + [ + 12, + 17668.0, + 0.0 + ], + [ + 392, + 46656.8, + 0.002 + ], + [ + 12, + 108593.3, + 0.0 + ] + ], + "MPI_Irecv": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 10, + 0.0, + 0.0 + ], + [ + 1, + 176.0, + 0.0 + ], + [ + 1, + 352.0, + 0.0 + ], + [ + 9870, + 2529.2, + 0.002 + ], + [ + 392, + 7584.8, + 0.0 + ], + [ + 9870, + 15549.4, + 0.002 + ], + [ + 12, + 17714.7, + 0.0 + ], + [ + 392, + 46650.1, + 0.0 + ], + [ + 12, + 109102.0, + 0.0 + ] + ], + "MPI_Sendrecv": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 36, + 8.0, + 0.0 + ] + ], + "MPI_Bcast": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 80, + 3.4, + 0.0 + ], + [ + 3, + 7.7, + 0.0 + ], + [ + 4, + 13.2, + 0.0 + ], + [ + 20, + 24.5, + 0.0 + ], + [ + 12, + 49.0, + 0.0 + ], + [ + 2, + 96.0, + 0.0 + ], + [ + 1, + 312.0, + 0.0 + ], + [ + 1, + 992.0, + 0.0 + ], + [ + 1, + 2048.0, + 0.0 + ], + [ + 1, + 3840.0, + 0.0 + ], + [ + 3, + 24239.7, + 0.0 + ], + [ + 1, + 53248.0, + 0.0 + ] + ], + "MPI_Reduce": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 1, + 4.0, + 0.0 + ], + [ + 3, + 8.0, + 0.0 + ] + ], + "MPI_Allreduce": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 14, + 4.0, + 0.0 + ], + [ + 5125, + 8.0, + 0.006 + ], + [ + 13, + 15.4, + 0.0 + ], + [ + 12, + 24.0, + 0.0 + ], + [ + 3, + 40.0, + 0.0 + ] + ], + "MPI_Allgather": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 1, + 4.0, + 0.0 + ] + ] + } + }, + { + "rank": 1, + "total_ranks": 4, + "times_mpi_init_to_mpi_finalize": [ + [ + "mpi_routine", + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + "MPI_Comm_rank", + 10, + 0.0, + 0.0 + ], + [ + "MPI_Comm_size", + 4, + 0.0, + 0.0 + ], + [ + "MPI_Send", + 20560, + 9788.2, + 0.017 + ], + [ + "MPI_Irecv", + 20560, + 9787.4, + 0.004 + ], + [ + "MPI_Sendrecv", + 36, + 8.0, + 0.0 + ], + [ + "MPI_Wait", + 20560, + 0.0, + 1.601 + ], + [ + "MPI_Bcast", + 129, + 1044.8, + 0.001 + ], + [ + "MPI_Barrier", + 7, + 0.0, + 0.0 + ], + [ + "MPI_Reduce", + 4, + 7.0, + 0.0 + ], + [ + "MPI_Allreduce", + 5167, + 8.1, + 0.009 + ], + [ + "MPI_Allgather", + 1, + 4.0, + 0.0 + ], + [ + "MPI_Allgatherv", + 1, + 7296.0, + 0.0 + ] + ], + "communication_time_description": "MPI task 1 of 4 had the median communication time.", + "total communication time": "1.633 seconds.", + "total elapsed time": "14.510 seconds.", + "user cpu time": "13.993 seconds.", + "system time": "0.508 seconds.", + "max resident set size": "129.074 MiB.", + "message_size_distributions": { + "MPI_Send": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 8, + 0.0, + 0.0 + ], + [ + 1, + 176.0, + 0.0 + ], + [ + 2, + 352.0, + 0.0 + ], + [ + 1, + 528.0, + 0.0 + ], + [ + 9870, + 2541.4, + 0.003 + ], + [ + 392, + 7626.1, + 0.0 + ], + [ + 9870, + 15539.6, + 0.011 + ], + [ + 12, + 17794.0, + 0.0 + ], + [ + 392, + 46617.9, + 0.002 + ], + [ + 12, + 108990.0, + 0.0 + ] + ], + "MPI_Irecv": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 7, + 0.0, + 0.0 + ], + [ + 3, + 176.0, + 0.0 + ], + [ + 1, + 352.0, + 0.0 + ], + [ + 1, + 528.0, + 0.0 + ], + [ + 9870, + 2541.4, + 0.002 + ], + [ + 392, + 7626.0, + 0.0 + ], + [ + 9870, + 15538.2, + 0.002 + ], + [ + 12, + 17803.3, + 0.0 + ], + [ + 392, + 46623.9, + 0.0 + ], + [ + 12, + 108532.7, + 0.0 + ] + ], + "MPI_Sendrecv": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 36, + 8.0, + 0.0 + ] + ], + "MPI_Bcast": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 80, + 3.4, + 0.0 + ], + [ + 3, + 7.7, + 0.0 + ], + [ + 4, + 13.2, + 0.0 + ], + [ + 20, + 24.5, + 0.0 + ], + [ + 12, + 49.0, + 0.0 + ], + [ + 2, + 96.0, + 0.0 + ], + [ + 1, + 312.0, + 0.0 + ], + [ + 1, + 992.0, + 0.0 + ], + [ + 1, + 2048.0, + 0.0 + ], + [ + 1, + 3840.0, + 0.0 + ], + [ + 3, + 24239.7, + 0.0 + ], + [ + 1, + 53248.0, + 0.0 + ] + ], + "MPI_Reduce": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 1, + 4.0, + 0.0 + ], + [ + 3, + 8.0, + 0.0 + ] + ], + "MPI_Allreduce": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 14, + 4.0, + 0.0 + ], + [ + 5125, + 8.0, + 0.009 + ], + [ + 13, + 15.4, + 0.0 + ], + [ + 12, + 24.0, + 0.0 + ], + [ + 3, + 40.0, + 0.0 + ] + ], + "MPI_Allgather": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 1, + 4.0, + 0.0 + ] + ] + } + }, + { + "rank": 0, + "total_ranks": 4, + "times_mpi_init_to_mpi_finalize": [ + [ + "mpi_routine", + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + "MPI_Comm_rank", + 10, + 0.0, + 0.0 + ], + [ + "MPI_Comm_size", + 4, + 0.0, + 0.0 + ], + [ + "MPI_Send", + 20560, + 9780.7, + 0.008 + ], + [ + "MPI_Irecv", + 20560, + 9781.5, + 0.003 + ], + [ + "MPI_Sendrecv", + 36, + 8.0, + 0.001 + ], + [ + "MPI_Wait", + 20560, + 0.0, + 7.251 + ], + [ + "MPI_Bcast", + 129, + 1044.8, + 0.001 + ], + [ + "MPI_Barrier", + 7, + 0.0, + 0.003 + ], + [ + "MPI_Reduce", + 4, + 7.0, + 0.0 + ], + [ + "MPI_Allreduce", + 5167, + 8.1, + 0.012 + ], + [ + "MPI_Allgather", + 1, + 4.0, + 0.0 + ], + [ + "MPI_Allgatherv", + 1, + 7392.0, + 0.0 + ] + ], + "communication_time_description": "MPI task 0 of 4 had the maximum communication time.", + "total communication time": "7.279 seconds.", + "total elapsed time": "14.510 seconds.", + "user cpu time": "12.155 seconds.", + "system time": "2.337 seconds.", + "max resident set size": "137.273 MiB.", + "message_size_distributions": { + "MPI_Send": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 7, + 0.0, + 0.0 + ], + [ + 3, + 176.0, + 0.0 + ], + [ + 1, + 352.0, + 0.0 + ], + [ + 1, + 528.0, + 0.0 + ], + [ + 9870, + 2529.2, + 0.002 + ], + [ + 392, + 7584.8, + 0.0 + ], + [ + 9870, + 15538.2, + 0.004 + ], + [ + 12, + 17714.7, + 0.0 + ], + [ + 392, + 46623.9, + 0.001 + ], + [ + 12, + 108532.7, + 0.0 + ] + ], + "MPI_Irecv": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 8, + 0.0, + 0.0 + ], + [ + 1, + 176.0, + 0.0 + ], + [ + 2, + 352.0, + 0.0 + ], + [ + 1, + 528.0, + 0.0 + ], + [ + 9870, + 2529.1, + 0.001 + ], + [ + 392, + 7585.4, + 0.0 + ], + [ + 9870, + 15539.6, + 0.001 + ], + [ + 12, + 17668.0, + 0.0 + ], + [ + 392, + 46617.9, + 0.0 + ], + [ + 12, + 108990.0, + 0.0 + ] + ], + "MPI_Sendrecv": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 36, + 8.0, + 0.001 + ] + ], + "MPI_Bcast": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 80, + 3.4, + 0.0 + ], + [ + 3, + 7.7, + 0.0 + ], + [ + 4, + 13.2, + 0.0 + ], + [ + 20, + 24.5, + 0.001 + ], + [ + 12, + 49.0, + 0.0 + ], + [ + 2, + 96.0, + 0.0 + ], + [ + 1, + 312.0, + 0.0 + ], + [ + 1, + 992.0, + 0.0 + ], + [ + 1, + 2048.0, + 0.0 + ], + [ + 1, + 3840.0, + 0.0 + ], + [ + 3, + 24239.7, + 0.0 + ], + [ + 1, + 53248.0, + 0.0 + ] + ], + "MPI_Reduce": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 1, + 4.0, + 0.0 + ], + [ + 3, + 8.0, + 0.0 + ] + ], + "MPI_Allreduce": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 14, + 4.0, + 0.0 + ], + [ + 5125, + 8.0, + 0.012 + ], + [ + 13, + 15.4, + 0.0 + ], + [ + 12, + 24.0, + 0.0 + ], + [ + 3, + 40.0, + 0.0 + ] + ], + "MPI_Allgather": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 1, + 4.0, + 0.0 + ] + ], + "MPI_Allgatherv": [ + [ + "number_calls", + "average_bytes", + "time_seconds" + ], + [ + 1, + 7392.0, + 0.0 + ] + ] + }, + "summary_tasks": { + "Rank 0 reported the largest memory utilization": "137.27 MiB", + "Rank 2 reported the largest elapsed time": "14.51 sec", + "minimum communication time": "0.085 sec for task 2", + "median communication time": "1.633 sec for task 1", + "maximum communication time": "7.279 sec for task 0" + }, + "mpi_timing_summary": [ + [ + "taskid", + "host", + "cpu", + "comm(s)", + "elapsed(s)", + "user(s)", + "system(s)", + "size(MiB)", + "switches" + ], + [ + 0, + "metricset-sample-l-0-0", + 1, + 7.28, + 14.51, + 12.16, + 2.34, + 137.27, + 842 + ], + [ + 1, + "metricset-sample-l-0-0", + 5, + 1.63, + 14.51, + 13.99, + 0.51, + 129.07, + 63 + ], + [ + 2, + "metricset-sample-l-0-0", + 7, + 0.08, + 14.51, + 14.45, + 0.05, + 129.86, + 43 + ], + [ + 3, + "metricset-sample-l-0-0", + 10, + 2.7, + 14.51, + 13.73, + 0.78, + 131.18, + 39 + ] + ] + } +] \ No newline at end of file diff --git a/examples/python/addon-mpitrace/parse-metric.py b/examples/python/addon-mpitrace/parse-metric.py new file mode 100644 index 0000000..de67ee0 --- /dev/null +++ b/examples/python/addon-mpitrace/parse-metric.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 + +import argparse +import os +import sys +import metricsoperator.utils as utils +import metricsoperator.metrics as mutils + +here = os.path.abspath(os.path.dirname(__file__)) + + +def get_parser(): + parser = argparse.ArgumentParser( + description="Parse MPI Trace Output", + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument( + "indir", + help="input directory with files", + ) + parser.add_argument( + "--out", + help="json file to save results", + default=os.path.join(here, "metrics.json"), + ) + parser.add_argument( + "--prefix", + help="prefix for mpi trace process files (defaults to mpi_profile)", + default="mpi_profile", + ) + return parser + + +def main(): + """ + Run a job. + """ + parser = get_parser() + args, _ = parser.parse_known_args() + + # Save listing of results + results = [] + + if not args.indir or not os.path.exists(args.indir): + sys.exit("Input directory {args.indir} does not exist") + + # Create an instance of the metrics parser + metric = mutils.get_metric("addon-mpitrace")() + indir = os.path.abspath(args.indir) + + for filename in utils.recursive_find(indir, pattern=args.prefix): + print(f"Parsing filename {filename}") + log = utils.read_file(filename) + results.append(metric.parse_log(log)) + utils.write_json(results, args.out) + + +if __name__ == "__main__": + main() diff --git a/examples/python/addon-mpitrace/requirements.txt b/examples/python/addon-mpitrace/requirements.txt new file mode 100644 index 0000000..faae0ca --- /dev/null +++ b/examples/python/addon-mpitrace/requirements.txt @@ -0,0 +1 @@ +metricsoperator \ No newline at end of file diff --git a/sdk/python/v1alpha2/CHANGELOG.md b/sdk/python/v1alpha2/CHANGELOG.md index 8359696..88f2a1a 100644 --- a/sdk/python/v1alpha2/CHANGELOG.md +++ b/sdk/python/v1alpha2/CHANGELOG.md @@ -14,6 +14,7 @@ and **Merged pull requests**. Critical items to know are: The versions coincide with releases on pip. Only major versions will be released as tags on Github. ## [0.0.x](https://github.com/converged-computing/metrics-operator/tree/main) (0.0.x) + - parsing for MPItrace output (0.1.13) - initContainer support for mpitrace and function to get parser (0.1.12) - Support to provide custom kubeconfig (0.1.11) - LAMMPS parsing should include row names for component names (0.1.1) diff --git a/sdk/python/v1alpha2/metricsoperator/metrics/__init__.py b/sdk/python/v1alpha2/metricsoperator/metrics/__init__.py index aa1d63f..889edf9 100644 --- a/sdk/python/v1alpha2/metricsoperator/metrics/__init__.py +++ b/sdk/python/v1alpha2/metricsoperator/metrics/__init__.py @@ -1,6 +1,7 @@ # Copyright 2023 Lawrence Livermore National Security, LLC # (c.f. AUTHORS, NOTICE.LLNS, COPYING) +import metricsoperator.metrics.addon as addons import metricsoperator.metrics.app as apps import metricsoperator.metrics.base as base import metricsoperator.metrics.network as network @@ -15,6 +16,7 @@ "io-fio": storage.io_fio, "app-lammps": apps.app_lammps, "app-amg": apps.app_amg, + "addon-mpitrace": addons.mpitrace, } @@ -25,5 +27,6 @@ def get_metric(name=None): metric = metrics.get(name) # If we don't have a matching metric, return base (for raw logs) if not metric: + print(f"Warning: {name} is not a known metric, returning raw parser") return base.MetricBase return metric diff --git a/sdk/python/v1alpha2/metricsoperator/metrics/addon/__init__.py b/sdk/python/v1alpha2/metricsoperator/metrics/addon/__init__.py new file mode 100644 index 0000000..daf177a --- /dev/null +++ b/sdk/python/v1alpha2/metricsoperator/metrics/addon/__init__.py @@ -0,0 +1 @@ +from .mpitrace import mpitrace diff --git a/sdk/python/v1alpha2/metricsoperator/metrics/addon/mpitrace.py b/sdk/python/v1alpha2/metricsoperator/metrics/addon/mpitrace.py new file mode 100644 index 0000000..3ba1cb7 --- /dev/null +++ b/sdk/python/v1alpha2/metricsoperator/metrics/addon/mpitrace.py @@ -0,0 +1,163 @@ +# Copyright 2023 Lawrence Livermore National Security, LLC +# (c.f. AUTHORS, NOTICE.LLNS, COPYING) + +import re + +from metricsoperator.metrics.base import MetricBase + + +class mpitrace(MetricBase): + """ + Parse mpitrace (raw text) logs + + MPI trace doesn't stream to a log, so instead we take the raw lines + for a single log. Each log should be one process. + """ + + def parse_log(self, lines): + """ + Given lines of output, parse and return json + """ + result = {} + + # change avg. bytes average_bytes, and others more readable + lines = lines.replace("avg. bytes", "average_bytes") + lines = lines.replace("#calls", "number_calls") + lines = lines.replace("time(sec)", "time_seconds") + lines = lines.strip().split("\n") + while lines: + line = lines.pop(0) + + # The MPI rank we are parsing + if line.startswith("Data for MPI rank"): + _, rank, _, total_ranks = line.strip(":").rsplit(" ", 3) + result["rank"] = int(rank) + result["total_ranks"] = int(total_ranks) + continue + + if line.startswith("MPI Routine"): + result["times_mpi_init_to_mpi_finalize"] = parse_init_finalize_table( + lines + ) + # The next line is a description about communication time + result["communication_time_description"] = lines.pop(0) + + # Next lines are key value pairs + line = lines.pop(0) + while "=" in line: + key, value = line.split("=", 1) + result[key.strip()] = value.strip() + line = lines.pop(0) + continue + + # Message size distribution table + if line.startswith("Message size distributions:"): + result["message_size_distributions"] = parse_message_sizes(lines) + continue + + if line.startswith("Summary for all tasks"): + result["summary_tasks"] = parse_summary(lines) + continue + + if line.startswith("MPI timing summary"): + result["mpi_timing_summary"] = parse_mpi_timing_summary(lines) + + return result + + +def parse_mpi_timing_summary(lines): + line = lines.pop(0) + columns = re.split("\\s+", line.strip()) + rows = [columns] + while lines: + line = lines.pop(0) + if not line: + continue + row = re.split("\\s+", line.strip()) + row = [ + int(row[0]), + row[1], + int(row[2]), + float(row[3]), + float(row[4]), + float(row[5]), + float(row[6]), + float(row[7]), + int(row[8]), + ] + rows.append(row) + return rows + + +def parse_summary(lines): + summary = {} + count = 0 + while True and count < 3: + line = lines.pop(0) + if not line: + count += 1 + continue + sep = ":" if ":" in line else "=" + key, value = line.split(sep) + summary[key.strip()] = value.strip() + + return summary + + +def parse_message_sizes(lines): + """ + Parse the times from the Message size Distributions tables + """ + # pop top line that is empty + lines.pop(0) + + tables = {} + + # columns should not change + rows = [] + routine = None + while True and lines: + line = lines.pop(0) + + # Last line of multiple sections + if "----" in line: + break + + # this is a row of the same table + if line.startswith(" "): + row = re.split("\\s+", line.strip()) + rows.append([int(row[0]), float(row[1]), float(row[2])]) + + # This is the row of a new table + else: + if routine: + tables[routine] = rows + rows = [] + # This is the header + row = re.split("\\s+", line.strip()) + routine, row = row[0], row[1:] + rows.append(row) + + return tables + + +def parse_init_finalize_table(lines): + """ + Parse the Times from MPI_Init() to MPI_Finalize() table + """ + # pop top line that is a divider + lines.pop(0) + + # columns should not change + columns = ["mpi_routine", "number_calls", "average_bytes", "time_seconds"] + rows = [columns] + + while True: + line = lines.pop(0) + # Last line + if "----" in line: + break + row = re.split("\\s+", line) + row = [row[0], int(row[1]), float(row[2]), float(row[3])] + rows.append(row) + return rows diff --git a/sdk/python/v1alpha2/setup.py b/sdk/python/v1alpha2/setup.py index ee90790..9cde96c 100644 --- a/sdk/python/v1alpha2/setup.py +++ b/sdk/python/v1alpha2/setup.py @@ -30,7 +30,7 @@ if __name__ == "__main__": setup( name="metricsoperator", - version="0.1.12", + version="0.1.13", author="Vanessasaurus", author_email="vsoch@users.noreply.github.com", maintainer="Vanessasaurus", diff --git a/setup.cfg b/setup.cfg index a105d5a..b6a6c4d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,3 +6,4 @@ per-file-ignores = docs/conf.py:E501 sdk/python/v1alpha2/metricsoperator/metrics/network/__init__.py:F401 sdk/python/v1alpha2/metricsoperator/metrics/app/__init__.py:F401 + sdk/python/v1alpha2/metricsoperator/metrics/addon/__init__.py:F401