diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index cf455180e18a..8994eb724730 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -16,6 +16,7 @@ env: CONDA_BUILD_INDEX_ENV_PY_VER: '3.12' # conda does not support python 3.13 CONDA_BUILD_VERSION: '25.1.1' CONDA_INDEX_VERSION: '0.5.0' + LATEST_PYTHON: '3.13' RERUN_TESTS_ON_FAILURE: 'true' RUN_TESTS_MAX_ATTEMPTS: 2 TEST_ENV_NAME: 'test' @@ -211,14 +212,19 @@ jobs: - name: Run tests if: env.RERUN_TESTS_ON_FAILURE != 'true' run: | - python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + if [[ ${{ matrix.python }} == ${{ env.LATEST_PYTHON }} ]]; then + export DPNP_TEST_ALL_INT_TYPES=1 + python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + else + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + fi - name: Run tests if: env.RERUN_TESTS_ON_FAILURE == 'true' id: run_tests_linux uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0 with: - timeout_minutes: 15 + timeout_minutes: 25 max_attempts: ${{ env.RUN_TESTS_MAX_ATTEMPTS }} retry_on: any command: | @@ -226,112 +232,12 @@ jobs: . $CONDA/etc/profile.d/mamba.sh mamba activate ${{ env.TEST_ENV_NAME }} - python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests - - test_linux_all_dtypes: - name: Test_All_dtypes - - needs: build - - runs-on: ${{ matrix.os }} - - defaults: - run: - shell: bash -el {0} - - strategy: - fail-fast: false - matrix: - python: ['3.12'] - os: [ubuntu-latest] - - env: - channel-path: '${{ github.workspace }}/channel/' - pkg-path-in-channel: '${{ github.workspace }}/channel/linux-64/' - ver-json-path: '${{ github.workspace }}/version.json' - - steps: - - name: Download artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }} - path: ${{ env.pkg-path-in-channel }} - - - name: Setup miniconda - id: setup_miniconda - continue-on-error: true - uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 - with: - miniforge-version: latest - use-mamba: 'true' - channels: conda-forge - conda-remove-defaults: 'true' - python-version: ${{ env.CONDA_BUILD_INDEX_ENV_PY_VER}} - activate-environment: ${{ env.TEST_ENV_NAME }} - - - name: ReSetup miniconda - if: steps.setup_miniconda.outcome == 'failure' - uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 - with: - miniforge-version: latest - use-mamba: 'true' - channels: conda-forge - conda-remove-defaults: 'true' - python-version: ${{ env.CONDA_BUILD_INDEX_ENV_PY_VER}} - activate-environment: ${{ env.TEST_ENV_NAME }} - - - name: Install conda-index - run: | - mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} - - - name: Create conda channel - run: | - python -m conda_index ${{ env.channel-path }} - - - name: Test conda channel - run: | - conda search ${{ env.PACKAGE_NAME }} -c ${{ env.channel-path }} --override-channels --info --json > ${{ env.ver-json-path }} - cat ${{ env.ver-json-path }} - - - name: Get package version - run: | - export PACKAGE_VERSION=$(python -c "${{ env.VER_SCRIPT1 }} ${{ env.VER_SCRIPT2 }}") - - echo PACKAGE_VERSION=${PACKAGE_VERSION} - echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV - - # conda-index does not support python 3.13 - - name: Remove conda-index - run: mamba remove conda-index - - - name: Install dpnp - id: install_dpnp - continue-on-error: true - run: | - mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} - env: - TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' - - - name: ReInstall dpnp - if: steps.install_dpnp.outcome == 'failure' - run: | - mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} - env: - TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' - - - name: List installed packages - run: mamba list - - - name: Smoke test - run: | - python -c "import dpctl; dpctl.lsplatform()" - python -c "import dpnp; print(dpnp.__version__)" - - - name: Run tests for all dtypes - env: - DPNP_TEST_ALL_INT_TYPES: 1 - run: | - python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + if [[ ${{ matrix.python }} == ${{ env.LATEST_PYTHON }} ]]; then + export DPNP_TEST_ALL_INT_TYPES=1 + python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + else + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + fi test_windows: name: Test @@ -453,141 +359,28 @@ jobs: - name: Run tests if: env.RERUN_TESTS_ON_FAILURE != 'true' run: | - python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + if (${{ matrix.python }} -eq ${{ env.LATEST_PYTHON }}) { + set DPNP_TEST_ALL_INT_TYPES=1 + python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + } else { + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + } - name: Run tests if: env.RERUN_TESTS_ON_FAILURE == 'true' id: run_tests_win uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0 with: - timeout_minutes: 17 + timeout_minutes: 35 max_attempts: ${{ env.RUN_TESTS_MAX_ATTEMPTS }} retry_on: any command: | - python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests - - test_windows_all_dtypes: - name: Test_All_dtypes - - needs: build - - runs-on: ${{ matrix.os }} - - defaults: - run: - shell: cmd /C CALL {0} - - strategy: - fail-fast: false - matrix: - python: ['3.12'] - os: [windows-2019] - - env: - channel-path: '${{ github.workspace }}\channel\' - pkg-path-in-channel: '${{ github.workspace }}\channel\win-64\' - ver-json-path: '${{ github.workspace }}\version.json' - workdir: '${{ github.workspace }}' - - steps: - - name: Download artifact - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }} - path: ${{ env.pkg-path-in-channel }} - - - name: Store a path to package archive - run: | - @echo on - - set SEARCH_SCRIPT="DIR ${{ env.pkg-path-in-channel }} /s/b | FINDSTR /r "dpnp-.*\.conda"" - FOR /F "tokens=* USEBACKQ" %%F IN (`%SEARCH_SCRIPT%`) DO ( - SET FULL_PACKAGE_PATH=%%F - ) - echo FULL_PACKAGE_PATH: %FULL_PACKAGE_PATH% - (echo FULL_PACKAGE_PATH=%FULL_PACKAGE_PATH%) >> %GITHUB_ENV% - - - name: Setup miniconda - uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3.1.1 - with: - miniforge-version: latest - use-mamba: 'true' - channels: conda-forge - conda-remove-defaults: 'true' - python-version: ${{ env.CONDA_BUILD_INDEX_ENV_PY_VER}} - activate-environment: ${{ env.TEST_ENV_NAME }} - - - name: Store conda paths as envs - run: | - @echo on - (echo CONDA_LIB_PATH=%CONDA_PREFIX%\Library\lib\) >> %GITHUB_ENV% - (echo CONDA_LIB_BIN_PATH=%CONDA_PREFIX%\Library\bin\) >> %GITHUB_ENV% - - - name: Install conda-index - run: | - mamba install conda-index=${{ env.CONDA_INDEX_VERSION }} - - - name: Create conda channel - run: | - @echo on - python -m conda_index ${{ env.channel-path }} - - - name: Test conda channel - run: | - @echo on - conda search ${{ env.PACKAGE_NAME }} -c ${{ env.channel-path }} --override-channels --info --json > ${{ env.ver-json-path }} - - - name: Dump version.json - run: more ${{ env.ver-json-path }} - - - name: Get package version - run: | - @echo on - set "SCRIPT=${{ env.VER_SCRIPT1 }} ${{ env.VER_SCRIPT2 }}" - FOR /F "tokens=* USEBACKQ" %%F IN (`python -c "%SCRIPT%"`) DO ( - set PACKAGE_VERSION=%%F - ) - echo PACKAGE_VERSION: %PACKAGE_VERSION% - (echo PACKAGE_VERSION=%PACKAGE_VERSION%) >> %GITHUB_ENV% - - # conda-index does not support python 3.13 - - name: Remove conda-index - run: mamba remove conda-index - - - name: Install dpnp - run: | - @echo on - mamba install ${{ env.PACKAGE_NAME }}=${{ env.PACKAGE_VERSION }} pytest python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} - env: - TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.CHANNELS }}' - MAMBA_NO_LOW_SPEED_LIMIT: 1 - - - name: List installed packages - run: mamba list - - - name: Activate OCL CPU RT - shell: pwsh - run: | - $script_path="$env:CONDA_PREFIX\Scripts\set-intel-ocl-icd-registry.ps1" - if (Test-Path $script_path) { - &$script_path - } else { - Write-Warning "File $script_path was NOT found!" - } - # Check the variable assisting OpenCL CPU driver to find TBB DLLs which are not located where it expects them by default - $cl_cfg="$env:CONDA_PREFIX\Library\lib\cl.cfg" - Get-Content -Tail 5 -Path $cl_cfg - - - name: Smoke test - run: | - python -c "import dpctl; dpctl.lsplatform()" - python -c "import dpnp; print(dpnp.__version__)" - - - name: Run tests for all dtypes - env: - DPNP_TEST_ALL_INT_TYPES: 1 - run: | - python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + if ( ${{ matrix.python }} -eq ${{ env.LATEST_PYTHON }} ) { + set DPNP_TEST_ALL_INT_TYPES=1 + python -m pytest -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + } else { + python -m pytest -n auto -ra --pyargs ${{ env.PACKAGE_NAME }}.tests + } upload: name: Upload diff --git a/dpnp/dpnp_utils/dpnp_utils_linearalgebra.py b/dpnp/dpnp_utils/dpnp_utils_linearalgebra.py index 5767fdd4e52f..8dfc3b5e0ffe 100644 --- a/dpnp/dpnp_utils/dpnp_utils_linearalgebra.py +++ b/dpnp/dpnp_utils/dpnp_utils_linearalgebra.py @@ -509,8 +509,8 @@ def _gemm_special_case(x1, x2, res_dtype, call_flag): while `gemv` does not. """ - # TODO: replace with dpnp.int8 when it is added - is_int8 = x1.dtype == numpy.int8 and x2.dtype == numpy.int8 + + is_int8 = x1.dtype == dpnp.int8 and x2.dtype == dpnp.int8 is_int32_or_f32 = res_dtype in [dpnp.int32, dpnp.float32] flag = is_int8 and is_int32_or_f32 and call_flag in ["gemm", "gemm_batch"] diff --git a/dpnp/tests/test_indexing.py b/dpnp/tests/test_indexing.py index 78b0407bf340..1efef172cf6c 100644 --- a/dpnp/tests/test_indexing.py +++ b/dpnp/tests/test_indexing.py @@ -473,7 +473,7 @@ def test_input_1d(self, a_dt, indices, ind_dt, ivals, mode): b.put(ind, vals, mode=mode) ib.put(iind, ivals, mode=mode) assert_array_equal(ib, b) - elif numpy.issubdtype(ind_dt, numpy.uint64): + elif ind_dt == numpy.uint64: # For this special case, NumPy raises an error but dpnp works assert_raises(TypeError, numpy.put, a, ind, vals, mode=mode) assert_raises(TypeError, b.put, ind, vals, mode=mode) @@ -508,7 +508,7 @@ def test_input_2d(self, a_dt, indices, ind_dt, mode): ind = get_abs_array(indices, ind_dt) iind = dpnp.array(ind) - if numpy.issubdtype(ind_dt, numpy.uint64): + if ind_dt == numpy.uint64: # For this special case, NumPy raises an error but dpnp works assert_raises(TypeError, numpy.put, a, ind, vals, mode=mode) @@ -656,7 +656,7 @@ def test_broadcast(self, arr_dt, idx_dt): ind = numpy.arange(10, dtype=idx_dt).reshape((1, 2, 5)) % 4 ia, iind = dpnp.array(a), dpnp.array(ind) - if numpy.issubdtype(idx_dt, numpy.uint64): + if idx_dt == numpy.uint64: numpy.put_along_axis(a, ind, 20, axis=1) dpnp.put_along_axis(ia, iind, 20, axis=1) assert_array_equal(ia, a) @@ -701,7 +701,7 @@ def test_1d(self, a_dt, ind_dt, indices, mode): result = dpnp.take(ia, iind, mode=mode) expected = numpy.take(a, ind, mode=mode) assert_array_equal(result, expected) - elif numpy.issubdtype(ind_dt, numpy.uint64): + elif ind_dt == numpy.uint64: # For this special case, although casting `ind_dt` to numpy.intp # is not safe, both NumPy and dpnp work properly # NumPy < "2.2.0" raises an error @@ -726,7 +726,7 @@ def test_2d(self, a_dt, ind_dt, indices, mode, axis): ind = get_abs_array(indices, ind_dt) ia, iind = dpnp.array(a), dpnp.array(ind) - if numpy.issubdtype(ind_dt, numpy.uint64): + if ind_dt == numpy.uint64: # For this special case, NumPy raises an error on Windows result = ia.take(iind, axis=axis, mode=mode) expected = a.take(ind.astype(numpy.int64), axis=axis, mode=mode) @@ -1461,6 +1461,16 @@ def test_choose_inds_all_dtypes(self, dtype): chcs = dpnp.ones(1, dtype=dtype) with pytest.raises(TypeError): dpnp.choose(inds, chcs) + elif dtype == numpy.uint64: + # For this special case, NumPy raises an error but dpnp works + inds_np = numpy.array([1, 0, 1], dtype=dtype) + inds = dpnp.array(inds_np) + chcs_np = numpy.array([1, 2, 3], dtype=dtype) + chcs = dpnp.array(chcs_np) + assert_raises(TypeError, numpy.choose, inds_np, chcs_np) + expected = numpy.choose(inds_np.astype(numpy.int64), chcs_np) + result = dpnp.choose(inds, chcs) + assert_array_equal(expected, result) else: inds_np = numpy.array([1, 0, 1], dtype=dtype) inds = dpnp.array(inds_np) diff --git a/dpnp/tests/test_linalg.py b/dpnp/tests/test_linalg.py index 7f1ae77966fa..7e0fb98ea498 100644 --- a/dpnp/tests/test_linalg.py +++ b/dpnp/tests/test_linalg.py @@ -2401,10 +2401,10 @@ def test_qr(self, dtype, shape, mode): decimal=5, ) else: # mode=="raw" - assert_dtype_allclose(dpnp_q, np_q) + assert_dtype_allclose(dpnp_q, np_q, factor=24) if mode in ("raw", "r"): - assert_dtype_allclose(dpnp_r, np_r) + assert_dtype_allclose(dpnp_r, np_r, factor=24) @pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True)) @pytest.mark.parametrize( diff --git a/dpnp/tests/test_product.py b/dpnp/tests/test_product.py index 6629e55aafb2..b7cbfcf61e6d 100644 --- a/dpnp/tests/test_product.py +++ b/dpnp/tests/test_product.py @@ -836,7 +836,11 @@ def test_dtype_matrix(self, dt_in1, dt_in2, dt_out, shape1, shape2): assert_allclose(result, expected, rtol=1e-5, atol=1e-5) else: assert_raises(TypeError, dpnp.matmul, ia, ib, dtype=dt_out) - assert_raises(TypeError, numpy.matmul, a, b, dtype=dt_out) + # If one of the inputs is `uint64`, and dt_out is not unsigned int + # NumPy raises TypeError when `out` is provide but not when `dtype` + # is provided. dpnp raises TypeError in both cases as expected + if a.dtype != numpy.uint64 and b.dtype != numpy.uint64: + assert_raises(TypeError, numpy.matmul, a, b, dtype=dt_out) assert_raises(TypeError, dpnp.matmul, ia, ib, out=iout) assert_raises(TypeError, numpy.matmul, a, b, out=out) @@ -1444,8 +1448,8 @@ def setup_method(self): ], ) def test_basic(self, dtype, shape1, shape2): - a = generate_random_numpy_array(shape1, dtype) - b = generate_random_numpy_array(shape2, dtype) + a = generate_random_numpy_array(shape1, dtype, low=-5, high=5) + b = generate_random_numpy_array(shape2, dtype, low=-5, high=5) ia, ib = dpnp.array(a), dpnp.array(b) result = dpnp.matvec(ia, ib) @@ -2170,8 +2174,8 @@ def setup_method(self): ], ) def test_basic(self, dtype, shape1, shape2): - a = generate_random_numpy_array(shape1, dtype) - b = generate_random_numpy_array(shape2, dtype) + a = generate_random_numpy_array(shape1, dtype, low=-5, high=5) + b = generate_random_numpy_array(shape2, dtype, low=-5, high=5) ia, ib = dpnp.array(a), dpnp.array(b) result = dpnp.vecmat(ia, ib) diff --git a/dpnp/tests/test_statistics.py b/dpnp/tests/test_statistics.py index d5d0e72b030d..eb064334378f 100644 --- a/dpnp/tests/test_statistics.py +++ b/dpnp/tests/test_statistics.py @@ -219,8 +219,14 @@ def test_correlate(self, a, v, mode, dtype, method): @pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True)) @pytest.mark.parametrize("method", ["auto", "direct", "fft"]) def test_correlate_random(self, a_size, v_size, mode, dtype, method): - an = generate_random_numpy_array(a_size, dtype, probability=0.9) - vn = generate_random_numpy_array(v_size, dtype, probability=0.9) + if dtype in [numpy.int8, numpy.uint8]: + pytest.skip("avoid overflow.") + an = generate_random_numpy_array( + a_size, dtype, low=-3, high=3, probability=0.9 + ) + vn = generate_random_numpy_array( + v_size, dtype, low=-3, high=3, probability=0.9 + ) ad = dpnp.array(an) vd = dpnp.array(vn)