Skip to content

Commit 0577c64

Browse files
committed
enabled caching of analysed prvs
1 parent 19be949 commit 0577c64

File tree

1 file changed

+86
-37
lines changed

1 file changed

+86
-37
lines changed

pypop/prv.py

Lines changed: 86 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from io import StringIO
1717
import pickle
1818

19-
from .utils.io import zipopen
19+
from pypop.utils.io import zipopen
2020

2121
try:
2222
from tqdm.auto import tqdm
@@ -85,20 +85,49 @@ class PRV:
8585

8686
def __init__(self, prv_path):
8787

88-
try:
89-
self._load_prv_and_pcf(prv_path)
88+
self._prv_path = prv_path
89+
self._no_prv = False
9090

91-
except ValueError:
91+
self._omp_region_data = None
92+
self._event_names = {}
93+
self._event_vals = {}
94+
self.state = None
95+
self.event = None
96+
self.comm = None
97+
98+
try:
99+
self._load_pickle(prv_path)
100+
self._no_prv = True
101+
except (pickle.UnpicklingError, ValueError):
92102
try:
93-
self._load_pickle(prv_path)
94-
except ValueError:
95-
raise ValueError("Not a prv or valid pickle")
103+
self._load_pickle(PRV._generate_event_cache_name(prv_path))
104+
except (pickle.UnpicklingError, ValueError):
105+
try:
106+
self._load_prv_and_pcf(prv_path)
107+
self.save(PRV._generate_event_cache_name(prv_path))
108+
except ValueError:
109+
raise ValueError("Not a prv or valid pickle")
96110

97-
self._omp_region_data = None
111+
@staticmethod
112+
def _generate_event_cache_name(prvfile):
113+
return prvfile + ".eventcache"
114+
115+
@staticmethod
116+
def _generate_region_cache_name(prvfile):
117+
if "eventcache" in prvfile:
118+
return prvfile.replace("eventcache", "regioncache")
119+
120+
return prvfile + ".regioncache"
121+
122+
def reload(self):
123+
if self._no_prv:
124+
warn("Data loaded directly from cachefile, reload from PRV not possible")
125+
return
126+
127+
self._parse_pcf()
128+
self._parse_prv()
98129

99130
def _load_prv_and_pcf(self, prv_path):
100-
self._event_names = {}
101-
self._event_vals = {}
102131
self._parse_pcf(prv_path)
103132

104133
self._parse_prv(prv_path)
@@ -196,33 +225,49 @@ def _process_commline(self, line, writer):
196225
pass
197226

198227
def save(self, filename):
199-
savedata = (self.metadata, self.state, self.event, self.comm)
228+
savedata = (
229+
self.metadata,
230+
self.state,
231+
self.event,
232+
self.comm,
233+
self._event_names,
234+
self._event_vals,
235+
)
200236

201237
with gzip.open(filename, "wb", compresslevel=6) as fh:
202238
pickle.dump(savedata, fh)
203239

204240
def _load_pickle(self, filename):
205-
try:
206-
with gzip.open(filename, "rb") as fh:
207-
data = pickle.load(fh)
208-
except gzip.BadGzipFile:
209-
try:
210-
with open(filename, "rb") as fh:
211-
data = pickle.load(fh)
212-
except pickle.UnpicklingError:
213-
raise ValueError("Invalid pickle -- missing data")
241+
with zipopen(filename, "rb") as fh:
242+
data = pickle.load(fh)
214243

215-
self.metadata, self.state, self.event, self.comm = data
244+
try:
245+
(
246+
self.metadata,
247+
self.state,
248+
self.event,
249+
self.comm,
250+
self._event_names,
251+
self._event_vals,
252+
) = data
216253
except ValueError:
217254
raise ValueError("Invalid pickle -- missing data")
218255

219-
def profile_openmp_regions(self, no_progress=False):
256+
def profile_openmp_regions(self, no_progress=False, ignore_cache=False):
220257
"""Profile OpenMP Region Info
221258
"""
222259

223260
if self._omp_region_data is not None:
224261
return self._omp_region_data
225262

263+
if not ignore_cache:
264+
try:
265+
with zipopen(PRV._generate_region_cache_name(self._prv_path), 'rb') as fh:
266+
self._omp_region_data = pickle.load(fh)
267+
return self._omp_region_data
268+
except (FileNotFoundError, pickle.UnpicklingError):
269+
pass
270+
226271
idx_master_threads = pd.IndexSlice[:, 1]
227272

228273
# First generate appropriate event subsets grouped by rank
@@ -419,6 +464,9 @@ def profile_openmp_regions(self, no_progress=False):
419464

420465
self._omp_region_data = pd.concat(rank_stats, names=["rank", "region"])
421466

467+
with zipopen(PRV._generate_region_cache_name(self._prv_path), 'wb') as fh:
468+
pickle.dump(self._omp_region_data, fh)
469+
422470
return self._omp_region_data
423471

424472
def region_location_from_fingerprint(self, fingerprint):
@@ -470,41 +518,42 @@ def openmp_region_summary(self, by_location=False):
470518
fingerprint_key = "Region Function Fingerprint"
471519

472520
runtime = self.metadata.ns_elapsed
521+
nproc = len(set(self._omp_region_data["Rank"]))
473522

474523
self.profile_openmp_regions()
475524

476525
summary = self._omp_region_data.groupby(fingerprint_key).agg(
477526
**{
478527
"Instances": ("Maximum Computation Time", "count"),
479-
"Relative Load Balance Efficiency": (
480-
"Load Balance",
481-
lambda x: np.average(
482-
x, weights=self._omp_region_data.loc[x.index, "Region Length"],
483-
),
528+
"Total Parallel Inefficiency Contribution": (
529+
"Region Delay Time",
530+
lambda x: np.sum(x) / (nproc * runtime),
484531
),
485-
"Relative Parallel Efficiency": (
532+
"Total Load Imbalance Contribution": (
533+
"Computation Delay Time",
534+
lambda x: np.sum(x) / (nproc * runtime),
535+
),
536+
"Average Parallel Efficiency": (
486537
"Parallel Efficiency",
487538
lambda x: np.average(
488539
x, weights=self._omp_region_data.loc[x.index, "Region Length"]
489540
),
490541
),
491-
"Load Balance Efficiency": (
492-
"Computation Delay Time",
493-
lambda x: 1 - np.sum(x / runtime),
494-
),
495-
"Parallel Efficiency": (
496-
"Region Delay Time",
497-
lambda x: 1 - np.sum(x / runtime),
542+
"Average Load Balance": (
543+
"Load Balance",
544+
lambda x: np.average(
545+
x, weights=self._omp_region_data.loc[x.index, "Region Length"],
546+
),
498547
),
499548
"Accumulated Region Time": ("Region Length", np.sum),
500549
"Accumulated Computation Time": ("Region Total Computation", np.sum),
501550
"Average Computation Time": ("Average Computation Time", np.average),
502551
"Maximum Computation Time": ("Maximum Computation Time", np.max),
503-
"Region Functions": (fingerprint_key, lambda x: x[0],),
552+
"Region Functions": (fingerprint_key, lambda x: x.iloc[0],),
504553
}
505554
)
506555

507-
return summary.sort_values("Load Balance Efficiency")
556+
return summary.sort_values("Total Parallel Inefficiency Contribution")
508557

509558

510559
def _format_timedate(prv_td):

0 commit comments

Comments
 (0)