diff --git a/CMakeLists.txt b/CMakeLists.txt index 87c0053926b3..f36ddfe9ceab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,27 +75,73 @@ option(DPNP_USE_ONEMKL_INTERFACES "Build DPNP with oneMKL Interfaces" OFF ) +set(HIP_TARGETS "" CACHE STRING "HIP architecture for target") + set(_dpnp_sycl_targets) +set(_dpnp_amd_targets) +set(_use_onemkl_interfaces OFF) set(_use_onemkl_interfaces_cuda OFF) +set(_use_onemkl_interfaces_hip OFF) + +set(_dpnp_sycl_target_compile_options) +set(_dpnp_sycl_target_link_options) +set(_dpnp_sycl_mkl_target_compile_options) +set(_dpnp_sycl_mkl_target_link_options) + if ("x${DPNP_SYCL_TARGETS}" STREQUAL "x") - if(DPNP_TARGET_CUDA) - set(_dpnp_sycl_targets "nvptx64-nvidia-cuda,spir64-unknown-unknown") - set(_use_onemkl_interfaces_cuda ON) - else() - if(DEFINED ENV{DPNP_TARGET_CUDA}) - set(_dpnp_sycl_targets "nvptx64-nvidia-cuda,spir64-unknown-unknown") - set(_use_onemkl_interfaces_cuda ON) - endif() - endif() + if(DPNP_TARGET_CUDA) + set(_dpnp_sycl_targets "nvptx64-nvidia-cuda,spir64-unknown-unknown") + set(_use_onemkl_interfaces_cuda ON) + endif() + + if (NOT "x${HIP_TARGETS}" STREQUAL "x") + set(_dpnp_amd_targets ${HIP_TARGETS}) + set(_use_onemkl_interfaces_hip ON) + + if ("x${_dpnp_sycl_targets}" STREQUAL "x") + set(_dpnp_sycl_targets "amdgcn-amd-amdhsa,${_dpnp_sycl_targets}") + else() + set(_dpnp_sycl_targets "amdgcn-amd-amdhsa,spir64-unknown-unknown") + endif() + endif() else() - set(_dpnp_sycl_targets ${DPNP_SYCL_TARGETS}) + set(_dpnp_sycl_targets ${DPNP_SYCL_TARGETS}) + + if (DPNP_SYCL_TARGETS MATCHES "nvptx64-nvidia-cuda") + set(_use_onemkl_interfaces_cuda ON) + endif() + + if (DPNP_SYCL_TARGETS MATCHES "amdgcn-amd-amdhsa") + set(_use_onemkl_interfaces_hip ON) + + if (NOT "x${HIP_TARGETS}" STREQUAL "x") + set(_dpnp_amd_targets ${HIP_TARGETS}) + else() + message(FATAL_ERROR "HIP_TARGETS must be specified when using HIP backend") + endif() + endif() endif() -if(_dpnp_sycl_targets) +if (_dpnp_sycl_targets) message(STATUS "Compiling for -fsycl-targets=${_dpnp_sycl_targets}") + list(APPEND _dpnp_sycl_target_compile_options -fsycl-targets=${_dpnp_sycl_targets}) + list(APPEND _dpnp_sycl_target_link_options -fsycl-targets=${_dpnp_sycl_targets}) + list(APPEND _dpnp_sycl_mkl_target_compile_options -fsycl-targets=${_dpnp_sycl_targets}) + list(APPEND _dpnp_sycl_mkl_target_link_options -fsycl-targets=${_dpnp_sycl_targets}) + if(_dpnp_amd_targets) + set(_dpnp_hip_compile_options -Xsycl-target-backend=amdgcn-amd-amdhsa --offload-arch=${_dpnp_amd_targets}) + set(_dpnp_hip_mkl_compile_options -Xsycl-target-backend --offload-arch=${_dpnp_amd_targets}) + + # Append HIP-specific flags for general SYCL modules + list(APPEND _dpnp_sycl_target_compile_options ${_dpnp_hip_compile_options}) + list(APPEND _dpnp_sycl_target_link_options ${_dpnp_hip_compile_options}) + + # Append HIP-specific flags for MKL modules + list(APPEND _dpnp_sycl_mkl_target_compile_options -fsycl-unnamed-lambda ${_dpnp_hip_mkl_compile_options}) + list(APPEND _dpnp_sycl_mkl_target_link_options ${_dpnp_hip_mkl_compile_options}) + endif() endif() -set(_use_onemkl_interfaces OFF) if(DPNP_USE_ONEMKL_INTERFACES) set(_use_onemkl_interfaces ON) else() @@ -107,13 +153,20 @@ endif() if(_use_onemkl_interfaces) set(BUILD_FUNCTIONAL_TESTS False) set(BUILD_EXAMPLES False) + set(ENABLE_MKLGPU_BACKEND True) + set(ENABLE_MKLCPU_BACKEND True) + if(_use_onemkl_interfaces_cuda) set(ENABLE_CUBLAS_BACKEND True) set(ENABLE_CUSOLVER_BACKEND True) set(ENABLE_CUFFT_BACKEND True) # set(ENABLE_CURAND_BACKEND True) - set(ENABLE_MKLGPU_BACKEND True) - set(ENABLE_MKLCPU_BACKEND True) + endif() + if(_use_onemkl_interfaces_hip) + set(ENABLE_ROCBLAS_BACKEND True) + set(ENABLE_ROCSOLVER_BACKEND True) + set(ENABLE_ROCFFT_BACKEND True) + # set(ENABLE_ROCRAND_BACKEND True) endif() if(DPNP_ONEMKL_INTERFACES_DIR) diff --git a/doc/quick_start_guide.rst b/doc/quick_start_guide.rst index b21cd06a4104..4758799c2f3c 100644 --- a/doc/quick_start_guide.rst +++ b/doc/quick_start_guide.rst @@ -130,18 +130,52 @@ Building ``dpnp`` for these targets requires that these CodePlay plugins be inst installation layout of compatible version. The following plugins from CodePlay are supported: - `oneAPI for NVIDIA(R) GPUs `_ + - `oneAPI for AMD GPUs `_ .. _codeplay_nv_plugin: https://developer.codeplay.com/products/oneapi/nvidia/ +.. _codeplay_amd_plugin: https://developer.codeplay.com/products/oneapi/amd/ Building ``dpnp`` also requires `building Data Parallel Control Library for custom SYCL targets. `_ -Build ``dpnp`` as follows: +``dpnp`` can be built for CUDA devices as follows: .. code-block:: bash python scripts/build_locally.py --target=cuda +And for AMD devices: + +.. code-block:: bash + + python scripts/build_locally.py --target-hip= + +Note that the *oneAPI for AMD GPUs* plugin requires the architecture be specified and only +one architecture can be specified at a time. + +To determine the architecture code (````) for your AMD GPU, run: + +.. code-block:: bash + + rocminfo | grep 'Name: *gfx.*' + +This will print names like ``gfx90a``, ``gfx1030``, etc. +You can then use one of them as the argument to ``--target-hip``. + +For example: + +.. code-block:: bash + python scripts/build_locally.py --target-hip=gfx90a + + +It is, however, possible to build for Intel devices, CUDA devices, and an AMD device +architecture all at once: + +.. code-block:: bash + + python scripts/build_locally.py --target=cuda --target-hip=gfx90a + + Testing ======= diff --git a/dpnp/backend/extensions/blas/CMakeLists.txt b/dpnp/backend/extensions/blas/CMakeLists.txt index d5639a24b268..3bf15efc3f7a 100644 --- a/dpnp/backend/extensions/blas/CMakeLists.txt +++ b/dpnp/backend/extensions/blas/CMakeLists.txt @@ -40,12 +40,12 @@ if(_dpnp_sycl_targets) target_compile_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_mkl_target_compile_options} ) target_link_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_mkl_target_link_options} ) endif() diff --git a/dpnp/backend/extensions/fft/CMakeLists.txt b/dpnp/backend/extensions/fft/CMakeLists.txt index 38b8028ad56d..880885258559 100644 --- a/dpnp/backend/extensions/fft/CMakeLists.txt +++ b/dpnp/backend/extensions/fft/CMakeLists.txt @@ -37,12 +37,12 @@ if(_dpnp_sycl_targets) target_compile_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_mkl_target_compile_options} ) target_link_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_mkl_target_link_options} ) endif() diff --git a/dpnp/backend/extensions/indexing/CMakeLists.txt b/dpnp/backend/extensions/indexing/CMakeLists.txt index df90ea36f256..527097d4ffdf 100644 --- a/dpnp/backend/extensions/indexing/CMakeLists.txt +++ b/dpnp/backend/extensions/indexing/CMakeLists.txt @@ -38,12 +38,12 @@ if(_dpnp_sycl_targets) target_compile_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_target_compile_options} ) target_link_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_target_link_options} ) endif() diff --git a/dpnp/backend/extensions/lapack/CMakeLists.txt b/dpnp/backend/extensions/lapack/CMakeLists.txt index a196b6fac8d0..6f9fad44affa 100644 --- a/dpnp/backend/extensions/lapack/CMakeLists.txt +++ b/dpnp/backend/extensions/lapack/CMakeLists.txt @@ -57,12 +57,12 @@ if(_dpnp_sycl_targets) target_compile_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_mkl_target_compile_options} ) target_link_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_mkl_target_link_options} ) endif() diff --git a/dpnp/backend/extensions/statistics/CMakeLists.txt b/dpnp/backend/extensions/statistics/CMakeLists.txt index 2a5467bff382..1c9027870f92 100644 --- a/dpnp/backend/extensions/statistics/CMakeLists.txt +++ b/dpnp/backend/extensions/statistics/CMakeLists.txt @@ -43,12 +43,12 @@ if(_dpnp_sycl_targets) target_compile_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_target_compile_options} ) target_link_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_target_link_options} ) endif() diff --git a/dpnp/backend/extensions/ufunc/CMakeLists.txt b/dpnp/backend/extensions/ufunc/CMakeLists.txt index d363910f74df..b0e101078c33 100644 --- a/dpnp/backend/extensions/ufunc/CMakeLists.txt +++ b/dpnp/backend/extensions/ufunc/CMakeLists.txt @@ -78,12 +78,12 @@ if(_dpnp_sycl_targets) target_compile_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_target_compile_options} ) target_link_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_target_link_options} ) endif() diff --git a/dpnp/backend/extensions/window/CMakeLists.txt b/dpnp/backend/extensions/window/CMakeLists.txt index a1c329f8a205..27b60c0fdc64 100644 --- a/dpnp/backend/extensions/window/CMakeLists.txt +++ b/dpnp/backend/extensions/window/CMakeLists.txt @@ -38,12 +38,12 @@ if(_dpnp_sycl_targets) target_compile_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_target_compile_options} ) target_link_options( ${python_module_name} PRIVATE - -fsycl-targets=${_dpnp_sycl_targets} + ${_dpnp_sycl_target_link_options} ) endif() diff --git a/scripts/build_locally.py b/scripts/build_locally.py index 33732829650d..3403f98304eb 100644 --- a/scripts/build_locally.py +++ b/scripts/build_locally.py @@ -39,6 +39,7 @@ def run( verbose=False, cmake_opts="", target="intel", + target_hip=None, onemkl_interfaces=False, onemkl_interfaces_dir=None, ): @@ -97,6 +98,9 @@ def run( if "DPL_ROOT" in os.environ: os.environ["DPL_ROOT_HINT"] = os.environ["DPL_ROOT"] + if not target.strip(): + target = "intel" + if target == "cuda": cmake_args += [ "-DDPNP_TARGET_CUDA=ON", @@ -104,6 +108,17 @@ def run( # Always builds using oneMKL interfaces for the cuda target onemkl_interfaces = True + if target_hip is not None: + if not target_hip.strip(): + raise ValueError( + "--target-hip requires an architecture (e.g., gfx90a)" + ) + cmake_args += [ + f"-DHIP_TARGETS={target_hip}", + ] + # Always builds using oneMKL interfaces for the hip target + onemkl_interfaces = True + if onemkl_interfaces: cmake_args += [ "-DDPNP_USE_ONEMKL_INTERFACES=ON", @@ -177,6 +192,13 @@ def run( default="intel", type=str, ) + driver.add_argument( + "--target-hip", + required=False, + help="Enable HIP target for build. " + "Must specify HIP architecture (e.g., --target-hip=gfx90a)", + type=str, + ) driver.add_argument( "--onemkl-interfaces", help="Build using oneMKL Interfaces", @@ -244,6 +266,7 @@ def run( verbose=args.verbose, cmake_opts=args.cmake_opts, target=args.target, + target_hip=args.target_hip, onemkl_interfaces=args.onemkl_interfaces, onemkl_interfaces_dir=args.onemkl_interfaces_dir, )