Skip to content

Commit

Permalink
Create a workflow to test PennyLane with NumPy 1.26 (#6275)
Browse files Browse the repository at this point in the history
**Context:** In #6061, we started using by default NumPy 2 (instead of
NumPy 1) on the CI to test every PR targeting the master branch. Some
jobs (for example, those requiring `tensorflow`) still automatically
downgrade to NumPy 1.26 since not all interfaces are supported at the
current stage.

This PR aims to create another workflow to test some jobs with NumPy
1.26 (those that don't automatically downgrade to NumPy 1 during the
day). Such a workflow should run at night to ensure PennyLane is still
compatible with NumPy 1.26.

**We'll keep this workflow only temporarily** (probably a quarter, but
this still has to be established). After that, we'll get rid of it.

Finally, It has been verified (see
[here](https://github.com/PennyLaneAI/pennylane/actions/runs/10927439038))
that the tests introduced with this PR are green. This has been verified
a second time (see
[here](https://github.com/PennyLaneAI/pennylane/actions/runs/10946347640)
before merging this PR into master).

**Description of the Change:** As above.

**Benefits:** We ensure that PennyLane is still compatible with NumPy
1.26.

**Possible Drawbacks:** 

- This issue was discovered accidentally (and potentially fixed) during
this PR. The `TestSinglePrecision` class in the `test_jax_jit_qnode.py`
file contains tests that change the JAX precision with
`jax.config.update("jax_enable_x64", False)`. When running the jax tests
using multiple workers, we can face race conditions if some workers
change jax configuration, because other workers in other test classes
downgrade to a single precision causing numerous failures. To avoid
this, we add
[--dist=loadscope](https://pytest-xdist.readthedocs.io/en/latest/distribution.html)
as additional pytest arg for jax tests, grouping tests by module for
test functions and by class for test methods.

- The new workflow is it is to a large extent a (very simplified) copy
of `interface-unit-tests.yml`. This is against the principle of avoiding
code duplication whenever possible. Still, this is just a temporary
workflow that lasts for a few months at most (and runs only at night),
and it may be convenient to disentangle it as much as possible from the
usual test interface.

**Related GitHub Issues:** None.

**Related Shortcut Stories:** [sc-73744]
  • Loading branch information
PietropaoloFrisoni committed Sep 20, 2024
1 parent a1d6545 commit 2aee2e1
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 1 deletion.
10 changes: 10 additions & 0 deletions .github/workflows/install_deps/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ inputs:
description: The version of Python to use in order to run unit tests
required: false
default: '3.10'
install_numpy_1:
description: Indicate if numpy 1 should be installed or not
required: false
type: boolean
default: false
install_jax:
description: Indicate if JAX should be installed or not
required: false
Expand Down Expand Up @@ -67,6 +72,11 @@ runs:
pip install -r requirements-ci.txt --upgrade
pip install -r requirements-dev.txt --upgrade
- name: Install numpy 1 version
shell: bash
if: inputs.install_numpy_1 == 'true'
run: pip install "numpy==1.26.4"

- name: Install PyTorch
shell: bash
if: inputs.install_pytorch == 'true'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/interface-unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ jobs:
install_pennylane_lightning_master: true
pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }}
pytest_markers: jax and not qcut and not finite-diff and not param-shift
pytest_additional_args: --splits 5 --group ${{ matrix.group }}
pytest_additional_args: --dist=loadscope --splits 5 --group ${{ matrix.group }}
pytest_durations_file_path: '.github/workflows/jax_tests_durations.json'
pytest_store_durations: ${{ inputs.pytest_store_durations }}
additional_pip_packages: pytest-split
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/numpy_1_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: NumPy 1 - Tests
on:

schedule:
# Runs daily at 6 AM UTC (1 AM Toronto in winter, 2 AM in summer)
- cron: '0 6 * * *'

# Allows to run this workflow manually from the Actions tab
workflow_dispatch:

concurrency:
group: numpy-1-unit-tests-${{ github.ref }}
cancel-in-progress: true

jobs:
tests:
uses: ./.github/workflows/numpy_1_unit-tests.yml
with:
branch: ${{ github.ref }}
230 changes: 230 additions & 0 deletions .github/workflows/numpy_1_unit-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
# TODO: remove this workflow once compatibility with NumPy 1
# will no longer be tested.

name: NumPy 1 - Unit Tests - Interfaces
on:
workflow_call:
inputs:
branch:
description: The PennyLane branch to checkout and run unit tests for
required: true
type: string
pipeline_mode:
description: The pipeline mode can be unit-tests, benchmarks, or reference-benchmarks
required: false
type: string
default: 'unit-tests'
disable_new_opmath:
description: Whether to disable the new op_math or not when running the tests
required: false
type: string
default: "False"

jobs:
setup-ci-load:
runs-on: ubuntu-latest

steps:
- name: Setup Python Versions
id: python_versions

run: |
cat >python_versions.json <<-EOF
{
"default": ["3.10", "3.11", "3.12"],
"torch-tests": ["3.10", "3.12"],
"jax-tests": ["3.10", "3.12"],
"external-libraries-tests": ["3.10"],
"data-tests": ["3.10"]
}
EOF
jq . python_versions.json
echo "python_versions=$(jq -r tostring python_versions.json)" >> $GITHUB_OUTPUT
- name: Set NumPy Version
id: numpy_version
run: echo "NUMPY_VERSION=1.26" >> $GITHUB_ENV

- name: Setup Matrix Max Parallel
id: max_parallel
run: |
cat >matrix_max_parallel.json <<-EOF
{
"default": 1,
"core-tests": 5,
"jax-tests": 10,
"torch-tests": 2
}
EOF
jq . matrix_max_parallel.json
echo "matrix_max_parallel=$(jq -r tostring matrix_max_parallel.json)" >> $GITHUB_OUTPUT
outputs:
matrix-max-parallel: ${{ steps.max_parallel.outputs.matrix_max_parallel }}
python-version: ${{ steps.python_versions.outputs.python_versions }}

torch-tests:
needs:
- setup-ci-load
strategy:
max-parallel: >-
${{
fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).torch-tests
|| fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).default
}}
matrix:
python-version: >-
${{
fromJSON(needs.setup-ci-load.outputs.python-version).torch-tests
|| fromJSON(needs.setup-ci-load.outputs.python-version).default
}}
uses: ./.github/workflows/unit-test.yml
with:
job_name: torch-tests (${{ matrix.python-version }}, numpy-1.26)
branch: ${{ inputs.branch }}
coverage_artifact_name: core-interfaces-coverage-torch-${{ matrix.python-version }}-numpy-1.26
python_version: ${{ matrix.python-version }}
pipeline_mode: ${{ inputs.pipeline_mode }}
install_numpy_1: true
install_jax: false
install_tensorflow: false
install_pytorch: true
install_pennylane_lightning_master: true
pytest_markers: torch and not qcut and not finite-diff and not param-shift
requirements_file: ${{ github.event_name == 'schedule' && strategy.job-index == 0 && 'torch.txt' || '' }}
disable_new_opmath: ${{ inputs.disable_new_opmath }}


autograd-tests:
needs:
- setup-ci-load
strategy:
max-parallel: >-
${{
fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).autograd-tests
|| fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).default
}}
matrix:
python-version: >-
${{
fromJSON(needs.setup-ci-load.outputs.python-version).autograd-tests
|| fromJSON(needs.setup-ci-load.outputs.python-version).default
}}
uses: ./.github/workflows/unit-test.yml
with:
job_name: autograd-tests (${{ matrix.python-version }}, numpy-1.26)
branch: ${{ inputs.branch }}
coverage_artifact_name: core-interfaces-coverage-autograd-${{ matrix.python-version }}-numpy-1.26
python_version: ${{ matrix.python-version }}
pipeline_mode: ${{ inputs.pipeline_mode }}
install_numpy_1: true
install_jax: false
install_tensorflow: false
install_pytorch: false
install_pennylane_lightning_master: true
pytest_markers: autograd and not qcut and not finite-diff and not param-shift
disable_new_opmath: ${{ inputs.disable_new_opmath }}


jax-tests:
needs:
- setup-ci-load
strategy:
max-parallel: >-
${{
fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).jax-tests
|| fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).default
}}
matrix:
group: [1, 2, 3, 4, 5]
python-version: >-
${{
fromJSON(needs.setup-ci-load.outputs.python-version).jax-tests
|| fromJSON(needs.setup-ci-load.outputs.python-version).default
}}
uses: ./.github/workflows/unit-test.yml
with:
job_name: jax-tests (${{ matrix.group }}, ${{ matrix.python-version }}, numpy-1.26)
branch: ${{ inputs.branch }}
coverage_artifact_name: core-interfaces-coverage-jax-${{ matrix.python-version }}-${{ matrix.group }}-numpy-1.26
python_version: ${{ matrix.python-version }}
pipeline_mode: ${{ inputs.pipeline_mode }}
install_numpy_1: true
install_jax: true
install_tensorflow: false
install_pytorch: false
install_pennylane_lightning_master: true
pytest_markers: jax and not qcut and not finite-diff and not param-shift
pytest_additional_args: --dist=loadscope --splits 5 --group ${{ matrix.group }}
additional_pip_packages: pytest-split
requirements_file: ${{ github.event_name == 'schedule' && strategy.job-index == 0 && 'jax.txt' || '' }}
disable_new_opmath: ${{ inputs.disable_new_opmath }}


core-tests:
needs:
- setup-ci-load
strategy:
max-parallel: >-
${{
fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).core-tests
|| fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).default
}}
matrix:
group: [1, 2, 3, 4, 5]
python-version: >-
${{
fromJSON(needs.setup-ci-load.outputs.python-version).core-tests
|| fromJSON(needs.setup-ci-load.outputs.python-version).default
}}
uses: ./.github/workflows/unit-test.yml
with:
job_name: core-tests (${{ matrix.group }}, ${{ matrix.python-version }}, numpy-1.26)
branch: ${{ inputs.branch }}
coverage_artifact_name: core-interfaces-coverage-core-${{ matrix.python-version }}-${{ matrix.group }}-numpy-1.26
python_version: ${{ matrix.python-version }}
pipeline_mode: ${{ inputs.pipeline_mode }}
install_numpy_1: true
install_jax: false
install_tensorflow: false
install_pytorch: false
install_pennylane_lightning_master: true
pytest_markers: core and not qcut and not finite-diff and not param-shift
pytest_additional_args: --splits 5 --group ${{ matrix.group }}
additional_pip_packages: pytest-split
requirements_file: ${{ github.event_name == 'schedule' && strategy.job-index == 0 && 'core.txt' || '' }}
disable_new_opmath: ${{ inputs.disable_new_opmath }}


data-tests:
needs:
- setup-ci-load
strategy:
max-parallel: >-
${{
fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).data-tests
|| fromJSON(needs.setup-ci-load.outputs.matrix-max-parallel).default
}}
matrix:
python-version: >-
${{
fromJSON(needs.setup-ci-load.outputs.python-version).data-tests
|| fromJSON(needs.setup-ci-load.outputs.python-version).default
}}
uses: ./.github/workflows/unit-test.yml
with:
job_name: data-tests (${{ matrix.python-version }}, numpy-1.26)
branch: ${{ inputs.branch }}
coverage_artifact_name: data-coverage-${{ matrix.python-version }}-numpy-1.26
python_version: ${{ matrix.python-version }}
pipeline_mode: ${{ inputs.pipeline_mode }}
install_numpy_1: true
install_jax: false
install_tensorflow: false
install_pytorch: false
install_pennylane_lightning_master: true
pytest_markers: data
additional_pip_packages: h5py
disable_new_opmath: ${{ inputs.disable_new_opmath }}
6 changes: 6 additions & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ on:
required: false
type: string
default: '3.10'
install_numpy_1:
description: Indicate if numpy 1 should be installed or not
required: false
type: boolean
default: false
pipeline_mode:
description: The pipeline mode can be unit-tests, benchmarks, or reference-benchmark
required: false
Expand Down Expand Up @@ -158,6 +163,7 @@ jobs:
uses: ./.github/workflows/install_deps
with:
python_version: ${{ inputs.python_version }}
install_numpy_1: ${{ inputs.install_numpy_1 }}
install_pytorch: ${{ inputs.install_pytorch }}
install_tensorflow: ${{ inputs.install_tensorflow }}
install_jax: ${{ inputs.install_jax }}
Expand Down

0 comments on commit 2aee2e1

Please sign in to comment.