From d83176d21b3268ee44cba3338e85465a78d1339c Mon Sep 17 00:00:00 2001 From: Ishaan Desai Date: Mon, 23 Dec 2024 16:09:38 +0100 Subject: [PATCH] Fix adaptivity CPU time export (#138) * Check why adaptivity cpu time output is not working * Move initialization of adaptivity_cpu_time outside of the coupling loop * Log CPU time of micro output communication part of the adaptivity * Measure peak memory usage for the solve() call of micro simulations * Use correct data name for export: sole_mem_use * fix tests * Add logic to calculate peak memory usage of micro simulation for adaptive case * Add tracemalloc.start() and tracemalloc.reset_peak() calls * Remove code pertaining to the Micro Manager measuring memory consumption of the micro simulation * Remove last traces of tracemalloc --- micro_manager/config.py | 24 --------------- micro_manager/micro_manager.py | 30 +++++++++++-------- tests/unit/test_micro_manager.py | 4 ++- .../test_micro_simulation_crash_handling.py | 4 +-- 4 files changed, 23 insertions(+), 39 deletions(-) diff --git a/micro_manager/config.py b/micro_manager/config.py index 26f99b3..4e2cc32 100644 --- a/micro_manager/config.py +++ b/micro_manager/config.py @@ -38,7 +38,6 @@ def __init__(self, config_file_name): self._diagnostics_data_names = dict() self._output_micro_sim_time = False - self._output_micro_mem_use = False self._interpolate_crash = False @@ -143,18 +142,6 @@ def _read_json(self, config_file_name): "Micro manager will not output time required to solve each micro simulation." ) - try: - if self._data["diagnostics"]["output_micro_sim_solve_mem_use"] == "True": - self._output_micro_mem_use = True - self._write_data_names["solve_mem_use"] = False - self._logger.log_info_one_rank( - "Calculating memory usage of the solve call of each micro micro simulation will slow down the Micro Manager. This option is intended for diagnostic purposes." - ) - except BaseException: - self._logger.log_info_one_rank( - "Micro manager will not output memory usage for solving each micro simulation." - ) - def read_json_micro_manager(self): """ Reads Micro Manager relevant information from JSON configuration file @@ -484,17 +471,6 @@ def write_micro_solve_time(self): """ return self._output_micro_sim_time - def write_micro_mem_use(self): - """ - Depending on user input, micro manager will calculate memory usage of solve() step of every micro simulation - - Returns - ------- - output_micro_mem_use : bool - True if micro simulation memory usage is required. - """ - return self._output_micro_mem_use - def turn_on_adaptivity(self): """ Boolean stating whether adaptivity is ot or not. diff --git a/micro_manager/micro_manager.py b/micro_manager/micro_manager.py index cdb2d3a..9636b83 100644 --- a/micro_manager/micro_manager.py +++ b/micro_manager/micro_manager.py @@ -74,11 +74,6 @@ def __init__(self, config_file: str) -> None: self._is_micro_solve_time_required = self._config.write_micro_solve_time() - self._is_micro_solve_mem_use_required = self._config.write_micro_mem_use() - - if self._is_micro_solve_mem_use_required: - tracemalloc = importlib.import_module("tracemalloc") - self._macro_mesh_name = self._config.get_macro_mesh_name() self._macro_bounds = self._config.get_macro_domain_bounds() @@ -168,9 +163,9 @@ def solve(self) -> None: self._data_for_adaptivity, ) - while self._participant.is_coupling_ongoing(): + adaptivity_cpu_time = 0.0 - adaptivity_cpu_time = 0.0 + while self._participant.is_coupling_ongoing(): dt = min(self._participant.get_max_time_step_size(), self._micro_dt) @@ -207,9 +202,10 @@ def solve(self) -> None: micro_sims_input = self._read_data_from_precice(dt) - micro_sims_output = micro_sim_solve(micro_sims_input, dt) + micro_sims_output, adaptivity_time = micro_sim_solve(micro_sims_input, dt) if self._output_adaptivity_cpu_time: + adaptivity_cpu_time += adaptivity_time for i in range(self._local_number_of_sims): micro_sims_output[i]["adaptivity_cpu_time"] = adaptivity_cpu_time @@ -627,7 +623,7 @@ def _write_data_to_precice(self, data: list) -> None: self._macro_mesh_name, dname, [], np.array([]) ) - def _solve_micro_simulations(self, micro_sims_input: list, dt: float) -> list: + def _solve_micro_simulations(self, micro_sims_input: list, dt: float) -> tuple: """ Solve all micro simulations and assemble the micro simulations outputs in a list of dicts format. @@ -701,11 +697,11 @@ def _solve_micro_simulations(self, micro_sims_input: list, dt: float) -> list: micro_sims_input, micro_sims_output, unset_sim ) - return micro_sims_output + return micro_sims_output, 0.0 def _solve_micro_simulations_with_adaptivity( self, micro_sims_input: list, dt: float - ) -> list: + ) -> tuple: """ Adaptively solve micro simulations and assemble the micro simulations outputs in a list of dicts format. @@ -723,12 +719,18 @@ def _solve_micro_simulations_with_adaptivity( List of dicts in which keys are names of data and the values are the data of the output of the micro simulations. """ + adaptivity_cpu_time = 0.0 + if self._adaptivity_in_every_implicit_step: + start_time = time.process_time() self._adaptivity_controller.compute_adaptivity( dt, self._micro_sims, self._data_for_adaptivity, ) + end_time = time.process_time() + + adaptivity_cpu_time = end_time - start_time active_sim_ids = self._adaptivity_controller.get_active_sim_ids() @@ -805,9 +807,13 @@ def _solve_micro_simulations_with_adaptivity( micro_sims_input, micro_sims_output, unset_sim, active_sim_ids ) + start_time = time.process_time() micro_sims_output = self._adaptivity_controller.get_full_field_micro_output( micro_sims_output ) + end_time = time.process_time() + + adaptivity_cpu_time += end_time - start_time # Resolve micro sim output data for inactive simulations for inactive_id in inactive_sim_ids: @@ -824,7 +830,7 @@ def _solve_micro_simulations_with_adaptivity( for name in self._adaptivity_micro_data_names: self._data_for_adaptivity[name][i] = micro_sims_output[i][name] - return micro_sims_output + return micro_sims_output, adaptivity_cpu_time def _get_solve_variant(self) -> Callable[[list, float], list]: """ diff --git a/tests/unit/test_micro_manager.py b/tests/unit/test_micro_manager.py index 24afea8..216cb25 100644 --- a/tests/unit/test_micro_manager.py +++ b/tests/unit/test_micro_manager.py @@ -105,7 +105,9 @@ def test_solve_micro_sims(self): manager._micro_sims = [MicroSimulation(i) for i in range(4)] manager._micro_sims_active_steps = np.zeros(4, dtype=np.int32) - micro_sims_output = manager._solve_micro_simulations(self.fake_read_data, 1.0) + micro_sims_output, _ = manager._solve_micro_simulations( + self.fake_read_data, 1.0 + ) for data, fake_data in zip(micro_sims_output, self.fake_write_data): self.assertEqual(data["micro-scalar-data"], 2) diff --git a/tests/unit/test_micro_simulation_crash_handling.py b/tests/unit/test_micro_simulation_crash_handling.py index 0cdbf9f..940342e 100644 --- a/tests/unit/test_micro_simulation_crash_handling.py +++ b/tests/unit/test_micro_simulation_crash_handling.py @@ -52,7 +52,7 @@ def test_crash_handling(self): ) manager._micro_sims = [MicroSimulation(i) for i in range(4)] - micro_sims_output = manager._solve_micro_simulations(macro_data, 1.0) + micro_sims_output, _ = manager._solve_micro_simulations(macro_data, 1.0) # Crashed simulation has interpolated value data_crashed = micro_sims_output[2] @@ -106,7 +106,7 @@ def test_crash_handling_with_adaptivity(self): [-2, -2, -2, -2, 2] ) - micro_sims_output = manager._solve_micro_simulations_with_adaptivity( + micro_sims_output, _ = manager._solve_micro_simulations_with_adaptivity( macro_data, 1.0 )