|
2 | 2 | import os |
3 | 3 | import queue |
4 | 4 | import time |
5 | | -from typing import Callable, Optional |
| 5 | +from typing import Optional |
6 | 6 |
|
7 | | -from executorlib.standalone.command import get_interactive_execute_command |
8 | | -from executorlib.standalone.interactive.communication import ( |
9 | | - SocketInterface, |
10 | | - interface_bootup, |
11 | | -) |
12 | | -from executorlib.standalone.interactive.spawner import BaseSpawner, MpiExecSpawner |
| 7 | +from executorlib.standalone.interactive.communication import SocketInterface |
13 | 8 | from executorlib.standalone.serialize import serialize_funct |
14 | 9 |
|
15 | 10 |
|
16 | | -def execute_multiple_tasks( |
17 | | - future_queue: queue.Queue, |
18 | | - cores: int = 1, |
19 | | - spawner: type[BaseSpawner] = MpiExecSpawner, |
20 | | - hostname_localhost: Optional[bool] = None, |
21 | | - init_function: Optional[Callable] = None, |
22 | | - cache_directory: Optional[str] = None, |
23 | | - cache_key: Optional[str] = None, |
24 | | - queue_join_on_shutdown: bool = True, |
25 | | - log_obj_size: bool = False, |
26 | | - error_log_file: Optional[str] = None, |
27 | | - worker_id: Optional[int] = None, |
28 | | - **kwargs, |
29 | | -) -> None: |
30 | | - """ |
31 | | - Execute a single tasks in parallel using the message passing interface (MPI). |
32 | | -
|
33 | | - Args: |
34 | | - future_queue (queue.Queue): task queue of dictionary objects which are submitted to the parallel process |
35 | | - cores (int): defines the total number of MPI ranks to use |
36 | | - spawner (BaseSpawner): Spawner to start process on selected compute resources |
37 | | - hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the |
38 | | - context of an HPC cluster this essential to be able to communicate to an |
39 | | - Executor running on a different compute node within the same allocation. And |
40 | | - in principle any computer should be able to resolve that their own hostname |
41 | | - points to the same address as localhost. Still MacOS >= 12 seems to disable |
42 | | - this look up for security reasons. So on MacOS it is required to set this |
43 | | - option to true |
44 | | - init_function (Callable): optional function to preset arguments for functions which are submitted later |
45 | | - cache_directory (str, optional): The directory to store cache files. Defaults to "executorlib_cache". |
46 | | - cache_key (str, optional): By default the cache_key is generated based on the function hash, this can be |
47 | | - overwritten by setting the cache_key. |
48 | | - queue_join_on_shutdown (bool): Join communication queue when thread is closed. Defaults to True. |
49 | | - log_obj_size (bool): Enable debug mode which reports the size of the communicated objects. |
50 | | - error_log_file (str): Name of the error log file to use for storing exceptions raised by the Python functions |
51 | | - submitted to the Executor. |
52 | | - worker_id (int): Communicate the worker which ID was assigned to it for future reference and resource |
53 | | - distribution. |
54 | | - """ |
55 | | - interface = interface_bootup( |
56 | | - command_lst=get_interactive_execute_command( |
57 | | - cores=cores, |
58 | | - ), |
59 | | - connections=spawner(cores=cores, **kwargs), |
60 | | - hostname_localhost=hostname_localhost, |
61 | | - log_obj_size=log_obj_size, |
62 | | - worker_id=worker_id, |
63 | | - ) |
64 | | - if init_function is not None: |
65 | | - interface.send_dict( |
66 | | - input_dict={"init": True, "fn": init_function, "args": (), "kwargs": {}} |
67 | | - ) |
68 | | - while True: |
69 | | - task_dict = future_queue.get() |
70 | | - if "shutdown" in task_dict and task_dict["shutdown"]: |
71 | | - interface.shutdown(wait=task_dict["wait"]) |
72 | | - _task_done(future_queue=future_queue) |
73 | | - if queue_join_on_shutdown: |
74 | | - future_queue.join() |
75 | | - break |
76 | | - elif "fn" in task_dict and "future" in task_dict: |
77 | | - _execute_task_dict( |
78 | | - task_dict=task_dict, |
79 | | - interface=interface, |
80 | | - cache_directory=cache_directory, |
81 | | - cache_key=cache_key, |
82 | | - error_log_file=error_log_file, |
83 | | - ) |
84 | | - _task_done(future_queue=future_queue) |
85 | | - |
86 | | - |
87 | | -def execute_single_task( |
88 | | - task_dict: dict, |
89 | | - cores: int = 1, |
90 | | - spawner: type[BaseSpawner] = MpiExecSpawner, |
91 | | - hostname_localhost: Optional[bool] = None, |
92 | | - cache_directory: Optional[str] = None, |
93 | | - cache_key: Optional[str] = None, |
94 | | - log_obj_size: bool = False, |
95 | | - error_log_file: Optional[str] = None, |
96 | | - worker_id: Optional[int] = None, |
97 | | - **kwargs, |
98 | | -) -> None: |
99 | | - """ |
100 | | - Execute a single tasks in parallel using the message passing interface (MPI). |
101 | | -
|
102 | | - Args: |
103 | | - future_queue (queue.Queue): task queue of dictionary objects which are submitted to the parallel process |
104 | | - cores (int): defines the total number of MPI ranks to use |
105 | | - spawner (BaseSpawner): Spawner to start process on selected compute resources |
106 | | - hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the |
107 | | - context of an HPC cluster this essential to be able to communicate to an |
108 | | - Executor running on a different compute node within the same allocation. And |
109 | | - in principle any computer should be able to resolve that their own hostname |
110 | | - points to the same address as localhost. Still MacOS >= 12 seems to disable |
111 | | - this look up for security reasons. So on MacOS it is required to set this |
112 | | - option to true |
113 | | - init_function (Callable): optional function to preset arguments for functions which are submitted later |
114 | | - cache_directory (str, optional): The directory to store cache files. Defaults to "executorlib_cache". |
115 | | - cache_key (str, optional): By default the cache_key is generated based on the function hash, this can be |
116 | | - overwritten by setting the cache_key. |
117 | | - queue_join_on_shutdown (bool): Join communication queue when thread is closed. Defaults to True. |
118 | | - log_obj_size (bool): Enable debug mode which reports the size of the communicated objects. |
119 | | - error_log_file (str): Name of the error log file to use for storing exceptions raised by the Python functions |
120 | | - submitted to the Executor. |
121 | | - worker_id (int): Communicate the worker which ID was assigned to it for future reference and resource |
122 | | - distribution. |
123 | | - """ |
124 | | - _execute_task_dict( |
125 | | - task_dict=task_dict, |
126 | | - interface=interface_bootup( |
127 | | - command_lst=get_interactive_execute_command( |
128 | | - cores=cores, |
129 | | - ), |
130 | | - connections=spawner(cores=cores, **kwargs), |
131 | | - hostname_localhost=hostname_localhost, |
132 | | - log_obj_size=log_obj_size, |
133 | | - worker_id=worker_id, |
134 | | - ), |
135 | | - cache_directory=cache_directory, |
136 | | - cache_key=cache_key, |
137 | | - error_log_file=error_log_file, |
138 | | - ) |
139 | | - |
140 | | - |
141 | | -def _execute_task_dict( |
| 11 | +def execute_task_dict( |
142 | 12 | task_dict: dict, |
143 | 13 | interface: SocketInterface, |
144 | 14 | cache_directory: Optional[str] = None, |
@@ -171,6 +41,11 @@ def _execute_task_dict( |
171 | 41 | ) |
172 | 42 |
|
173 | 43 |
|
| 44 | +def task_done(future_queue: queue.Queue): |
| 45 | + with contextlib.suppress(ValueError): |
| 46 | + future_queue.task_done() |
| 47 | + |
| 48 | + |
174 | 49 | def _execute_task_without_cache(interface: SocketInterface, task_dict: dict): |
175 | 50 | """ |
176 | 51 | Execute the task in the task_dict by communicating it via the interface. |
@@ -233,8 +108,3 @@ def _execute_task_with_cache( |
233 | 108 | _, _, result = get_output(file_name=file_name) |
234 | 109 | future = task_dict["future"] |
235 | 110 | future.set_result(result) |
236 | | - |
237 | | - |
238 | | -def _task_done(future_queue: queue.Queue): |
239 | | - with contextlib.suppress(ValueError): |
240 | | - future_queue.task_done() |
0 commit comments