This is an automated email from the ASF dual-hosted git repository.
leandron pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new f5315ca [Docs] Added documentation on pytest target parametrization.
(#8638)
f5315ca is described below
commit f5315cab3b9ed8e88652ee6002a603f7f44ec2ea
Author: Lunderberg <[email protected]>
AuthorDate: Wed Aug 11 03:46:58 2021 -0500
[Docs] Added documentation on pytest target parametrization. (#8638)
* [Docs] Added documentation on pytest target parametrization.
Follow-up from #8542, to document existing features.
* [Docs] Updated pytest parametrization documentation following review
Co-authored-by: Eric Lunderberg <[email protected]>
---
docs/dev/how_to.rst | 1 +
docs/dev/pytest_target_parametrization.rst | 266 +++++++++++++++++++++++++++++
2 files changed, 267 insertions(+)
diff --git a/docs/dev/how_to.rst b/docs/dev/how_to.rst
index ff078fc..dcf8df2 100644
--- a/docs/dev/how_to.rst
+++ b/docs/dev/how_to.rst
@@ -29,3 +29,4 @@ various areas of the TVM stack.
relay_add_pass
relay_bring_your_own_codegen
codebase_walkthrough
+ pytest_target_parametrization
diff --git a/docs/dev/pytest_target_parametrization.rst
b/docs/dev/pytest_target_parametrization.rst
new file mode 100644
index 0000000..186c1c4
--- /dev/null
+++ b/docs/dev/pytest_target_parametrization.rst
@@ -0,0 +1,266 @@
+.. 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.
+
+Python Target Parametrization
+=============================
+
+Summary
+-------
+
+A single python function in the test suite can expand to several
+parametrized 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/6.2.x/mark.html
+
+Each test file has one or more test functions. The test functions can
+be decorated with `pytest marks <pytest-marks>`_ to include metadata.
+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
+ command-line arguments ``-m gpu`` or ``-m 'not gpu'`` to restrict
+ which tests pytest will executed. This should be called on its own,
+ but is part of other marks used in unit-tests.
+
+- ``@tvm.testing.uses_gpu`` - Applies ``@pytest.mark.gpu``. This
+ should be used to mark a unit tests that may use the GPU, if one is
+ present. This decorator is only needed for tests that explicitly
+ loop over ``tvm.testing.enabled_targets()``, but that is no longer
+ the preferred style of writing unit tests (see below). When using
+ ``tvm.testing.parametrize_targets()``, this decorator is implicit
+ for GPU targets, and does not need to be explicitly applied.
+
+- ``@tvm.testing.requires_gpu`` - Applies ``@tvm.testing.uses_gpu``,
+ and additionally marks that the test should be skipped
+ (``@pytest.mark.skipif``) entirely if no GPU is present.
+
+- ``@tvfm.testing.requires_RUNTIME`` - Several decorators
+ (e.g. ``@tvm.testing.requires_cuda``), each of which skips a test if
+ the specified runtime cannot be used. A runtime cannot be used if it
+ is disabled in the ``config.cmake``, or if a compatible device is
+ not present. For runtimes that use the GPU, this includes
+ ``@tvm.testing.requires_gpu``.
+
+A single test can loop over ``tvm.testing.enabled_targets()`` to
+validate all enabled targets, based on the environment variable
+``TVM_TEST_TARGETS``, the build configuration, and the physical
+hardware present. Most current tests use this style, but it is not
+recommended 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
+
+The recommended method to run a test on multiple targets is by
+parametrizing the test. This can be done explicitly for a fixed list
+of targets by decorating with
+``@tvm.testing.parametrize_targets('target_1', 'target_2', ...)``, and
+accepting ``target`` or ``dev`` as function arguments. The function will
+be run once for each target listed, and the success/failure of each
+target is reported separately. Each test run is decorated with the
+``@tvm.testing.requires_RUNTIME`` that corresponds to the target being
+used. As a result, if a target is disabled in ``config.cmake`` or does
+not have appropriate hardware to run, it will be explicitly listed as
+skipped.
+
+.. code-block:: python
+
+ # Explicit listing of targets to use.
+ @tvm.testing.parametrize_target('llvm', 'cuda')
+ def test_function(target, dev):
+ # Test code goes here
+
+For tests that should run correctly on all targets, the decorator can
+be omitted. Any test that accepts a ``target`` or ``dev`` argument
+will automatically be parametrized over all targets specified in
+``TVM_TEST_TARGETS``. The parametrization provides the same
+pass/fail/skipped report for each target, while allowing the test
+suite to be easily extended to cover additional targets.
+
+.. code-block:: python
+
+ # Implicitly parametrized to run on all targets
+ # in environment variable TVM_TEST_TARGETS
+ def test_function(target, dev):
+ # Test code goes here
+
+The ``@tvm.testing.parametrize_targets`` can also be used as a bare
+decorator to explicitly draw attention to the parametrization, but has
+no additional effect.
+
+.. code-block:: python
+
+ # Explicitly parametrized to run on all targets
+ # in environment variable TVM_TEST_TARGETS
+ @tvm.testing.parametrize_targets
+ def test_function(target, dev):
+ # Test code goes here
+
+
+Specific targets can be excluded or marked as expected to fail using
+the ``@tvm.testing.exclude_targets`` or
+``@tvm.testing.known_failing_targets`` decorators. For more
+information on their intended use cases, please see their docstrings.
+
+Lastly, in some cases it may be necessary to parametrize across
+multiple parameters. For instance, there may be target-specific
+implementations that should be tested, where some targets have more
+than one implementation. These can be done by explicitly
+parametrizing over tuples of arguments, such as shown below. In these
+cases, only the explicitly listed targets will run, but they will
+still have the appropriate ``@tvm.testing.requires_RUNTIME`` mark
+applied to them.
+
+.. code-block:: python
+
+ @pytest.mark.parametrize('target,impl', [
+ ('llvm', cpu_implementation),
+ ('cuda', gpu_implementation_small_batch),
+ ('cuda', gpu_implementation_large_batch),
+ ])
+ def test_function(target, dev, impl):
+ # 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/frontend`` on a
+ system without a specific frontend 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 ``m 'not
+ gpu'``.
+
+ 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 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 at the top of the Jenkinsfile located
+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`` and ``Integration Test`` stages of the Jenkinsfile
+ determine 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/script/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.