Skip to content

Commit be64527

Browse files
authored
Store metadata only once for array jobs (#1042)
* store metadata only once for array jobs * remove todo comments * fix typo * add troubleshooting comment to clustertools/readme * use metadata instead of meta_data everywhere * update changelog
1 parent f902584 commit be64527

File tree

4 files changed

+29
-23
lines changed

4 files changed

+29
-23
lines changed

cluster_tools/Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ For upgrade instructions, please check the respective *Breaking Changes* section
1414
### Added
1515

1616
### Changed
17+
- Array jobs are spawned faster now, because common meta data is not serialized for each subjob. The performance improvement is especially big, when custom logging code is configured for array jobs. [#1042](https://github.com/scalableminds/webknossos-libs/pull/1042)
1718
- Updated ruff to v0.4.0 [1047](https://github.com/scalableminds/webknossos-libs/pull/1047)
1819

1920
### Fixed

cluster_tools/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ If you would like to configure these limits independently, you can do so by sett
7474
## Dev Setup
7575

7676
```
77+
# See ./dockered-slurm/README.md for troubleshooting
7778
cd dockered-slurm
7879
docker-compose up -d
7980
docker exec -it slurmctld bash

cluster_tools/cluster_tools/remote.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,14 @@ def worker(
6363
custom_main_path = get_custom_main_path(workerid, executor)
6464
with open(input_file_name, "rb") as f:
6565
unpickled_tuple = pickling.load(f, custom_main_path)
66-
if len(unpickled_tuple) == 4:
67-
fun, args, kwargs, meta_data = unpickled_tuple
68-
output_pickle_path = executor.format_outfile_name(
69-
cfut_dir, workerid_with_idx
70-
)
71-
else:
72-
assert len(unpickled_tuple) == 5, "Unexpected encoding"
73-
fun, args, kwargs, meta_data, output_pickle_path = unpickled_tuple
74-
75-
if isinstance(fun, str):
76-
with open(fun, "rb") as function_file:
77-
fun = pickling.load(function_file, custom_main_path)
66+
assert len(unpickled_tuple) == 4, "Unexpected encoding"
67+
fun_and_metadata, args, kwargs, output_pickle_path = unpickled_tuple
68+
69+
if isinstance(fun_and_metadata, str):
70+
with open(fun_and_metadata, "rb") as function_file:
71+
fun, meta_data = pickling.load(function_file, custom_main_path)
72+
else:
73+
fun, meta_data = fun_and_metadata
7874

7975
setup_logging(meta_data, executor, cfut_dir)
8076

cluster_tools/cluster_tools/schedulers/cluster_executor.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,14 @@ def __init__(
148148
partial(_handle_kill_through_weakref, ref(self), existing_sigint_handler),
149149
)
150150

151-
self.meta_data = {}
151+
self.metadata = {}
152152
assert not (
153153
"logging_config" in kwargs and "logging_setup_fn" in kwargs
154154
), "Specify either logging_config OR logging_setup_fn but not both at once"
155155
if "logging_config" in kwargs:
156-
self.meta_data["logging_config"] = kwargs["logging_config"]
156+
self.metadata["logging_config"] = kwargs["logging_config"]
157157
if "logging_setup_fn" in kwargs:
158-
self.meta_data["logging_setup_fn"] = kwargs["logging_setup_fn"]
158+
self.metadata["logging_setup_fn"] = kwargs["logging_setup_fn"]
159159

160160
@classmethod
161161
def as_completed(cls, futs: List["Future[_T]"]) -> Iterator["Future[_T]"]:
@@ -412,7 +412,7 @@ def submit( # type: ignore[override]
412412

413413
# Start the job.
414414
serialized_function_info = pickling.dumps(
415-
(__fn, args, kwargs, self.meta_data, output_pickle_path)
415+
((__fn, self.metadata), args, kwargs, output_pickle_path)
416416
)
417417
with open(self.format_infile_name(self.cfut_dir, workerid), "wb") as f:
418418
f.write(serialized_function_info)
@@ -451,9 +451,10 @@ def get_workerid_with_index(cls, workerid: str, index: Union[int, str]) -> str:
451451
def get_jobid_with_index(cls, jobid: Union[str, int], index: int) -> str:
452452
return f"{jobid}_{index}"
453453

454-
def get_function_pickle_path(self, workerid: str) -> str:
454+
def get_function_and_metadata_pickle_path(self, workerid: str) -> str:
455455
return self.format_infile_name(
456-
self.cfut_dir, self.get_workerid_with_index(workerid, "function")
456+
self.cfut_dir,
457+
self.get_workerid_with_index(workerid, "function-and-metadata"),
457458
)
458459

459460
@staticmethod
@@ -484,10 +485,12 @@ def map_to_futures(
484485
futs_with_output_paths = []
485486
workerid = random_string()
486487

487-
pickled_function_path = self.get_function_pickle_path(workerid)
488-
self.files_to_clean_up.append(pickled_function_path)
489-
with open(pickled_function_path, "wb") as file:
490-
pickling.dump(fn, file)
488+
pickled_function_and_metadata_path = self.get_function_and_metadata_pickle_path(
489+
workerid
490+
)
491+
self.files_to_clean_up.append(pickled_function_and_metadata_path)
492+
with open(pickled_function_and_metadata_path, "wb") as file:
493+
pickling.dump((fn, self.metadata), file)
491494
self.store_main_path_to_meta_file(workerid)
492495

493496
for index, arg in enumerate(args):
@@ -511,7 +514,12 @@ def map_to_futures(
511514
os.unlink(preliminary_output_pickle_path)
512515

513516
serialized_function_info = pickling.dumps(
514-
(pickled_function_path, [arg], {}, self.meta_data, output_pickle_path)
517+
(
518+
pickled_function_and_metadata_path,
519+
[arg],
520+
{},
521+
output_pickle_path,
522+
)
515523
)
516524
infile_name = self.format_infile_name(self.cfut_dir, workerid_with_index)
517525

0 commit comments

Comments
 (0)