From f2faf5ce7537c39aa0bb78b0a4e93b73818c7d8f Mon Sep 17 00:00:00 2001 From: Richard Liaw Date: Sun, 5 May 2019 00:04:13 -0700 Subject: [PATCH] [tune] Contributor Guide and Design Page (#4716) * Move setup script out * some changes * Finished Contributor guide * some comments to the design * move * Apply suggestions from code review Co-Authored-By: richardliaw * sourcecode * comments --- doc/source/images/tune-arch.png | Bin 0 -> 32689 bytes doc/source/index.rst | 2 + doc/source/rllib-dev.rst | 2 +- doc/source/tune-contrib.rst | 112 ++++++++++++++++++ doc/source/tune-design.rst | 75 ++++++++++++ doc/source/tune.rst | 6 + .../setup-rllib-dev.py => setup-dev.py} | 0 7 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 doc/source/images/tune-arch.png create mode 100644 doc/source/tune-contrib.rst create mode 100644 doc/source/tune-design.rst rename python/ray/{rllib/setup-rllib-dev.py => setup-dev.py} (100%) diff --git a/doc/source/images/tune-arch.png b/doc/source/images/tune-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..0f1751b8dd39a1954752008c12cd8cf232aebfdd GIT binary patch literal 32689 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 Hmu~$xV&(gN literal 0 HcmV?d00001 diff --git a/doc/source/index.rst b/doc/source/index.rst index d47dcbacc..48c0c0d0e 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -84,7 +84,9 @@ Ray comes with libraries that accelerate deep learning and reinforcement learnin tune-schedulers.rst tune-searchalg.rst tune-package-ref.rst + tune-design.rst tune-examples.rst + tune-contrib.rst .. toctree:: :maxdepth: 1 diff --git a/doc/source/rllib-dev.rst b/doc/source/rllib-dev.rst index 1445e043f..5425879fd 100644 --- a/doc/source/rllib-dev.rst +++ b/doc/source/rllib-dev.rst @@ -4,7 +4,7 @@ RLlib Development Development Install ------------------- -You can develop RLlib locally without needing to compile Ray by using the `setup-rllib-dev.py `__ script. This sets up links between the ``rllib`` dir in your git repo and the one bundled with the ``ray`` package. When using this script, make sure that your git branch is in sync with the installed Ray binaries (i.e., you are up-to-date on `master `__ and have the latest `wheel `__ installed.) +You can develop RLlib locally without needing to compile Ray by using the `setup-dev.py `__ script. This sets up links between the ``rllib`` dir in your git repo and the one bundled with the ``ray`` package. When using this script, make sure that your git branch is in sync with the installed Ray binaries (i.e., you are up-to-date on `master `__ and have the latest `wheel `__ installed.) API Stability ------------- diff --git a/doc/source/tune-contrib.rst b/doc/source/tune-contrib.rst new file mode 100644 index 000000000..f945ee679 --- /dev/null +++ b/doc/source/tune-contrib.rst @@ -0,0 +1,112 @@ +Contributing to Tune +==================== + +We welcome (and encourage!) all forms of contributions to Tune, including and not limited to: + +- Code reviewing of patches and PRs. +- Pushing patches. +- Documentation and examples. +- Community participation in forums and issues. +- Code readability and code comments to improve readability. +- Test cases to make the codebase more robust. +- Tutorials, blog posts, talks that promote the project. + + +Setting up a development environment +------------------------------------ + +If you have Ray installed via pip (``pip install -U ray``), you can develop Tune locally without needing to compile Ray. + + +First, you will need your own [fork](https://help.github.com/en/articles/fork-a-repo) to work on the code. Press the Fork button on the `ray project page `__. +Then, clone the project to your machine and connect your repository to the upstream (main project) ray repository. + +.. code-block:: shell + + git clone https://github.com/[your username]/ray.git [path to ray directory] + cd [path to ray directory] + git remote add upstream https://github.com/ray-project/ray.git + + +Then, run `[path to ray directory]/python/ray/setup-dev.py` `(also here on Github) `__ script. +This sets up links between the ``tune`` dir (among other directories) in your local repo and the one bundled with the ``ray`` package. + +When using this script, make sure that your git branch is in sync with the installed Ray binaries (i.e., you are up-to-date on `master `__ and have the latest `wheel `__ installed.) + + +What can I work on? +------------------- + +We use Github to track issues, feature requests, and bugs. Take a look at the +ones labeled `"good first issue" `__ and `"help wanted" `__ for a place to start. Look for issues with "[tune]" in the title. + +.. note:: + + If raising a new issue or PR related to Tune, be sure to include "[tune]" in the beginning of the title. + +For project organization, Tune maintains a relatively up-to-date organization of +issues on the `Tune Github Project Board `__. +Here, you can track and identify how issues are organized. + + +Submitting and Merging a Contribution +------------------------------------- + +There are a couple steps to merge a contribution. + +1. First rebase your development branch on the most recent version of master. + + .. code:: bash + + git remote add upstream https://github.com/ray-project/ray.git + git fetch upstream + git rebase upstream/master + +2. Make sure all existing tests `pass `__. +3. If introducing a new feature or patching a bug, be sure to add new test cases + in the relevant file in `tune/tests/`. +4. Document the code. Public functions need to be documented, and remember to provide an usage + example if applicable. +5. Request code reviews from other contributors and address their comments. One fast way to get reviews is + to help review others' code so that they return the favor. You should aim to improve the code as much as + possible before the review. We highly value patches that can get in without extensive reviews. +6. Reviewers will merge and approve the pull request; be sure to ping them if + the pull request is getting stale. + + +Testing +------- + +Even though we have hooks to run unit tests automatically for each pull request, +we recommend you to run unit tests locally beforehand to reduce reviewers’ +burden and speedup review process. + + +.. code-block:: shell + + pytest ray/python/ray/tune/tests/ + +Documentation should be documented in `Google style `__ format. + +We also have tests for code formatting and linting that need to pass before merge. +Install `yapf==0.23, flake8, flake8-quotes`. You can run the following locally: + +.. code-block:: shell + + ray/scripts/format.sh + + +Becoming a Reviewer +------------------- + +We identify reviewers from active contributors. Reviewers are individuals who +not only actively contribute to the project and are also willing +to participate in the code review of new contributions. +A pull request to the project has to be reviewed by at least one reviewer in order to be merged. +There is currently no formal process, but active contributors to Tune will be +solicited by current reviewers. + + +.. note:: + + These tips are based off of the TVM `contributor guide `__. diff --git a/doc/source/tune-design.rst b/doc/source/tune-design.rst new file mode 100644 index 000000000..b8bf09a08 --- /dev/null +++ b/doc/source/tune-design.rst @@ -0,0 +1,75 @@ +Tune Design Guide +================= + +In this part of the documentation, we overview the design and architecture +of Tune. + +.. image:: images/tune-arch.png + +The blue boxes refer to internal components, and green boxes are public-facing. +Please refer to the package reference for `user-facing APIs `__. + +Main Components +--------------- + +Tune's main components consist of TrialRunner, Trial objects, TrialExecutor, SearchAlg, TrialScheduler, and Trainable. + +TrialRunner +~~~~~~~~~~~ +[`source code `__] +This is the main driver of the training loop. This component +uses the TrialScheduler to prioritize and execute trials, +queries the SearchAlgorithm for new +configurations to evaluate, and handles the fault tolerance logic. + +**Fault Tolerance**: The TrialRunner executes checkpointing if ``checkpoint_freq`` +is set, along with automatic trial restarting in case of trial failures (if ``max_failures`` is set). +For example, if a node is lost while a trial (specifically, the corresponding +Trainable of the trial) is still executing on that node and checkpointing +is enabled, the trial will then be reverted to a ``"PENDING"`` state and resumed +from the last available checkpoint when it is run. +The TrialRunner is also in charge of checkpointing the entire experiment execution state +upon each loop iteration. This allows users to restart their experiment +in case of machine failure. + +Trial objects +~~~~~~~~~~~~~ +[`source code `__] +This is an internal data structure that contains metadata about each training run. Each Trial +object is mapped one-to-one with a Trainable object but are not themselves +distributed/remote. Trial objects transition among +the following states: ``"PENDING"``, ``"RUNNING"``, ``"PAUSED"``, ``"ERRORED"``, and +``"TERMINATED"``. + +TrialExecutor +~~~~~~~~~~~~~ +[`source code `__] +The TrialExecutor is a component that interacts with the underlying execution framework. +It also manages resources to ensure the cluster isn't overloaded. By default, the TrialExecutor uses Ray to execute trials. + +SearchAlg +~~~~~~~~~ +[`source code `__] The SearchAlgorithm is a user-provided object +that is used for querying new hyperparameter configurations to evaluate. + +SearchAlgorithms will be notified every time a trial finishes +executing one training step (of ``train()``), every time a trial +errors, and every time a trial completes. + +TrialScheduler +~~~~~~~~~~~~~~ +[`source code `__] TrialSchedulers operate over a set of possible trials to run, +prioritizing trial execution given available cluster resources. + +TrialSchedulers are given the ability to kill or pause trials, +and also are given the ability to reorder/prioritize incoming trials. + +Trainables +~~~~~~~~~~ +[`source code `__] +These are user-provided objects that are used for +the training process. If a class is provided, it is expected to conform to the +Trainable interface. If a function is provided. it is wrapped into a +Trainable class, and the function itself is executed on a separate thread. + +Trainables will execute one step of ``train()`` before notifying the TrialRunner. diff --git a/doc/source/tune.rst b/doc/source/tune.rst index 7f6aafa2a..bfeb729e6 100644 --- a/doc/source/tune.rst +++ b/doc/source/tune.rst @@ -91,6 +91,12 @@ For the function you wish to tune, pass in a ``reporter`` object: Tune can be used anywhere Ray can, e.g. on your laptop with ``ray.init()`` embedded in a Python script, or in an `auto-scaling cluster `__ for massive parallelism. +Contribute to Tune +------------------ + +Take a look at our `Contributor Guide `__ for guidelines on contributing. + + Citing Tune ----------- diff --git a/python/ray/rllib/setup-rllib-dev.py b/python/ray/setup-dev.py similarity index 100% rename from python/ray/rllib/setup-rllib-dev.py rename to python/ray/setup-dev.py