
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "examples/examples_parallelism/plot_profile_worker_utilization.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_examples_examples_parallelism_plot_profile_worker_utilization.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_examples_examples_parallelism_plot_profile_worker_utilization.py:


Profile the Worker Utilization
==============================

**Author(s)**: Romain Egele.

In this example, you will learn how to profile the activity of workers during a 
search. 

We start by defining an artificial black-box ``run``-function by using the Ackley function:

.. image:: https://www.sfu.ca/~ssurjano/ackley.png
  :width: 400
  :alt: Ackley Function in 2D

.. GENERATED FROM PYTHON SOURCE LINES 17-33

.. dropdown:: Code (Import statements)

    .. code-block:: Python


        import time

        import matplotlib.pyplot as plt
        import numpy as np

        from deephyper.analysis import figure_size
        from deephyper.analysis.hpo import (
            plot_search_trajectory_single_objective_hpo,
            plot_worker_utilization,
        )
        from deephyper.evaluator import Evaluator, profile
        from deephyper.evaluator.callback import TqdmCallback
        from deephyper.hpo import CBO, HpProblem








.. GENERATED FROM PYTHON SOURCE LINES 34-35

We define the Ackley function:

.. GENERATED FROM PYTHON SOURCE LINES 35-46

.. dropdown:: Code (Ackley function)

    .. code-block:: Python


        def ackley(x, a=20, b=0.2, c=2 * np.pi):
            d = len(x)
            s1 = np.sum(x**2)
            s2 = np.sum(np.cos(c * x))
            term1 = -a * np.exp(-b * np.sqrt(s1 / d))
            term2 = -np.exp(s2 / d)
            y = term1 + term2 + a + np.exp(1)
            return y








.. GENERATED FROM PYTHON SOURCE LINES 47-53

We will use the ``time.sleep`` function to simulate a budget of 2 secondes of execution in average 
which helps illustrate the advantage of parallel evaluations. The ``@profile`` decorator is useful 
to collect starting/ending time of the ``run``-function execution which help us know exactly when 
we are inside the black-box. This decorator is necessary when profiling the worker utilization. When 
using this decorator, the ``run``-function will return a dictionnary with 2 new keys ``"timestamp_start"`` 
and ``"timestamp_end"``.

.. GENERATED FROM PYTHON SOURCE LINES 53-66

.. code-block:: Python


    @profile
    def run_ackley(config, sleep_loc=2, sleep_scale=0.5):
        # to simulate the computation of an expensive black-box
        if sleep_loc > 0:
            t_sleep = np.random.normal(loc=sleep_loc, scale=sleep_scale)
            t_sleep = max(t_sleep, 0)
            time.sleep(t_sleep)

        x = np.array([config[k] for k in config if "x" in k])
        x = np.asarray_chkfinite(x)  # ValueError if any NaN or Inf
        return -ackley(x)  # maximisation is performed








.. GENERATED FROM PYTHON SOURCE LINES 67-70

Then we define the variable(s) we want to optimize. For this problem we
optimize Ackley in a 2-dimensional search space, the true minimul is
located at ``(0, 0)``.

.. GENERATED FROM PYTHON SOURCE LINES 70-82

.. code-block:: Python


    def create_problem(nb_dim=2):
        nb_dim = 2
        problem = HpProblem()
        for i in range(nb_dim):
            problem.add_hyperparameter((-32.768, 32.768), f"x{i}")
        return problem

    problem = create_problem()
    problem






.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Configuration space object:
      Hyperparameters:
        x0, Type: UniformFloat, Range: [-32.768, 32.768], Default: 0.0
        x1, Type: UniformFloat, Range: [-32.768, 32.768], Default: 0.0




.. GENERATED FROM PYTHON SOURCE LINES 83-86

Then we define a parallel search.
 As the ``run``-function is defined in the same module  we use the "loky" backend 
that serialize by value.

.. GENERATED FROM PYTHON SOURCE LINES 86-112

.. code-block:: Python

    def execute_search(timeout, num_workers):

        evaluator = Evaluator.create(
            run_ackley,
            method="loky",
            method_kwargs={
                "num_workers": num_workers,
                "callbacks": [TqdmCallback()],
            },
        )

        search = CBO(
            problem,
            multi_point_strategy="qUCBd",
            random_state=42,
        )

        results = search.search(evaluator, timeout=timeout)

        return results

    if __name__ == "__main__":
        timeout = 20
        num_workers = 4
        results = execute_search(timeout, num_workers)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    0it [00:00, ?it/s]    1it [00:00, 7530.17it/s, failures=0, objective=-19.8]    2it [00:01,  2.00it/s, failures=0, objective=-19.8]      2it [00:01,  2.00it/s, failures=0, objective=-19.8]    3it [00:01,  2.00it/s, failures=0, objective=-19.8]    4it [00:01,  2.41it/s, failures=0, objective=-19.8]    4it [00:01,  2.41it/s, failures=0, objective=-19.8]    5it [00:01,  2.99it/s, failures=0, objective=-19.8]    5it [00:01,  2.99it/s, failures=0, objective=-19.8]    6it [00:02,  1.78it/s, failures=0, objective=-19.8]    6it [00:02,  1.78it/s, failures=0, objective=-19.8]    7it [00:03,  1.99it/s, failures=0, objective=-19.8]    7it [00:03,  1.99it/s, failures=0, objective=-15.4]    8it [00:03,  2.26it/s, failures=0, objective=-15.4]    8it [00:03,  2.26it/s, failures=0, objective=-15.4]    9it [00:04,  1.84it/s, failures=0, objective=-15.4]    9it [00:04,  1.84it/s, failures=0, objective=-15.4]    10it [00:05,  1.42it/s, failures=0, objective=-15.4]    10it [00:05,  1.42it/s, failures=0, objective=-15.4]    11it [00:05,  1.58it/s, failures=0, objective=-15.4]    11it [00:05,  1.58it/s, failures=0, objective=-15.4]    12it [00:06,  1.82it/s, failures=0, objective=-15.4]    12it [00:06,  1.82it/s, failures=0, objective=-14.2]    13it [00:07,  1.37it/s, failures=0, objective=-14.2]    13it [00:07,  1.37it/s, failures=0, objective=-14.2]    14it [00:07,  1.68it/s, failures=0, objective=-14.2]    14it [00:07,  1.68it/s, failures=0, objective=-14.2]    15it [00:08,  1.85it/s, failures=0, objective=-14.2]    15it [00:08,  1.85it/s, failures=0, objective=-14.2]    16it [00:08,  1.83it/s, failures=0, objective=-14.2]    16it [00:08,  1.83it/s, failures=0, objective=-10.8]    17it [00:09,  1.85it/s, failures=0, objective=-10.8]    17it [00:09,  1.85it/s, failures=0, objective=-10.8]    18it [00:09,  2.20it/s, failures=0, objective=-10.8]    18it [00:09,  2.20it/s, failures=0, objective=-10.8]    19it [00:10,  1.43it/s, failures=0, objective=-10.8]    19it [00:10,  1.43it/s, failures=0, objective=-10.8]    20it [00:10,  1.80it/s, failures=0, objective=-10.8]    20it [00:10,  1.80it/s, failures=0, objective=-6.95]    21it [00:12,  1.36it/s, failures=0, objective=-6.95]    21it [00:12,  1.36it/s, failures=0, objective=-5.75]    22it [00:12,  1.71it/s, failures=0, objective=-5.75]    22it [00:12,  1.71it/s, failures=0, objective=-5.75]    23it [00:12,  1.99it/s, failures=0, objective=-5.75]    23it [00:12,  1.99it/s, failures=0, objective=-5.75]    24it [00:13,  2.05it/s, failures=0, objective=-5.75]    24it [00:13,  2.05it/s, failures=0, objective=-5.75]    25it [00:14,  1.33it/s, failures=0, objective=-5.75]    25it [00:14,  1.33it/s, failures=0, objective=-5.75]    26it [00:15,  1.43it/s, failures=0, objective=-5.75]    26it [00:15,  1.43it/s, failures=0, objective=-5.75]    27it [00:15,  1.65it/s, failures=0, objective=-5.75]    27it [00:15,  1.65it/s, failures=0, objective=-3.36]    28it [00:15,  1.85it/s, failures=0, objective=-3.36]    28it [00:15,  1.85it/s, failures=0, objective=-3.36]    29it [00:17,  1.21it/s, failures=0, objective=-3.36]    29it [00:17,  1.21it/s, failures=0, objective=-3.36]    30it [00:17,  1.49it/s, failures=0, objective=-3.36]    30it [00:17,  1.49it/s, failures=0, objective=-3.36]    31it [00:17,  1.49it/s, failures=0, objective=-3.36]    32it [00:17,  1.49it/s, failures=0, objective=-3.36]    33it [00:18,  1.88it/s, failures=0, objective=-3.36]    33it [00:18,  1.88it/s, failures=0, objective=-3.36]    34it [00:20,  1.52it/s, failures=0, objective=-3.36]    34it [00:20,  1.52it/s, failures=0, objective=-2.07]    35it [00:20,  1.52it/s, failures=0, objective=-0.727]    36it [00:20,  1.52it/s, failures=0, objective=-0.727]



.. GENERATED FROM PYTHON SOURCE LINES 113-114

Finally, we plot the results from the collected DataFrame.

.. GENERATED FROM PYTHON SOURCE LINES 114-137

.. dropdown:: Code (Plot search trajectory an workers utilization)

    .. code-block:: Python


        if __name__ == "__main__":
            t0 = results["m:timestamp_start"].iloc[0]
            results["m:timestamp_start"] = results["m:timestamp_start"] - t0
            results["m:timestamp_end"] = results["m:timestamp_end"] - t0
            tmax = results["m:timestamp_end"].max()

            fig, axes = plt.subplots(
                nrows=2,
                ncols=1,
                sharex=True,
                figsize=figure_size(width=600),
                tight_layout=True,
            )

            _ = plot_search_trajectory_single_objective_hpo(
                results, mode="min", x_units="seconds", ax=axes[0],
            )

            _ = plot_worker_utilization(
                results, num_workers=num_workers, profile_type="start/end", ax=axes[1],
            )



.. image-sg:: /examples/examples_parallelism/images/sphx_glr_plot_profile_worker_utilization_001.png
   :alt: plot profile worker utilization
   :srcset: /examples/examples_parallelism/images/sphx_glr_plot_profile_worker_utilization_001.png
   :class: sphx-glr-single-img






.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 23.347 seconds)


.. _sphx_glr_download_examples_examples_parallelism_plot_profile_worker_utilization.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: plot_profile_worker_utilization.ipynb <plot_profile_worker_utilization.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: plot_profile_worker_utilization.py <plot_profile_worker_utilization.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: plot_profile_worker_utilization.zip <plot_profile_worker_utilization.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
