Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] improve parameters support of the callbacks #64

Merged
merged 45 commits into from Apr 26, 2023

Conversation

Thecave3
Copy link
Collaborator

  • adaptation of parallelrunner.py to support all versions of Python
  • minor bugs fixed

- adaptation of parallelrunner.py to support all versions of Python
- minor bugs fixed
@Thecave3 Thecave3 marked this pull request as ready for review March 17, 2023 15:36
@pagmatt pagmatt self-requested a review March 17, 2023 18:53
@pagmatt pagmatt self-assigned this Mar 17, 2023
@@ -4,7 +4,7 @@ on:
push:
branches: [ master, develop ]
pull_request:
branches: [ master, develop ]
# branches: [ master, develop ]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed...?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably not

@@ -1,20 +1,27 @@
from .runner import SimulationRunner
from multiprocessing import Pool
from .utils import CallbackBase
from multiprocessing.pool import ThreadPool as Pool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was taken from StackOverflow right? What about explaining with a few lines the reasoning behind this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ThreadPool should share the memory with the main process, which is important to correctly use the callbacks.
The main difference between with Pool is that Pool spawn 5 independent processes (https://stackoverflow.com/questions/46045956/whats-the-difference-between-threadpool-vs-pool-in-the-multiprocessing-module).

@Thecave3
Copy link
Collaborator Author

At the current moment, I have included a simple test to check the effective working of the callback system, but I am having some issues since it cannot find the hash-example script.

Here is reported the full log of the execution:

(sem-py3.8) root@7c295de5c346:/workspace/sem# python -m pytest ./tests/test_utils.py
Getting and compiling ns-3...
=============================================================================================== test session starts ================================================================================================
platform linux -- Python 3.8.10, pytest-7.3.1, pluggy-1.0.0
rootdir: /workspace/sem
configfile: pyproject.toml
plugins: cov-4.0.0, xdist-3.2.1
collected 4 items

tests/test_utils.py ...F                                                                                                                                                                                     [100%]

===================================================================================================== FAILURES =====================================================================================================
__________________________________________________________________________________________________ test_callback ___________________________________________________________________________________________________

ns_3_compiled = '/tmp/pytest-of-root/pytest-11/test_callback0/ns-3-compiled'
config = {'campaign_dir': '/tmp/pytest-of-root/pytest-11/test_callback0/test_campaign', 'commit': '511132dd5cf9a691e40074113623fd6cff90ca61', 'params': {'dict': '/usr/share/dict/words', 'time': False}, 'script': 'hash-example'}
parameter_combination = OrderedDict([('dict', '/usr/share/dict/american-english'), ('time', False), ('RngRun', '0')])

    def test_callback(ns_3_compiled, config, parameter_combination):
        cb = TestCallback()
        n_runs = 10
        expected_output = 'Starting the simulations!\n' + f'Start single run!\nRun ended {0}\n' * n_runs + 'Simulations are over!\n'

>       campaign = CampaignManager.new(ns_3_compiled, config['script'], config['campaign_dir'], runner_type='SimulationRunner', overwrite=True,
                                           skip_configuration=True,
                                           check_repo=False
                                           #, optimized=True, max_parallel_processes=max_parallel_processes
                                           )

tests/test_utils.py:128:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
sem/manager.py:157: in new
    runner = CampaignManager.create_runner(ns_path, script,
sem/manager.py:260: in create_runner
    return locals().get(runner_type,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <sem.runner.SimulationRunner object at 0x7fd6864deeb0>, path = '/tmp/pytest-of-root/pytest-11/test_callback0/ns-3-compiled', script = 'hash-example', optimized = True, skip_configuration = True
max_parallel_processes = None

    def __init__(self, path, script, optimized=True, skip_configuration=False,
                 max_parallel_processes=None):
        """
        Initialization function.

        Args:
            path (str): absolute path to the ns-3 installation this Runner
                should lock on.
            script (str): ns-3 script that will be used by this Runner.
            optimized (bool): whether this Runner should build ns-3 with the
                optimized profile.
            skip_configuration (bool): whether to skip the configuration step,
                and only perform compilation.
        """

        # Save member variables
        self.path = path
        self.script = script
        self.optimized = optimized
        self.max_parallel_processes = max_parallel_processes

        if optimized:
            # For old ns-3 installations, the library is in build, while for
            # recent ns-3 installations it's in build/lib. Both paths are
            # thus required to support all versions of ns-3.
            library_path = "%s:%s" % (
                os.path.join(path, 'build/optimized'),
                os.path.join(path, 'build/optimized/lib'))
        else:
            library_path = "%s:%s" % (
                os.path.join(path, 'build/'),
                os.path.join(path, 'build/lib'))

        # We use both LD_ and DYLD_ to support Linux and Mac OS.
        self.environment = {
            'LD_LIBRARY_PATH': library_path,
            'DYLD_LIBRARY_PATH': library_path}

        # Configure and build ns-3
        self.configure_and_build(path, optimized=optimized,
                                 skip_configuration=skip_configuration)

        # ns-3's build status output is used to get the executable path for the
        # specified script.
        if os.path.exists(os.path.join(self.path, "ns3")):
            # In newer versions of ns-3 (3.36+), the name of the build status file is
            # platform-dependent
            build_status_fname = ".lock-ns3_%s_build" % sys.platform
            build_status_path = os.path.join(path, build_status_fname)
        else:
            build_status_fname = "build.py"
            if optimized:
                build_status_path = os.path.join(path,
                                                'build/optimized/build-status.py')
            else:
                build_status_path = os.path.join(path,
                                                'build/build-status.py')

        # By importing the file, we can naturally get the dictionary
        loader = importlib.machinery.SourceFileLoader(build_status_fname, build_status_path)
        mod = types.ModuleType(loader.name)
        loader.exec_module(mod)


        # Search is simple: we look for the script name in the program field.
        # Note that this could yield multiple matches, in case the script name
        # string is contained in another script's name.
        # matches contains [program, path] for each program matching the script
        matches = [{'name': program,
                    'path': os.path.abspath(os.path.join(path, program))} for
                   program in mod.ns3_runnable_programs if self.script
                   in program]

        if not matches:
>           raise ValueError("Cannot find %s script" % self.script)
E           ValueError: Cannot find hash-example script

sem/runner.py:100: ValueError
----------------------------------------------------------------------------------------------- Captured stderr call -----------------------------------------------------------------------------------------------
Building ns-3: 100%|██████████| 2/2 [00:00<00:00, 108.11file/s]
================================================================================================= warnings summary =================================================================================================
tests/test_utils.py:104
  /workspace/sem/tests/test_utils.py:104: PytestCollectionWarning: cannot collect test class 'TestCallback' because it has a __init__ constructor (from: tests/test_utils.py)
    class TestCallback(CallbackBase):

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
============================================================================================= short test summary info ==============================================================================================
FAILED tests/test_utils.py::test_callback - ValueError: Cannot find hash-example script
===================================================================================== 1 failed, 3 passed, 1 warning in 29.18s ======================================================================================
(sem-py3.8) root@7c295de5c346:/workspace/sem#

@pagmatt pagmatt assigned Thecave3 and unassigned pagmatt Apr 26, 2023
@pagmatt pagmatt added the enhancement New feature or request label Apr 26, 2023
@pagmatt pagmatt merged commit 242f98a into signetlabdei:callback-support Apr 26, 2023
pagmatt added a commit that referenced this pull request May 5, 2023
#67)

* Draft base callback

* Add cb param in manager

* Draft base callback

* Add cb param in manager

* Support paraller runner

* Re-introduce support for parent cb init

* Merge changes in utils

* Small fixes

* fix ctrld by parent flag for callbacks

* Improve parameters support of the callbacks (#64)

---------

Co-authored-by: pagmatt <mattpagg@gmail.com>
Co-authored-by: Andrea Lacava <lacava.a@norhteastern.edu>

---------

Co-authored-by: Andrea Lacava <thecave003@gmail.com>
Co-authored-by: Andrea Lacava <lacava.a@norhteastern.edu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants