diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 5398458e67df..10ae39a62db5 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -269,6 +269,119 @@ jobs: python -m pytest -n auto -ra --pyargs dpnp.tests.tensor + test_examples_linux: + name: Test examples + + needs: build + + runs-on: ubuntu-latest + timeout-minutes: 60 + + defaults: + run: + shell: bash -el {0} + + strategy: + matrix: + python: ['3.14'] + + env: + dpnp-repo-path: '${{ github.workspace }}/source/' + create-conda-channel-env: 'source/environments/create_conda_channel.yml' + channel-path: '${{ github.workspace }}/channel/' + pkg-path-in-channel: '${{ github.workspace }}/channel/linux-64/' + ver-json-path: '${{ github.workspace }}/version.json' + examples-env-name: 'examples_test' + + steps: + - name: Checkout DPNP repo + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: ${{ env.fetch-depth }} + path: ${{ env.dpnp-repo-path }} + + - name: Download artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + 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@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1 + with: + miniforge-version: latest + use-mamba: 'true' + conda-remove-defaults: 'true' + environment-file: ${{ env.create-conda-channel-env }} + activate-environment: ${{ env.examples-env-name }} + + - name: ReSetup miniconda + if: steps.setup_miniconda.outcome == 'failure' + uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1 + with: + miniforge-version: latest + use-mamba: 'true' + conda-remove-defaults: 'true' + environment-file: ${{ env.create-conda-channel-env }} + activate-environment: ${{ env.examples-env-name }} + + - 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: | + PACKAGE_VERSION=$(python -c "${{ env.ver-script-part1 }} ${{ env.ver-script-part2 }}") + echo "PACKAGE_VERSION=${PACKAGE_VERSION}" >> "$GITHUB_ENV" + + - name: Install dpnp + id: install_dpnp + continue-on-error: true + run: | + mamba install ${{ env.package-name }}=${{ env.PACKAGE_VERSION }} python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} + env: + TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.channels-list }}' + + - name: ReInstall dpnp + if: steps.install_dpnp.outcome == 'failure' + run: | + mamba install ${{ env.package-name }}=${{ env.PACKAGE_VERSION }} python=${{ matrix.python }} ${{ env.TEST_CHANNELS }} + env: + TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.channels-list }}' + + - name: Install example requirements + run: | + mamba install pytest dpcpp_linux-64">=2026.0.0" cmake ninja scikit-build ${{ env.TEST_CHANNELS }} + env: + TEST_CHANNELS: '-c ${{ env.channel-path }} ${{ env.channels-list }}' + + - 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: Build and run pybind11 examples + run: | + cd ${{ env.dpnp-repo-path }}/examples/pybind11 + for d in */; do + pushd "$d" > /dev/null + CC=icx CXX=icpx python setup.py build_ext --inplace -G Ninja || exit 1 + if [ -d tests ]; then + python -m pytest tests || exit 1 + fi + popd > /dev/null + done + test_windows: name: Test @@ -451,7 +564,7 @@ jobs: upload: name: Upload - needs: [test_linux, test_windows] + needs: [test_linux, test_windows, test_examples_linux] strategy: fail-fast: false diff --git a/.gitignore b/.gitignore index f66bfbb3fdd8..ec273636cf6e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ _skbuild build_cython cython_debug dpnp.egg-info +*.egg-info # Byte-compiled / optimized / DLL files __pycache__/ @@ -27,9 +28,13 @@ dpnp_pytest.* # Build examples example3 +# moved cmake scripts +dpnp/resources/cmake + *dpnp_backend* dpnp/include/dpnp/tensor/*.h dpnp/**/*.cpython*.so dpnp/**/*.pyd *~ core +*.so diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d4c677dd4dd..687e57d6ef1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -327,6 +327,21 @@ else() message(FATAL_ERROR "Unsupported system.") endif() +# install dpnp-config.cmake for find_package() support +install( + FILES ${CMAKE_SOURCE_DIR}/cmake/dpnp-config.cmake + DESTINATION dpnp/resources/cmake +) +install(FILES ${CMAKE_SOURCE_DIR}/cmake/dpnp-config.cmake DESTINATION lib/cmake/dpnp) + +# install dpnp4pybind11.hpp and usm_ndarray_constants.h into include folder +install( + DIRECTORY ${CMAKE_SOURCE_DIR}/dpnp/include/ + DESTINATION dpnp/include + FILES_MATCHING + REGEX "\\.(h|hpp)$" +) + # Define flags for CMAKE_BUILD_TYPE=Coverage set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_DEBUG} -O1 -g1 -DDEBUG") set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG} -O1 -g1 -DDEBUG") diff --git a/cmake/dpnp-config.cmake b/cmake/dpnp-config.cmake new file mode 100644 index 000000000000..74f648942485 --- /dev/null +++ b/cmake/dpnp-config.cmake @@ -0,0 +1,65 @@ +#.rst: +# +# Find the include directory for ``dpnp4pybind11.hpp`` and dpnp tensor kernels. +# +# This module sets the following variables: +# +# ``Dpnp_FOUND`` +# True if DPNP was found. +# ``Dpnp_INCLUDE_DIR`` +# The include directory needed to use dpnp. +# ``Dpnp_TENSOR_INCLUDE_DIR`` +# The include directory for tensor kernels implementation. +# ``Dpnp_VERSION`` +# The version of dpnp found. +# +# The module will also explicitly define two cache variables: +# +# ``Dpnp_INCLUDE_DIR`` +# ``Dpnp_TENSOR_INCLUDE_DIR`` +# + +if(NOT Dpnp_FOUND) + find_package(Python 3.10 REQUIRED COMPONENTS Interpreter Development.Module) + + if(Python_EXECUTABLE) + execute_process( + COMMAND "${Python_EXECUTABLE}" -m dpnp --include-dir + OUTPUT_VARIABLE _dpnp_include_dir + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + execute_process( + COMMAND "${Python_EXECUTABLE}" -c "import dpnp; print(dpnp.__version__)" + OUTPUT_VARIABLE Dpnp_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + endif() +endif() + +find_path( + Dpnp_INCLUDE_DIR + dpnp4pybind11.hpp + PATHS "${_dpnp_include_dir}" "${Python_INCLUDE_DIRS}" + PATH_SUFFIXES dpnp/include +) +get_filename_component(_dpnp_dir "${Dpnp_INCLUDE_DIR}" DIRECTORY) + +find_path(Dpnp_TENSOR_INCLUDE_DIR kernels PATHS "${_dpnp_dir}/tensor/libtensor/include") + +find_path(Dpnp_TENSOR_INCLUDE_DIR utils PATHS "${_dpnp_dir}/tensor/libtensor/include") + +set(Dpnp_INCLUDE_DIRS ${Dpnp_INCLUDE_DIR}) + +# handle the QUIETLY and REQUIRED arguments and set Dpnp_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + Dpnp + REQUIRED_VARS Dpnp_INCLUDE_DIR Dpnp_TENSOR_INCLUDE_DIR + VERSION_VAR Dpnp_VERSION +) + +mark_as_advanced(Dpnp_INCLUDE_DIR) +mark_as_advanced(Dpnp_TENSOR_INCLUDE_DIR) diff --git a/dpnp/__main__.py b/dpnp/__main__.py index 4368144a02eb..7520a63a784d 100644 --- a/dpnp/__main__.py +++ b/dpnp/__main__.py @@ -41,7 +41,7 @@ def _dpnp_dir() -> str: def get_include_dir() -> str: """Returns path to dpnp include directory containing dpnp4pybind11.hpp""" - return os.path.join(_dpnp_dir(), "backend", "include") + return os.path.join(_dpnp_dir(), "include") def print_include_flags() -> None: @@ -61,6 +61,13 @@ def print_tensor_include_flags() -> None: print("-I " + libtensor_dir) +def print_cmake_dir() -> None: + """Prints directory with dpnp-config.cmake""" + dpnp_dir = _dpnp_dir() + cmake_dir = os.path.join(dpnp_dir, "resources", "cmake") + print(cmake_dir) + + def main() -> None: """Main entry-point.""" parser = argparse.ArgumentParser() @@ -84,6 +91,11 @@ def main() -> None: action="store_true", help="Path to dpnp libtensor include directory.", ) + parser.add_argument( + "--cmakedir", + action="store_true", + help="CMake module directory, ideal for setting -DDpnp_ROOT in CMake.", + ) args = parser.parse_args() if not sys.argv[1:]: parser.print_help() @@ -95,6 +107,8 @@ def main() -> None: print_tensor_include_flags() if args.tensor_include_dir: print(get_tensor_include_dir()) + if args.cmakedir: + print_cmake_dir() if __name__ == "__main__": diff --git a/dpnp/backend/extensions/blas/CMakeLists.txt b/dpnp/backend/extensions/blas/CMakeLists.txt index b4013d82eb40..6b65984e0a76 100644 --- a/dpnp/backend/extensions/blas/CMakeLists.txt +++ b/dpnp/backend/extensions/blas/CMakeLists.txt @@ -70,7 +70,7 @@ target_include_directories( ${python_module_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../common - ${CMAKE_SOURCE_DIR}/dpnp/backend/include + ${CMAKE_SOURCE_DIR}/dpnp/include ${CMAKE_SOURCE_DIR}/dpnp/tensor/libtensor/include ) diff --git a/dpnp/backend/extensions/blas/dot_common.hpp b/dpnp/backend/extensions/blas/dot_common.hpp index d4819be74036..0cf0c929642e 100644 --- a/dpnp/backend/extensions/blas/dot_common.hpp +++ b/dpnp/backend/extensions/blas/dot_common.hpp @@ -32,6 +32,8 @@ #include +#include "dpnp4pybind11.hpp" + // dpnp tensor headers #include "utils/memory_overlap.hpp" #include "utils/output_validation.hpp" diff --git a/dpnp/backend/extensions/fft/CMakeLists.txt b/dpnp/backend/extensions/fft/CMakeLists.txt index 9c452d94bd23..7c8367b467e6 100644 --- a/dpnp/backend/extensions/fft/CMakeLists.txt +++ b/dpnp/backend/extensions/fft/CMakeLists.txt @@ -63,7 +63,7 @@ set_target_properties( target_include_directories( ${python_module_name} PRIVATE - ${CMAKE_SOURCE_DIR}/dpnp/backend/include + ${CMAKE_SOURCE_DIR}/dpnp/include ${CMAKE_SOURCE_DIR}/dpnp/tensor/libtensor/include ) diff --git a/dpnp/backend/extensions/indexing/CMakeLists.txt b/dpnp/backend/extensions/indexing/CMakeLists.txt index ce800a87124c..827a830e43a1 100644 --- a/dpnp/backend/extensions/indexing/CMakeLists.txt +++ b/dpnp/backend/extensions/indexing/CMakeLists.txt @@ -68,7 +68,7 @@ target_include_directories( PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../ ${CMAKE_CURRENT_SOURCE_DIR}/../common - ${CMAKE_SOURCE_DIR}/dpnp/backend/include + ${CMAKE_SOURCE_DIR}/dpnp/include ${CMAKE_SOURCE_DIR}/dpnp/tensor/libtensor/include ) diff --git a/dpnp/backend/extensions/lapack/CMakeLists.txt b/dpnp/backend/extensions/lapack/CMakeLists.txt index 6c898df05236..ecb0c31d391f 100644 --- a/dpnp/backend/extensions/lapack/CMakeLists.txt +++ b/dpnp/backend/extensions/lapack/CMakeLists.txt @@ -87,7 +87,7 @@ target_include_directories( ${python_module_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../common - ${CMAKE_SOURCE_DIR}/dpnp/backend/include + ${CMAKE_SOURCE_DIR}/dpnp/include ${CMAKE_SOURCE_DIR}/dpnp/tensor/libtensor/include ) diff --git a/dpnp/backend/extensions/lapack/evd_batch_common.hpp b/dpnp/backend/extensions/lapack/evd_batch_common.hpp index 088f64a0678e..f57e68af2a35 100644 --- a/dpnp/backend/extensions/lapack/evd_batch_common.hpp +++ b/dpnp/backend/extensions/lapack/evd_batch_common.hpp @@ -31,6 +31,8 @@ #include #include +#include "dpnp4pybind11.hpp" + // dpnp tensor headers #include "utils/type_dispatch.hpp" diff --git a/dpnp/backend/extensions/lapack/evd_common.hpp b/dpnp/backend/extensions/lapack/evd_common.hpp index cfba50e87722..c16f1995f8a8 100644 --- a/dpnp/backend/extensions/lapack/evd_common.hpp +++ b/dpnp/backend/extensions/lapack/evd_common.hpp @@ -31,6 +31,8 @@ #include #include +#include "dpnp4pybind11.hpp" + // dpnp tensor headers #include "utils/type_dispatch.hpp" diff --git a/dpnp/backend/extensions/lapack/evd_common_utils.hpp b/dpnp/backend/extensions/lapack/evd_common_utils.hpp index ab792d47c08c..f8f8056bfeb0 100644 --- a/dpnp/backend/extensions/lapack/evd_common_utils.hpp +++ b/dpnp/backend/extensions/lapack/evd_common_utils.hpp @@ -30,6 +30,8 @@ #include +#include "dpnp4pybind11.hpp" + // dpnp tensor headers #include "utils/memory_overlap.hpp" #include "utils/output_validation.hpp" diff --git a/dpnp/backend/extensions/lapack/gesv_common_utils.hpp b/dpnp/backend/extensions/lapack/gesv_common_utils.hpp index 44bfbffd7181..f492054b071f 100644 --- a/dpnp/backend/extensions/lapack/gesv_common_utils.hpp +++ b/dpnp/backend/extensions/lapack/gesv_common_utils.hpp @@ -30,6 +30,8 @@ #include +#include "dpnp4pybind11.hpp" + // dpnp tensor headers #include "utils/memory_overlap.hpp" #include "utils/output_validation.hpp" diff --git a/dpnp/backend/extensions/lapack/gesvd_common_utils.hpp b/dpnp/backend/extensions/lapack/gesvd_common_utils.hpp index 201cd5212e06..8e2760a9bd4c 100644 --- a/dpnp/backend/extensions/lapack/gesvd_common_utils.hpp +++ b/dpnp/backend/extensions/lapack/gesvd_common_utils.hpp @@ -30,6 +30,8 @@ #include #include +#include "dpnp4pybind11.hpp" + // dpnp tensor headers #include "utils/memory_overlap.hpp" #include "utils/output_validation.hpp" diff --git a/dpnp/backend/extensions/statistics/CMakeLists.txt b/dpnp/backend/extensions/statistics/CMakeLists.txt index 434d223de3ab..1d5b5947e556 100644 --- a/dpnp/backend/extensions/statistics/CMakeLists.txt +++ b/dpnp/backend/extensions/statistics/CMakeLists.txt @@ -73,7 +73,7 @@ target_include_directories( PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../ ${CMAKE_CURRENT_SOURCE_DIR}/../common - ${CMAKE_SOURCE_DIR}/dpnp/backend/include + ${CMAKE_SOURCE_DIR}/dpnp/include ${CMAKE_SOURCE_DIR}/dpnp/tensor/libtensor/include ) diff --git a/dpnp/backend/extensions/statistics/sliding_dot_product1d.hpp b/dpnp/backend/extensions/statistics/sliding_dot_product1d.hpp index 131469500016..4cab1b41e4b3 100644 --- a/dpnp/backend/extensions/statistics/sliding_dot_product1d.hpp +++ b/dpnp/backend/extensions/statistics/sliding_dot_product1d.hpp @@ -28,10 +28,13 @@ #pragma once -#include "ext/dispatch_table.hpp" #include #include +#include "dpnp4pybind11.hpp" + +#include "ext/dispatch_table.hpp" + namespace statistics::sliding_window1d { struct SlidingDotProduct1d diff --git a/dpnp/backend/extensions/ufunc/CMakeLists.txt b/dpnp/backend/extensions/ufunc/CMakeLists.txt index 2b01823d01f3..9c0b68c4cc9d 100644 --- a/dpnp/backend/extensions/ufunc/CMakeLists.txt +++ b/dpnp/backend/extensions/ufunc/CMakeLists.txt @@ -90,7 +90,7 @@ target_include_directories( PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../ ${CMAKE_CURRENT_SOURCE_DIR}/../common - ${CMAKE_SOURCE_DIR}/dpnp/backend/include + ${CMAKE_SOURCE_DIR}/dpnp/include ${CMAKE_SOURCE_DIR}/dpnp/tensor/libtensor/include ) diff --git a/dpnp/backend/extensions/vm/CMakeLists.txt b/dpnp/backend/extensions/vm/CMakeLists.txt index 05aa64e0d814..5c58136744d7 100644 --- a/dpnp/backend/extensions/vm/CMakeLists.txt +++ b/dpnp/backend/extensions/vm/CMakeLists.txt @@ -112,7 +112,7 @@ target_include_directories( ${python_module_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../common - ${CMAKE_SOURCE_DIR}/dpnp/backend/include + ${CMAKE_SOURCE_DIR}/dpnp/include ${CMAKE_SOURCE_DIR}/dpnp/tensor/libtensor/include ) diff --git a/dpnp/backend/extensions/window/CMakeLists.txt b/dpnp/backend/extensions/window/CMakeLists.txt index 9dac2df9d0df..536f9c0ad2fd 100644 --- a/dpnp/backend/extensions/window/CMakeLists.txt +++ b/dpnp/backend/extensions/window/CMakeLists.txt @@ -68,7 +68,7 @@ target_include_directories( PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../ ${CMAKE_CURRENT_SOURCE_DIR}/../common - ${CMAKE_SOURCE_DIR}/dpnp/backend/include + ${CMAKE_SOURCE_DIR}/dpnp/include ${CMAKE_SOURCE_DIR}/dpnp/tensor/libtensor/include ) diff --git a/dpnp/backend/include/dpnp4pybind11.hpp b/dpnp/include/dpnp4pybind11.hpp similarity index 99% rename from dpnp/backend/include/dpnp4pybind11.hpp rename to dpnp/include/dpnp4pybind11.hpp index a64a5074beb7..22764bb11bd6 100644 --- a/dpnp/backend/include/dpnp4pybind11.hpp +++ b/dpnp/include/dpnp4pybind11.hpp @@ -35,7 +35,7 @@ #include "dpnp/tensor/_usmarray.h" #include "dpnp/tensor/_usmarray_api.h" // Include usm_ndarray constants (flags, type numbers) -#include "../../tensor/include/usm_ndarray_constants.h" +#include "usm_ndarray_constants.h" #include #include diff --git a/dpnp/tensor/include/usm_ndarray_constants.h b/dpnp/include/usm_ndarray_constants.h similarity index 100% rename from dpnp/tensor/include/usm_ndarray_constants.h rename to dpnp/include/usm_ndarray_constants.h diff --git a/dpnp/tensor/CMakeLists.txt b/dpnp/tensor/CMakeLists.txt index d0fe57cade64..3a74361336c5 100644 --- a/dpnp/tensor/CMakeLists.txt +++ b/dpnp/tensor/CMakeLists.txt @@ -74,7 +74,10 @@ file(GLOB _cython_sources *.pyx) foreach(_cy_file ${_cython_sources}) get_filename_component(_trgt ${_cy_file} NAME_WLE) build_dpnp_tensor_ext(${_trgt} ${_cy_file} "dpnp/tensor" RELATIVE_PATH "..") - target_include_directories(${_trgt} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) + target_include_directories( + ${_trgt} + PRIVATE ${CMAKE_SOURCE_DIR}/dpnp/include ${CMAKE_CURRENT_SOURCE_DIR}/include + ) endforeach() if(WIN32) @@ -352,7 +355,7 @@ foreach(python_module_name ${_py_trgts}) target_include_directories( ${python_module_name} PRIVATE - ${CMAKE_SOURCE_DIR}/dpnp/backend/include + ${CMAKE_SOURCE_DIR}/dpnp/include ${Dpctl_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libtensor/include ${CMAKE_CURRENT_SOURCE_DIR}/libtensor/source/ diff --git a/dpnp/tests/test_cli_options.py b/dpnp/tests/test_cli_options.py index 1d353e9fddf8..86fca7c18523 100644 --- a/dpnp/tests/test_cli_options.py +++ b/dpnp/tests/test_cli_options.py @@ -1,3 +1,4 @@ +import os import subprocess import sys @@ -36,3 +37,13 @@ def test_tensor_includes(): assert res.stdout dir = res.stdout.decode("utf-8") assert flags == "-I " + dir + + +def test_cmakedir(): + res = subprocess.run( + [sys.executable, "-m", "dpnp", "--cmakedir"], capture_output=True + ) + assert res.returncode == 0 + assert res.stdout + cmake_dir = res.stdout.decode("utf-8").strip() + assert os.path.exists(os.path.join(cmake_dir, "dpnp-config.cmake")) diff --git a/examples/pybind11/use_dpnp_array/CMakeLists.txt b/examples/pybind11/use_dpnp_array/CMakeLists.txt new file mode 100644 index 000000000000..09212a4e8f08 --- /dev/null +++ b/examples/pybind11/use_dpnp_array/CMakeLists.txt @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# ***************************************************************************** +# Copyright (c) 2026, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# - Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# ***************************************************************************** + +cmake_minimum_required(VERSION 3.21...3.27 FATAL_ERROR) + +project( + use_dpnp_array + VERSION 0.1 + LANGUAGES CXX + DESCRIPTION "Example of using dpnp::tensor::usm_ndarray type caster" +) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Fetch pybind11 +include(FetchContent) +FetchContent_Declare( + pybind11 + URL https://github.com/pybind/pybind11/archive/refs/tags/v3.0.4.tar.gz + URL_HASH SHA256=74b6a2c2b4573a400cafb6ecbf60c98df300cd3d0041296b913d02b2cbbb2676 + FIND_PACKAGE_ARGS NAMES pybind11 +) +FetchContent_MakeAvailable(pybind11) + +find_package(Python REQUIRED COMPONENTS Development.Module) +find_package(Dpctl REQUIRED) +find_package(IntelSYCL REQUIRED) +find_package(Dpnp REQUIRED) + +set(py_module_name _use_dpnp_array) +set(_sources use_dpnp_array/_example.cpp) +pybind11_add_module(${py_module_name} MODULE ${_sources}) +add_sycl_to_target(TARGET ${py_module_name} SOURCES ${_sources}) + +target_include_directories( + ${py_module_name} + PRIVATE ${Dpnp_INCLUDE_DIR} ${Dpctl_INCLUDE_DIR} +) + +install(TARGETS ${py_module_name} DESTINATION use_dpnp_array) + +set(ignoreMe "${SKBUILD}") diff --git a/examples/pybind11/use_dpnp_array/setup.py b/examples/pybind11/use_dpnp_array/setup.py new file mode 100644 index 000000000000..175f17493edb --- /dev/null +++ b/examples/pybind11/use_dpnp_array/setup.py @@ -0,0 +1,38 @@ +# ***************************************************************************** +# Copyright (c) 2026, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# - Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# ***************************************************************************** + +from skbuild import setup + +setup( + name="use_dpnp_array", + version="0.0.1", + description="Example of using dpnp::tensor::usm_ndarray with pybind11", + author="Intel Corporation", + license="BSD-3-Clause", + packages=["use_dpnp_array"], +) diff --git a/examples/pybind11/use_dpnp_array/tests/test_use_dpnp_array.py b/examples/pybind11/use_dpnp_array/tests/test_use_dpnp_array.py new file mode 100644 index 000000000000..8b2206ef177e --- /dev/null +++ b/examples/pybind11/use_dpnp_array/tests/test_use_dpnp_array.py @@ -0,0 +1,77 @@ +# ***************************************************************************** +# Copyright (c) 2026, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# - Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# ***************************************************************************** + +import use_dpnp_array as uda + +import dpnp.tensor as dpt + + +def test_ndim(): + arr = dpt.usm_ndarray((3, 4), dtype="i4") + assert uda.get_ndim(arr) == 2 + arr = dpt.usm_ndarray(10, dtype="f4") + assert uda.get_ndim(arr) == 1 + + +def test_shape(): + arr = dpt.usm_ndarray((5, 7, 3), dtype="f8") + assert uda.get_shape(arr) == [5, 7, 3] + + +def test_size(): + arr = dpt.usm_ndarray((4, 5), dtype="i4") + assert uda.get_size(arr) == 20 + + +def test_elemsize(): + arr_f4 = dpt.usm_ndarray(10, dtype="f4") + assert uda.get_elemsize(arr_f4) == 4 + + arr_f8 = dpt.usm_ndarray(10, dtype="f8") + assert uda.get_elemsize(arr_f8) == 8 + + +def test_c_contiguous(): + arr = dpt.usm_ndarray((3, 4), dtype="f4", order="C") + assert uda.is_c_contiguous(arr) is True + + +def test_f_contiguous(): + arr = dpt.usm_ndarray((3, 4), dtype="f4", order="F") + assert uda.is_f_contiguous(arr) is True + + +def test_writable(): + arr = dpt.usm_ndarray(10, dtype="i4") + assert uda.is_writable(arr) is True + + +def test_typenum(): + arr_f4 = dpt.usm_ndarray(5, dtype="f4") + arr_f8 = dpt.usm_ndarray(5, dtype="f8") + assert uda.get_typenum(arr_f4) != uda.get_typenum(arr_f8) diff --git a/examples/pybind11/use_dpnp_array/use_dpnp_array/__init__.py b/examples/pybind11/use_dpnp_array/use_dpnp_array/__init__.py new file mode 100644 index 000000000000..4b896c222c31 --- /dev/null +++ b/examples/pybind11/use_dpnp_array/use_dpnp_array/__init__.py @@ -0,0 +1,49 @@ +# ***************************************************************************** +# Copyright (c) 2026, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# - Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# - Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# ***************************************************************************** + +from ._use_dpnp_array import ( + get_elemsize, + get_ndim, + get_shape, + get_size, + get_typenum, + is_c_contiguous, + is_f_contiguous, + is_writable, +) + +__all__ = [ + "get_ndim", + "get_shape", + "get_size", + "get_typenum", + "get_elemsize", + "is_c_contiguous", + "is_f_contiguous", + "is_writable", +] diff --git a/examples/pybind11/use_dpnp_array/use_dpnp_array/_example.cpp b/examples/pybind11/use_dpnp_array/use_dpnp_array/_example.cpp new file mode 100644 index 000000000000..27d337bed08c --- /dev/null +++ b/examples/pybind11/use_dpnp_array/use_dpnp_array/_example.cpp @@ -0,0 +1,89 @@ +//***************************************************************************** +// Copyright (c) 2026, Intel Corporation +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// - Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// - Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// - Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +//***************************************************************************** +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines basic pybind11 extension example using +/// dpnp::tensor::usm_ndarray. +//===----------------------------------------------------------------------===// + +#include "dpnp4pybind11.hpp" +#include +#include + +namespace py = pybind11; + +int get_ndim(const dpnp::tensor::usm_ndarray &arr) { return arr.get_ndim(); } + +std::vector get_shape(const dpnp::tensor::usm_ndarray &arr) +{ + return arr.get_shape_vector(); +} + +py::ssize_t get_size(const dpnp::tensor::usm_ndarray &arr) +{ + return arr.get_size(); +} + +int get_typenum(const dpnp::tensor::usm_ndarray &arr) +{ + return arr.get_typenum(); +} + +int get_elemsize(const dpnp::tensor::usm_ndarray &arr) +{ + return arr.get_elemsize(); +} + +bool is_c_contiguous(const dpnp::tensor::usm_ndarray &arr) +{ + return arr.is_c_contiguous(); +} + +bool is_f_contiguous(const dpnp::tensor::usm_ndarray &arr) +{ + return arr.is_f_contiguous(); +} + +bool is_writable(const dpnp::tensor::usm_ndarray &arr) +{ + return arr.is_writable(); +} + +PYBIND11_MODULE(_use_dpnp_array, m) +{ + m.def("get_ndim", &get_ndim); + m.def("get_shape", &get_shape); + m.def("get_size", &get_size); + m.def("get_typenum", &get_typenum); + m.def("get_elemsize", &get_elemsize); + m.def("is_c_contiguous", &is_c_contiguous); + m.def("is_f_contiguous", &is_f_contiguous); + m.def("is_writable", &is_writable); +} diff --git a/setup.py b/setup.py index 1193b61ac2a8..37e22207891f 100644 --- a/setup.py +++ b/setup.py @@ -48,10 +48,11 @@ ], package_data={ "dpnp": [ - "backend/include/*.hpp", + "include/*.h*", "libdpnp_backend_c.so", "dpnp_backend_c.lib", "dpnp_backend_c.dll", + "resources/cmake/*.cmake", "tensor/libtensor/include/kernels/*.h*", "tensor/libtensor/include/kernels/*/*.h*", "tensor/libtensor/include/utils/*.h*",