Skip to content
Draft
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
170 changes: 170 additions & 0 deletions .github/workflows/adaptivecpp-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
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
conda install -y ${{ env.CHANNELS }} \
"python=${{ matrix.python_spec }}" \
"adaptivecpp=*=cpu_llvm19*" "clang=19.*" "clangxx=19.*" \
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 dpctl/tests

- name: Run dpctl/tests on the OpenCL CPU device
env:
ACPP_VISIBILITY_MASK: ocl
run: |
python -m pytest -q 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" \))
79 changes: 53 additions & 26 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ option(DPCTL_GENERATE_COVERAGE_FOR_PYBIND11_EXTENSIONS
OFF
)

# SYCL provider selection
set(DPCTL_SYCL_PROVIDER "Intel" CACHE STRING "SYCL compiler provider (Intel or AdaptiveCpp)")
set_property(CACHE DPCTL_SYCL_PROVIDER PROPERTY STRINGS Intel AdaptiveCpp)

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 @@ -38,24 +42,11 @@ set(DPCTL_TARGET_HIP
CACHE STRING
"Build DPCTL to target a HIP device architecture"
)
option(
DPCTL_WITH_REDIST
"Build DPCTL assuming DPC++ redistributable is installed into Python prefix"
OFF)
option(
DPCTL_OFFLOAD_COMPRESS
"Build using offload section compression feature of DPC++ to reduce \
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
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 +60,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 @@ -94,12 +95,38 @@ 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 the ACPP_TARGETS variable directly during find_package
if(_acpp_targets_list)
string(REPLACE ";" ";" ACPP_TARGETS "${_acpp_targets_list}")
set(ACPP_TARGETS "${ACPP_TARGETS}" CACHE STRING "AdaptiveCpp Targets" FORCE)
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
17 changes: 11 additions & 6 deletions dpctl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,14 @@ function(build_dpctl_ext _trgt _src _dest)
Python_add_library(${_trgt} MODULE WITH_SOABI ${_generated_src})
if (BUILD_DPCTL_EXT_SYCL)
add_sycl_to_target(TARGET ${_trgt} SOURCES ${_generated_src})
target_compile_options(${_trgt} PRIVATE -fno-sycl-id-queries-fit-in-int)
target_link_options(${_trgt} PRIVATE -fsycl-device-code-split=per_kernel)
if (DPCTL_OFFLOAD_COMPRESS)
target_link_options(${_trgt} PRIVATE --offload-compress)
endif()
# Only apply DPC++ specific compiler optimizations
if(DPCTL_SYCL_PROVIDER STREQUAL "Intel")
target_compile_options(${_trgt} PRIVATE -fno-sycl-id-queries-fit-in-int)
target_link_options(${_trgt} PRIVATE -fsycl-device-code-split=per_kernel)
if (DPCTL_OFFLOAD_COMPRESS)
target_link_options(${_trgt} PRIVATE --offload-compress)
endif()
endif()
if(_dpctl_sycl_targets)
# make fat binary
target_compile_options(
Expand All @@ -134,7 +137,9 @@ function(build_dpctl_ext _trgt _src _dest)
if (DPCTL_GENERATE_COVERAGE)
target_compile_definitions(${_trgt} PRIVATE CYTHON_TRACE=1 CYTHON_TRACE_NOGIL=1)
if (BUILD_DPCTL_EXT_SYCL)
target_compile_options(${_trgt} PRIVATE -fno-sycl-use-footer)
if(DPCTL_SYCL_PROVIDER STREQUAL "Intel")
target_compile_options(${_trgt} PRIVATE -fno-sycl-use-footer)
endif()
endif()
endif()
target_link_libraries(${_trgt} PRIVATE DPCTLSyclInterface)
Expand Down
1 change: 1 addition & 0 deletions dpctl/_backend.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cdef extern from "syclinterface/dpctl_sycl_enum_types.h":
_HIP "DPCTL_HIP"
_LEVEL_ZERO "DPCTL_LEVEL_ZERO"
_OPENCL "DPCTL_OPENCL"
_OPENMP "DPCTL_OPENMP"
_UNKNOWN_BACKEND "DPCTL_UNKNOWN_BACKEND"

ctypedef enum _device_type "DPCTLSyclDeviceType":
Expand Down
4 changes: 3 additions & 1 deletion dpctl/_device_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ def select_device_with_aspects(required_aspects, excluded_aspects=None):
if not hasattr(SyclDevice, "has_aspect_" + asp):
raise AttributeError(f"The {asp} aspect is not supported in dpctl")
devs = get_devices()
max_score = 0
# get_devices only reports devices with a non-negative score, and a score
# of zero is a valid one
max_score = -1
selected_dev = None

for dev in devs:
Expand Down
16 changes: 16 additions & 0 deletions dpctl/_diagnostics.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,26 @@
import contextlib
import os

from ._backend cimport DPCTLCString_Delete


cdef extern from "syclinterface/dpctl_service.h":
cdef void DPCTLService_InitLogger(const char *, const char *)
cdef void DPCTLService_ShutdownLogger()
cdef const char *DPCTLService_GetSyclProvider()


def sycl_provider():
"""Return the SYCL implementation `dpctl` was built with.

Returns:
str:
Either ``"Intel"`` or ``"AdaptiveCpp"``.
"""
cdef const char *c_str = DPCTLService_GetSyclProvider()
cdef bytes byte_str = <bytes>c_str
DPCTLCString_Delete(c_str)
return byte_str.decode("utf-8")


def _init_logger(log_dir=None):
Expand Down
4 changes: 4 additions & 0 deletions dpctl/_sycl_device.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ cdef str _backend_type_to_filter_string_part(_backend_type BTy):
return "level_zero"
elif BTy == _backend_type._OPENCL:
return "opencl"
elif BTy == _backend_type._OPENMP:
return "openmp"
else:
return "unknown"

Expand Down Expand Up @@ -560,6 +562,8 @@ cdef class SyclDevice(_SyclDevice):
return backend_type.level_zero
elif BTy == _backend_type._OPENCL:
return backend_type.opencl
elif BTy == _backend_type._OPENMP:
return backend_type.openmp
else:
raise ValueError("Unknown backend type.")

Expand Down
Loading
Loading