tplot_profiling.py - pism - [fork] customized build of PISM, the parallel ice sheet model (tillflux branch)
 (HTM) git clone git://src.adamsgaard.dk/pism
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
       tplot_profiling.py (4816B)
       ---
            1 #!/usr/bin/env python3
            2 import pylab as plt
            3 import numpy as np
            4 from argparse import ArgumentParser
            5 import importlib
            6 import sys
            7 import os.path
            8 
            9 """ Produce pie charts using PISM's profiling output produced using
           10 the -profile option. """
           11 
           12 parser = ArgumentParser()
           13 parser.add_argument("FILE", nargs=1)
           14 options = parser.parse_args()
           15 
           16 filename = options.FILE[0]
           17 
           18 dirname, basename = os.path.split(filename)
           19 sys.path.insert(0, dirname)
           20 
           21 modulename = os.path.splitext(basename)[0]
           22 r = importlib.import_module(modulename)
           23 
           24 colors = [(141, 211, 199), (255, 255, 179), (190, 186, 218), (251, 128, 114),
           25           (128, 177, 211), (253, 180, 98), (179, 222, 105), (252, 205, 229),
           26           (217, 217, 217), (188, 128, 189), (204, 235, 197), (255, 237, 111)]
           27 colors = np.array(colors) / 255.0
           28 
           29 n_procs = r.size
           30 s = r.Stages["time-stepping loop"]
           31 
           32 big_events = ["basal_yield_stress",
           33               "stress_balance",
           34               "surface",
           35               "ocean",
           36               "age",
           37               "energy",
           38               "basal_hydrology",
           39               "fracture_density",
           40               "mass_transport",
           41               "calving",
           42               "bed_deformation",
           43               "io"]
           44 
           45 small_events = {}
           46 small_events["energy"] = ["ice_energy", "btu"]
           47 small_events["stress_balance"] = ["stress_balance.shallow", "stress_balance.modifier",
           48                                   "stress_balance.strain_heat", "stress_balance.vertical_velocity"]
           49 small_events["stress_balance.modifier"] = ["sia.bed_smoother",
           50                                            "sia.gradient", "sia.flux", "sia.3d_velocity"]
           51 small_events["io"] = ["io.backup", "io.extra_file", "io.model_state"]
           52 
           53 better_names = {"stress_balance.shallow": "SSA",
           54                 "stress_balance.modifier": "SIA",
           55                 "stress_balance.strain_heat": "Strain heating",
           56                 "stress_balance.vertical_velocity": "Vertical velocity"}
           57 
           58 
           59 def get_event_times(event, n_procs):
           60     result = [s[event][j]["time"] for j in range(n_procs)]
           61 
           62     max = np.max(result)
           63     min = np.min(result)
           64 
           65     if max > 0:
           66         return max, min, min / max
           67     else:
           68         return max, min, 0.0
           69 
           70 
           71 total_time = np.max([s["summary"][j]["time"] for j in range(n_procs)])
           72 
           73 
           74 def get_data(event_list):
           75     "Get event data from the time-stepping loop stage."
           76     return {e: get_event_times(e, n_procs) for e in event_list if e in list(s.keys())}
           77 
           78 
           79 def aggregate(data, total_time):
           80     "Combine small events."
           81     d = data.copy()
           82     other = [0, 0, 0]
           83     other_label = ""
           84     for event in data:
           85         if data[event][0] / float(total_time) < 0.01:
           86             print("Lumping '%s' (%f%%) with others..." % (event,
           87                                                           100.0 * data[event][0] / total_time))
           88             del d[event]
           89             other[0] += data[event][0]
           90             other[1] += data[event][1]
           91             if other[0] > 0:
           92                 other[2] = other[1] / other[0]
           93             else:
           94                 other[2] = 0.0
           95             other_label += "\n{}".format(event)
           96 
           97     d["other"] = other
           98     return d
           99 
          100 
          101 def plot(data, total, grand_total):
          102 
          103     events = [(e, data[e][0]) for e in data]
          104     events.sort(key=lambda x: x[1])
          105 
          106     def better_name(n):
          107         if n in list(better_names.keys()):
          108             return better_names[n]
          109         else:
          110             return n
          111 
          112     names = [e[0] for e in events]
          113     times = [e[1] for e in events]
          114     times_percent = [100.0 * t / float(total) for t in times]
          115 
          116     if grand_total is not None:
          117         comments = ["(%3.1f s, %3.1f%%)" % (time, 100.0 * time / grand_total) for time in times]
          118     else:
          119         comments = ["(%3.1f s)" % time for time in times]
          120 
          121     labels = [better_name(name) + " " + comment for name, comment in zip(names, comments)]
          122 
          123     explode = [0.05]*len(times)
          124     plt.pie(times_percent, autopct="%3.1f%%", labels=labels, colors=colors, startangle=0.0, explode=explode)
          125     plt.margins(x=0.2, y=0.1)
          126     plt.axis('equal')
          127 
          128 
          129 def figure(title, event_list, total, grand_total=None):
          130     plt.figure(figsize=(10,5))
          131     plt.title("%s (%s)" % (title, filename))
          132     data = get_data(event_list)
          133     plot(aggregate(data, total), total, grand_total)
          134     # plot(data, total, grand_total)
          135     return data
          136 
          137 
          138 big = figure("Time-stepping loop",
          139              big_events,
          140              total_time)
          141 
          142 energy = figure("Energy step",
          143                 small_events["energy"],
          144                 big["energy"][0], total_time)
          145 
          146 stressbalance = figure("Stress balance",
          147                        small_events["stress_balance"],
          148                        big["stress_balance"][0], total_time)
          149 
          150 sia = figure("SIA",
          151              small_events["stress_balance.modifier"],
          152              stressbalance["stress_balance.modifier"][0], total_time)
          153 
          154 io = figure("I/O during run",
          155             small_events["io"],
          156             big["io"][0], total_time)
          157 
          158 plt.show()