diff --git a/docs/data_structures/libE_specs.rst b/docs/data_structures/libE_specs.rst index 2a9195cea..ff8c20767 100644 --- a/docs/data_structures/libE_specs.rst +++ b/docs/data_structures/libE_specs.rst @@ -195,6 +195,10 @@ libEnsemble is primarily customized by setting options within a ``LibeSpecs`` cl a local Python path, calling script, and manager/server format-fields for ``manager_ip``, ``manager_port``, ``authkey``, and ``workerID``. ``nworkers`` is specified normally. + **worker_launcher** [Callable]: + TCP Only: Worker launcher function. Accepts ``libE_specs``. An alternative to + ``worker_cmd`` for initiating workers via third-party launchers. + .. tab-item:: History **save_every_k_sims** [int]: diff --git a/libensemble/gen_funcs/persistent_aposmm.py b/libensemble/gen_funcs/persistent_aposmm.py index c5c3aa5e6..13f8cbebc 100644 --- a/libensemble/gen_funcs/persistent_aposmm.py +++ b/libensemble/gen_funcs/persistent_aposmm.py @@ -9,6 +9,7 @@ __all__ = ["aposmm", "initialize_APOSMM", "decide_where_to_start_localopt", "update_history_dist"] +import warnings from math import log, pi, sqrt import numpy as np @@ -163,6 +164,11 @@ def aposmm(H, persis_info, gen_specs, libE_info): """ try: + warnings.warn( + "Use of persistent_aposmm as a persistent generator function is deprecated. " + + "From libEnsemble v2.0 onward, use the libensemble.gen_classes.aposmm ask/tell generator. See the docs for more information.", + FutureWarning, + ) user_specs = gen_specs["user"] ps = PersistentSupport(libE_info, EVAL_GEN_TAG) n, n_s, rk_const, ld, mu, nu, comm, local_H = initialize_APOSMM(H, user_specs, libE_info) diff --git a/libensemble/gen_funcs/persistent_gpCAM.py b/libensemble/gen_funcs/persistent_gpCAM.py index c95b9cac1..81eff41ce 100644 --- a/libensemble/gen_funcs/persistent_gpCAM.py +++ b/libensemble/gen_funcs/persistent_gpCAM.py @@ -1,6 +1,7 @@ """Persistent generator exposing gpCAM functionality""" import time +import warnings import numpy as np from gpcam import GPOptimizer as GP @@ -17,6 +18,12 @@ def _initialize_gpcAM(user_specs, libE_info): """Extract user params""" + warnings.warn( + "Use of persistent_gpCAM as a persistent generator function is deprecated. " + + "From libEnsemble v2.0 onward, Use the libensemble.gen_classes.gpcam ask/tell generator. " + + "See the docs for more information.", + FutureWarning, + ) b = user_specs["batch_size"] lb = np.array(user_specs["lb"]) ub = np.array(user_specs["ub"]) diff --git a/libensemble/libE.py b/libensemble/libE.py index 2762890bc..467788720 100644 --- a/libensemble/libE.py +++ b/libensemble/libE.py @@ -120,6 +120,7 @@ import socket import sys import traceback +import warnings from pathlib import Path from typing import Callable, Dict @@ -590,6 +591,7 @@ def libE_tcp_mgr(sim_specs, gen_specs, exit_criteria, persis_info, alloc_specs, workers = None nworkers = libE_specs["nworkers"] elif libE_specs.get("workers"): + warnings.warn("LibeSpecs.workers will be renamed to LibeSpecs.worker_hosts in v2.0", FutureWarning) workers = libE_specs["workers"] nworkers = len(workers) ip = libE_specs["ip"] or get_ip() diff --git a/libensemble/manager.py b/libensemble/manager.py index 99321ce6a..99666f1e0 100644 --- a/libensemble/manager.py +++ b/libensemble/manager.py @@ -12,6 +12,7 @@ import sys import time import traceback +import warnings from typing import Any, Union import numpy as np @@ -204,6 +205,7 @@ def __init__( timer.start() self.date_start = timer.date_start.replace(" ", "_") self.safe_mode = libE_specs.get("safe_mode") + self.kill_canceled_sims = libE_specs.get("kill_canceled_sims") self.hist = hist self.hist.safe_mode = self.safe_mode @@ -221,6 +223,12 @@ def __init__( dyn_keys = ("resource_sets", "num_procs", "num_gpus") dyn_keys_in_H = any(k in self.hist.H.dtype.names for k in dyn_keys) self.use_resource_sets = dyn_keys_in_H or self.libE_specs.get("num_resource_sets") + if self.libE_specs.get("num_resource_sets", 0): + warnings.warn( + "Direct specification of number of resource sets is deprecated, to be removed in v2.0. " + + "From v2.0 onward, generators should specify `num_procs` or `num_gpus` instead.", + DeprecationWarning, + ) self.gen_num_procs = libE_specs.get("gen_num_procs", 0) self.gen_num_gpus = libE_specs.get("gen_num_gpus", 0) @@ -483,8 +491,18 @@ def _update_state_on_worker_msg(self, persis_info: dict, D_recv: dict, w: int) - final_data = D_recv.get("calc_out", None) if isinstance(final_data, np.ndarray): if calc_status is FINISHED_PERSISTENT_GEN_TAG and self.libE_specs.get("use_persis_return_gen", False): + warnings.warn( + "LibeSpecs.use_persis_return_gen is deprecated, to be removed in v2.0. From v2.0 onward, " + + "libEnsemble will honor all data returned on completion of a persistent generator.", + DeprecationWarning, + ) self.hist.update_history_x_in(w, final_data, self.W[w]["gen_started_time"]) elif calc_status is FINISHED_PERSISTENT_SIM_TAG and self.libE_specs.get("use_persis_return_sim", False): + warnings.warn( + "LibeSpecs.use_persis_return_sim is deprecated, to be removed in v2.0. From v2.0 onward, " + + " libEnsemble will honor all data returned on completion of a persistent simulator function.", + DeprecationWarning, + ) self.hist.update_history_f(D_recv, self.kill_canceled_sims) else: logger.info(_PERSIS_RETURN_WARNING) @@ -577,6 +595,12 @@ def _final_receive_and_kill(self, persis_info: dict) -> (dict, int, int): for w in self.W["worker_id"][self.W["persis_state"] > 0]: logger.debug(f"Manager sending PERSIS_STOP to worker {w}") if self.libE_specs.get("final_gen_send", False): + warnings.warn( + "LibeSpecs.final_gen_send is deprecated, to be removed in v2.0. From v2.0 onward, " + + "upon a workflow completing, libEnsemble will automatically send any outstanding " + + "finished simulations to the generator.", + DeprecationWarning, + ) rows_to_send = np.where(self.hist.H["sim_ended"] & ~self.hist.H["gen_informed"])[0] work = { "H_fields": self.gen_specs["persis_in"], diff --git a/libensemble/resources/resources.py b/libensemble/resources/resources.py index 443424ec3..58b759f27 100644 --- a/libensemble/resources/resources.py +++ b/libensemble/resources/resources.py @@ -6,6 +6,7 @@ import logging import os import socket +import warnings from libensemble.resources import node_resources from libensemble.resources.env_resources import EnvResources @@ -166,6 +167,13 @@ def __init__(self, libE_specs: dict, platform_info: dict = {}, top_level_dir: st self.top_level_dir = top_level_dir self.dedicated_mode = libE_specs.get("dedicated_mode", False) self.zero_resource_workers = libE_specs.get("zero_resource_workers", []) + if len(self.zero_resource_workers): + warnings.warn( + "libE_specs.zero_resource_workers is deprecated, to be removed in v2.0." + + "Set libE_specs.gen_workers instead for generator-workers that require no resources.", + DeprecationWarning, + 2, + ) self.num_resource_sets = libE_specs.get("num_resource_sets", None) self.enforce_worker_core_bounds = libE_specs.get("enforce_worker_core_bounds", False) self.gpus_per_group = libE_specs.get("gpus_per_group") diff --git a/libensemble/specs.py b/libensemble/specs.py index 494dd23f4..a16d1b744 100644 --- a/libensemble/specs.py +++ b/libensemble/specs.py @@ -403,7 +403,13 @@ class LibeSpecs(BaseModel): """ TCP Only: Split string corresponding to worker/client Python process invocation. Contains a local Python path, calling script, and manager/server format-fields for ``manager_ip``, - ``manager_port``, ``authkey``, and ``workerID``. ``nworkers`` is specified normally. + ``manager_port``, ``authkey``, and ``workerID``. ``nworkers`` is specified normally. Launched + locally for each worker. + """ + + worker_launcher: Optional[Callable] = None + """ TCP Only: Worker launcher function. Accepts ``libE_specs``. An alternative to + ``worker_cmd`` for initiating workers via third-party launchers. """ use_persis_return_gen: Optional[bool] = False diff --git a/libensemble/utils/specs_checkers.py b/libensemble/utils/specs_checkers.py index cf33d359f..0bf148cb0 100644 --- a/libensemble/utils/specs_checkers.py +++ b/libensemble/utils/specs_checkers.py @@ -5,6 +5,7 @@ import logging import secrets +import warnings from pathlib import Path import numpy as np @@ -33,6 +34,7 @@ def _check_output_fields(values): if scg(values, "gen_specs"): out_names += [e[0] for e in scg(values, "gen_specs").outputs] if scg(values, "alloc_specs"): + warnings.warn('AllocSpecs.out / alloc_specs["out"] is deprecated, to be removed in v2.0.', DeprecationWarning) out_names += [e[0] for e in scg(values, "alloc_specs").outputs] for name in scg(values, "sim_specs").inputs: