executorlib 1.10.2__tar.gz → 1.10.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {executorlib-1.10.2 → executorlib-1.10.3}/PKG-INFO +10 -10
- {executorlib-1.10.2 → executorlib-1.10.3}/pyproject.toml +12 -10
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/__init__.py +29 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/_version.py +2 -2
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/interactive/communication.py +4 -2
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/serialize.py +16 -11
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/file/shared.py +27 -19
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/file/spawner_pysqa.py +56 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/blockallocation.py +31 -21
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/shared.py +33 -22
- {executorlib-1.10.2 → executorlib-1.10.3}/.gitignore +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/LICENSE +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/README.md +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/api.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/backend/__init__.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/backend/cache_parallel.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/backend/cache_serial.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/backend/interactive_parallel.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/backend/interactive_serial.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/executor/__init__.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/executor/base.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/executor/flux.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/executor/single.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/executor/slurm.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/__init__.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/batched.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/command.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/command_pysqa.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/error.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/hdf.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/inputcheck.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/interactive/__init__.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/interactive/arguments.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/interactive/backend.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/interactive/spawner.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/queue.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/select.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/validate.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/__init__.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/base.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/file/__init__.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/file/backend.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/file/spawner_subprocess.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/file/task_scheduler.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/__init__.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/dependency.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/dependency_plot.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/onetoone.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/spawner_flux.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/spawner_pysqa.py +0 -0
- {executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/spawner_slurm.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: executorlib
|
|
3
|
-
Version: 1.10.
|
|
3
|
+
Version: 1.10.3
|
|
4
4
|
Summary: Up-scale python functions for high performance computing (HPC) with executorlib.
|
|
5
5
|
Project-URL: Homepage, https://github.com/pyiron/executorlib
|
|
6
6
|
Project-URL: Documentation, https://executorlib.readthedocs.io
|
|
@@ -49,31 +49,31 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
49
49
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
50
50
|
Requires-Python: <3.15,>3.9
|
|
51
51
|
Requires-Dist: cloudpickle<=3.1.2,>=2.0.0
|
|
52
|
-
Requires-Dist: pyzmq<=27.
|
|
52
|
+
Requires-Dist: pyzmq<=27.2.0,>=25.0.0
|
|
53
53
|
Provides-Extra: all
|
|
54
54
|
Requires-Dist: h5py<=3.16.0,>=3.6.0; extra == 'all'
|
|
55
55
|
Requires-Dist: ipython<=9.9.0,>=7.33.0; extra == 'all'
|
|
56
56
|
Requires-Dist: mpi4py<=4.1.2,>=3.1.4; extra == 'all'
|
|
57
57
|
Requires-Dist: networkx<=3.6.1,>=2.8.8; extra == 'all'
|
|
58
|
-
Requires-Dist: pydantic<=2.13.
|
|
59
|
-
Requires-Dist: pygraphviz<=1
|
|
60
|
-
Requires-Dist: pysqa==0.
|
|
58
|
+
Requires-Dist: pydantic<=2.13.5,>=2.5.3; extra == 'all'
|
|
59
|
+
Requires-Dist: pygraphviz<=2.0.1,>=1.10; extra == 'all'
|
|
60
|
+
Requires-Dist: pysqa==1.0.0; extra == 'all'
|
|
61
61
|
Provides-Extra: cache
|
|
62
62
|
Requires-Dist: h5py<=3.16.0,>=3.6.0; extra == 'cache'
|
|
63
63
|
Provides-Extra: cluster
|
|
64
64
|
Requires-Dist: h5py<=3.16.0,>=3.6.0; extra == 'cluster'
|
|
65
|
-
Requires-Dist: pysqa==0.
|
|
65
|
+
Requires-Dist: pysqa==1.0.0; extra == 'cluster'
|
|
66
66
|
Provides-Extra: graph
|
|
67
67
|
Requires-Dist: networkx<=3.6.1,>=2.8.8; extra == 'graph'
|
|
68
|
-
Requires-Dist: pygraphviz<=1
|
|
68
|
+
Requires-Dist: pygraphviz<=2.0.1,>=1.10; extra == 'graph'
|
|
69
69
|
Provides-Extra: graphnotebook
|
|
70
70
|
Requires-Dist: ipython<=9.9.0,>=7.33.0; extra == 'graphnotebook'
|
|
71
71
|
Requires-Dist: networkx<=3.6.1,>=2.8.8; extra == 'graphnotebook'
|
|
72
|
-
Requires-Dist: pygraphviz<=1
|
|
72
|
+
Requires-Dist: pygraphviz<=2.0.1,>=1.10; extra == 'graphnotebook'
|
|
73
73
|
Provides-Extra: mpi
|
|
74
74
|
Requires-Dist: mpi4py<=4.1.2,>=3.1.4; extra == 'mpi'
|
|
75
75
|
Provides-Extra: validation
|
|
76
|
-
Requires-Dist: pydantic<=2.13.
|
|
76
|
+
Requires-Dist: pydantic<=2.13.5,>=2.5.3; extra == 'validation'
|
|
77
77
|
Description-Content-Type: text/markdown
|
|
78
78
|
|
|
79
79
|
# executorlib
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
requires = [
|
|
3
|
-
"hatchling>=1.27.0,<=1.
|
|
3
|
+
"hatchling>=1.27.0,<=1.32.0",
|
|
4
4
|
"hatch-vcs==0.5.0",
|
|
5
5
|
"cloudpickle>=2.0.0,<=3.1.2",
|
|
6
|
-
"pyzmq>=25.0.0,<=27.
|
|
6
|
+
"pyzmq>=25.0.0,<=27.2.0",
|
|
7
7
|
]
|
|
8
8
|
build-backend = "hatchling.build"
|
|
9
9
|
|
|
@@ -31,7 +31,7 @@ classifiers = [
|
|
|
31
31
|
]
|
|
32
32
|
dependencies = [
|
|
33
33
|
"cloudpickle>=2.0.0,<=3.1.2",
|
|
34
|
-
"pyzmq>=25.0.0,<=27.
|
|
34
|
+
"pyzmq>=25.0.0,<=27.2.0",
|
|
35
35
|
]
|
|
36
36
|
dynamic = ["version"]
|
|
37
37
|
|
|
@@ -43,28 +43,28 @@ Repository = "https://github.com/pyiron/executorlib"
|
|
|
43
43
|
[project.optional-dependencies]
|
|
44
44
|
cache = ["h5py>=3.6.0,<=3.16.0"]
|
|
45
45
|
graph = [
|
|
46
|
-
"pygraphviz>=1.10,<=1
|
|
46
|
+
"pygraphviz>=1.10,<=2.0.1",
|
|
47
47
|
"networkx>=2.8.8,<=3.6.1",
|
|
48
48
|
]
|
|
49
49
|
graphnotebook = [
|
|
50
|
-
"pygraphviz>=1.10,<=1
|
|
50
|
+
"pygraphviz>=1.10,<=2.0.1",
|
|
51
51
|
"networkx>=2.8.8,<=3.6.1",
|
|
52
52
|
"ipython>=7.33.0,<=9.9.0",
|
|
53
53
|
]
|
|
54
54
|
mpi = ["mpi4py>=3.1.4,<=4.1.2"]
|
|
55
55
|
cluster = [
|
|
56
|
-
"pysqa==0.
|
|
56
|
+
"pysqa==1.0.0",
|
|
57
57
|
"h5py>=3.6.0,<=3.16.0",
|
|
58
58
|
]
|
|
59
59
|
validation = [
|
|
60
|
-
"pydantic>=2.5.3,<=2.13.
|
|
60
|
+
"pydantic>=2.5.3,<=2.13.5",
|
|
61
61
|
]
|
|
62
62
|
all = [
|
|
63
63
|
"mpi4py>=3.1.4,<=4.1.2",
|
|
64
|
-
"pysqa==0.
|
|
64
|
+
"pysqa==1.0.0",
|
|
65
65
|
"h5py>=3.6.0,<=3.16.0",
|
|
66
|
-
"pydantic>=2.5.3,<=2.13.
|
|
67
|
-
"pygraphviz>=1.10,<=1
|
|
66
|
+
"pydantic>=2.5.3,<=2.13.5",
|
|
67
|
+
"pygraphviz>=1.10,<=2.0.1",
|
|
68
68
|
"networkx>=2.8.8,<=3.6.1",
|
|
69
69
|
"ipython>=7.33.0,<=9.9.0",
|
|
70
70
|
]
|
|
@@ -102,6 +102,8 @@ ignore = [
|
|
|
102
102
|
"PLR0912",
|
|
103
103
|
# Too many arguments in function definition
|
|
104
104
|
"PLR0913",
|
|
105
|
+
# Too many statements
|
|
106
|
+
"PLR0915",
|
|
105
107
|
# Too many not-keyword-only arguments,
|
|
106
108
|
"PLR0917",
|
|
107
109
|
# Magic value used in comparison
|
|
@@ -44,6 +44,35 @@ def get_cache_data(cache_directory: str) -> list[dict]:
|
|
|
44
44
|
return get_cache_data(cache_directory=cache_directory)
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
def get_cache_data_queue(
|
|
48
|
+
cache_directory: str,
|
|
49
|
+
queue_type: Optional[str] = None,
|
|
50
|
+
config_directory: Optional[str] = None,
|
|
51
|
+
) -> list[dict]:
|
|
52
|
+
"""
|
|
53
|
+
Collect all HDF5 files in the cache directory and check their status in the queue system
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
cache_directory (str): The directory to store cache files.
|
|
57
|
+
queue_type (str, optional): The type of the queue system ["slurm", "flux"].
|
|
58
|
+
config_directory (str, optional): The directory containing the configuration for the queue system.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
list[dict]: List of dictionaries each representing on of the HDF5 files in the
|
|
62
|
+
cache directory with their status in the queue system.
|
|
63
|
+
"""
|
|
64
|
+
from executorlib.standalone.hdf import get_cache_data
|
|
65
|
+
from executorlib.task_scheduler.file.spawner_pysqa import (
|
|
66
|
+
get_queue_system_cache_data,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
return get_queue_system_cache_data(
|
|
70
|
+
cache_dict=get_cache_data(cache_directory=cache_directory),
|
|
71
|
+
queue_type=queue_type,
|
|
72
|
+
config_directory=config_directory,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
47
76
|
def get_future_from_cache(
|
|
48
77
|
cache_directory: str,
|
|
49
78
|
cache_key: str,
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.10.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 10,
|
|
21
|
+
__version__ = version = '1.10.3'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 10, 3)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/interactive/communication.py
RENAMED
|
@@ -150,9 +150,11 @@ class SocketInterface:
|
|
|
150
150
|
"""
|
|
151
151
|
result = None
|
|
152
152
|
if self._spawner.poll():
|
|
153
|
-
|
|
153
|
+
output = self.send_and_receive_dict(
|
|
154
154
|
input_dict={"shutdown": True, "wait": wait}
|
|
155
|
-
)
|
|
155
|
+
)
|
|
156
|
+
if "result" in output:
|
|
157
|
+
result = output["result"]
|
|
156
158
|
self._spawner.shutdown(wait=wait)
|
|
157
159
|
self._reset_socket()
|
|
158
160
|
return result
|
|
@@ -34,7 +34,7 @@ def serialize_funct(
|
|
|
34
34
|
fn_kwargs: Optional[dict] = None,
|
|
35
35
|
resource_dict: Optional[dict] = None,
|
|
36
36
|
cache_key: Optional[str] = None,
|
|
37
|
-
) -> tuple[str, dict]:
|
|
37
|
+
) -> tuple[str, dict, Optional[Exception]]:
|
|
38
38
|
"""
|
|
39
39
|
Serialize a function and its arguments and keyword arguments into an HDF5 file.
|
|
40
40
|
|
|
@@ -56,7 +56,8 @@ def serialize_funct(
|
|
|
56
56
|
overwritten by setting the cache_key.
|
|
57
57
|
|
|
58
58
|
Returns:
|
|
59
|
-
Tuple[str, dict]: A tuple containing the task key
|
|
59
|
+
Tuple[str, dict, Optional[Exception]]: A tuple containing the task key, the serialized data and an
|
|
60
|
+
exception if the serialization failed.
|
|
60
61
|
|
|
61
62
|
"""
|
|
62
63
|
if fn_args is None:
|
|
@@ -68,21 +69,25 @@ def serialize_funct(
|
|
|
68
69
|
if cache_key is not None:
|
|
69
70
|
task_key = cache_key
|
|
70
71
|
else:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
try:
|
|
73
|
+
binary_all = cloudpickle.dumps(
|
|
74
|
+
{
|
|
75
|
+
"fn": fn,
|
|
76
|
+
"args": fn_args,
|
|
77
|
+
"kwargs": fn_kwargs,
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
except Exception as e:
|
|
81
|
+
return "", {}, e
|
|
82
|
+
else:
|
|
83
|
+
task_key = _get_function_name(fn=fn) + _get_hash(binary=binary_all)
|
|
79
84
|
data = {
|
|
80
85
|
"fn": fn,
|
|
81
86
|
"args": fn_args,
|
|
82
87
|
"kwargs": fn_kwargs,
|
|
83
88
|
"resource_dict": resource_dict,
|
|
84
89
|
}
|
|
85
|
-
return task_key, data
|
|
90
|
+
return task_key, data, None
|
|
86
91
|
|
|
87
92
|
|
|
88
93
|
def _get_hash(binary: bytes) -> str:
|
|
@@ -129,7 +129,7 @@ def execute_tasks_h5(
|
|
|
129
129
|
executor_kwargs=executor_kwargs,
|
|
130
130
|
)
|
|
131
131
|
)
|
|
132
|
-
task_key, data_dict = serialize_funct(
|
|
132
|
+
task_key, data_dict, serialize_exception = serialize_funct(
|
|
133
133
|
fn=task_dict["fn"],
|
|
134
134
|
fn_args=task_args,
|
|
135
135
|
fn_kwargs=task_kwargs,
|
|
@@ -137,7 +137,9 @@ def execute_tasks_h5(
|
|
|
137
137
|
cache_key=cache_key,
|
|
138
138
|
)
|
|
139
139
|
data_dict["error_log_file"] = error_log_file
|
|
140
|
-
if
|
|
140
|
+
if serialize_exception is not None:
|
|
141
|
+
task_dict["future"].set_exception(serialize_exception)
|
|
142
|
+
elif task_key not in memory_dict:
|
|
141
143
|
if os.path.join(
|
|
142
144
|
cache_directory, task_key + "_o.h5"
|
|
143
145
|
) not in get_cache_files(cache_directory=cache_directory):
|
|
@@ -156,25 +158,31 @@ def execute_tasks_h5(
|
|
|
156
158
|
)
|
|
157
159
|
)
|
|
158
160
|
task_dependent_lst = []
|
|
159
|
-
|
|
160
|
-
|
|
161
|
+
try:
|
|
162
|
+
process_dict[task_key] = execute_function(
|
|
163
|
+
command=get_cache_execute_command(
|
|
164
|
+
file_name=file_name,
|
|
165
|
+
cores=task_resource_dict["cores"],
|
|
166
|
+
backend=backend,
|
|
167
|
+
exclusive=task_resource_dict.get("exclusive", False),
|
|
168
|
+
openmpi_oversubscribe=task_resource_dict.get(
|
|
169
|
+
"openmpi_oversubscribe", False
|
|
170
|
+
),
|
|
171
|
+
pmi_mode=pmi_mode,
|
|
172
|
+
),
|
|
161
173
|
file_name=file_name,
|
|
162
|
-
|
|
174
|
+
data_dict=data_dict,
|
|
175
|
+
task_dependent_lst=task_dependent_lst,
|
|
176
|
+
resource_dict=task_resource_dict,
|
|
177
|
+
config_directory=pysqa_config_directory,
|
|
163
178
|
backend=backend,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
data_dict=data_dict,
|
|
172
|
-
task_dependent_lst=task_dependent_lst,
|
|
173
|
-
resource_dict=task_resource_dict,
|
|
174
|
-
config_directory=pysqa_config_directory,
|
|
175
|
-
backend=backend,
|
|
176
|
-
cache_directory=cache_directory,
|
|
177
|
-
)
|
|
179
|
+
cache_directory=cache_directory,
|
|
180
|
+
)
|
|
181
|
+
except Exception as e:
|
|
182
|
+
task_dict["future"].set_exception(e)
|
|
183
|
+
memory_dict[task_key] = task_dict["future"]
|
|
184
|
+
future_queue.task_done()
|
|
185
|
+
continue
|
|
178
186
|
file_name = os.path.join(cache_directory, task_key + "_o.h5")
|
|
179
187
|
file_name_dict[task_key] = file_name
|
|
180
188
|
queue_id = get_queue_id(file_name=file_name)
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/file/spawner_pysqa.py
RENAMED
|
@@ -2,6 +2,7 @@ import os
|
|
|
2
2
|
from subprocess import CalledProcessError
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
5
|
+
from pandas import DataFrame
|
|
5
6
|
from pysqa import QueueAdapter
|
|
6
7
|
|
|
7
8
|
from executorlib.standalone.command_pysqa import pysqa_execute_command, pysqa_terminate
|
|
@@ -154,3 +155,58 @@ def terminate_task_in_cache(
|
|
|
154
155
|
backend=backend,
|
|
155
156
|
)
|
|
156
157
|
os.remove(file_name)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def get_queue_system_cache_data(
|
|
161
|
+
cache_dict: list[dict],
|
|
162
|
+
queue_type: Optional[str] = None,
|
|
163
|
+
config_directory: Optional[str] = None,
|
|
164
|
+
) -> list[dict]:
|
|
165
|
+
"""
|
|
166
|
+
Get the status of the queue system.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
cache_dict (list[dict]): List of dictionaries each representing on of the HDF5 files in the cache directory.
|
|
170
|
+
queue_type (str, optional): The type of the queue system ["slurm", "flux"].
|
|
171
|
+
config_directory (str, optional): The directory containing the configuration for the queue system.
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
cache_dict (list[dict]): List of dictionaries each representing on of the HDF5 files in the cache directory.
|
|
175
|
+
"""
|
|
176
|
+
return _merge_cache_with_queue_status(
|
|
177
|
+
cache_dict=cache_dict,
|
|
178
|
+
dataframe=QueueAdapter(
|
|
179
|
+
directory=config_directory,
|
|
180
|
+
queue_type=queue_type,
|
|
181
|
+
).get_queue_status(),
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _merge_cache_with_queue_status(
|
|
186
|
+
cache_dict: list[dict], dataframe: DataFrame
|
|
187
|
+
) -> list[dict]:
|
|
188
|
+
"""
|
|
189
|
+
Merge the cache data with the queue status.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
cache_dict (list[dict]): List of dictionaries each representing on of the HDF5 files in the cache directory.
|
|
193
|
+
dataframe (DataFrame): DataFrame containing the status of the queue system.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
cache_dict (list[dict]): List of dictionaries each representing on of the HDF5 files in the cache directory.
|
|
197
|
+
"""
|
|
198
|
+
cache_updated_dict = []
|
|
199
|
+
for row in cache_dict:
|
|
200
|
+
if "output" in row and row["output"]:
|
|
201
|
+
row["status"] = "finished"
|
|
202
|
+
elif "queue_id" in row and row["queue_id"] in dataframe["jobid"].values:
|
|
203
|
+
row["status"] = dataframe[dataframe["jobid"] == row["queue_id"]][
|
|
204
|
+
"status"
|
|
205
|
+
].values[-1]
|
|
206
|
+
elif "queue_id" not in row:
|
|
207
|
+
row["status"] = "running"
|
|
208
|
+
else:
|
|
209
|
+
row["status"] = "aborted"
|
|
210
|
+
cache_updated_dict.append(row)
|
|
211
|
+
|
|
212
|
+
return cache_updated_dict
|
|
@@ -80,35 +80,37 @@ class BlockAllocationTaskScheduler(TaskSchedulerBase):
|
|
|
80
80
|
executor_kwargs["restart_limit"] = restart_limit
|
|
81
81
|
self._process_kwargs = executor_kwargs
|
|
82
82
|
self._max_workers = max_workers
|
|
83
|
-
|
|
84
|
-
self._self_id = self_id
|
|
83
|
+
self._self_id = random.getrandbits(128)
|
|
85
84
|
_interrupt_bootup_dict[self._self_id] = False
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
self._alive_workers = [max_workers]
|
|
86
|
+
self._alive_workers_lock = Lock()
|
|
87
|
+
self._bootup_events = [Event() for _ in range(self._max_workers)]
|
|
88
|
+
self._bootup_events[0].set()
|
|
90
89
|
self._set_process(
|
|
91
90
|
process=[
|
|
92
91
|
Thread(
|
|
93
92
|
target=_execute_multiple_tasks,
|
|
94
|
-
kwargs=
|
|
95
|
-
| {
|
|
96
|
-
"worker_id": worker_id,
|
|
97
|
-
"stop_function": lambda: _interrupt_bootup_dict[self_id],
|
|
98
|
-
"bootup_event": bootup_events[worker_id],
|
|
99
|
-
"next_bootup_event": (
|
|
100
|
-
bootup_events[worker_id + 1]
|
|
101
|
-
if worker_id + 1 < self._max_workers
|
|
102
|
-
else None
|
|
103
|
-
),
|
|
104
|
-
"alive_workers": alive_workers,
|
|
105
|
-
"alive_workers_lock": alive_workers_lock,
|
|
106
|
-
},
|
|
93
|
+
kwargs=self._worker_kwargs(worker_id),
|
|
107
94
|
)
|
|
108
95
|
for worker_id in range(self._max_workers)
|
|
109
96
|
],
|
|
110
97
|
)
|
|
111
98
|
|
|
99
|
+
def _worker_kwargs(self, worker_id: int) -> dict:
|
|
100
|
+
self_id = self._self_id
|
|
101
|
+
return self._process_kwargs | {
|
|
102
|
+
"worker_id": worker_id,
|
|
103
|
+
"stop_function": lambda: _interrupt_bootup_dict[self_id],
|
|
104
|
+
"bootup_event": self._bootup_events[worker_id],
|
|
105
|
+
"next_bootup_event": (
|
|
106
|
+
self._bootup_events[worker_id + 1]
|
|
107
|
+
if worker_id + 1 < len(self._bootup_events)
|
|
108
|
+
else None
|
|
109
|
+
),
|
|
110
|
+
"alive_workers": self._alive_workers,
|
|
111
|
+
"alive_workers_lock": self._alive_workers_lock,
|
|
112
|
+
}
|
|
113
|
+
|
|
112
114
|
@property
|
|
113
115
|
def max_workers(self) -> int:
|
|
114
116
|
return self._max_workers
|
|
@@ -126,12 +128,20 @@ class BlockAllocationTaskScheduler(TaskSchedulerBase):
|
|
|
126
128
|
process for process in self._process if process.is_alive()
|
|
127
129
|
]
|
|
128
130
|
elif self._max_workers < max_workers:
|
|
131
|
+
old_max_workers = self._max_workers
|
|
132
|
+
self._bootup_events.extend(
|
|
133
|
+
Event() for _ in range(max_workers - old_max_workers)
|
|
134
|
+
)
|
|
135
|
+
for idx in range(old_max_workers, max_workers):
|
|
136
|
+
self._bootup_events[idx].set()
|
|
137
|
+
with self._alive_workers_lock:
|
|
138
|
+
self._alive_workers[0] += max_workers - old_max_workers
|
|
129
139
|
new_process_lst = [
|
|
130
140
|
Thread(
|
|
131
141
|
target=_execute_multiple_tasks,
|
|
132
|
-
kwargs=self.
|
|
142
|
+
kwargs=self._worker_kwargs(worker_id),
|
|
133
143
|
)
|
|
134
|
-
for
|
|
144
|
+
for worker_id in range(old_max_workers, max_workers)
|
|
135
145
|
]
|
|
136
146
|
for process_instance in new_process_lst:
|
|
137
147
|
process_instance.start()
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/shared.py
RENAMED
|
@@ -101,13 +101,17 @@ def _execute_task_without_cache(
|
|
|
101
101
|
Returns:
|
|
102
102
|
bool: True if the task was submitted successfully, False otherwise.
|
|
103
103
|
"""
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return False
|
|
104
|
+
try:
|
|
105
|
+
output = interface.send_and_receive_dict(input_dict=task_dict)
|
|
106
|
+
except Exception as e:
|
|
107
|
+
future_obj.set_exception(exception=e)
|
|
109
108
|
else:
|
|
110
|
-
|
|
109
|
+
if "result" in output:
|
|
110
|
+
future_obj.set_result(output["result"])
|
|
111
|
+
elif isinstance(output["error"], ExecutorlibSocketError):
|
|
112
|
+
return False
|
|
113
|
+
else:
|
|
114
|
+
future_obj.set_exception(exception=output["error"])
|
|
111
115
|
return True
|
|
112
116
|
|
|
113
117
|
|
|
@@ -132,27 +136,34 @@ def _execute_task_with_cache(
|
|
|
132
136
|
"""
|
|
133
137
|
from executorlib.standalone.hdf import dump, get_cache_files, get_output
|
|
134
138
|
|
|
135
|
-
task_key, data_dict = serialize_funct(
|
|
139
|
+
task_key, data_dict, serialize_exception = serialize_funct(
|
|
136
140
|
fn=task_dict["fn"],
|
|
137
141
|
fn_args=task_dict["args"],
|
|
138
142
|
fn_kwargs=task_dict["kwargs"],
|
|
139
143
|
resource_dict=task_dict.get("resource_dict", {}),
|
|
140
144
|
cache_key=cache_key,
|
|
141
145
|
)
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
time_start = time.time()
|
|
145
|
-
output = interface.send_and_receive_dict(input_dict=task_dict)
|
|
146
|
-
if "result" in output:
|
|
147
|
-
data_dict["output"] = output["result"]
|
|
148
|
-
data_dict["runtime"] = time.time() - time_start
|
|
149
|
-
dump(file_name=file_name, data_dict=data_dict)
|
|
150
|
-
future_obj.set_result(output["result"])
|
|
151
|
-
elif isinstance(output["error"], ExecutorlibSocketError):
|
|
152
|
-
return False
|
|
153
|
-
else:
|
|
154
|
-
future_obj.set_exception(exception=output["error"])
|
|
146
|
+
if serialize_exception is not None:
|
|
147
|
+
future_obj.set_exception(exception=serialize_exception)
|
|
155
148
|
else:
|
|
156
|
-
|
|
157
|
-
|
|
149
|
+
file_name = os.path.abspath(os.path.join(cache_directory, task_key + "_o.h5"))
|
|
150
|
+
if file_name not in get_cache_files(cache_directory=cache_directory):
|
|
151
|
+
time_start = time.time()
|
|
152
|
+
try:
|
|
153
|
+
output = interface.send_and_receive_dict(input_dict=task_dict)
|
|
154
|
+
except Exception as e:
|
|
155
|
+
future_obj.set_exception(exception=e)
|
|
156
|
+
return True
|
|
157
|
+
if "result" in output:
|
|
158
|
+
data_dict["output"] = output["result"]
|
|
159
|
+
data_dict["runtime"] = time.time() - time_start
|
|
160
|
+
dump(file_name=file_name, data_dict=data_dict)
|
|
161
|
+
future_obj.set_result(output["result"])
|
|
162
|
+
elif isinstance(output["error"], ExecutorlibSocketError):
|
|
163
|
+
return False
|
|
164
|
+
else:
|
|
165
|
+
future_obj.set_exception(exception=output["error"])
|
|
166
|
+
else:
|
|
167
|
+
_, _, result = get_output(file_name=file_name)
|
|
168
|
+
future_obj.set_result(result)
|
|
158
169
|
return True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/interactive/__init__.py
RENAMED
|
File without changes
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/standalone/interactive/arguments.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/file/spawner_subprocess.py
RENAMED
|
File without changes
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/file/task_scheduler.py
RENAMED
|
File without changes
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/__init__.py
RENAMED
|
File without changes
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/dependency.py
RENAMED
|
File without changes
|
|
File without changes
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/onetoone.py
RENAMED
|
File without changes
|
{executorlib-1.10.2 → executorlib-1.10.3}/src/executorlib/task_scheduler/interactive/spawner_flux.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|