Skip to content

Commit 049276d

Browse files
committed
FIX: optional import handling of multiprocess module.
1 parent 2169db1 commit 049276d

File tree

7 files changed

+424
-974
lines changed

7 files changed

+424
-974
lines changed

docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/monte_carlo_class_example.inputs.txt

Lines changed: 100 additions & 20 deletions
Large diffs are not rendered by default.

docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/monte_carlo_class_example.kml

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.

docs/notebooks/monte_carlo_analysis/monte_carlo_analysis_outputs/monte_carlo_class_example.outputs.txt

Lines changed: 100 additions & 20 deletions
Large diffs are not rendered by default.

docs/notebooks/monte_carlo_analysis/monte_carlo_class_usage.ipynb

Lines changed: 159 additions & 911 deletions
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ env-analysis = [
5252

5353
monte-carlo = [
5454
"imageio",
55-
"h5py",
56-
"multiprocess"
55+
"multiprocess>=0.70"
5756
]
5857

5958
all = ["rocketpy[env-analysis]", "rocketpy[monte-carlo]"]

requirements-optional.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ ipywidgets>=7.6.3
44
jsonpickle
55
timezonefinder
66
imageio
7-
h5py
8-
multiprocess
7+
multiprocess>=0.70

rocketpy/simulation/monte_carlo.py

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
import numpy as np
2626
import simplekml
27-
from multiprocess import Event, Lock, Process, Semaphore, shared_memory
28-
from multiprocess.managers import BaseManager
2927

3028
from rocketpy import Function
3129
from rocketpy._encoders import RocketPyEncoder
@@ -40,6 +38,7 @@
4038
from rocketpy.tools import (
4139
generate_monte_carlo_ellipses,
4240
generate_monte_carlo_ellipses_coordinates,
41+
import_optional_dependency,
4342
)
4443

4544
# TODO: Create evolution plots to analyze convergence
@@ -355,6 +354,8 @@ def __run_in_parallel(self, n_workers=None):
355354
# calculate the number of simulations that can be stored in memory
356355
n_sim_memory = max(n_workers - 2, 2) # at least a double buffer
357356

357+
multiprocess, shared_memory, managers = import_multiprocess()
358+
358359
# initialize shared memory buffer
359360
shared_inputs_buffer = shared_memory.SharedMemory(
360361
create=True, size=inputs_size * n_sim_memory, name="shared_inputs"
@@ -364,7 +365,7 @@ def __run_in_parallel(self, n_workers=None):
364365
)
365366

366367
try:
367-
with MonteCarloManager() as manager:
368+
with create_multiprocess_manager(multiprocess, managers) as manager:
368369
# initialize queue
369370
errors_lock = manager.Lock()
370371

@@ -404,9 +405,10 @@ def __run_in_parallel(self, n_workers=None):
404405

405406
# Creates n_workers processes then starts them
406407
for _ in range(n_workers - 2): # leave 2 cores for the writer workers
407-
p = Process(
408+
p = multiprocess.Process(
408409
target=self.__run_simulation_worker,
409410
args=(
411+
shared_memory,
410412
self.error_file,
411413
self.export_list,
412414
self.environment,
@@ -436,9 +438,10 @@ def __run_in_parallel(self, n_workers=None):
436438
input_writer_stop_event = manager.Event()
437439
results_writer_stop_event = manager.Event()
438440

439-
input_writer = Process(
441+
input_writer = multiprocess.Process(
440442
target=self._write_data_worker,
441443
args=(
444+
shared_memory,
442445
self.input_file,
443446
go_write_inputs,
444447
go_read_inputs,
@@ -449,9 +452,10 @@ def __run_in_parallel(self, n_workers=None):
449452
),
450453
)
451454

452-
results_writer = Process(
455+
results_writer = multiprocess.Process(
453456
target=self._write_data_worker,
454457
args=(
458+
shared_memory,
455459
self.output_file,
456460
go_write_results,
457461
go_read_results,
@@ -500,6 +504,7 @@ def __run_in_parallel(self, n_workers=None):
500504

501505
@staticmethod
502506
def __run_simulation_worker(
507+
shared_memory,
503508
error_file,
504509
export_list,
505510
sto_env,
@@ -523,6 +528,8 @@ def __run_simulation_worker(
523528
524529
Parameters
525530
----------
531+
shared_memory : module
532+
Shared memory handler of multiprocess module.
526533
error_file : Path
527534
Path of the error file.
528535
export_list : list
@@ -820,6 +827,7 @@ def __loop_though_buffer(
820827

821828
@staticmethod
822829
def _write_data_worker(
830+
shared_memory,
823831
file_path,
824832
go_write_semaphores,
825833
go_read_semaphores,
@@ -833,6 +841,8 @@ def _write_data_worker(
833841
834842
Parameters
835843
----------
844+
shared_memory : module
845+
Shared memory handler of multiprocess module.
836846
file_path : str
837847
Path to the file to write the data.
838848
go_write_semaphores : list
@@ -1672,16 +1682,50 @@ def prepare_export_data(obj, sample_time=0.1, remove_functions=False):
16721682
return result
16731683

16741684

1675-
class MonteCarloManager(BaseManager):
1676-
def __init__(self):
1677-
super().__init__()
1678-
self.register('Lock', Lock)
1679-
self.register('Event', Event)
1680-
self.register('Semaphore', Semaphore)
1681-
self.register('SimCounter', SimCounter)
1682-
self.register('StochasticEnvironment', StochasticEnvironment)
1683-
self.register('StochasticRocket', StochasticRocket)
1684-
self.register('StochasticFlight', StochasticFlight)
1685+
def import_multiprocess():
1686+
"""Import the necessary modules for the multiprocess module.
1687+
1688+
Returns
1689+
-------
1690+
tuple
1691+
Tuple containing the imported modules.
1692+
"""
1693+
multiprocess = import_optional_dependency("multiprocess")
1694+
shared_memory = import_optional_dependency("multiprocess.shared_memory")
1695+
managers = import_optional_dependency("multiprocess.managers")
1696+
1697+
return multiprocess, shared_memory, managers
1698+
1699+
1700+
def create_multiprocess_manager(multiprocess, managers):
1701+
"""Creates a manager for the multiprocess control of the
1702+
Monte Carlo simulation.
1703+
1704+
Parameters
1705+
----------
1706+
multiprocess : module
1707+
Multiprocess module.
1708+
managers : module
1709+
Managing submodules of the multiprocess module.
1710+
1711+
Returns
1712+
-------
1713+
MonteCarloManager
1714+
Subclass of BaseManager with the necessary classes registered.
1715+
"""
1716+
1717+
class MonteCarloManager(managers.BaseManager):
1718+
def __init__(self):
1719+
super().__init__()
1720+
self.register('Lock', multiprocess.Lock)
1721+
self.register('Event', multiprocess.Event)
1722+
self.register('Semaphore', multiprocess.Semaphore)
1723+
self.register('SimCounter', SimCounter)
1724+
self.register('StochasticEnvironment', StochasticEnvironment)
1725+
self.register('StochasticRocket', StochasticRocket)
1726+
self.register('StochasticFlight', StochasticFlight)
1727+
1728+
return MonteCarloManager()
16851729

16861730

16871731
class SimCounter:

0 commit comments

Comments
 (0)