Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding benchmark functionality #1711

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
322 changes: 322 additions & 0 deletions parcels/tools/performance_logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,322 @@
import time as time_module

import numpy as np

try:
from mpi4py import MPI
except:
MPI = None

from threading import Event, Thread
from time import sleep


class TimingLog:
stime = 0
etime = 0
mtime = 0
_samples = []
_times_steps = []
_iter = 0

def __init__(self):
self.stime = 0
self.etime = 0
self.mtime = 0
self._samples = []
self._times_steps = []
self._iter = 0

Check warning on line 28 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L22-L28

Added lines #L22 - L28 were not covered by tests

@property
def timing(self):
return self._times_steps

Check warning on line 32 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L31-L32

Added lines #L31 - L32 were not covered by tests

@property
def samples(self):
return self._samples

Check warning on line 36 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L35-L36

Added lines #L35 - L36 were not covered by tests

def __len__(self):
return len(self._samples)

Check warning on line 39 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L38-L39

Added lines #L38 - L39 were not covered by tests

def get_values(self):
return self._times_steps

Check warning on line 42 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L41-L42

Added lines #L41 - L42 were not covered by tests

def get_value(self, index):
N = len(self._times_steps)
result = 0
if N > 0:
result = self._times_steps[min(max(index, 0), N - 1)]
return result

Check warning on line 49 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L44-L49

Added lines #L44 - L49 were not covered by tests

def start_timing(self):

Check warning on line 51 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L51

Added line #L51 was not covered by tests
if MPI:
mpi_comm = MPI.COMM_WORLD
mpi_rank = mpi_comm.Get_rank()
if mpi_rank == 0:

Check warning on line 55 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L53-L55

Added lines #L53 - L55 were not covered by tests
# self.stime = MPI.Wtime()
# self.stime = time_module.perf_counter()
self.stime = time_module.process_time()

Check warning on line 58 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L58

Added line #L58 was not covered by tests
else:
self.stime = time_module.process_time()

Check warning on line 60 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L60

Added line #L60 was not covered by tests

def stop_timing(self):

Check warning on line 62 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L62

Added line #L62 was not covered by tests
if MPI:
mpi_comm = MPI.COMM_WORLD
mpi_rank = mpi_comm.Get_rank()
if mpi_rank == 0:

Check warning on line 66 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L64-L66

Added lines #L64 - L66 were not covered by tests
# self.etime = MPI.Wtime()
# self.etime = time_module.perf_counter()
self.etime = time_module.process_time()

Check warning on line 69 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L69

Added line #L69 was not covered by tests
else:
self.etime = time_module.process_time()

Check warning on line 71 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L71

Added line #L71 was not covered by tests

def accumulate_timing(self):

Check warning on line 73 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L73

Added line #L73 was not covered by tests
if MPI:
mpi_comm = MPI.COMM_WORLD
mpi_rank = mpi_comm.Get_rank()
if mpi_rank == 0:
self.mtime += self.etime - self.stime

Check warning on line 78 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L75-L78

Added lines #L75 - L78 were not covered by tests
else:
self.mtime = 0

Check warning on line 80 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L80

Added line #L80 was not covered by tests
else:
self.mtime += self.etime - self.stime

Check warning on line 82 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L82

Added line #L82 was not covered by tests

def advance_iteration(self):

Check warning on line 84 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L84

Added line #L84 was not covered by tests
if MPI:
mpi_comm = MPI.COMM_WORLD
mpi_rank = mpi_comm.Get_rank()
if mpi_rank == 0:
self._times_steps.append(self.mtime)
self._samples.append(self._iter)
self._iter += 1
self.mtime = 0

Check warning on line 92 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L86-L92

Added lines #L86 - L92 were not covered by tests
else:
self._times_steps.append(self.mtime)
self._samples.append(self._iter)
self._iter += 1
self.mtime = 0

Check warning on line 97 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L94-L97

Added lines #L94 - L97 were not covered by tests

def add_aux_measure(self, value):

Check warning on line 99 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L99

Added line #L99 was not covered by tests
if MPI:
mpi_comm = MPI.COMM_WORLD
mpi_rank = mpi_comm.Get_rank()
if mpi_rank == 0:
self.mtime += value

Check warning on line 104 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L101-L104

Added lines #L101 - L104 were not covered by tests
else:
self.mtime += 0

Check warning on line 106 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L106

Added line #L106 was not covered by tests
else:
self.mtime += value

Check warning on line 108 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L108

Added line #L108 was not covered by tests

def sum(self):
result = 0

Check warning on line 111 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L110-L111

Added lines #L110 - L111 were not covered by tests
if MPI:
mpi_comm = MPI.COMM_WORLD
mpi_rank = mpi_comm.Get_rank()
if mpi_rank == 0:
result = np.array(self._times_steps).sum()

Check warning on line 116 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L113-L116

Added lines #L113 - L116 were not covered by tests
else:
result = np.array(self._times_steps).sum()
return result

Check warning on line 119 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L118-L119

Added lines #L118 - L119 were not covered by tests

def reset(self):
if self._times_steps is not None and len(self._times_steps) > 0:
del self._times_steps[:]
if self._samples is not None and len(self._samples) > 0:
del self._samples[:]
self.stime = 0
self.etime = 0
self.mtime = 0
self._samples = []
self._times_steps = []
self._iter = 0

Check warning on line 131 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L121-L131

Added lines #L121 - L131 were not covered by tests


class ParamLogging:
_samples = []
_params = []
_iter = 0

def __init__(self):
self._samples = []
self._params = []
self._iter = 0

Check warning on line 142 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L139-L142

Added lines #L139 - L142 were not covered by tests

@property
def samples(self):
return self._samples

Check warning on line 146 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L145-L146

Added lines #L145 - L146 were not covered by tests

@property
def params(self):
return self._params

Check warning on line 150 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L149-L150

Added lines #L149 - L150 were not covered by tests

def get_params(self):
return self._params

Check warning on line 153 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L152-L153

Added lines #L152 - L153 were not covered by tests

def get_param(self, index):
N = len(self._params)
result = 0
if N > 0:
result = self._params[min(max(index, 0), N - 1)]
return result

Check warning on line 160 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L155-L160

Added lines #L155 - L160 were not covered by tests

def __len__(self):
return len(self._samples)

Check warning on line 163 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L162-L163

Added lines #L162 - L163 were not covered by tests

def advance_iteration(self, param):

Check warning on line 165 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L165

Added line #L165 was not covered by tests
if MPI:
# mpi_comm = MPI.COMM_WORLD
# mpi_rank = mpi_comm.Get_rank()

self._params.append(param)
self._samples.append(self._iter)
self._iter += 1

Check warning on line 172 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L170-L172

Added lines #L170 - L172 were not covered by tests
# if mpi_rank == 0:
# self._params.append(param)
# self._samples.append(self._iter)
# self._iter += 1
else:
self._params.append(param)
self._samples.append(self._iter)
self._iter += 1

Check warning on line 180 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L178-L180

Added lines #L178 - L180 were not covered by tests


class Asynchronous_ParamLogging:
_samples = []
_params = []
_iter = 0
_measure_func = None
_measure_start_value = None # for differential measurements
_measure_partial_values = []
_measure_interval = 0.25 # 250 ms
_event = None
_thread = None
differential_measurement = False

def __init__(self):
self._samples = []
self._params = []
self._measure_partial_values = []
self._iter = 0
self._measure_func = None
self._measure_start_value = None
self._measure_interval = 0.25 # 250 ms
self._event = None
self._thread = None
self.differential_measurement = False

Check warning on line 205 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L195-L205

Added lines #L195 - L205 were not covered by tests

def __del__(self):
del self._samples[:]
del self._params[:]
del self._measure_partial_values[:]

Check warning on line 210 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L207-L210

Added lines #L207 - L210 were not covered by tests

@property
def samples(self):
return self._samples

Check warning on line 214 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L213-L214

Added lines #L213 - L214 were not covered by tests

@property
def params(self):
return self._params

Check warning on line 218 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L217-L218

Added lines #L217 - L218 were not covered by tests

@property
def measure_func(self):
return self._measure_func

Check warning on line 222 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L221-L222

Added lines #L221 - L222 were not covered by tests

@measure_func.setter
def measure_func(self, function):
self._measure_func = function

Check warning on line 226 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L225-L226

Added lines #L225 - L226 were not covered by tests

@property
def measure_interval(self):
return self._measure_interval

Check warning on line 230 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L229-L230

Added lines #L229 - L230 were not covered by tests

@measure_interval.setter
def measure_interval(self, interval):

Check warning on line 233 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L233

Added line #L233 was not covered by tests
"""
Set measure interval in seconds
:param interval: interval in seconds (fractional possible)
:return: None
"""
self._measure_interval = interval

Check warning on line 239 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L239

Added line #L239 was not covered by tests

@property
def measure_start_value(self):
return self._measure_start_value

Check warning on line 243 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L242-L243

Added lines #L242 - L243 were not covered by tests

@measure_start_value.setter
def measure_start_value(self, value):
self._measure_start_value = value

Check warning on line 247 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L246-L247

Added lines #L246 - L247 were not covered by tests

def async_run(self):
if self.differential_measurement:
self.async_run_diff_measurement()

Check warning on line 251 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L249-L251

Added lines #L249 - L251 were not covered by tests
else:
pass

Check warning on line 253 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L253

Added line #L253 was not covered by tests

def async_run_diff_measurement(self):
if self._measure_start_value is None:
self._measure_start_value = self._measure_func()
self._measure_partial_values.append(0)
while not self._event.is_set():
self._measure_partial_values.append(self._measure_func() - self._measure_start_value)
sleep(self._measure_interval)

Check warning on line 261 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L255-L261

Added lines #L255 - L261 were not covered by tests

def async_run_measurement(self):
while not self._event.is_set():
self._measure_partial_values.append(self.measure_func())
sleep(self.measure_interval)

Check warning on line 266 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L263-L266

Added lines #L263 - L266 were not covered by tests

def start_partial_measurement(self):
assert self._measure_func is not None, "Measurement function is None - invalid. Exiting ..."
assert self._thread is None, "Measurement already running - double-start invalid. Exiting ..."
if len(self._measure_partial_values) > 0:
del self._measure_partial_values[:]
self._measure_partial_values = []
self._event = Event()
self._thread = Thread(target=self.async_run_measurement)
self._thread.start()

Check warning on line 276 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L268-L276

Added lines #L268 - L276 were not covered by tests

def stop_partial_measurement(self):

Check warning on line 278 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L278

Added line #L278 was not covered by tests
"""
function to stop the measurement. The function also internally advances the iteration with the mean (or max)
of the measured partial values.
:return: None
"""
self._event.set()
self._thread.join()
sleep(self._measure_interval)

Check warning on line 286 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L284-L286

Added lines #L284 - L286 were not covered by tests
del self._thread
self._thread = None
self._measure_start_value = None

Check warning on line 289 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L288-L289

Added lines #L288 - L289 were not covered by tests
# param_partial_mean = np.array(self._measure_partial_values).mean()
param_partial_mean = np.array(self._measure_partial_values).max()
self.advance_iteration(param_partial_mean)

Check warning on line 292 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L291-L292

Added lines #L291 - L292 were not covered by tests

def get_params(self):
return self._params

Check warning on line 295 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L294-L295

Added lines #L294 - L295 were not covered by tests

def get_param(self, index):
N = len(self._params)
result = 0
if N > 0:
result = self._params[min(max(index, 0), N - 1)]
return result

Check warning on line 302 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L297-L302

Added lines #L297 - L302 were not covered by tests

def __len__(self):
return len(self._samples)

Check warning on line 305 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L304-L305

Added lines #L304 - L305 were not covered by tests

def advance_iteration(self, param):

Check warning on line 307 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L307

Added line #L307 was not covered by tests
if MPI:
# mpi_comm = MPI.COMM_WORLD
# mpi_rank = mpi_comm.Get_rank()

self._params.append(param)
self._samples.append(self._iter)
self._iter += 1

Check warning on line 314 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L312-L314

Added lines #L312 - L314 were not covered by tests
# if mpi_rank == 0:
# self._params.append(param)
# self._samples.append(self._iter)
# self._iter += 1
else:
self._params.append(param)
self._samples.append(self._iter)
self._iter += 1

Check warning on line 322 in parcels/tools/performance_logger.py

View check run for this annotation

Codecov / codecov/patch

parcels/tools/performance_logger.py#L320-L322

Added lines #L320 - L322 were not covered by tests
Loading