chore: import upstream snapshot with attribution
Lint / lint (push) Has been cancelled
CI / MacOS (push) Has been cancelled
CI / Windows (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:36:25 +08:00
commit 26446540fa
3151 changed files with 974126 additions and 0 deletions
+249
View File
@@ -0,0 +1,249 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _ci_guide:
Using TVM's CI
==============
.. contents::
:local:
TVM uses a combination of Jenkins and GitHub Actions for continuous integration (CI).
- **Jenkins** runs Linux CI tests on
`branches <https://ci.tlcpack.ai/job/tvm/>`_ and
`pull requests <https://ci.tlcpack.ai/job/tvm/view/change-requests/>`_ through a
build configuration specified in `Jenkinsfile templates <https://github.com/apache/tvm/blob/main/ci/jenkins/templates/>`_.
Jenkins is the primary CI step that is codified to block merging.
- **GitHub Actions** runs `linting <https://github.com/apache/tvm/blob/main/.github/workflows/lint.yml>`_
(via pre-commit hooks) on pushes and pull requests, as well as minimal
Windows and macOS build-and-test jobs.
This page describes how contributors and committers can use TVM's CI to verify their code. You can
read more about the design of TVM CI in the `tlc-pack/ci <https://github.com/tlc-pack/ci>`_ repo.
For Contributors
----------------
A standard Jenkins CI run looks something like this viewed in `Jenkins' BlueOcean viewer <https://ci.tlcpack.ai/blue/organizations/jenkins/tvm/activity>`_.
CI runs usually take a couple hours to complete and pull requests (PRs) cannot be merged before CI
has successfully completed. To diagnose failing steps, click through to the failing
pipeline stage then to the failing step to see the output logs. For GitHub Actions jobs (lint,
Windows, macOS), check the "Actions" tab on the pull request or repository page.
.. image:: https://github.com/tlc-pack/web-data/raw/main/images/contribute/ci.png
:width: 800
:alt: The Jenkins UI for a CI run
Debugging Failures
^^^^^^^^^^^^^^^^^^
When CI fails for some reason, there are several methods to diagnose the issue.
Jenkins Logs
""""""""""""
.. |pytest| replace:: ``pytest``
.. _pytest: https://docs.pytest.org/en/stable/
The first place to look for a failure is in the CI logs, follow the red Xs on
the failing job to view the logs. Note:
* Jenkins does not display the full log by default, at the top of the log viewer
is a button "Show complete log" which will take you to a plaintext version of the log
* |pytest|_ failures are summarized at the bottom of the log but you will likely
need to scroll up to view the actual failure.
Reproduce Failures
""""""""""""""""""
Most TVM Python tests run under |pytest|_ and can be run as described in :ref:`pr-testing`.
Reporting Issues
^^^^^^^^^^^^^^^^
Issues with CI should be `reported on GitHub <https://github.com/apache/tvm/issues/new?assignees=&labels=&template=ci-problem.md&title=%5BCI+Problem%5D+>`_
with a link to the relevant jobs, commits, or PRs.
For Maintainers
---------------
This section discusses processes ran by TVM Maintainers.
Procedures for Keeping CI Green
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This section talks about common procedures used to keep CI passing.
Broken CI due to Simultaneous Merge
"""""""""""""""""""""""""""""""""""
Developers rely on the TVM CI to get signal on their PRs before merging. Occasionally, two
different PRs can pass CI individually but break ``main`` when both land. This in turn causes an
error to show up on an unrelated PR that is based on the broken commit(s). Broken commits can be
identified `through GitHub <https://github.com/apache/tvm/commits/main>`_ via the commit status icon
or via `Jenkins <https://ci.tlcpack.ai/blue/organizations/jenkins/tvm/activity?branch=main>`_.
In these situations it is ultimately the responsibility of the TVM Committer who merged the PR to
fix CI (others are encouraged to help). Typical responses to this situation are:
1. revert the offending commit
2. submit a forward fix to address the issue.
It is up to the committer and commit author which option to choose. A broken CI affects all TVM
developers and should be fixed as soon as possible, while a revert may be especially painful for the
author of the offending PR when that PR is large.
Dealing with Flakiness
^^^^^^^^^^^^^^^^^^^^^^
If you notice a failure on your PR that seems unrelated to your change, you should
search `recent GitHub issues related to flaky tests <https://github.com/apache/tvm/issues?q=is%3Aissue+%5BCI+Problem%5D+Flaky>`_ and
`file a new issue <https://github.com/apache/tvm/issues/new?assignees=&labels=&template=ci-problem.md&title=%5BCI+Problem%5D>`_
if you don't see any reports of the failure. If a certain test or class of tests affects
several PRs or commits on ``main`` with flaky failures, the test should be disabled via
`pytest's @xfail decorator <https://docs.pytest.org/en/stable/how-to/skipping.html#xfail-mark-test-functions-as-expected-to-fail>`_ with `strict=False <https://docs.pytest.org/en/stable/how-to/skipping.html#strict-parameter>`_ and the relevant issue linked in the
disabling PR.
.. code-block:: python
@pytest.mark.xfail(strict=False, reason="Flaky test: https://github.com/apache/tvm/issues/1234")
def test_something_flaky():
pass
Then submit a PR as usual
.. code-block:: bash
git add <test file>
git commit -m'[skip ci][ci] Disable flaky test: ``<test_name>``
See #<issue number>
'
gh pr create
Skipping CI
^^^^^^^^^^^
For reverts and trivial forward fixes, adding ``[skip ci]`` to the revert's
PR title will cause Jenkins CI to shortcut and only run lint. Committers should
take care that they only merge CI-skipped PRs to fix a failure on ``main`` and
not in cases where the submitter wants to shortcut CI to merge a change faster.
The PR title is checked when the build is first run (specifically during the Jenkins lint
step, so changes after that has run do not affect CI and will require the job to
be re-triggered by another ``git push``). Note that GitHub Actions lint always
runs independently via pre-commit hooks.
.. code-block:: bash
# Revert HEAD commit, make sure to insert '[skip ci]' at the beginning of
# the commit subject
git revert HEAD
git checkout -b my_fix
# After you have pushed your branch, create a PR as usual.
git push my_repo
# Example: Skip CI on a branch with an existing PR
# Adding this commit to an existing branch will cause a new CI run where
# Jenkins is skipped
git commit --allow-empty --message "[skip ci] Trigger skipped CI"
git push my_repo
Docker Images
^^^^^^^^^^^^^
Each CI job runs most of its work inside a Docker container, built from files
in the `docker/ <https://github.com/apache/tvm/tree/main/docker>`_ folder.
Updating a Docker Image Tag
"""""""""""""""""""""""""""
To update a tag, a new image needs to be built and uploaded to Docker Hub, then
the image tags in `docker-images.ini <https://github.com/apache/tvm/tree/main/ci/jenkins/docker-images.ini>`_
need to be updated to match the image tags on Docker Hub.
Docker images are built automatically nightly via the `tvm-docker <https://ci.tlcpack.ai/job/tvm-docker/>`_,
which uploads the built images to https://hub.docker.com/u/tlcpackstaging once
they have passed CI. Post-merge CI runs on ``main`` build Docker images ad-hoc
and upload them to the ``tlcpackstaging`` Docker Hub account as well. There is an
auto-promotion process for ``tlcpackstaging`` Docker images to be moved to the
``tlcpack`` account. This means that image tags from ``tlcpackstaging`` can be
used in CI and they will be automatically moved to ``tlcpack`` after a successful
post-merge CI run on ``main``. So the steps to update the image are:
1. Merge a PR that changes the Dockerfiles under ``docker/`` or scripts in ``docker/install``.
2. Do either of:
a. Wait for the post-merge CI build from the PR to complete and upload the newly built image to the `tlcpackstaging <https://hub.docker.com/u/tlcpackstaging>`_ Docker Hub.
b. Wait for the nightly Docker image build to complete and upload the newly built image to the `tlcpackstaging <https://hub.docker.com/u/tlcpackstaging>`_ Docker Hub.
3. Find the newly uploaded image tag on the `tlcpackstaging <https://hub.docker.com/u/tlcpackstaging>`_ Docker Hub, for example ``20221208-070144-22ff38dff`` and update the tag in ``ci/jenkins/docker-images.ini`` to use the tlcpackstaging tag but under the tlcpack account, e.g. ``tlcpack/ci-arm:20221208-070144-22ff38dff``. Send in a PR with these changes and wait for it to run through CI to ensure the new images are valid.
4. Merge the ``docker-images.ini`` update PR. Once post-merge CI finishes running on ``main`` the ``tlcpackstaging`` tag will be re-uploaded to ``tlcpack`` automatically.
Adding a New Docker Image
"""""""""""""""""""""""""
New docker images can be added to test TVM on a variety of platforms. Here are the steps for adding
a new CI image:
1. Define the ``docker/Dockerfile.ci_foo`` and associated scripts in ``docker/install``. Create a PR containing only these changes (no ``Jenkinsfile`` changes).
Example: https://github.com/apache/tvm/pull/12230/files
2. A committer verifies the image builds locally and then reviews/approves this PR.
3. A committer creates the ci-foo repos in https://hub.docker.com/u/tlcpack and https://hub.docker.com/u/tlcpackstaging.
4. Create a PR to create an ECR repo for the image in tlcpack/ci: https://github.com/tlc-pack/ci/pull/46/files
5. A committer creates and gets merged a PR to add the image to the ``Jenkinsfile``
Example: https://github.com/apache/tvm/pull/12369/files.
**NOTE**: The PR must be opened from a branch in apache/tvm, not from a branch in a forked repo.
6. A committer adds this image to the daily docker rebuild/validation run in tlcpack.
Example: https://github.com/tlc-pack/tlcpack/pull/131
``ci-docker-staging``
^^^^^^^^^^^^^^^^^^^^^
The `ci-docker-staging <https://github.com/apache/tvm/tree/ci-docker-staging>`_
branch is typically used to test updates to Docker images and ``Jenkinsfile`` changes. When
running a build for a normal PR from a forked repository, Jenkins uses the code
from the PR except for the ``Jenkinsfile`` itself, which comes from the base branch.
When branches are built, the ``Jenkinsfile`` in the branch is used, so a committer
with write access must push PRs to a branch in apache/tvm to properly test
``Jenkinsfile`` changes. If your PR makes changes to the ``Jenkinsfile``, make sure
to @ a `committer <https://github.com/apache/tvm/tree/main/CONTRIBUTORS.md>`_
and ask them to push your PR as a branch to test the changes.
CI Monitoring Rotation
^^^^^^^^^^^^^^^^^^^^^^
Some tests are also flaky and occasionally fail for reasons unrelated to the PR. The
`CI monitoring rotation <https://github.com/apache/tvm/wiki/CI-Monitoring-Runbook>`_ watches for these failures and
disables tests as necessary. It is the responsibility of those who wrote the test to ultimately fix
and re-enable the test.
+185
View File
@@ -0,0 +1,185 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _code_guide:
Code Guide and Tips
===================
.. contents::
:depth: 2
:local:
This is a document used to record tips in TVM codebase for reviewers and contributors.
Most of them are summarized through lessons during the contributing and process.
C++ Code Styles
---------------
- Use the Google C/C++ style.
- The public facing functions are documented in doxygen format.
- Favor concrete type declaration over ``auto`` as long as it is short.
- Favor passing by const reference (e.g. ``const Expr&``) over passing by value.
Except when the function consumes the value by copy constructor or move,
pass by value is better than pass by const reference in such cases.
- Favor ``const`` member function when possible.
We use ``clang-format`` to enforce the code style. Because different version
of clang-format might change by its version, it is recommended to use the same
version of the clang-format as the main one.
You can use pre-commit hooks to run formatting checks:
.. code:: bash
# Run clang-format on all files
pre-commit run clang-format --all-files
# Run all linters (Python + C++ + custom checks)
pre-commit run --all-files
clang-format is also not perfect, when necessary, you can use disble clang-format on certain code regions.
.. code :: c
// clang-format off
void Test() {
// clang-format will be disabled in this region.
}
// clang-format on
Because clang-format may not recognize macros, it is recommended to use macro like normal function styles.
.. code :: c
#define MACRO_IMPL { custom impl; }
#define MACRO_FUNC(x)
// not preferred, because clang-format might recognize it as types.
virtual void Func1() MACRO_IMPL
// preferred
virtual void Func2() MACRO_IMPL;
void Func3() {
// preferred
MACRO_FUNC(xyz);
}
Python Code Styles
------------------
- The functions and classes are documented in `numpydoc <https://numpydoc.readthedocs.io/en/latest/>`_ format.
- Check your code style using ``pre-commit run --all-files``
- Stick to language features in ``python 3.10``
- For functions with early returns, prefer ``if``/``elif``/``else``
chains for functions with parallel and short bodies to the
conditions, such as functions that apply a simple mapping to the
arguments. For more procedural functions, especially where the
final ``else`` block would be much longer than the ``if`` and
``elif`` blocks, prefer having the final ``else`` case unindented.
The pylint check ``no-else-return`` is disabled to allow for this
distinction. See further discussion `here
<https://github.com/apache/tvm/pull/11327>`_.
.. code:: python
# All cases have bodies with similar flow control. While this could
# be expressed as a sequence of if conditions, a reader would need to
# inspect the body of each condition to know that only one conditional
# body may be reached.
def sign(x):
if x > 0:
return "+"
elif x < 0:
return "-"
else:
return ""
# The initial special case is an early return for a special case,
# followed by a more general method. Using an else block for the
# condition would add unnecessary indentation for the remainder of the
# function.
def num_unique_subsets(values):
if len(values)==0:
return 1
# Longer, more general solution here
...
Writing Python Tests
--------------------
We use `pytest <https://docs.pytest.org/en/stable/>`_ for all Python testing. Regular tests live
under ``tests/python``, while environment-specific nightly tests live under ``tests/nightly/python``.
See :doc:`testing` for details on running tests, target parametrization,
and the target-specific marks used by CI.
If you want your test to run over a variety of targets, parametrize over ``target`` with ``@pytest.mark.parametrize``, tag GPU targets with ``@pytest.mark.gpu`` so the CI routes them to GPU nodes, and skip a target that is unavailable on the current machine with :py:func:`tvm.testing.device_enabled`. For example:
.. code:: python
@pytest.mark.parametrize("target", ["llvm", pytest.param("cuda", marks=pytest.mark.gpu)])
def test_mytest(target):
if not tvm.testing.device_enabled(target):
pytest.skip(f"{target} not enabled")
dev = tvm.device(target)
...
will run ``test_mytest`` with ``target="llvm"`` and ``target="cuda"``, skipping any target whose device is not present. If you only want to test against a single target, drop the parametrization and hardcode the target. Mark GPU tests with ``@pytest.mark.gpu`` so the CI can select them, and skip when the required feature is unavailable with ``@pytest.mark.skipif``. For example, CUDA tests use:
.. code:: python
@pytest.mark.gpu
@pytest.mark.skipif(not tvm.testing.env.has_cuda(), reason="need cuda")
def test_mycudatest():
...
The ``tvm.testing.env`` module exposes a ``has_*()`` probe for each runtime and hardware feature (e.g. ``has_cuda()``, ``has_rocm()``, ``has_vulkan()``, ``has_llvm()``). To skip a test when an optional Python package is missing, use ``pytest.importorskip("package_name")``.
Network Resources
-----------------
In CI, downloading files from the Internet is a big source of flaky test failures (e.g. remote
server can go down or be slow), so try to avoid using the network at all during tests. In some cases
this isn't a reasonable proposition (e.g. the docs tutorials which need to download models).
New network downloads are rejected by the CI `request hook
<https://github.com/apache/tvm/blob/main/tests/python/request_hook.py>`_. Prefer
checked-in fixtures or generated data. If a download is unavoidable, arrange a stable
project-managed mirror with the maintainers and add an explicit ``URL_MAP`` entry.
Handle Integer Constant Expression
----------------------------------
We often need to handle constant integer expressions in TVM. Before we do so, the first question we want to ask is that is it really necessary to get a constant integer. If symbolic expression also works and let the logic flow, we should use symbolic expression as much as possible. So the generated code works for shapes that are not known ahead of time.
Note that in some cases we cannot know certain information, e.g. sign of symbolic variable, it is ok to make assumptions in certain cases. While adding precise support if the variable is constant.
If we do have to get constant integer expression, we should get the constant value using type ``int64_t`` instead of ``int``, to avoid potential integer overflow. We can always reconstruct an integer with the corresponding expression type via ``make_const``. The following code gives an example.
.. code:: c++
Expr CalculateExpr(Expr value) {
int64_t int_value = GetConstInt<int64_t>(value);
int_value = CalculateExprInInt64(int_value);
return make_const(value.type(), int_value);
}
+221
View File
@@ -0,0 +1,221 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _code_review_guide:
Code Reviews
============
.. contents::
:depth: 2
:local:
Open source code is maintained by a community with diverse backgrounds, interests, and goals.
Hence it is important to provide clear, documented and maintainable code and processes. Code reviews are a
shepherding process used to collectively spot potential problems, improve quality of the code, and educate both contributors
and reviewers about the code base and its assumptions. It is also one mechanism to ensure there are multiple people who can
maintain a related piece of code together. Contributors are encouraged to polish the code to a reviewable
state before requesting reviews. This is especially important for committer candidates, as committers are expected
to participate in not only writing code but also reviewing it.
This document is a living guideline for code review in open source. Please also take sometime to read
:ref:`community_guide` about the general development process.
Building Trust
--------------
First and foremost, we are building a community that based on trust, which takes time
and effort to both build and maintain. We expect our community members to work together in a
constructive way and work together with common sense. Although we all have different sets of backgrounds,
interests and goals we must work together to find solutions that work for the larger community.
Trust-based collaboration is also a key tenant of the Apache way and an important factor to consider in growing the community,
and promoting members to official roles.
Community Participation
-----------------------
Everyone is welcomed to comment on PRs. We encourage committers to wait for some period of time(e.g. three days)
before merging PR that contains a major architecture change. The goal is to give people time to speak up and
express interest in reviewing and participate.
Remembering that we are all coming from different backgrounds is important here. For example some community members
work in different time zones, only work on open source during work hours, or may be traveling or having other events
going on in their lives. An important part of working in a large project is ensuring there is collective understanding,
so no one person is a bottleneck. While it is important to allow time for participation in code review we also can not
block all changes on all reviewers. Remember that helping people land PRs is a great way to encourage broader
participation, especially for those who volunteer their time to contribute.
Part of this is trusting and communicating with fellow maintainers that if changes need to be applied in the future
that PR authors will later follow through on their promises. It is the responsibility of committers to listen to all
feedback whether from PMC members or new contributors and consider what actions need to be taken.
Read the code carefully
-----------------------
Sometimes we may quickly read through the code and only pick up on a selective aspects of the code. These type of comments
are usually helpful and should be welcomed in the community. However, they are only part of performing code review and
should be part of more comprehensive feedback. A good and careful code review is a large time investment and sometimes
can be longer than writing the actual contribution.
For example receiving only highly critical feedback on minor aspects of your PR rarely feels good, and it can be discouraging
if your time and effort was not reciprocated during review. Practicing empathy when acting both as a contributor and committer
is important and can help make you a more effective code reviewer and contributor.
We expect that all committers carefully read and understand the code before signing off. There is a lot of trust involved when
a committer hits the merge button. In the meantime, we acknowledge that sometimes problems slip through, in that case, the
merger is responsible for ensuring the correct follow up actions are taken.
Be Respectful
-------------
- To everyone who are making comments: making constructive comment will help new contributors to land their PRs
timely and help us welcome new members to the community.
- To authors: reviewers should spend significant time reading the code, and a careful review could be as time intensive
as writing the code from scratch. Respectfully address review comments and reciprocate the review by helping review
others changes in the future.
Most importantly focus on having a constructive conversation, and try to assume best intentions when interacting as a reviewer.
If there is something in the process not working, consider getting some face time with the other contributors and discussing
how to improve the process or communication.
Factors to Consider about Code Quality
--------------------------------------
High quality code is critical to the long term success of the project. There are many factors of code quality to consider
during a code review:
- F0: Overall architecture. This includes the definition of public modules, key data structures and public interfaces.
Good architectural choices are critical to the success of the project in the long run.
- F1: Architectural consistency. There are usually multiple ways to implement a new feature. We must ensure new
features are consistent with previous overall architectural choices and interact well with the existing code.
Every new feature increases the complexity of the project, and a consistent design ideally minimizes the increase
in complexity bought by a new feature, making it easier to maintain code in the long run.
- F2: Code robustness and test coverage. Ensure code runs correctly in all possible settings(platforms), ensure
test coverage of the new feature. Clear error messages for user facing errors.
- F3: User facing API documentation: documentation of public user facing APIs and key module interfaces are mandatory.
This includes the API, data structures that appears in the public interface (i.e., `include/tvm` and user facing python APIs).
We generally encourage well documented code and include some form of documentations for internal APIs that are used in
multiple places, see also F4.
- F4: Code readability. Readability involves multiple aspects: instructive and consistent function names, clear implementation
of the overall flow, descriptive comments for complex code logic and internal functions. Readable code is easier to maintain.
Architectural design and consistency are the most important factors since they are likely to introduce the most long term technical debt.
As a result, committers should most carefully consider these factors before merging the code.
Test coverage and API documentation are expected for code contributions.
Code readability is relatively a subjective matter compared to the other ones.
Different people have different thoughts on how to best write code. Reviewers should make constructive and actionable comments.
In the meantime, code review should not be used as a way to get others to write code exactly the way you would.
Conversely you should also consider that what you may easily understand, or find acceptable might not work for the larger
community or other members. Use your judgment on what is appropriate based on the content and the scope of the contribution
and where the contributor is coming from.
We follow common :ref:`code_guide` when writing code. Style guides help ensure that code is readable and maintainable by others,
long after the original author has moved on. Style guides are more than about code formatting — they also pertain
to the correct way to document code, variable naming, and other conventions that are not enforced by automatic formatters.
Consensus Building
------------------
Disagreements can happen during code reviews. We encourage building consensus among the people involved. We are working together
and building trust with each other in OSS. The nature of OSS means sometimes we make compromises on less significant issues to
make steady progress and welcome broader participation in the community. Compromise unfortunately means sometimes the world will
not be exactly as we would like, this true even for leaders of the community.
- Be civil and build consensus through constructive technical-based conversations.
- A committer who owns the area can serve as a shepherd to drive the discussion by taking all the conversations into consideration,
and suggest a resolution with to move forward.
- Because a lot of trust is involved on the committer(shepherd), they should read the PR carefully before sign off. Additionally,
the merger should also take the responsibility to followup in case there are problems caused by the merge.
Consistency
-----------
A final remark is that we are all human and its hard to always be perfectly consistent. If contributors feel that you didn't apply these guidelines
in a consistent way it is important to listen and hear folks out. We will constantly have to iterate on processes and guidelines as we evolve as a community.
Our goal is to strive to be consistent and objective but all of us are unfortunately human and imperfect and will need to adjust and learn.
Additional Recommendations
--------------------------
Deliberate on API and Data Structures
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A minimum and stable API is critical to the projects life. A good API makes a huge difference. Always think very carefully about all the aspects including naming, argument definitions and behavior.
When possible, pay more attention still to the proposed API design during code reviews.
Remember, it is easier to improve code implementation, but it is extremely hard to change an API once accepted.
We should treat data structures that are shared across modules(e.g. AST) in the same way.
If/when uncertain, start a conversation with more developers before committing.
Here are some useful principles for designing APIs:
- Be consistent with existing well-known packages APIs if the features overlap.
For example, tensor operation APIs should always be consistent with the numpy API.
- Be consistent with existing APIs in the same project.
For example, we should use the same argument ordering across all the optimization passes,
so there is no "surprise" when using them.
- Think about whether the API will change in the future.
For example, we will have more options like loop_unrolling and device placement policy
as we add more optimizations in build. We can package optimization knobs into a build
configuration object. In this way, the build API is stable over time, even though it may be enriched.
- Write documentation. Documentation is mandatory for APIs and sometimes writing documents helps
us to think further about the design as well as whether we need to add further clarifications.
- Minimum. Think about how many lines of code a user has to write to use the API.
Remove layers of abstraction when possible.
Minimize Dependencies
~~~~~~~~~~~~~~~~~~~~~
Always be cautious in introducing dependencies. While it is important to reuse code and avoid reinventing the wheel,
dependencies can increase burden of users in deployment. A good design principle is that a feature or function
should only have a dependency if/when a user actually use it.
Concise Implementation
~~~~~~~~~~~~~~~~~~~~~~
Some basic principles applied here: favor vectorized array code over loops, use existing APIs that solve the problem.
Document Lessons in Code Reviews
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When you find there are some common or recurring lessons that can be summarized,
add it to the :ref:`code_guide`.
It is always good to refer to the guideline document when requesting changes,
so the lessons can be shared to all the community.
Learn from other Code Reviews
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There can be multiple reviewers reviewing the same changes. Many times other reviewers
may spot things you did not find. Try to learn from other code reviews, when possible, document these lessons.
Approve and Request Changes Explicitly
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The contributor and code owner can request code reviews from multiple reviewers.
Remember to approve changes when your comments are addressed in a code review.
To do so -- please click on changes tab in the pull request, then select approve,
or comment on the code and click request changes.
Code owner can decide if the code can be merged in case by case if some of the reviewers
did not respond in time(e.g. a week) and existing reviews are sufficient.
Reviewers
~~~~~~~~~
Reviewers should strive to leave timely feedback on pull requests for which their
review was requested. Reviewing code is an important part of the project's health
and should be considered a regular responsibility for contributors. Automated
tooling helps out in this regard, as PRs with no activity for a set amount of
time will get a bot comment pinging the relevant parties.
+121
View File
@@ -0,0 +1,121 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _committer_guide:
Committer Guide
===============
.. contents::
:depth: 2
:local:
This is an evolving document to provide some helpful tips for committers.
Most of them are lessons learned during development.
We welcome every committer to contribute to this document.
See the :ref:`community_guide` for an overview of
the committership and the general development process.
Community First
---------------
The collective effort of the community moves the project forward and
makes the project awesome for everyone.
When we make a decision, it is always helpful to keep the community in mind.
Here are some example questions that we can ask:
- How can I encourage new contributors to get more involved in the project?
- Can I help to save my fellow committers' time?
- Have I enabled the rest of the community to participate the
design proposals?
Public Archive Principle
------------------------
While private channels such as face to face discussion are useful for development,
they also create barriers for the broader community's participation.
The Apache way of development requires all decisions
to be made in public channels, which are archived and accessible to everyone.
As a result, any contributor can keep up with the development by watching the
archives and join the development anytime.
While this principle applies to every contributor,
it is especially important for committers.
Here are some example applications of this principle:
- When getting a project-related question from a personal channel,
encourage the person to open a public thread in the discuss forum,
so others in the community can benefit from the answer.
- After an in-person discussion, send a summary to public channels
(as an RFC or a discuss thread).
Independent Project Management
------------------------------
Everyone is presumed to be wearing their Apache committer hat when participating in the project.
That is, committers should act - in the context of the project activities - in the best interests of the project.
Separating your hat between committer and any other roles you may have is important in all aspects.
In the context of project participation, it can be helpful to state which hat you are wearing in cases where that
can cause confusion, especially in cases where you are not wearing committer hat. Two examples:
- "Wearing [foo] hat: [message when serving as foo's role and not as committer]".
- "Wearing Apache TVM hat: [messages when serving as committer]".
Shepherd a Pull Request
-----------------------
Here are some tips to shepherd a pull request.
You can also take a look at the :ref:`code_review_guide`.
- Assign the PR to yourself, so that other committers
know that the PR has already been tended to.
- Make use of the status label to indicate the current status.
- Check if an RFC needs to be sent.
- If the contributor has not requested a reviewer, kindly
ask the contributor to do so.
If the PR comes from a new contributor,
help the contributor to request reviewers
and ask the contributor to do so next time.
- Moderate the reviews, ask reviewers to approve explicitly.
- Mark the PR as accepted and acknowledge the contributor/reviewers.
- Merge the PR :)
Time Management
---------------
There are many things that a committer can do, such as
moderating discussions, pull request reviews and
code contributions.
Working on an open source project can be rewarding,
but also be a bit overwhelming sometimes.
A little bit of time management might be helpful to alleviate the problem.
For example, some committers have a "community day" in a week
when they actively manage outstanding PRs,
but watch the community less frequently in the rest of the time.
Remember that your merit will never go away, so please
take your time and pace when contributing to the project :)
Broad Collaboration
-------------------
Sometimes, we tend to only interact with people we know.
However, broad collaborations are necessary to the success of the project.
Try to keep that in mind, shepherd PRs for, and request code reviews from
community members who you do not interact physically.
+64
View File
@@ -0,0 +1,64 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _community_guide:
TVM Community Guidelines
========================
.. contents::
:depth: 2
:local:
TVM adopts the Apache style model and governs by merit. We believe that it is important to create an inclusive community where everyone can use, contribute to, and influence the direction of the project. See `CONTRIBUTORS.md <https://github.com/apache/tvm/blob/main/CONTRIBUTORS.md>`_ for the current list of contributors.
General Development Process
---------------------------
Everyone in the community is welcomed to send patches, documents, and propose new directions to the project. The key guideline here is to enable everyone in the community to get involved and participate the decision and development. When major changes are proposed, an RFC should be sent to allow discussion by the community. We encourage public discussion, archivable channels such as issues, discuss forum and mailing-list, so that everyone in the community can participate and review the process later.
Code reviews are one of the key ways to ensure the quality of the code. High-quality code reviews prevent technical debt for long-term and are crucial to the success of the project. A pull request needs to be reviewed before it gets merged. A committer who has the expertise of the corresponding area would moderate the pull request and the merge the code when it is ready. The corresponding committer could request multiple reviewers who are familiar with the area of the code. We encourage contributors to request code reviews themselves and help review each other's code -- remember everyone is volunteering their time to the community, high-quality code review itself costs as much as the actual code contribution, you could get your code quickly reviewed if you do others the same favor.
The community should strive to reach a consensus on technical decisions through discussion. We expect committers and PMCs to moderate technical discussions in a diplomatic way, and provide suggestions with clear technical reasoning when necessary.
Strategy Decision Process
-------------------------
It takes lazy 2/3 majority (at least 3 votes and twice as many +1 votes as -1 votes) of binding decisions to make the following
strategic decisions in the TVM community:
- Adoption of a guidance-level community strategy to enable new directions or overall project evolution.
- Establishment of a new module in the project.
- Adoption of a new codebase: When the codebase for an existing, released product is to be replaced with an alternative codebase.
If such a vote fails to gain approval, the existing code base will continue. This also covers the creation of new sub-projects within the project.
All these decisions are made after community conversations that get captured as part of the summary.
Committers
----------
Committers are individuals who are granted the write access to the project. A committer is usually responsible for a certain area or several areas of the code where they oversee the code review process. The area of contribution can take all forms, including code contributions and code reviews, documents, education, and outreach. Committers are essential for a high quality and healthy project. The community actively look for new committers from contributors. Here is a list of useful traits that help the community to recognize potential committers:
- Sustained contribution to the project, demonstrated by discussion over RFCs, code reviews and proposals of new features, and other development activities. Being familiar with, and being able to take ownership on one or several areas of the project.
- Quality of contributions: High-quality, readable code contributions indicated by pull requests that can be merged without a substantial code review. History of creating clean, maintainable code and including good test cases. Informative code reviews to help other contributors that adhere to a good standard.
- Community involvement: active participation in the discussion forum, promote the projects via tutorials, talks and outreach. We encourage committers to collaborate broadly, e.g. do code reviews and discuss designs with community members that they do not interact physically.
The `Project Management Committee (PMC) <https://projects.apache.org/committee.html?tvm>`_ consists group of active committers that moderate the discussion, manage the project release, and proposes new committer/PMC members. Potential candidates are usually proposed via an internal discussion among PMCs, followed by a consensus approval, (i.e. at least 3 +1 votes, and no vetoes). Any veto must be accompanied by reasoning. PMCs should serve the community by upholding the community practices and guidelines TVM a better community for everyone. PMCs should strive to only nominate new candidates outside of their own organization.
Reviewers
---------
Reviewers are individuals who actively contributed to the project and are willing to participate in the code review of new contributions. We identify reviewers from active contributors. The committers should explicitly solicit reviews from reviewers. High-quality code reviews prevent technical debt for long-term and are crucial to the success of the project. A pull request to the project has to be reviewed by at least one reviewer in order to be merged.
+257
View File
@@ -0,0 +1,257 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _doc_guide:
Documentation
=============
.. contents::
:depth: 2
:local:
TVM documentation loosely follows the `formal documentation style described by
Divio <https://documentation.divio.com>`_. This system has been chosen because
it is a "simple, comprehensive and nearly universally-applicable scheme. It is
proven in practice across a wide variety of fields and applications."
This document describes the organization of TVM documentation, and how to write
new documentation. See `docs/README.md <https://github.com/apache/tvm/tree/main/docs#build-locally>`_
for instructions on building the docs.
The Four Document Types
***********************
Introductory Tutorials
----------------------
These are step by step guides to introduce new users to a project. An
introductory tutorial is designed to get a user engaged with the software
without necessarily explaining why the software works the way it does. Those
explanations can be saved for other document types. An introductory tutorial
focuses on a successful first experience. These are the most important docs to
turning newcomers into new users and developers. A fully end-to-end
tutorial — from installing TVM and supporting ML software, to creating and
training a model, to compiling to different architectures — will give a new
user the opportunity to use TVM in the most efficient way possible. A tutorial
teaches a beginner something they need to know. This is in contrast with a
how-to, which is meant to be an answer to a question that a user with some
experience would ask.
Tutorials need to be repeatable and reliable, because the lack of success means
a user will look for other solutions.
How-to Guides
-------------
These are step by step guides on how to solve particular problems. The user can
ask meaningful questions, and the documents provide answers. An examples of
this type of document might be, "how do I compile an optimized model for ARM
architecture?" or "how do I compile and optimize a PyTorch model?" These
documents should be open enough that a user could see how to apply it to a new
use case. Practical usability is more important than completeness. The title
should tell the user what problem the how-to is solving.
How are tutorials different from how-tos? A tutorial is oriented towards the
new developer, and focuses on successfully introducing them to the software and
community. A how-to, in contrast, focuses on accomplishing a specific task
within the context of basic understanding. A tutorial helps to on-board and
assumes no prior knowledge. A how-to assumes minimum knowledge, and is meant to
guide someone to accomplish a specific task.
Reference
---------
Reference documentation describes how the software is configured and operated.
APIs, key functions, commands, and interfaces are all candidates for reference
documentation. These are the technical manuals that let users build their own
interfaces and programs. They are information oriented, focused on lists and
descriptions. You can assume that the audience has a grasp on how the software
works and is looking for specific answers to specific questions. Ideally, the
reference documentation should have the same structure as the code base and be
generated automatically as much as possible.
Architecture Guides
-------------------
Architecture Guides are explanations are background material on a topic. These
documents help to illuminate and understand the application environment. Why
are things the way they are? What were the design decisions, what alternatives
were considered, what are the RFCs describing the existing system? This
includes academic papers and links to publications relevant to the software.
Within these documents you can explore contradictory and conflicting position,
and help the reader make sense of how and why the software was built the way it
is. It's not the place for how-tos and descriptions on how to accomplish tasks.
They instead focus on higher level concepts that help with the understanding of
the project. Generally these are written by the architects and developers of
the project, but can useful to help both users and developers to have a deeper
understanding of why the software works the way it does, and how to contribute
to it in ways that are consistent with the underlying design principles.
Special considerations for TVM
------------------------------
The TVM community has some special considerations that require deviation from
the simple docs style outlined by Divio. The first consideration is that there
is frequently overlap between the user and developer communities. Many projects
document the developer and user experience with separate systems, but it is
appropriate to consider both in this system, with differentiations where
appropriate. As a result the tutorials and how-tos will be divided between
"User Guides" that focus on the user experience, and "Developer Guides" that
focus on the developer experience.
The next consideration is that there are special topics within the TVM
community that benefit from additional attention. Special "Topic Guides" can be
created to index existing material, and provide context on how to navigate that
material most effectively.
To facilitate newcomers, a special "Getting Started" section with installation
instructions, a overview of why to use TVM, and other first-experience
documents will be produced.
Technical Details
*****************
We use the `Sphinx <https://www.sphinx-doc.org>`_ for the main documentation.
Sphinx supports both reStructuredText and markdown. When possible, we
encourage reStructuredText as it has richer features. Note that the
Python doc-string and tutorials allow you to embed reStructuredText syntax.
See
`docs/README.md <https://github.com/apache/tvm/tree/main/docs#build-locally>`_
for instructions on building the docs.
Python Reference Documentation
------------------------------
We use the `numpydoc <https://numpydoc.readthedocs.io/en/latest/>`_ format to
document the function and classes. The following snippet gives an example
docstring. We always document all the public functions, and when necessary,
provide a usage example of the features we support (as shown below).
.. code:: python
def myfunction(arg1, arg2, arg3=3):
"""Briefly describe my function.
Parameters
----------
arg1 : Type1
Description of arg1
arg2 : Type2
Description of arg2
arg3 : Type3, optional
Description of arg3
Returns
-------
rv1 : RType1
Description of return type one
Examples
--------
.. code:: python
# Example usage of myfunction
x = myfunction(1, 2)
"""
return rv1
Be careful to leave blank lines between sections of your documents. In the
above case, there has to be a blank line before ``Parameters``, ``Returns`` and
``Examples`` in order for the doc to be built correctly. To add a new function to
the docs, we need to add the `sphinx.autodoc
<https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html>`_ rules to
`docs/reference/api/python <https://github.com/apache/tvm/tree/main/docs/reference/api/python>`_.
You can refer to the existing files under this folder on how to add the
functions.
C++ Reference Documentation
---------------------------
We use the doxygen format to document c++ functions. The following snippet
shows an example of c++ docstring.
.. code:: c++
/*!
* \brief Description of my function
* \param arg1 Description of arg1
* \param arg2 Description of arg2
* \returns describe return value
*/
int myfunction(int arg1, int arg2) {
// When necessary, also add comment to clarify internal logics
}
Besides documenting function usages, we also highly recommend contributors to
add comments about code logics to improve readability.
Sphinx Gallery How-Tos
----------------------
We use `sphinx-gallery <https://sphinx-gallery.github.io/>`_ to build many
Python how-tos. You can find the source code under `docs/how_to/tutorials
<https://github.com/apache/tvm/tree/main/docs/how_to/tutorials>`_.
One thing that worth noting is that the comment blocks are written in
reStructuredText instead of markdown so be aware of the syntax.
The how-to code will run on our build server to generate the document page. So
we may have a restriction like not being able to access a remote Raspberry Pi,
in such case add a flag variable to the tutorial (e.g. ``use_rasp``) and allow
users to easily switch to the real device by changing one flag. Then use the
existing environment to demonstrate the usage.
If you add a new categorization of how-to, you will need to add references to
`conf.py <https://github.com/apache/tvm/tree/main/docs/conf.py>`_ and the
`top-level docs index <https://github.com/apache/tvm/tree/main/docs/index.rst>`_
(how-to entries are registered there directly, not in a separate how-to index).
Refer to Another Location in the Document
-----------------------------------------
Please use sphinx's ``:ref:`` markup to refer to another location in the same doc.
.. code-block:: rst
.. _document-my-section-tag
My Section
----------
You can use :ref:`document-my-section-tag` to refer to My Section.
Documents with Images / Figures
-------------------------------
reStructuredText's `figure <https://docutils.sourceforge.io/docs/ref/rst/directives.html#figure>`_
and `image <https://docutils.sourceforge.io/docs/ref/rst/directives.html#image>`_
elements allow a document to include an image URL.
Image files created for TVM documentation should reside in the `<https://github.com/tlc-pack/web-data>`_
repository, while the `.rst` files *using* those images should reside in the main TVM repostitory
(`<https://github.com/apache/tvm>`_).
This will require two GitHub Pull Requests, one for the image files and another for the `.rst` files.
Discussion between the contributor and reviewers may be necessary to coordinate the review process.
*IMPORTANT NOTE:* When using two Pull Requests as described above, please merge the
Pull Request in `<https://github.com/tlc-pack/web-data>`_ *before* merging
the Pull Request in `<https://github.com/apache/tvm>`_.
This helps ensure that all URL links in TVM's online documentation are valid.
+97
View File
@@ -0,0 +1,97 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _error-handling-guide:
Error Handling Guide
====================
.. contents::
:depth: 2
:local:
TVM contains structured error classes to indicate specific types of error.
Please raise a specific error type when possible, so that users can
write code to handle a specific error category if necessary.
You can directly raise the specific error object in python.
In other languages like c++, you simply add ``<ErrorType>:`` prefix to
the error message(see below).
.. note::
Please refer to :py:mod:`tvm.error` for the list of errors.
Raise a Specific Error in C++
-----------------------------
You can add ``<ErrorType>:`` prefix to your error message to
raise an error of the corresponding type.
Note that you do not have to add a new type
:py:class:`tvm.error.InternalError` will be raised by default when
there is no error type prefix in the message.
This mechanism works for both ``LOG(FATAL)`` and ``TVM_FFI_ICHECK`` macros.
The following code gives an example on how to do so.
.. code:: c
// src/api_test.cc
void ErrorTest(int x, int y) {
TVM_FFI_ICHECK_EQ(x, y) << "ValueError: expect x and y to be equal."
if (x == 1) {
LOG(FATAL) << "InternalError: cannot reach here";
}
}
When a C++ function registered via the FFI raises an error with a typed prefix,
the TVM FFI system will automatically map it to the corresponding Python exception
class. For example, a ``ValueError:`` prefix in the error message will raise a Python
``ValueError``, and an ``InternalError:`` prefix will raise ``tvm.error.InternalError``.
TVM's FFI system combines both the Python and C++ stacktraces into a single message,
and generates the corresponding error class automatically.
How to choose an Error Type
---------------------------
You can go through the error types are listed below, try to use common
sense and also refer to the choices in the existing code.
We try to keep a reasonable amount of error types.
If you feel there is a need to add a new error type, do the following steps:
- Send a RFC proposal with a description and usage examples in the current codebase.
- Add the new error type to :py:mod:`tvm.error` with clear documents.
- Update the list in this file to include the new error type.
- Change the code to use the new error type.
We also recommend to use less abstraction when creating the short error messages.
The code is more readable in this way, and also opens path to craft specific
error messages when necessary.
.. code:: python
def preferred():
# Very clear about what is being raised and what is the error message.
raise OpNotImplemented("Operator relu is not implemented in the ONNX frontend")
def _op_not_implemented(op_name):
return OpNotImplemented("Operator {} is not implemented.").format(op_name)
def not_preferred():
# Introduces another level of indirection.
raise _op_not_implemented("relu")
If we need to introduce a wrapper function that constructs multi-line error messages,
please put wrapper in the same file so other developers can look up the implementation easily.
+143
View File
@@ -0,0 +1,143 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _git-howto:
Git Usage Tips
==============
.. contents::
:depth: 2
:local:
Here are some tips for git workflow.
How to resolve a conflict with ``main``
---------------------------------------
- First rebase to most recent main
.. code:: bash
# The first two steps can be skipped after you do it once.
git remote add upstream [url to tvm repo]
git fetch upstream
git rebase upstream/main
- The git may show some conflicts it cannot merge, say ``conflicted.py``.
- Manually modify the file to resolve the conflict.
- After you resolved the conflict, mark it as resolved by
.. code:: bash
git add conflicted.py
- Then you can continue rebase by
.. code:: bash
git rebase --continue
- Finally push to your fork, you may need to force push here.
.. code:: bash
git push --force
How to combine multiple commits into one
----------------------------------------
Sometimes we want to combine multiple commits, especially when later commits are only fixes to previous ones,
to create a PR with set of meaningful commits. You can do it by following steps.
- Before doing so, configure the default editor of git if you haven't done so before.
.. code:: bash
git config core.editor the-editor-you-like
- Assume we want to merge last 3 commits, type the following commands
.. code:: bash
git rebase -i HEAD~3
- It will pop up an text editor. Set the first commit as ``pick``, and change later ones to ``squash``.
- After you saved the file, it will pop up another text editor to ask you modify the combined commit message.
- Push the changes to your fork, you need to force push.
.. code:: bash
git push --force
Reset to the most recent main branch
------------------------------------
You can always use git reset to reset your version to the most recent main.
Note that **all your local changes will get lost**.
So only do it when you do not have local changes or when your pull request just get merged.
.. code:: bash
git fetch origin main
git reset --hard FETCH_HEAD
Recover a Previous Commit after Reset
-------------------------------------
Sometimes we could mistakenly reset a branch to a wrong commit.
When that happens, you can use the following command to show the list
of recent commits
.. code:: bash
git reflog
Once you get the right hashtag, you can use git reset again to change
the head to the right commit.
Apply only k-Latest Commits on to the main
------------------------------------------
Sometimes it is useful to only apply your k-latest changes on top of the main.
This usually happens when you have other m-commits that are already merged
before these k-commits. Directly rebase against the main might cause merge conflicts
on these first m-commits (which can be safely discarded).
You can instead use the following command
.. code:: bash
# k is the concrete number
# Put HEAD~2 for the last 1 commit.
git rebase --onto upstream/main HEAD~k
You can then force push to the main. Note that the above command will discard
all the commits before tha last k ones.
What is the consequence of force push
-------------------------------------
The previous two tips requires force push, this is because we altered the path of the commits.
It is fine to force push to your own fork, as long as the commits changed are only yours.
+53
View File
@@ -0,0 +1,53 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
Contributor Guide
=================
TVM has been developed by community members.
Everyone is welcomed to contribute.
We value all forms of contributions, including, but not limited to:
- Code reviewing of the existing patches.
- Documentation and usage examples
- Community participation in forums and issues.
- Code readability and developer guide
- We welcome contributions that add code comments
to improve readability
- We also welcome contributions to docs to explain the
design choices of the internal.
- Test cases to make the codebase more robust
- Tutorials, blog posts, talks that promote the project.
Here are guidelines for contributing to various aspect of the project:
.. toctree::
:maxdepth: 2
community
pull_request
code_review
committer_guide
document
code_guide
testing
git_howto
ci
release_process
error_handling
+267
View File
@@ -0,0 +1,267 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
Submit a Pull Request
=====================
.. contents::
:depth: 2
:local:
Guidelines
----------
- We recommend authors send well scoped PRs that are easy to review and revert in case there is a problem. As such, authors should avoid merging multiple unrelated changes into a single PR
- Before you submit a PR, please rebase your code on the most recent version of ``main``, you can do it by
running
.. code:: bash
git remote add upstream [url to tvm repo]
git fetch upstream
git rebase upstream/main
- Make sure code passes lint checks
.. code:: bash
# Run all lint checks via pre-commit hooks
pre-commit run --all-files
# Run specific linters individually
pre-commit run ruff-check --all-files # Python lint
pre-commit run ruff-format --all-files # Python format
pre-commit run clang-format --all-files # C++ format
- Add test-cases to cover the new features or bugfix the patch introduces.
- Document the code you wrote, see more at :ref:`doc_guide`
- `Create a pull request <https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request>`_ and fix the problems reported by CI checks.
- Request code reviews from other contributors and improve your patch according
to their reviews by ``@``-ing them in your pull request. Use relevant topic
tags in PR titles to make the affected area clear (e.g. ``[microTVM] Add a
cool change`` and not ``a cool change for microTVM``).
Please see the Commit Message Guideline below on the guidelines about the tags
in a PR/commit title and how to write good PR/commit messages.
- To get your code reviewed quickly, we encourage you to help review others' code so they can do the favor in return.
- Code review is a shepherding process that helps to improve contributor's code quality.
We should treat it proactively, to improve the code as much as possible before the review.
We highly value patches that can get in without extensive reviews.
- The detailed guidelines and summarizes useful lessons.
- The PR can be merged after the reviewers approve the pull request.
Commit Message Guideline
------------------------
Apache TVM uses the GitHub (GH) platform for patch submission and code review
via Pull Requests (PRs). The final commit (title and body) that is merged into
the Apache TVM main tree is composed of the PR's title and body and must be kept
updated and reflecting the new changes in the code as per the reviews and
discussions.
Although these guidelines apply essentially to the PRs title and body messages,
because GH auto-generates the PRs title and body from the commits on a given
branch, its recommended to follow these guidelines right from the beginning,
when preparing commits in general to be submitted to the Apache TVM project.
This will ease the creation of a new PR, avoiding rework, and also will help the
review.
The rules below will help to achieve uniformity that has several benefits, both
for review and for the code base maintenance as a whole, helping you to write
commit messages with a good quality suitable for the Apache TVM project,
allowing fast log searches, bisecting, and so on.
*PR/commit title*:
- Guarantee a title exists (enforced);
- Dont use GitHub usernames in the title, like @username (enforced);
- A tag must be present as a hint about what component(s) of the code
the PRs / commits “touch” (enforced). For example [BugFix], [CI], [microTVM],
and [TVMC]. Tags go between square brackets and appear first in the title. If
more than one tag exist, multiple brackets should be used, like [BugFix][CI].
The case recommended for tags, in geral, is the upper camel case. For example,
prefer the forms [Fix], [BugFix], and [Docker] instead of [fix], [bug_fix],
and [docker]. Acronyms should be kept as such so, for example, use [CI] and
[TVMC] instead of [ci] and [tvmc]. Tags help reviewers to identify the PRs
they can/want to review and also help the release folks when generating the
release notes;
- Use an imperative mood. Avoid titles like “Added operator X” and “Updated
image Y in the CI”, instead use the forms “Add feature X” and “Update image Y
in the CI” instead;
- Observe proper use of caps at the beginning (uppercase for the first letter)
and for acronyms, like, for instance, TVM, FVP, OpenCL. Hence instead of
“fix tvm use of opencl library”, write it as “Fix TVM use of OpenCL library”;
- Do not put a period at the end of the title.
*PR/commit body*:
- Guarantee a body exists (enforced);
- Dont use GitHub usernames in body text, like @username (enforced);
- Avoid “bullet” commit message bodies: “bullet” commit message bodies are not
bad per se, but “bullet” commit messages without any description or
explanation is likely as bad as commits without any description, rationale,
or explanation in the body.
For minor deviations from these guidelines, the community will normally favor
reminding the contributor of this policy over reverting or blocking a commit /
PR.
Commits and PRs without a title and/or a body are not considered minor
deviations from these guidelines and hence must be avoided.
Most importantly, the contents of the commit message, especially the body,
should be written to convey the intention of the change, so it should avoid
being vague. For example, commits with a title like “Fix”, “Cleanup”, and
“Fix flaky test” and without any body text should be avoided. Also, for the
review, it will leave the reviewer wondering about what exactly was fixed or
changed and why the change is necessary, slowing the review.
Below is an example that can be used as a model:
::
[microTVM] Zephyr: Remove zephyr_board option from build, flash, and open_transport methods
Currently its necessary to pass the board type via zephyr_board option to
the Project API build, flash, and open_transport methods.
However, since the board type is already configured when the project is
created (i.e. when the generate_project method is called), its possible to
avoid this redundancy by obtaining the board type from the project
configuration files.
This commit adds code to obtain the board type from the project CMake files,
removing this option from build, flash, and open_transport methods, so its
only necessary to specify the zephyr_board option when calling
generate_project.
This commit also moves the verbose and west_cmd options from build
method to generate_project, reducing further the number of required options
when building a project, since the build method is usually called more often
than the generate_project.
After a new PR is created and the review starts its common that reviewers will
request changes. Usually the author will address the reviewers comments and
push additional commits on top of the initial ones. For these additional commits
there is no recommendation regarding the commit messages. However if the
additional commits render the PR title and/or body outdated then it's the
author's responsibility to keep the PR title and body in sync with new changes
in the code and updated the PR title and body accordingly (remember that the PR
title and body will be used to compose the final commit message that will land
in the main tree).
Committers will seek to fix any issues with the commit message prior to
committing but they retain the right to inform the author of the rules and
encourage them to follow them in future. Also, they retain the right to ask to
the author to update the PR title and/or body when they are not correctly
updated or fixed.
CI Environment
--------------
We use Docker images to create stable CI environments that can be deployed to multiple machines.
Follow the steps in `this issue template <https://github.com/apache/tvm/issues/new?assignees=&labels=&template=ci-image.md&title=%5BCI+Image%5D+>`_
to update a CI Docker image.
.. _pr-testing:
Testing
-------
Even though we have hooks to run unit tests automatically for each pull request, it's always recommended to run unit tests
locally beforehand to reduce reviewers' burden and speedup review process.
Docker (recommended)
^^^^^^^^^^^^^^^^^^^^
``tests/scripts/ci.py`` replicates the CI environment locally and provides a user-friendly interface.
The same Docker images and scripts used in CI are used directly to run tests. It also deposits builds
in different folders so you can maintain multiple test environments without rebuilding from scratch
each time (e.g. you can test a change in CPU and GPU while retaining incremental rebuilds).
.. code:: bash
# see all available platforms
python tests/scripts/ci.py --help
python tests/scripts/ci.py cpu --help
# run the CPU build in the ci_cpu docker container (build will be left in
# the build-cpu/ folder)
# note: the CPU and GPU Docker images are quite large and may take some
# time to download on their first use
python tests/scripts/ci.py cpu
# run the CPU build in the ci_cpu docker container and then run unittests
python tests/scripts/ci.py cpu --unittest
# quickly iterate by running a specific test and skipping the rebuild each time
python tests/scripts/ci.py cpu --skip-build --tests tests/python/s_tir/schedule/test_tir_schedule_rolling_buffer.py::test_upscale
# run the CPU build and drop into a shell in the container
python tests/scripts/ci.py cpu --interactive
We regularly update our docker images and, over time, stale images may unnecessarily consume disk
space. You can remove stale images that aren't used in the presently checked-out branch plus any
other worktrees using the following command:
.. code:: bash
docker/clear-stale-images.sh
Consult the ``--help`` for more options.
C++ (local)
^^^^^^^^^^^
Running the C++ tests requires installation of gtest, following the instructions in
:ref:`install-from-source-cpp-tests`
.. code:: bash
# assume you are in tvm source root
TVM_ROOT=`pwd`
./tests/scripts/task_cpp_unittest.sh
Python (local)
^^^^^^^^^^^^^^
Necessary dependencies:
.. code:: bash
pip install --user pytest pytest-xdist Cython
If you want to run all tests:
.. code:: bash
# build tvm (see install-from-source for CMake build instructions)
cd build && cmake .. && cmake --build . --parallel $(nproc) && cd ..
python -m pytest -vvs -n auto tests/python
If you want to run a single test:
.. code:: bash
# let python know where to find tvm related libraries
export PYTHONPATH=python
rm -rf python/tvm/*.pyc python/tvm/*/*.pyc python/tvm/*/*/*.pyc
python -m pytest -v tests/python/tirx-transform/test_tir_transform_storage_rewrite.py
# Additionally if you want to run a single test, for example test_add_one_2d inside a file.
python -m pytest -v -k "test_add_one_2d" tests/python/relax/test_frontend_tflite.py
+314
View File
@@ -0,0 +1,314 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
.. _release_process:
Release Process
===============
.. contents::
:depth: 2
:local:
The release manager role in TVM means you are responsible for a few different things:
- Preparing release notes
- Preparing your setup
- Preparing for release candidates
- Cutting a release branch
- Informing the community of timing
- Making any necessary code changes in that branch (versions are derived from Git tags, so there are no manual version-number edits)
- Running the voting process for a release
- Creating release candidates
- Calling votes and triaging issues
- Finalizing and posting a release:
- Updating the TVM website
- Finalizing release notes
- Announcing the release
Versioning
----------
TVM's version is derived automatically from the most recent Git tag by
`setuptools_scm <https://setuptools-scm.readthedocs.io/>`_ at build time (configured
under ``[tool.setuptools_scm]`` in ``pyproject.toml``). There are **no version numbers
to edit by hand** in ``pyproject.toml``, ``python/tvm/libinfo.py`` or
``include/tvm/runtime/base.h``; releasing is driven entirely by pushing Git tags:
- ``main`` carries a ``vMAJOR.MINOR.devN`` tag (e.g. ``v0.7.dev0``). Commits after it
are versioned ``0.7.devN`` where ``N`` is the number of commits since the tag. This
is why the next dev tag must be pushed on ``main`` when a release branch is cut:
without it, follow-up commits would keep deriving their version from the previous
cycle's tag.
- A release branch (e.g. ``v0.6``) is tagged ``v0.6.0.rc0`` for a candidate (wheel
version ``0.6.0rc0``) and ``v0.6.0`` for the formal release (wheel version
``0.6.0``). Release wheels are built on the exact tag, so the version is the tag
itself.
The legacy ``version.py`` stamping script has been removed. ``web/package.json`` (npm,
a separate ecosystem) is no longer auto-stamped; bump it by hand when starting a new dev
cycle or cutting a release. ``docs/conf.py`` reads ``tvm.__version__`` directly.
Prepare the Release Notes
-------------------------
Release note contains new features, improvement, bug fixes, known issues and deprecation, etc. TVM provides `monthly dev report <https://discuss.tvm.apache.org/search?q=TVM%20Monthly%20%23Announcement>`_ collects developing progress each month. It could be helpful to who writes the release notes.
It is recommended to open a GitHub issue to collect feedbacks for the release note draft before cutting the release branch. See the scripts in ``tests/scripts/release`` for some starting points.
Prepare the Release Candidate
-----------------------------
There may be some code changes necessary on the release branch before the release (for
example cherry-picked fixes). Version numbers are derived from the release tags (see
`Versioning`_), so there are no version numbers to update by hand.
Prepare the GPG Key
-------------------
You can skip this section if you have already uploaded your key.
After generating the gpg key, you need to upload your key to a public key server. Please refer to https://www.apache.org/dev/openpgp.html#generate-key for details.
If you want to do the release on another machine, you can transfer your gpg key to that machine via the ``gpg --export`` and ``gpg --import`` commands.
The last step is to update the KEYS file with your code signing key https://www.apache.org/dev/openpgp.html#export-public-key. Check in the changes to the TVM main branch, as well as ASF SVN,
.. code-block:: bash
# the --depth=files will avoid checkout existing folders
svn co --depth=files "https://dist.apache.org/repos/dist/dev/tvm" svn-tvm
cd svn-tvm
# edit KEYS file
svn ci --username $ASF_USERNAME --password "$ASF_PASSWORD" -m "Update KEYS"
# update downloads.apache.org (note that only PMC members can update the dist/release directory)
svn rm --username $ASF_USERNAME --password "$ASF_PASSWORD" https://dist.apache.org/repos/dist/release/tvm/KEYS -m "Update KEYS"
svn cp --username $ASF_USERNAME --password "$ASF_PASSWORD" https://dist.apache.org/repos/dist/dev/tvm/KEYS https://dist.apache.org/repos/dist/release/tvm/ -m "Update KEYS"
Cut a Release Candidate
-----------------------
To cut a release candidate for the ``v0.6`` release:
#. On the ``main`` commit that should be the last one included in the release, push the
**next** dev-cycle tag ``v0.7.dev0``. This tag is what makes subsequent ``main``
commits versioned ``0.7.devN`` (see `Versioning`_), so it must be pushed *before*
branching.
#. Cut the release branch off that same commit. Branches are named with the base
release version without the patch, e.g. ``v0.6`` for the ``v0.6.0`` release.
#. Push the first release-candidate tag ``v0.6.0.rc0`` on the release branch. CI then
builds the candidate wheel (version ``0.6.0rc0``) for PyPI/TestPyPI testing. Keep
this tag on a ``v0.6`` branch commit that is **not** also the ``v0.7.dev0``-tagged
branch point: when two tags share one commit, which one ``setuptools_scm`` picks is
fragile, so put the candidate tag on a release-prep commit on the branch.
.. code-block:: bash
git clone https://github.com/apache/tvm.git
cd tvm/
# 1. Tag the next dev cycle on main (drives main's 0.7.devN version),
# on the last commit to be included in the release.
git checkout <last-commit-for-release>
git tag v0.7.dev0
git push origin refs/tags/v0.7.dev0
# 2. Cut the release branch off that same commit.
git branch v0.6
git push --set-upstream origin v0.6
# 3. Tag the first release candidate on the release branch. Keep this tag on a
# release-prep commit, NOT the v0.7.dev0-tagged branch point, so the two tags
# never share a commit.
git checkout v0.6
# ... make any release-prep commits (release notes, etc.) here ...
git tag v0.6.0.rc0
git push origin refs/tags/v0.6.0.rc0
The wheel/distribution version is derived from these tags by ``setuptools_scm`` at build
time, so no source files need editing and you no longer run ``version.py`` to stamp the
version (see `Versioning`_).
Go to the GitHub repositories "releases" tab and click "Draft a new release",
- Verify the release by checking the version numbers and ensuring that TVM can build and run the unit tests.
- Provide the release tag in the form of ``v1.0.0.rc0`` where 0 means it's the first release candidate. The tag must match this pattern ``v[0-9]+\.[0-9]+\.[0-9]+\.rc[0-9]`` exactly!
- Select the commit by clicking Target: branch > Recent commits > $commit_hash
- Copy and paste release note draft into the description box
- Select "This is a pre-release"
- Click "Publish release"
Notice that one can still apply changes to the branch after the cut, while the tag is fixed. If any change is required for this release, a new tag has to be created.
Remove previous release candidate (if applied),
.. code-block:: bash
git push --delete origin v0.6.0.rc1
Create source code artifacts,
.. code-block:: bash
# Replace v0.6.0 with the relevant version
git clone git@github.com:apache/tvm.git apache-tvm-src-v0.6.0
cd apache-tvm-src-v0.6.0
git checkout v0.6
git submodule update --init --recursive
git checkout v0.6.0.rc0
rm -rf .DS_Store
find . -name ".git*" -print0 | xargs -0 rm -rf
cd ..
brew install gnu-tar
gtar -czvf apache-tvm-src-v0.6.0.rc0.tar.gz apache-tvm-src-v0.6.0
Use your GPG key to sign the created artifact. First make sure your GPG is set to use the correct private key,
.. code-block:: bash
$ cat ~/.gnupg/gpg.conf
default-key F42xxxxxxxxxxxxxxx
Create GPG signature as well as the hash of the file,
.. code-block:: bash
gpg --armor --output apache-tvm-src-v0.6.0.rc0.tar.gz.asc --detach-sig apache-tvm-src-v0.6.0.rc0.tar.gz
shasum -a 512 apache-tvm-src-v0.6.0.rc0.tar.gz > apache-tvm-src-v0.6.0.rc0.tar.gz.sha512
Update TVM Version on ``main``
------------------------------
The next dev-cycle tag pushed on ``main`` during the cut (step 1 above, e.g. ``v0.7.dev0``)
is what gives ``main`` its ``0.7.devN`` version — ``setuptools_scm`` derives it from that
tag, so there are **no source version numbers to bump** (the old two-commit ``[Dont Squash]``
bump and the ``python version.py`` stamping step are no longer needed). Make sure that tag
sits on the ``main`` commit immediately after the last one included in the release branch;
it is required so that nightly/dev packages built from ``main`` carry the correct
``0.7.devN`` version.
Upload the Release Candidate
----------------------------
Edit the release page on GitHub and upload the artifacts created by the previous steps.
The release manager also needs to upload the artifacts to ASF SVN,
.. code-block:: bash
# the --depth=files will avoid checkout existing folders
svn co --depth=files "https://dist.apache.org/repos/dist/dev/tvm" svn-tvm
cd svn-tvm
mkdir tvm-v0.6.0-rc0
# copy files into it
svn add tvm-0.6.0-rc0
svn ci --username $ASF_USERNAME --password "$ASF_PASSWORD" -m "Add RC"
Cherry-Picking
--------------
After a release branch has been cut but before the release has been voted on, the release manager may cherry-pick commits from ``main``. Since release branches are protected on GitHub, to merge this fixes into the release branch (e.g. ``v0.11``), the release manager must file a PR with the cherry-picked changes against the release branch. The PR should roughly match the original one from ``main`` with extra details on why the commit is being cherry-picked. The community then goes through a normal review and merge process for these PRs. Note that these PRs against the release branches must be `signed <https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits>`_.
Call a Vote on the Release Candidate
------------------------------------
The first voting takes place on the Apache TVM developers list (dev@tvm.apache.org). To get more attention, one can create a GitHub issue start with "[VOTE]" instead, it will be mirrored to dev@ automatically. Look at past voting threads to see how this proceeds. The email should follow this format.
- Provide the link to the draft of the release notes in the email
- Provide the link to the release candidate artifacts
- Make sure the email is in text format and the links are correct
For the dev@ vote, there must be at least 3 binding +1 votes and more +1 votes than -1 votes. Once the vote is done, you should also send out a summary email with the totals, with a subject that looks something like [VOTE][RESULT] ....
In ASF, votes are open at least 72 hours (3 days). If you don't get enough number of binding votes within that time, you cannot close the voting deadline. You need to extend it.
If the vote fails, the community needs to modify the release accordingly: create a new release candidate and re-run the voting process.
Post the Release
----------------
After the vote passes, to upload the binaries to Apache mirrors, you move the binaries from dev directory (this should be where they are voted) to release directory. This "moving" is the only way you can add stuff to the actual release directory. (Note: only PMC can move to release directory)
.. code-block:: bash
export SVN_EDITOR=vim
svn mkdir https://dist.apache.org/repos/dist/release/tvm
svn mv https://dist.apache.org/repos/dist/dev/tvm/tvm-v0.6.0-rc2 https://dist.apache.org/repos/dist/release/tvm/tvm-v0.6.0
# If you've added your signing key to the KEYS file, also update the release copy.
svn co --depth=files "https://dist.apache.org/repos/dist/release/tvm" svn-tvm
curl "https://dist.apache.org/repos/dist/dev/tvm/KEYS" > svn-tvm/KEYS
(cd svn-tvm && svn ci --username $ASF_USERNAME --password "$ASF_PASSWORD" -m"Update KEYS")
Remember to create a new release TAG (v0.6.0 in this case) on GitHub and remove the pre-release candidate TAG.
.. code-block:: bash
git push --delete origin v0.6.0.rc2
Update the TVM Website
----------------------
The website repository is located at `https://github.com/apache/tvm-site <https://github.com/apache/tvm-site>`_. Modify the download page to include the release artifacts as well as the GPG signature and SHA hash. Since TVM's docs are continually updated, upload a fixed version of the release docs. If CI has deleted the docs from the release by the time you go to update the website, you can restart the CI build for the release branch on Jenkins. See the example code below for a starting point.
.. code-block:: bash
git clone https://github.com/apache/tvm-site.git
pushd tvm-site
git checkout asf-site
pushd docs
# make release docs directory
mkdir v0.9.0
pushd v0.9.0
# download the release docs from CI
# find this URL by inspecting the CI logs for the most recent build of the release branch
curl -LO https://tvm-jenkins-artifacts-prod.s3.us-west-2.amazonaws.com/tvm/v0.9.0/1/docs/docs.tgz
tar xf docs.tgz
rm docs.tgz
# add the docs and push
git add .
git commit -m "Add v0.9.0 docs"
git push
Afterwards, modify the `downloads page <https://tvm.apache.org/download>`_ to support the latest release. An example of how to do this is `here <https://github.com/apache/tvm-site/pull/38>`_.
Post the Announcement
---------------------
Send out an announcement email to announce@apache.org, and dev@tvm.apache.org. The announcement should include the link to release note and download page.
Patch Releases
--------------
Patch releases should be reserved for critical bug fixes. Patch releases must go through the same process as normal releases, with the option at the release manager's discretion of a shortened release candidate voting window of 24 hours to ensure that fixes are delivered quickly. A patch release is cut purely by tagging the release base branch (e.g. ``v0.11``): push ``v0.11.1.rc0`` for the candidate and ``v0.11.1`` for the formal patch release; no source version numbers need bumping.
+312
View File
@@ -0,0 +1,312 @@
.. Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.. http://www.apache.org/licenses/LICENSE-2.0
.. Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
Testing TVM
===========
This page describes how to write and run Python tests for TVM,
including the target parametrization utilities used by CI.
Python Target Parametrization
-----------------------------
Summary
~~~~~~~
For any supported runtime, TVM should produce numerically
correct results. Therefore, when writing unit tests that validate
the numeric output, these unit tests should be run on all supported
runtimes. Since this is a very common use case, TVM has helper
functions to parametrize unit tests such that they will run on all
targets that are enabled and have a compatible device.
A single Python function in the test suite can expand to several
parameterized unit tests, each of which tests a single target device.
In order for a test to be run, all of the following must be true.
- The test exists in a file or directory that has been passed to
`pytest`.
- The pytest marks applied to the function, either explicitly or
through target parametrization, must be compatible with the
expression passed to pytest's `-m` argument.
- For parametrized tests using the `target` fixture, the target must
appear in the environment variable `TVM_TEST_TARGETS`.
- For parametrized tests using the `target` fixture, the build
configuration in `config.cmake` must enable the corresponding
runtime.
Unit-Test File Contents
~~~~~~~~~~~~~~~~~~~~~~~
.. _pytest-marks: https://docs.pytest.org/en/stable/how-to/mark.html
The recommended way to run a test on multiple targets is to parametrize
over ``target`` with ``@pytest.mark.parametrize``. Tag each GPU target
with ``pytest.mark.gpu`` so the CI routes it to a GPU node, skip a target
that cannot run on the current machine with
:py:func:`tvm.testing.device_enabled`, and obtain its device with
``tvm.device(target)``. The function is run once per target, the
success/failure of each is reported separately, and a target whose device
is disabled in ``config.cmake`` or absent from the machine is reported as
skipped.
.. code-block:: python
@pytest.mark.parametrize(
"target",
["llvm", pytest.param("cuda", marks=pytest.mark.gpu)],
)
def test_function(target):
if not tvm.testing.device_enabled(target):
pytest.skip(f"{target} not enabled")
dev = tvm.device(target)
# Test code goes here
For a test that only applies to a single target, omit the parametrization
and gate the test with ``@pytest.mark.skipif`` (plus ``@pytest.mark.gpu``
for a GPU target):
.. code-block:: python
@pytest.mark.gpu
@pytest.mark.skipif(
not tvm.testing.device_enabled("cuda"), reason="cuda not enabled"
)
def test_function():
target = "cuda"
dev = tvm.device(target)
# Test code goes here
To exclude a target, leave it out of the parametrize list. To mark a
target as expected to fail, wrap it with
``pytest.param("target", marks=pytest.mark.xfail(reason=...))``.
Additional parameters can be combined with the target parametrization by
stacking ``@pytest.mark.parametrize`` decorators, or by listing tuples of
arguments. Tag the GPU rows with ``pytest.mark.gpu`` and skip in the body
as above:
.. code-block:: python
@pytest.mark.parametrize("target,impl", [
("llvm", cpu_implementation),
pytest.param("cuda", gpu_implementation_small_batch, marks=pytest.mark.gpu),
pytest.param("cuda", gpu_implementation_large_batch, marks=pytest.mark.gpu),
])
def test_function(target, impl):
if not tvm.testing.device_enabled(target):
pytest.skip(f"{target} not enabled")
dev = tvm.device(target)
# Test code goes here
Tests gate on hardware and carry metadata using
`pytest marks <pytest-marks>`_. The most frequently applied
marks are as follows.
- ``@pytest.mark.gpu`` - Tags a function as using GPU
capabilities. This has no effect on its own, but can be paired with
the command-line arguments ``-m gpu`` or ``-m 'not gpu'`` to restrict
which tests pytest will execute. Apply it to any test that needs a
GPU so that the CI runs it only on GPU nodes.
- ``@pytest.mark.skipif(not tvm.testing.env.has_X(), reason=...)`` -
Skips a test when a required runtime or hardware feature is not
available. The :py:mod:`tvm.testing.env` module exposes one memoized
probe per capability (e.g. ``has_cuda()``, ``has_rocm()``,
``has_vulkan()``, ``has_gpu()``, ``has_llvm()``), each of which
returns ``False`` when the runtime is disabled in ``config.cmake`` or
no compatible device is present. Pair it with ``@pytest.mark.gpu``
for tests that use the GPU::
@pytest.mark.gpu
@pytest.mark.skipif(not tvm.testing.env.has_cuda(), reason="need cuda")
def test_cuda_vectorize_add():
# Test code goes here
- ``pytest.importorskip("package_name")`` - Skips a test (or the whole
module, when called at import time) if an optional Python package is
not installed. Use this instead of a ``skipif`` for package
dependencies.
Tests that execute on a local GPU must put the complete live-device
lifetime in a small callback passed to
:py:func:`tvm.testing.run_with_gpu_lock`. Target construction and
compilation remain outside so that pytest-xdist workers can compile in
parallel. Device creation, allocation, execution, synchronization,
host conversion, result checks, and child-process teardown remain inside
the callback so no device-backed object outlives the lock.
.. code-block:: python
@pytest.mark.gpu
@pytest.mark.skipif(not tvm.testing.env.has_cuda(), reason="need cuda")
def test_cuda_add_one():
target = tvm.target.Target("cuda -arch=sm_90")
executable = tvm.compile(make_add_one_module(), target)
host_input = np.arange(16, dtype="float32")
def run_and_check():
dev = tvm.cuda(0)
device_input = tvm.runtime.tensor(host_input, dev)
device_output = tvm.runtime.empty(host_input.shape, "float32", dev)
executable(device_input, device_output)
dev.sync()
tvm.testing.assert_allclose(device_output.numpy(), host_input + 1)
tvm.testing.run_with_gpu_lock(run_and_check)
The wrapper uses the existing :py:class:`tvm_ffi.utils.FileLock` with a
persistent machine-local path. A process exit releases the kernel lock;
the remaining file is not stale ownership. Test startup must never
delete or rotate it, because another process could then lock a different
inode. Set ``TVM_TEST_LOCK_DIR`` only when all cooperating processes need
an explicitly configured shared machine-local directory. The default
temporary path coordinates processes running as the same user. Multi-user
runners sharing a GPU must use one administrator-provisioned directory and
persistent lock file that every contender can write, or enforce exclusivity
through the runner. A per-user lock path cannot protect a GPU shared across
users because each user would lock a different file.
There also exists a ``tvm.testing.enabled_targets()`` that returns
all targets that are enabled and runnable on the current machine,
based on the environment variable ``TVM_TEST_TARGETS``, the build
configuration, and the physical hardware present. Some legacy tests
explicitly loop over the targets returned from ``enabled_targets()``,
but this style should not be used for new tests. The pytest output
for this style silently skips runtimes that are disabled in
``config.cmake``, or do not have a device on which they can run. In
addition, the test halts on the first target to fail, which is
ambiguous as to whether the error occurs on a particular target, or on
every target.
.. code-block:: python
# Old style, do not use.
def test_function():
for target, dev in tvm.testing.enabled_targets():
# Test code goes here
Running Locally
~~~~~~~~~~~~~~~
To run the Python unit tests locally, use the command ``pytest`` in
the ``${TVM_HOME}`` directory.
- Environment variables
- ``TVM_TEST_TARGETS`` should be a semicolon-separated list of
targets to run. If unset, will default to the targets defined in
``tvm.testing.DEFAULT_TEST_TARGETS``.
Note: If ``TVM_TEST_TARGETS`` does not contain any targets that
are both enabled, and have an accessible device of that type,
then the tests will fall back to running on the ``llvm`` target
only.
- ``TVM_LIBRARY_PATH`` should be a path to the ``libtvm.so``
library. This can be used, for example, to run tests using a
debug build. If unset, will search for ``libtvm.so`` relative to
the TVM source directory.
- Command-line arguments
- Passing a path to a folder or file will run only the unit tests
in that folder or file. This can be useful, for example, to
avoid running tests located in ``tests/python/contrib`` on a
system without a specific backend installed.
- The ``-m`` argument only runs unit tests that are tagged with a
specific pytest marker. The most frequent usage is to use
``-m gpu`` to run only tests that are marked with
``@pytest.mark.gpu`` and use a GPU to run. It can also be used
to run only tests that do not use a GPU, by passing ``not gpu``
as the marker expression to ``-m``.
Note: This filtering takes place after the selection of targets
based on the ``TVM_TEST_TARGETS`` environment variable. Even if
``-m gpu`` is specified, if ``TVM_TEST_TARGETS`` does not
contain GPU targets, no GPU tests will be run.
Running in a Local Docker Container
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _tlcpack: https://hub.docker.com/u/tlcpack
The ``docker/bash.sh`` script can be used to run unit tests inside the
same docker image as is used by the CI. The first argument should
specify which docker image to run (e.g. ``docker/bash.sh ci_gpu``).
Allowed image names are defined in ``ci/jenkins/data.py`` in the TVM source directory,
and map to images at `tlcpack`_.
If no additional arguments are given, the docker image will be loaded
with an interactive bash session. If a script is passed as an
optional argument (e.g. ``docker/bash.sh ci_gpu tests/scripts/task_python_unittest.sh``), then that script will be
executed inside the docker image.
Note: The docker images contain all system dependencies, but do not
include the ``build/config.cmake`` configuration file for those
systems. The TVM source directory is used as the home directory of
the docker image, and so this will default to using the same
config/build directories as the local config. One solution is to
maintain separate ``build_local`` and ``build_docker`` directories,
and make a symlink from ``build`` to the appropriate folder when
entering/exiting docker.
Running in CI
~~~~~~~~~~~~~
Everything in the CI starts from the task definitions present in the
Jenkinsfile. This includes defining which docker image gets used,
what the compile-time configuration is, and which tests are included
in which stages.
- Docker images
Each task of the Jenkinsfile (e.g. 'BUILD: CPU') makes calls to
``docker/bash.sh``. The argument following the call to
docker/bash.sh defines the docker image in CI, just as it does
locally.
- Compile-time configuration
The docker image does not have the ``config.cmake`` file built into
it, so this is the first step in each of the ``BUILD`` tasks. This
is done using the ``tests/scripts/task_config_build_*.sh`` scripts.
Which script is used depends on the build being tested, and is
specified in the Jenkinsfile.
Each ``BUILD`` task concludes by packing a library for use in later
tests.
- Which tests run
The ``Unit Test`` stage of the Jenkinsfile determines how ``pytest``
is called. Each task starts by unpacking a
compiled library that was previous compiled in the ``BUILD`` stage,
then runs a test script
(e.g. ``tests/scripts/task_python_unittest.sh``). These scripts set
the files/folders and command-line options that are passed to
``pytest``.
Several of these scripts include the ``-m gpu`` option, which
restricts the tests to only run tests that include the
``@pytest.mark.gpu`` mark.