Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 172 additions & 0 deletions .github/workflows/adaptivecpp-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
name: Build with AdaptiveCpp

on:
push:
branches:
- master
pull_request:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
CHANNELS: "-c conda-forge --override-channels"
# examples that AdaptiveCpp can build
SYCL_EXAMPLES: "cython/sycl_buffer cython/use_dpctl_sycl pybind11/external_usm_allocation pybind11/use_dpctl_sycl_queue"
C_EXAMPLES: "c/py_sycl_ls"

jobs:
test_linux:
name: Build and test with AdaptiveCpp, Python ${{ matrix.python }}
runs-on: ubuntu-latest
timeout-minutes: 120
defaults:
run:
shell: bash -el {0}

strategy:
fail-fast: false
matrix:
include:
- python: '3.14'
python_spec: '3.14.*=*_cp314'
- python: '3.14t'
python_spec: '3.14.*=*_cp314t'

steps:
- name: Checkout dpctl repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# the package version comes from git describe
fetch-depth: 0

- name: Cache conda packages
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
env:
CACHE_NUMBER: 0 # Increase to reset cache
with:
# the package directory that setup-miniconda configures
path: ~/conda_pkgs_dir
key:
${{ runner.os }}-conda-acpp-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-${{ hashFiles('.github/workflows/adaptivecpp-build.yml') }}
restore-keys: |
${{ runner.os }}-conda-acpp-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-
${{ runner.os }}-conda-acpp-${{ env.CACHE_NUMBER }}-

- uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1
with:
auto-update-conda: true
miniforge-version: latest
activate-environment: acpp
channels: conda-forge
conda-remove-defaults: true

- name: Install AdaptiveCpp and build dependencies
run: |
# the Python build string selects the GIL or the free-threaded variant,
# clang must come from the LLVM that adaptivecpp was built against, and
# intel-opencl-rt provides the OpenCL CPU device to run on; the HIP
# backend plugin links libamdhip64.so.6, which ROCm 7 does not provide
conda install -y ${{ env.CHANNELS }} \
"python=${{ matrix.python_spec }}" \
"adaptivecpp=*=cpu_llvm19*" "clang=19.*" "clangxx=19.*" \
"hip-runtime-amd=6.*" \
intel-opencl-rt \
cmake cython ninja numpy pybind11 pytest scikit-build "setuptools<80" versioneer

- name: Report the environment
run: |
conda list
python -VV
acpp-info -l

- name: Build dpctl
run: |
python scripts/build_locally.py --sycl-provider=AdaptiveCpp

- name: List platforms
run: |
python -m dpctl -f
python -c "from dpctl._diagnostics import sycl_provider; assert sycl_provider() == 'AdaptiveCpp'"

- name: Run dpctl/tests on the OpenMP device
env:
ACPP_VISIBILITY_MASK: omp
run: |
python -m pytest -q --capture=sys dpctl/tests

- name: Run dpctl/tests on the OpenCL CPU device
env:
ACPP_VISIBILITY_MASK: ocl
run: |
python -m pytest -q --capture=sys dpctl/tests

- name: Build examples of extensions
env:
PYTHONPATH: ${{ github.workspace }}
run: |
for d in ${SYCL_EXAMPLES}; do
pushd "examples/${d}" > /dev/null
CC="${CONDA_PREFIX}/bin/clang" CXX="${CONDA_PREFIX}/bin/acpp" \
python setup.py build_ext --inplace -G Ninja -- \
-DDPCTL_SYCL_PROVIDER=AdaptiveCpp \
-DDpctl_DIR="${GITHUB_WORKSPACE}/cmake"
popd > /dev/null
done
for d in ${C_EXAMPLES}; do
pushd "examples/${d}" > /dev/null
python setup.py build_ext --inplace
popd > /dev/null
done

- name: Run examples of extensions on the OpenMP device
env:
ACPP_VISIBILITY_MASK: omp
PYTHONPATH: ${{ github.workspace }}
run: |
for d in ${SYCL_EXAMPLES} ${C_EXAMPLES}; do
# the OpenMP backend allocates plain host memory, so every USM kind
# reports usm_type "host" and this example's checks cannot hold
if [ "${d}" = "pybind11/external_usm_allocation" ]; then
continue
fi
pushd "examples/${d}" > /dev/null
python -m pytest -q tests
popd > /dev/null
done

- name: Run examples of extensions on the OpenCL CPU device
env:
ACPP_VISIBILITY_MASK: ocl
PYTHONPATH: ${{ github.workspace }}
run: |
for d in ${SYCL_EXAMPLES} ${C_EXAMPLES}; do
pushd "examples/${d}" > /dev/null
python -m pytest -q tests
popd > /dev/null
done

- name: Run Python examples on the OpenMP device
working-directory: examples/python
env:
ACPP_VISIBILITY_MASK: omp
run: |
while IFS= read -r script; do
echo "Executing ${script}"
python "${script}" --run all
done < <(find . \( -not -name "_*" -and -name "*.py" \))

- name: Run Python examples on the OpenCL CPU device
working-directory: examples/python
env:
ACPP_VISIBILITY_MASK: ocl
run: |
while IFS= read -r script; do
echo "Executing ${script}"
python "${script}" --run all
done < <(find . \( -not -name "_*" -and -name "*.py" \))
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added `add_event` and `add_cleanup_event` methods and `cleanup_events` and `num_cleanup_events` properties to the order manager, for tracking the events that gate the release of objects used by offloaded tasks [gh-2359](https://github.com/IntelPython/dpctl/pull/2359)
* Added `SyclQueue_DeferRelease` C-API function, which defers a release callback until work submitted to a queue completes, and through which `dpctl::utils::keep_args_alive` keeps its arguments alive [gh-2359](https://github.com/IntelPython/dpctl/pull/2359)
* Added `dpctl::utils::defer_release` to `dpctl4pybind11.hpp`, which calls a release callback once the given events have completed [gh-2359](https://github.com/IntelPython/dpctl/pull/2359)
* Added support for building `dpctl` with AdaptiveCpp as the SYCL implementation, selected with `--sycl-provider=AdaptiveCpp` in `scripts/build_locally.py` or `-DDPCTL_SYCL_PROVIDER=AdaptiveCpp` [gh-2384](https://github.com/IntelPython/dpctl/pull/2384)
* Added `dpctl.backend_type.openmp` for the AdaptiveCpp OpenMP host device [gh-2384](https://github.com/IntelPython/dpctl/pull/2384)
* Added `DPCTLService_GetSyclProvider` C-API function and `dpctl._diagnostics.sycl_provider`, which report the SYCL implementation `dpctl` was built with [gh-2384](https://github.com/IntelPython/dpctl/pull/2384)

### Changed
* Object lifetime during offload is now managed by a list of releases deferred until the events that gate them have completed, rather than by a `host_task`. `dpctl` keeps one thread for looking over the list and running the releases that have come due, started by the first release deferred and again in the child of a `fork`, which takes the GIL to do so and lets a release call into the interpreter and free USM allocations [gh-2359](https://github.com/IntelPython/dpctl/pull/2359)
Expand All @@ -25,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Removed the deprecated `dpctl.program` submodule, use `dpctl.compiler` instead [gh-2407](https://github.com/IntelPython/dpctl/pull/2407)

### Fixed
* `dpctl.select_device_with_aspects` no longer raises `SyclDeviceCreationError` when every device with the required aspects has a selector score of zero [gh-2384](https://github.com/IntelPython/dpctl/pull/2384)
* Removed stale `select_host_device` and `has_host_device` names from `dpctl.__all__`, which made `from dpctl import *` fail with `AttributeError` [gh-2410](https://github.com/IntelPython/dpctl/pull/2410)
* A USM allocation that fails now drops the references held for offloaded tasks that have completed, and is attempted once more if that released anything, so that memory only waiting to be given up is not reported as unavailable [gh-2359](https://github.com/IntelPython/dpctl/pull/2359)

Expand Down
82 changes: 66 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,18 @@ option(DPCTL_GENERATE_COVERAGE_FOR_PYBIND11_EXTENSIONS
OFF
)

# SYCL provider selection
set(DPCTL_SYCL_PROVIDER "Intel" CACHE STRING "SYCL compiler provider (Intel or AdaptiveCpp)")
Comment thread
ndgrigorian marked this conversation as resolved.
Resolved
set_property(CACHE DPCTL_SYCL_PROVIDER PROPERTY STRINGS Intel AdaptiveCpp)
if(NOT DPCTL_SYCL_PROVIDER MATCHES "^(Intel|AdaptiveCpp)$")
message(FATAL_ERROR
"DPCTL_SYCL_PROVIDER must be Intel or AdaptiveCpp, not '${DPCTL_SYCL_PROVIDER}'"
)
endif()

set(DPCTL_TARGET_CUDA
""
CACHE STRING
""
CACHE STRING
"Build DPCTL to target CUDA device. \
Set to a truthy value (e.g., ON, TRUE) to use default architecture (sm_50), \
or to a specific architecture like sm_80."
Expand All @@ -49,13 +58,10 @@ size of shared object with offloading sections"
OFF
)

find_package(IntelSYCL REQUIRED PATHS ${CMAKE_SOURCE_DIR}/cmake NO_DEFAULT_PATH)

set(_dpctl_sycl_target_compile_options)
set(_dpctl_sycl_target_link_options)

# architecture mapping
Comment thread
ndgrigorian marked this conversation as resolved.
Resolved
set(_dpctl_sycl_targets)
set(_dpctl_cuda_arch)
set(_acpp_targets_list) # Used strictly for AdaptiveCpp

if ("x${DPCTL_SYCL_TARGETS}" STREQUAL "x")
if (DPCTL_TARGET_CUDA)
Expand All @@ -69,15 +75,25 @@ if ("x${DPCTL_SYCL_TARGETS}" STREQUAL "x")
"Expected 'ON', 'TRUE', 'YES', 'Y', '1', or a CUDA architecture like 'sm_80'."
)
endif()
set(_dpctl_sycl_targets "nvidia_gpu_${_dpctl_cuda_arch},spir64-unknown-unknown")

# Map to Provider Formats
if(DPCTL_SYCL_PROVIDER STREQUAL "Intel")
set(_dpctl_sycl_targets "nvidia_gpu_${_dpctl_cuda_arch},spir64-unknown-unknown")
elseif(DPCTL_SYCL_PROVIDER STREQUAL "AdaptiveCpp")
list(APPEND _acpp_targets_list "cuda:${_dpctl_cuda_arch}")
endif()
endif()

if (DPCTL_TARGET_HIP)
if(DPCTL_TARGET_HIP MATCHES "^gfx")
if(_dpctl_sycl_targets)
set(_dpctl_sycl_targets "amd_gpu_${DPCTL_TARGET_HIP},${_dpctl_sycl_targets}")
else()
set(_dpctl_sycl_targets "amd_gpu_${DPCTL_TARGET_HIP},spir64-unknown-unknown")
if(DPCTL_SYCL_PROVIDER STREQUAL "Intel")
if(_dpctl_sycl_targets)
set(_dpctl_sycl_targets "amd_gpu_${DPCTL_TARGET_HIP},${_dpctl_sycl_targets}")
else()
set(_dpctl_sycl_targets "amd_gpu_${DPCTL_TARGET_HIP},spir64-unknown-unknown")
endif()
elseif(DPCTL_SYCL_PROVIDER STREQUAL "AdaptiveCpp")
list(APPEND _acpp_targets_list "hip:${DPCTL_TARGET_HIP}")
endif()
else()
message(FATAL_ERROR
Expand All @@ -86,6 +102,11 @@ if ("x${DPCTL_SYCL_TARGETS}" STREQUAL "x")
)
endif()
endif()

if(_acpp_targets_list)
# generic runs dpctl's kernels on the OpenMP and OpenCL devices
list(PREPEND _acpp_targets_list generic)
endif()
else()
if ("${DPCTL_SYCL_TARGETS}" MATCHES "amdgcn-amd-amdhsa")
message(FATAL_ERROR
Expand All @@ -94,12 +115,41 @@ else()
)
endif()
set(_dpctl_sycl_targets ${DPCTL_SYCL_TARGETS})
if(DPCTL_SYCL_PROVIDER STREQUAL "AdaptiveCpp")
set(_acpp_targets_list ${DPCTL_SYCL_TARGETS})
endif()
endif()

if (_dpctl_sycl_targets)
message(STATUS "Compiling for -fsycl-targets=${_dpctl_sycl_targets}")
list(APPEND _dpctl_sycl_target_compile_options -fsycl-targets=${_dpctl_sycl_targets})
list(APPEND _dpctl_sycl_target_link_options -fsycl-targets=${_dpctl_sycl_targets})
# Load the SYCL env
set(_dpctl_sycl_target_compile_options)
set(_dpctl_sycl_target_link_options)

if(DPCTL_SYCL_PROVIDER STREQUAL "Intel")
message(STATUS "Using Intel DPC++ SYCL Provider")
find_package(IntelSYCL REQUIRED PATHS ${CMAKE_SOURCE_DIR}/cmake NO_DEFAULT_PATH)

if (_dpctl_sycl_targets)
message(STATUS "Compiling for -fsycl-targets=${_dpctl_sycl_targets}")
list(APPEND _dpctl_sycl_target_compile_options -fsycl-targets=${_dpctl_sycl_targets})
list(APPEND _dpctl_sycl_target_link_options -fsycl-targets=${_dpctl_sycl_targets})
endif()

elseif(DPCTL_SYCL_PROVIDER STREQUAL "AdaptiveCpp")
message(STATUS "Using AdaptiveCpp SYCL Provider")

# AdaptiveCpp reads ACPP_TARGETS during find_package. The empty cache entry
# keeps the derived targets below out of the cache.
set(ACPP_TARGETS "" CACHE STRING
"AdaptiveCpp targets, derived from DPCTL_TARGET_CUDA, DPCTL_TARGET_HIP or DPCTL_SYCL_TARGETS if empty"
)
if(_acpp_targets_list AND NOT ACPP_TARGETS AND "$ENV{ACPP_TARGETS}" STREQUAL "")
set(ACPP_TARGETS "${_acpp_targets_list}")
message(STATUS "Compiling for ACPP_TARGETS=${ACPP_TARGETS}")
endif()

# This automatically provides the add_sycl_to_target macro
find_package(AdaptiveCpp CONFIG REQUIRED)

endif()

add_subdirectory(libsyclinterface)
Expand Down
Loading
Loading