Skip to content

Commit 710b7a8

Browse files
authored
Merge pull request #1640 from Libensemble/asktell/only_persistent_is_default
start_only_persistent alloc_f is now the default alloc
2 parents 4a3cb6a + 5f74f54 commit 710b7a8

113 files changed

Lines changed: 539 additions & 570 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ repos:
3737
rev: v1.19.1
3838
hooks:
3939
- id: mypy
40+
exclude: ^libensemble/utils/(launcher|loc_stack|runners|pydantic|output_directory)\.py$|^libensemble/tests/regression_tests/support\.py$|^libensemble/tests/functionality_tests/

docs/data_structures/alloc_specs.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Can be constructed and passed to libEnsemble as a Python class or a dictionary.
1919
* libEnsemble uses the following defaults if the user doesn't provide their own ``alloc_specs``:
2020

2121
.. literalinclude:: ../../libensemble/specs.py
22-
:start-at: alloc_f: Callable = give_sim_work_first
22+
:start-at: alloc_f: Callable = start_only_persistent
2323
:end-before: end_alloc_tag
2424
:caption: Default settings for alloc_specs
2525

docs/examples/alloc_funcs.rst

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,31 @@ Many users use these unmodified.
1010
.. IMPORTANT::
1111
See the API for allocation functions :ref:`here<api_alloc_f>`.
1212

13+
**The default allocation function changed in libEnsemble v2.0 from `give_sim_work_first` to `start_only_persistent `.**
14+
1315
.. note::
14-
The default allocation function (for non-persistent generators) is :ref:`give_sim_work_first<gswf_label>`.
1516

16-
The most commonly used (for persistent generators) is :ref:`start_only_persistent<start_only_persistent_label>`.
17+
The default allocation function for persistent generators is :ref:`start_only_persistent<start_only_persistent_label>`.
18+
19+
The most commonly used allocation function for non-persistent generators is :ref:`give_sim_work_first<gswf_label>`.
1720

1821
.. role:: underline
1922
:class: underline
2023

24+
.. _start_only_persistent_label:
25+
26+
start_only_persistent
27+
---------------------
28+
.. automodule:: start_only_persistent
29+
:members:
30+
:undoc-members:
31+
32+
.. dropdown:: :underline:`start_only_persistent.py`
33+
34+
.. literalinclude:: ../../libensemble/alloc_funcs/start_only_persistent.py
35+
:language: python
36+
:linenos:
37+
2138
.. _gswf_label:
2239

2340
give_sim_work_first
@@ -44,20 +61,6 @@ fast_alloc
4461
:language: python
4562
:linenos:
4663

47-
.. _start_only_persistent_label:
48-
49-
start_only_persistent
50-
---------------------
51-
.. automodule:: start_only_persistent
52-
:members:
53-
:undoc-members:
54-
55-
.. dropdown:: :underline:`start_only_persistent.py`
56-
57-
.. literalinclude:: ../../libensemble/alloc_funcs/start_only_persistent.py
58-
:language: python
59-
:linenos:
60-
6164
start_persistent_local_opt_gens
6265
-------------------------------
6366
.. automodule:: start_persistent_local_opt_gens

docs/function_guides/allocator.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ The remaining values above are useful for efficient filtering of H values
128128

129129
Descriptions of included allocation functions can be found :doc:`here<../examples/alloc_funcs>`.
130130
The default allocation function is
131-
``give_sim_work_first``. During its worker ID loop, it checks if there's unallocated
131+
``start_only_persistent``. During its worker ID loop, it checks if there's unallocated
132132
work and assigns simulations for that work. Otherwise, it initializes
133133
generators for up to ``"num_active_gens"`` instances. Other settings like
134134
``batch_mode`` are also supported. See
135-
:ref:`here<gswf_label>` for more information about ``give_sim_work_first``.
135+
:ref:`here<start_only_persistent_label>` for more information.

docs/tutorials/calib_cancel_tutorial.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,9 @@ The allocation function used in this example is the *only_persistent_gens* funct
151151
152152
alloc_specs = {
153153
"alloc_f": alloc_f,
154-
"user": {
155-
"init_sample_size": init_sample_size,
156-
"async_return": True,
157-
"active_recv_gen": True,
158-
},
154+
"initial_batch_size": init_sample_size,
155+
"async_return": True,
156+
"active_recv_gen": True,
159157
}
160158
161159
**async_return** tells the allocation function to return results to the generator as soon

libensemble/alloc_funcs/fast_alloc.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def give_sim_work_first(W, H, sim_specs, gen_specs, alloc_specs, persis_info, li
77
to evaluate in the simulation function. The fields in ``sim_specs["in"]``
88
are given. If all entries in `H` have been given a be evaluated, a worker
99
is told to call the generator function, provided this wouldn't result in
10-
more than ``alloc_specs["user"]["num_active_gen"]`` active generators.
10+
more than ``gen_specs["num_active_gens"]`` or ``alloc_specs["user"]["num_active_gens"]`` active generators.
1111
1212
This fast_alloc variation of give_sim_work_first is useful for cases that
1313
simply iterate through H, issuing evaluations in order and, in particular,
@@ -23,7 +23,8 @@ def give_sim_work_first(W, H, sim_specs, gen_specs, alloc_specs, persis_info, li
2323
if libE_info["sim_max_given"] or not libE_info["any_idle_workers"]:
2424
return {}, persis_info
2525

26-
user = alloc_specs.get("user", {})
26+
user = {**gen_specs, **alloc_specs.get("user", {})}
27+
2728
manage_resources = libE_info["use_resource_sets"]
2829

2930
support = AllocSupport(W, manage_resources, persis_info, libE_info)

libensemble/alloc_funcs/fast_alloc_and_pausing.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@ def give_sim_work_first(W, H, sim_specs, gen_specs, alloc_specs, persis_info, li
2828
if libE_info["sim_max_given"] or not libE_info["any_idle_workers"]:
2929
return {}, persis_info
3030

31+
user = {**gen_specs, **alloc_specs.get("user", {})}
3132
manage_resources = libE_info["use_resource_sets"]
3233
support = AllocSupport(W, manage_resources, persis_info, libE_info)
3334
Work = {}
3435
gen_count = support.count_gens()
3536

3637
if gen_specs["user"].get("single_component_at_a_time"):
37-
assert alloc_specs["user"]["batch_mode"], "Must be in batch mode when using 'single_component_at_a_time'"
38+
assert alloc_specs["user"].get("batch_mode", False) or gen_specs.get(
39+
"batch_mode", False
40+
), "Must be in batch mode when using 'single_component_at_a_time'"
3841
if len(H) != persis_info["H_len"]:
3942
# Something new is in the history.
4043
persis_info["need_to_give"].update(H["sim_id"][persis_info["H_len"] :].tolist())
@@ -119,13 +122,13 @@ def give_sim_work_first(W, H, sim_specs, gen_specs, alloc_specs, persis_info, li
119122
break
120123

121124
while len(idle_gen_workers):
122-
if gen_count < alloc_specs["user"].get("num_active_gens", gen_count + 1):
125+
if gen_count < user.get("num_active_gens", gen_count + 1):
123126
lw = persis_info["last_worker"]
124127

125128
last_size = persis_info.get("last_size")
126129
if len(H):
127130
# Don't give gen instances in batch mode if points are unfinished
128-
if alloc_specs["user"].get("batch_mode") and not all(
131+
if (alloc_specs["user"].get("batch_mode") or gen_specs.get("batch_mode")) and not all(
129132
np.logical_or(H["sim_ended"][last_size:], H["paused"][last_size:])
130133
):
131134
break
@@ -142,7 +145,7 @@ def give_sim_work_first(W, H, sim_specs, gen_specs, alloc_specs, persis_info, li
142145
persis_info["last_worker"] = i
143146
persis_info["last_size"] = len(H)
144147

145-
elif gen_count >= alloc_specs["user"].get("num_active_gens", gen_count + 1):
148+
elif gen_count >= user.get("num_active_gens", gen_count + 1):
146149
idle_gen_workers = []
147150

148151
return Work, persis_info

libensemble/alloc_funcs/give_sim_work_first.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ def give_sim_work_first(
1414
alloc_specs: dict,
1515
persis_info: dict,
1616
libE_info: dict,
17-
) -> tuple[dict]:
17+
) -> tuple[dict, dict]:
1818
"""
1919
Decide what should be given to workers. This allocation function gives any
2020
available simulation work first, and only when all simulations are
21-
completed or running does it start (at most ``alloc_specs["user"]["num_active_gens"]``)
21+
completed or running does it start (at most ``gen_specs["num_active_gens"]`` or ``alloc_specs["user"]["num_active_gens"]``)
2222
generator instances.
2323
24-
Allows for a ``alloc_specs["user"]["batch_mode"]`` where no generation
24+
Allows for a ``gen_specs["batch_mode"]`` or ``alloc_specs["user"]["batch_mode"]`` where no generation
2525
work is given out unless all entries in ``H`` are returned.
2626
2727
Can give points in highest priority, if ``"priority"`` is a field in ``H``.
28-
If ``alloc_specs["user"]["give_all_with_same_priority"]`` is set to True, then
28+
If ``gen_specs["give_all_with_same_priority"]`` or ``alloc_specs["user"]["give_all_with_same_priority"]`` is set to True, then
2929
all points with the same priority value are given as a batch to the sim.
3030
3131
Workers performing sims will be assigned resources given in H["resource_sets"]
@@ -40,7 +40,7 @@ def give_sim_work_first(
4040
`test_uniform_sampling.py <https://github.com/Libensemble/libensemble/blob/develop/libensemble/tests/functionality_tests/test_uniform_sampling.py>`_ # noqa
4141
"""
4242

43-
user = alloc_specs.get("user", {})
43+
user = {**gen_specs, **alloc_specs.get("user", {})}
4444

4545
if "cancel_sims_time" in user:
4646
# Cancel simulations that are taking too long

libensemble/alloc_funcs/persistent_aposmm_alloc.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ def persistent_aposmm_alloc(W, H, sim_specs, gen_specs, alloc_specs, persis_info
2121
if libE_info["sim_max_given"] or not libE_info["any_idle_workers"]:
2222
return {}, persis_info
2323

24-
init_sample_size = gen_specs["user"]["initial_sample_size"]
24+
user = {**gen_specs, **alloc_specs.get("user", {})}
25+
init_sample_size = user["initial_batch_size"]
2526
manage_resources = libE_info["use_resource_sets"]
2627
support = AllocSupport(W, manage_resources, persis_info, libE_info)
2728
gen_count = support.count_persis_gens()

libensemble/alloc_funcs/start_only_persistent.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
def only_persistent_gens(W, H, sim_specs, gen_specs, alloc_specs, persis_info, libE_info):
88
"""
99
This allocation function will give simulation work if possible, but
10-
otherwise start up to ``alloc_specs["user"]["num_active_gens"]``
10+
otherwise start up to ``gen_specs["num_active_gens"]`` or ``alloc_specs["user"]["num_active_gens"]``
1111
persistent generators (defaulting to one).
1212
1313
By default, evaluation results are given back to the generator once
1414
all generated points have been returned from the simulation evaluation.
15-
If ``alloc_specs["user"]["async_return"]`` is set to True, then any
15+
If ``gen_specs["async_return"]`` or ``alloc_specs["user"]["async_return"]`` is set to True, then any
1616
returned points are given back to the generator.
1717
1818
If any workers are marked as zero_resource_workers, then these will only
@@ -56,19 +56,20 @@ def only_persistent_gens(W, H, sim_specs, gen_specs, alloc_specs, persis_info, l
5656
return {}, persis_info
5757

5858
# Initialize alloc_specs["user"] as user.
59-
user = alloc_specs.get("user", {})
59+
user = {**gen_specs, **alloc_specs.get("user", {})}
60+
6061
manage_resources = libE_info["use_resource_sets"]
6162

6263
active_recv_gen = user.get("active_recv_gen", False) # Persistent gen can handle irregular communications
63-
init_sample_size = user.get("init_sample_size", 0) # Always batch return until this many evals complete
64+
initial_batch_size = user.get("initial_batch_size", 0) # Always batch return until this many evals complete
6465
batch_give = user.get("give_all_with_same_priority", False)
6566

6667
support = AllocSupport(W, manage_resources, persis_info, libE_info)
6768
gen_count = support.count_persis_gens()
6869
Work = {}
6970

7071
# Asynchronous return to generator
71-
async_return = user.get("async_return", False) and sum(H["sim_ended"]) >= init_sample_size
72+
async_return = user.get("async_return", False) and sum(H["sim_ended"]) >= initial_batch_size
7273

7374
if gen_count < persis_info.get("num_gens_started", 0):
7475
# When a persistent worker is done, trigger a shutdown (returning exit condition of 1)

0 commit comments

Comments
 (0)