Skip to content

Commit 2d6666a

Browse files
authored
Documentation: Explain Interface Class Hierarchy (#633)
* Documentation: Explain Interface Class Hierarchy * fix table spacing
1 parent fb6a6c7 commit 2d6666a

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ as hierarchical job scheduler within the allocations.
156156
* [Pull Requests](https://executorlib.readthedocs.io/en/latest/4-developer.html#pull-requests)
157157
* [License](https://executorlib.readthedocs.io/en/latest/4-developer.html#license)
158158
* [Modules](https://executorlib.readthedocs.io/en/latest/4-developer.html#modules)
159+
* [Interface Class Hierarchy](https://executorlib.readthedocs.io/en/latest/4-developer.html#interface-class-hierarchy)
159160
* [Communication](https://executorlib.readthedocs.io/en/latest/4-developer.html#communication)
160161
* [External Executables](https://executorlib.readthedocs.io/en/latest/4-developer.html#external-executables)
161162
* [Interface](https://executorlib.readthedocs.io/en/latest/api.html)

notebooks/4-developer.ipynb

+29-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88
"language_info": {
99
"name": "python",
10-
"version": "3.12.9",
10+
"version": "3.12.10",
1111
"mimetype": "text/x-python",
1212
"codemirror_mode": {
1313
"name": "ipython",
@@ -77,7 +77,26 @@
7777
"* `interfaces` - the different `Executor` classes are defined here, namely `SingleNodeExecutor`, `SlurmClusterExecutor`, `SlurmJobExecutor`, `FluxClusterExecutor` and `FluxJobExecutor`.\n",
7878
"* `standalone` - the standalone module contains a number of utility functions which only depend on external libraries and do not have any internal dependency to other parts of `executorlib`. This includes the functionality to generate executable commands, the [h5py](https://www.h5py.org) based interface for caching, a number of input checks, routines to plot the dependencies of a number of future objects, functionality to interact with the [queues defined in the Python standard library](https://docs.python.org/3/library/queue.html), the interface for serialization based on [cloudpickle](https://github.com/cloudpipe/cloudpickle) and finally an extension to the [threading](https://docs.python.org/3/library/threading.html) of the Python standard library.\n",
7979
"\n",
80-
"Given the level of separation the integration of submodules from the standalone module in external software packages should be the easiest way to benefit from the developments in executorlib beyond just using the `Executor` class. "
80+
"Given the level of separation the integration of submodules from the standalone module in external software packages should be the easiest way to benefit from the developments in executorlib beyond just using the `Executor` class. \n",
81+
"\n",
82+
"## Interface Class Hierarchy\n",
83+
"executorlib provides five different interfaces, namely `SingleNodeExecutor`, `SlurmClusterExecutor`, `SlurmJobExecutor`, `FluxClusterExecutor` and `FluxJobExecutor`, internally these are mapped to four types of `Executor` classes, namely `BlockAllocationExecutor`, `DependencyExecutor`, `FileExecutor` and `OneTaskPerProcessExecutor` depending on which options are selected. The dependence is illustrated in the following table:\n",
84+
"\n",
85+
"| | `BlockAllocationExecutor` | `DependencyExecutor` | `FileExecutor` | `OneTaskPerProcessExecutor` |\n",
86+
"|-------------------------------------------------------------------------|---------------------------|--------------------------|----------------|-----------------------------|\n",
87+
"| `SingleNodeExecutor(disable_dependencies=False)` | | with `MpiExecSpawner` | | |\n",
88+
"| `SingleNodeExecutor(disable_dependencies=True, block_allocation=False)` | | | | with `MpiExecSpawner` |\n",
89+
"| `SingleNodeExecutor(disable_dependencies=True, block_allocation=True)` | with `MpiExecSpawner` | | | |\n",
90+
"| `SlurmClusterExecutor(plot_dependency_graph=False)` | | | with `pysqa` | |\n",
91+
"| `SlurmClusterExecutor(plot_dependency_graph=True)` | | with `SrunSpawner` | | |\n",
92+
"| `SlurmJobExecutor(disable_dependencies=False)` | | with `SrunSpawner` | | |\n",
93+
"| `SlurmJobExecutor(disable_dependencies=True, block_allocation=False)` | | | | with `SrunSpawner` |\n",
94+
"| `SlurmJobExecutor(disable_dependencies=True, block_allocation=True)` | with `SrunSpawner` | | | |\n",
95+
"| `FluxClusterExecutor(plot_dependency_graph=False)` | | | with `pysqa` | |\n",
96+
"| `FluxClusterExecutor(plot_dependency_graph=True)` | | with `FluxPythonSpawner` | | |\n",
97+
"| `FluxJobExecutor(disable_dependencies=False)` | | with `FluxPythonSpawner` | | |\n",
98+
"| `FluxJobExecutor(disable_dependencies=True, block_allocation=False)` | | | | with `FluxPythonSpawner` |\n",
99+
"| `FluxJobExecutor(disable_dependencies=True, block_allocation=True)` | with `FluxPythonSpawner` | | | |"
81100
],
82101
"metadata": {}
83102
},
@@ -110,7 +129,7 @@
110129
"cell_type": "code",
111130
"source": "from executorlib import SingleNodeExecutor",
112131
"metadata": {
113-
"trusted": true
132+
"trusted": false
114133
},
115134
"outputs": [],
116135
"execution_count": 1
@@ -120,7 +139,7 @@
120139
"cell_type": "code",
121140
"source": "def execute_shell_command(\n command: list, universal_newlines: bool = True, shell: bool = False\n):\n import subprocess\n\n return subprocess.check_output(\n command, universal_newlines=universal_newlines, shell=shell\n )",
122141
"metadata": {
123-
"trusted": true
142+
"trusted": false
124143
},
125144
"outputs": [],
126145
"execution_count": 2
@@ -130,7 +149,7 @@
130149
"cell_type": "code",
131150
"source": "with SingleNodeExecutor() as exe:\n future = exe.submit(\n execute_shell_command,\n [\"echo\", \"test\"],\n universal_newlines=True,\n shell=False,\n )\n print(future.result())",
132151
"metadata": {
133-
"trusted": true
152+
"trusted": false
134153
},
135154
"outputs": [
136155
{
@@ -152,7 +171,7 @@
152171
"cell_type": "code",
153172
"source": "count_script = \"\"\"\\\ndef count(iterations):\n for i in range(int(iterations)):\n print(i)\n print(\"done\")\n\n\nif __name__ == \"__main__\":\n while True:\n user_input = input()\n if \"shutdown\" in user_input:\n break\n else:\n count(iterations=int(user_input))\n\"\"\"\n\nwith open(\"count.py\", \"w\") as f:\n f.writelines(count_script)",
154173
"metadata": {
155-
"trusted": true
174+
"trusted": false
156175
},
157176
"outputs": [],
158177
"execution_count": 4
@@ -168,7 +187,7 @@
168187
"cell_type": "code",
169188
"source": "def init_process():\n import subprocess\n\n return {\n \"process\": subprocess.Popen(\n [\"python\", \"count.py\"],\n stdin=subprocess.PIPE,\n stdout=subprocess.PIPE,\n universal_newlines=True,\n shell=False,\n )\n }",
170189
"metadata": {
171-
"trusted": true
190+
"trusted": false
172191
},
173192
"outputs": [],
174193
"execution_count": 5
@@ -184,7 +203,7 @@
184203
"cell_type": "code",
185204
"source": "def interact(shell_input, process, lines_to_read=None, stop_read_pattern=None):\n process.stdin.write(shell_input)\n process.stdin.flush()\n lines_count = 0\n output = \"\"\n while True:\n output_current = process.stdout.readline()\n output += output_current\n lines_count += 1\n if stop_read_pattern is not None and stop_read_pattern in output_current:\n break\n elif lines_to_read is not None and lines_to_read == lines_count:\n break\n return output",
186205
"metadata": {
187-
"trusted": true
206+
"trusted": false
188207
},
189208
"outputs": [],
190209
"execution_count": 6
@@ -200,7 +219,7 @@
200219
"cell_type": "code",
201220
"source": "def shutdown(process):\n process.stdin.write(\"shutdown\\n\")\n process.stdin.flush()",
202221
"metadata": {
203-
"trusted": true
222+
"trusted": false
204223
},
205224
"outputs": [],
206225
"execution_count": 7
@@ -216,7 +235,7 @@
216235
"cell_type": "code",
217236
"source": "with SingleNodeExecutor(\n max_workers=1,\n init_function=init_process,\n block_allocation=True,\n) as exe:\n future = exe.submit(\n interact, shell_input=\"4\\n\", lines_to_read=5, stop_read_pattern=None\n )\n print(future.result())\n future_shutdown = exe.submit(shutdown)\n print(future_shutdown.result())",
218237
"metadata": {
219-
"trusted": true
238+
"trusted": false
220239
},
221240
"outputs": [
222241
{

0 commit comments

Comments
 (0)