Skip to content
Merged
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
101 changes: 89 additions & 12 deletions .github/workflows/ci-cpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ on:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Let main runs finish populating the native SDK cache.
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read
Expand Down Expand Up @@ -46,63 +47,134 @@ jobs:
- name: Check inline samples are up to date
run: python test/tools/inline_samples.py --check

build:
name: Build CPU Wheel (Python 3.12)
native-sdk:
name: Native SDK
runs-on: ubuntu-24.04
timeout-minutes: 360
env:
CUTILE_BUILD_VARIANT: cpu
outputs:
key: ${{ steps.key.outputs.key }}
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Compute native SDK cache key
id: key
# Bump v1 when the SDK build commands below change.
run: echo "key=cpu-native-sdk-v1-${ImageOS:?}-${RUNNER_ARCH}-${{ hashFiles('backends/cmake/**', 'backends/cpu/toolchain.cmake') }}" >> "$GITHUB_OUTPUT"

- name: Look up native SDK cache
id: cache
uses: actions/cache/restore@v6
with:
path: native-sdk
key: ${{ steps.key.outputs.key }}
lookup-only: true

- name: Set up Python
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install native build dependencies
- name: Build native SDK
if: steps.cache.outputs.cache-hit != 'true'
run: |
sudo apt-get update
sudo apt-get install --yes clang lld g++
python -m pip install 'cmake>=3.24,<4' ninja
cmake -S . -B build/native-sdk -G Ninja \
-DCUTILE_BUILD_VARIANT=cpu \
-DCUTILE_BUILD_NATIVE_SDK=ON \
-DCMAKE_INSTALL_PREFIX="$PWD/native-sdk"
cmake --build build/native-sdk
cmake --install build/native-sdk --component cuTileNativeSDK

- name: Save native SDK cache
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v6
with:
path: native-sdk
key: ${{ steps.key.outputs.key }}

- name: Verify native SDK cache
if: steps.cache.outputs.cache-hit != 'true'
# Save failures are only warnings; the wheel jobs need the entry.
uses: actions/cache/restore@v6
with:
path: native-sdk
key: ${{ steps.key.outputs.key }}
lookup-only: true
fail-on-cache-miss: true

build:
name: Build CPU Wheel (Python ${{ matrix.python-version }})
needs: native-sdk
runs-on: ubuntu-24.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
python-version: &python-versions ["3.11", "3.12", "3.13", "3.14", "3.14t", "3.15", "3.15t"]
env:
CUTILE_BUILD_VARIANT: cpu
CMAKE_ARGS: -DCUTILE_NATIVE_SDK_DIR=${{ github.workspace }}/native-sdk
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Restore native SDK
uses: actions/cache/restore@v6
with:
path: native-sdk
key: ${{ needs.native-sdk.outputs.key }}
fail-on-cache-miss: true

- name: Set up uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- name: Install CPU build dependencies
run: uv sync --group cpu --no-install-project
run: uv sync --group backend-build --no-install-project --python "$(command -v python)"

- name: Build CPU wheel
run: uv build --wheel --no-build-isolation --python .venv/bin/python

- name: Upload CPU wheel
uses: actions/upload-artifact@v6
with:
name: wheel-cpu-py3.12-linux-x86_64
name: wheel-cpu-py${{ matrix.python-version }}-linux-x86_64
path: dist/*.whl
if-no-files-found: error
retention-days: 7

test-cpu:
name: CPU Tests (Python 3.12)
name: CPU Tests (Python ${{ matrix.python-version }})
needs: build
runs-on: ubuntu-24.04
timeout-minutes: 360
strategy:
fail-fast: false
matrix:
python-version: *python-versions
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
python-version: ${{ matrix.python-version }}

- name: Download CPU wheel
uses: actions/download-artifact@v7
with:
name: wheel-cpu-py3.12-linux-x86_64
name: wheel-cpu-py${{ matrix.python-version }}-linux-x86_64
path: dist/

- name: Install test dependencies
Expand All @@ -111,13 +183,18 @@ jobs:
python -m pip install dist/*.whl numpy pytest pytest-benchmark pytest-env
python -m pip install setuptools==84.0.0 'cmake>=3.24,<4' ninja

- name: Check native extensions keep the GIL disabled
if: endsWith(matrix.python-version, 't')
# CPython only warns when an extension re-enables the GIL.
run: python -c "import sys, cuda.tile._cext, cuda.tile._backends._compiler, cuda.tile._backends.cpu._cpu; assert not sys._is_gil_enabled(), 'GIL re-enabled'"

- name: Run CPU backend tests
run: python -m pytest --durations=10 --junitxml=test-results.xml -m "not benchmark" backends/cpu backends/test

- name: Upload test results
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v6
with:
name: cpu-test-results
name: cpu-test-results-py${{ matrix.python-version }}
path: test-results.xml
retention-days: 7
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ cmake_minimum_required(VERSION 3.18)
project(cuda-tile-python)
enable_testing()

option(CUTILE_BUILD_NATIVE_SDK "Build and install the Python-independent native SDK" OFF)
if(CUTILE_BUILD_NATIVE_SDK)
add_subdirectory(backends)
return()
endif()

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

if (MSVC)
Expand Down
48 changes: 37 additions & 11 deletions backends/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ endif()
# dependencies, such as dlpack.
set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME cuTileBackend)

set(CUTILE_NATIVE_SDK_DIR "" CACHE PATH "Installed Python-independent native SDK")
if(CUTILE_BUILD_NATIVE_SDK)
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchTileIRToMLIR.cmake")
fetch_tileir_to_mlir()
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/TileIRToMLIR.cmake")
return()
endif()

find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
execute_process(
COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
Expand All @@ -37,16 +45,34 @@ find_package(nanobind CONFIG REQUIRED)
# Package directory of the backends, relative to the install prefix.
set(CUTILE_BACKEND_INSTALL_DIR cuda/tile/_backends)

include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchTileIRToMLIR.cmake")
fetch_tileir_to_mlir()
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/TileIRToMLIR.cmake")

install(FILES "${CUTILE_COMPILER_PATH}" DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}")
install(FILES "${CUTILE_LLVM_LICENSE_PATH}"
DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}/_licenses/llvm")
install(FILES "${CUTILE_TILEIR_TO_MLIR_DIR}/LICENSE"
DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}/_licenses/tileir-to-mlir")
install(FILES "${CUTILE_CUDA_TILE_SOURCE_DIR}/LICENSE.txt"
DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}/_licenses/cuda-tile")
if(CUTILE_NATIVE_SDK_DIR)
list(PREPEND CMAKE_PREFIX_PATH "${CUTILE_NATIVE_SDK_DIR}")
find_package(TileIRToMLIR REQUIRED CONFIG
PATHS "${CUTILE_NATIVE_SDK_DIR}" NO_DEFAULT_PATH)
find_package(LLD REQUIRED CONFIG)
add_library(TileIRToMLIR ALIAS TileIRToMLIR::TileIRToMLIR)
if(NOT TARGET CudaTileBytecodeReader)
add_library(CudaTileBytecodeReader ALIAS TileIRToMLIR::CudaTileBytecodeReader)
endif()
include("${CMAKE_CURRENT_SOURCE_DIR}/compiler.cmake")
install(FILES "${CUTILE_NATIVE_SDK_DIR}/share/cutile/llvm/LICENSE.TXT"
DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}/_licenses/llvm")
install(FILES "${CUTILE_NATIVE_SDK_DIR}/share/TileIRToMLIR/LICENSE"
DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}/_licenses/tileir-to-mlir")
install(FILES "${CUTILE_NATIVE_SDK_DIR}/share/TileIRToMLIR/cuda-tile/LICENSE.txt"
DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}/_licenses/cuda-tile")
else()
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchTileIRToMLIR.cmake")
fetch_tileir_to_mlir()
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/TileIRToMLIR.cmake")

install(FILES "${CUTILE_COMPILER_PATH}" DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}")
install(FILES "${CUTILE_LLVM_LICENSE_PATH}"
DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}/_licenses/llvm")
install(FILES "${CUTILE_TILEIR_TO_MLIR_DIR}/LICENSE"
DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}/_licenses/tileir-to-mlir")
install(FILES "${CUTILE_CUDA_TILE_SOURCE_DIR}/LICENSE.txt"
DESTINATION "${CUTILE_BACKEND_INSTALL_DIR}/_licenses/cuda-tile")
endif()

add_subdirectory("${CUTILE_BUILD_VARIANT}")
49 changes: 45 additions & 4 deletions backends/cmake/CheckoutLLVM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,57 @@ if(DEFINED REVISION AND NOT REVISION STREQUAL "")
set(_selected_revision "${REVISION}")
endif()

set(_patch "")
if(DEFINED PATCH AND NOT PATCH STREQUAL "")
file(READ "${PATCH}" _patch)
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${SOURCE_DIR}" rev-parse --absolute-git-dir
OUTPUT_VARIABLE _git_dir
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY)
# Copy of the patch applied to the working tree, needed to revert it.
set(_applied_patch "${_git_dir}/cutile-llvm.patch")
set(_applied "")
if(EXISTS "${_applied_patch}")
file(READ "${_applied_patch}" _applied)
endif()

execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${SOURCE_DIR}" rev-parse HEAD
RESULT_VARIABLE _head_result
OUTPUT_VARIABLE _head_revision
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
if(_head_result EQUAL 0 AND _head_revision STREQUAL _selected_revision)
if(_head_result EQUAL 0 AND _head_revision STREQUAL _selected_revision
AND _applied STREQUAL _patch)
return()
endif()

execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${SOURCE_DIR}" checkout --detach "${_selected_revision}"
COMMAND_ERROR_IS_FATAL ANY)
if(EXISTS "${_applied_patch}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${SOURCE_DIR}" apply --reverse "${_applied_patch}"
COMMAND_ERROR_IS_FATAL ANY)
file(REMOVE "${_applied_patch}")
endif()

if(NOT _head_revision STREQUAL _selected_revision)
execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${SOURCE_DIR}" checkout --detach "${_selected_revision}"
COMMAND_ERROR_IS_FATAL ANY)
endif()

if(NOT _patch STREQUAL "")
# Newer LLVM revisions may already contain the patch.
execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${SOURCE_DIR}" apply --reverse --check "${PATCH}"
RESULT_VARIABLE _patch_present
OUTPUT_QUIET
ERROR_QUIET)
if(NOT _patch_present EQUAL 0)
execute_process(
COMMAND "${GIT_EXECUTABLE}" -C "${SOURCE_DIR}" apply "${PATCH}"
COMMAND_ERROR_IS_FATAL ANY)
file(WRITE "${_applied_patch}" "${_patch}")
endif()
endif()
4 changes: 2 additions & 2 deletions backends/cmake/FetchTileIRToMLIR.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

set(TILEIR_TO_MLIR_REPOSITORY "https://github.com/libxsmm/tileir-to-mlir"
CACHE STRING "TileIRToMLIR repo URL")
set(TILEIR_TO_MLIR_REVISION "ba6c9e50274522089b7ad99b3e8a571480481330"
set(TILEIR_TO_MLIR_REVISION "7eeb1655cb4af986cc5aa53ca35ff87e7770d005"
CACHE STRING "TileIRToMLIR revision")
set(TILEIR_TO_MLIR_REVISION_SHA256
"f39644ec0eb4d98db8de6b8bcf51f82d67ea80081080e6c397695a20369eb0d4"
"c3946e02afeb443d4961dd81739f7d3fd3b94383871490df6f2cb2153b513c00"
CACHE STRING "Expected SHA256 of the pinned TileIRToMLIR archive")

set(CUDA_TILE_REPOSITORY "https://github.com/NVIDIA/cuda-tile"
Expand Down
Loading