diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4140839..63644a1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,8 +14,11 @@ jobs: name: pre-commit-hooks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v6 with: - python-version: "3.10" + fetch-depth: 0 + persist-credentials: false + - uses: actions/setup-python@v6 + with: + python-version: "3.11" - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 508d4a7..0c93034 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,12 +18,13 @@ jobs: source: ["conda-forge"] # os: ["ubuntu-latest"] # source: ["source"] - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.11", "3.12", "3.13", "3.14"] steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 + persist-credentials: false - name: Conda uses: conda-incubator/setup-miniconda@v3 with: diff --git a/.github/workflows/update_graphblas.yml b/.github/workflows/update_graphblas.yml index 153f1a7..532072f 100644 --- a/.github/workflows/update_graphblas.yml +++ b/.github/workflows/update_graphblas.yml @@ -27,11 +27,12 @@ jobs: if: github.repository == 'GraphBLAS/python-suitesparse-graphblas' || github.repository == 'alugowski/python-suitesparse-graphblas' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 + persist-credentials: false - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: "3.11" @@ -42,7 +43,7 @@ jobs: shell: bash - name: Create Pull Request - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@v8 with: # See documentation: https://github.com/peter-evans/create-pull-request # Action behavior: https://github.com/peter-evans/create-pull-request#action-behaviour diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 20434c0..05bebdd 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -34,9 +34,10 @@ jobs: name: Build SDist runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 + persist-credentials: false - name: Build SDist run: pipx run build --sdist @@ -60,58 +61,43 @@ jobs: - os: windows-latest cibw_archs: "auto64" - # Linux x86 manylinux + # Linux x86_64 manylinux - os: ubuntu-latest cibw_archs: "x86_64" - # Python 3.12 wheel requires libffi-devel to be installed. manylinux container uses yum - cibw_before_build_linux: "yum install -y libffi-devel" + # manylinux_2_28 uses dnf (not yum). libffi-devel needed for Python 3.12+ cffi. + cibw_before_build_linux: "dnf install -y libffi-devel || yum install -y libffi-devel || true" # skip musllinux cibw_skip: "*musl*" - # Linux x86 musllinux + # Linux x86_64 musllinux # Separate runner for a Musl build of graphblas. The glibc build is not guaranteed to be compatible. - os: ubuntu-latest cibw_archs: "x86_64" arch_note: "musl" - # skip manylinux (built elsewhere), PyPy (no musl numpy wheels), CPython 3.8 (no musl numpy wheels) - cibw_skip: "*many* pp* cp38*" + # skip manylinux (built elsewhere) + cibw_skip: "*many*" - # Linux aarch64 - # Separate runner because this requires emulation (only x86 runners are available) and is very slow. - - os: ubuntu-latest - cibw_archs: "aarch64" - # numpy wheels not available for aarch64 PyPy or musllinux - cibw_skip: "pp* *musl*" + # Linux aarch64 — native ARM runner (no QEMU emulation needed) + - os: ubuntu-24.04-arm + cibw_archs: "auto" + # numpy wheels not available for aarch64 musllinux + cibw_skip: "*musl*" - # macOS x86 - # Note: keep as old as possible as due to libomp this will be the oldest supported macOS version. - - os: macos-13 + # macOS x86_64 — macos-15-intel is the last Intel macOS runner. + # libomp from Homebrew determines the minimum supported macOS version. + - os: macos-15-intel cibw_archs: "x86_64" # macOS Apple Silicon - # Note: keep as old as possible as due to libomp this will be the oldest supported macOS version. + # Keep runner version as old as possible: libomp determines minimum macOS version. - os: macos-14 cibw_archs: "arm64" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 - - # aarch64 Linux builds are cross-compiled on x86 runners using emulation - # see https://cibuildwheel.readthedocs.io/en/stable/faq/#emulation - - name: Setup QEMU (for aarch64) - if: matrix.cibw_archs == 'aarch64' - uses: docker/setup-qemu-action@v3 - with: - platforms: arm64 - - - name: Setup env (for aarch64) - if: matrix.cibw_archs == 'aarch64' - # Ask suitesparse.sh to compile faster by optimizing fewer types. Otherwise, the build takes too long to finish - # in 6 hour limit. - run: | - echo "SUITESPARSE_FAST_BUILD=1" >> $GITHUB_ENV + persist-credentials: false - name: Setup for testing if: github.event_name == 'push' || github.event_name == 'pull_request' @@ -145,19 +131,23 @@ jobs: brew fetch --retry libomp && brew reinstall libomp echo MACOSX_DEPLOYMENT_TARGET=$(otool -l $(brew --prefix libomp)/lib/libomp.dylib | grep minos | awk '{print $2}') >> $GITHUB_ENV - - uses: pypa/cibuildwheel@v2.22 + - uses: pypa/cibuildwheel@v3.4 with: output-dir: wheelhouse env: # very verbose CIBW_BUILD_VERBOSITY: 3 + # cibuildwheel v3: PyPy no longer built by default; enable explicitly + # Note: cpython-freethreading not enabled because cffi doesn't support it yet + CIBW_ENABLE: "pypy" + # Build SuiteSparse CIBW_BEFORE_ALL: bash suitesparse.sh ${{ env.GB_VERSION_REF }} CIBW_BEFORE_BUILD_LINUX: ${{ matrix.cibw_before_build_linux }} - CIBW_ENVIRONMENT_PASS_LINUX: SUITESPARSE_FAST_BUILD SUITESPARSE_FASTEST_BUILD + CIBW_ENVIRONMENT_PASS_LINUX: SUITESPARSE_FASTEST_BUILD # CMAKE_GNUtoMS=ON asks suitesparse.sh to build libraries in MSVC style on Windows. CIBW_ENVIRONMENT_WINDOWS: CMAKE_GNUtoMS=ON GRAPHBLAS_PREFIX="C:/GraphBLAS" @@ -172,8 +162,7 @@ jobs: # Architectures to build specified in matrix CIBW_ARCHS: ${{ matrix.cibw_archs }} - # as of writing numpy does not support pypy 3.10 - CIBW_SKIP: "${{ matrix.cibw_skip }} pp310*" + CIBW_SKIP: "${{ matrix.cibw_skip }}" # Use delvewheel on Windows. # This copies graphblas.dll into the wheel. "repair" in cibuildwheel parlance includes copying any shared @@ -207,17 +196,17 @@ jobs: if: github.repository == 'GraphBLAS/python-suitesparse-graphblas' && ((github.event_name == 'release' && github.event.action == 'published') || (github.event_name == 'workflow_dispatch' && github.event.inputs.upload_dest != 'No Upload')) steps: - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: python-version: "3.x" - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: path: dist merge-multiple: true # Upload to PyPI - - uses: pypa/gh-action-pypi-publish@release/v1 + - uses: pypa/gh-action-pypi-publish@v1.13.0 name: Upload to PyPI if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.upload_dest == 'PyPI') with: @@ -227,7 +216,7 @@ jobs: password: ${{ secrets.PYPI_TOKEN }} # Upload to Test PyPI - - uses: pypa/gh-action-pypi-publish@release/v1 + - uses: pypa/gh-action-pypi-publish@v1.13.0 name: Upload to Test PyPI if: github.event_name == 'workflow_dispatch' && github.event.inputs.upload_dest == 'Test PyPI' with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2a8fd94..a88a72c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,12 +13,12 @@ repos: hooks: - id: check-added-large-files - id: check-case-conflict + - id: check-executables-have-shebangs - id: check-illegal-windows-names - id: check-merge-conflict - id: check-ast - id: check-toml - id: check-yaml - # - id: check-executables-have-shebangs - id: check-vcs-permalinks - id: debug-statements - id: destroyed-symlinks @@ -28,27 +28,29 @@ repos: - id: mixed-line-ending args: [--fix=lf] - id: trailing-whitespace + - id: name-tests-test + args: ["--pytest-test-first"] - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.24.1 + rev: v0.25 hooks: - id: validate-pyproject name: Validate pyproject.toml - repo: https://github.com/PyCQA/autoflake - rev: v2.3.1 + rev: v2.3.3 hooks: - id: autoflake args: [--in-place] - repo: https://github.com/pycqa/isort - rev: 6.0.1 + rev: 8.0.1 hooks: - id: isort - repo: https://github.com/asottile/pyupgrade - rev: v3.20.0 + rev: v3.21.2 hooks: - id: pyupgrade - args: [--py39-plus] + args: [--py311-plus] - repo: https://github.com/psf/black-pre-commit-mirror - rev: 25.1.0 + rev: 26.3.1 hooks: - id: black - repo: https://github.com/PyCQA/flake8 @@ -60,8 +62,8 @@ repos: # These versions need updated manually - flake8==7.3.0 - flake8-comprehensions==3.17.0 - - flake8-bugbear==24.12.12 - # - flake8-simplify==0.21.0 + - flake8-bugbear==25.11.29 + # - flake8-simplify==0.22.0 - repo: https://github.com/asottile/yesqa rev: v1.5.0 hooks: @@ -70,12 +72,24 @@ repos: # `pyroma` may help keep our package standards up to date if best practices change. # This is a "low value" check though and too slow to run as part of pre-commit. # - repo: https://github.com/regebro/pyroma - # rev: "4.2" + # rev: "5.0.1" # hooks: # - id: pyroma # args: [-n, "10", .] + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: "v0.11.0.1" + hooks: + - id: shellcheck + - repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.10.0 + hooks: + - id: python-check-blanket-noqa + - id: python-check-blanket-type-ignore + - id: python-no-eval + - id: python-no-log-warn + - id: text-unicode-replacement-char - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.33.3 + rev: 0.37.0 hooks: - id: check-dependabot - id: check-github-workflows diff --git a/Dockerfile b/Dockerfile index fa101e5..f20e91f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG BASE_CONTAINER=python:3.9-slim-buster +ARG BASE_CONTAINER=python:3.10-slim-buster FROM ${BASE_CONTAINER} as suitesparse ENV DEBIAN_FRONTEND=noninteractive @@ -24,7 +24,7 @@ ENV PYTHONUNBUFFERED 1 COPY --from=suitesparse /usr/include/GraphBLAS.h /usr/local/include/ COPY --from=suitesparse /usr/lib/x86_64-linux-gnu/libgraphblas* /usr/lib/x86_64-linux-gnu/ -COPY --from=suitesparse /build/pycparser/utils/fake_libc_include/* /usr/local/lib/python3.9/site-packages/pycparser/utils/fake_libc_include/ +COPY --from=suitesparse /build/pycparser/utils/fake_libc_include/* /usr/local/lib/python3.10/site-packages/pycparser/utils/fake_libc_include/ RUN apt-get update && apt-get install -yq build-essential git RUN pip3 install numpy cffi pytest cython @@ -44,4 +44,4 @@ RUN apt-get -y --purge remove git python3-pip && apt-get clean FROM ${BASE_CONTAINER} COPY --from=suitesparse /usr/lib/x86_64-linux-gnu/libgraphblas* /usr/lib/x86_64-linux-gnu/ COPY --from=suitesparse /usr/lib/x86_64-linux-gnu/libgomp* /usr/lib/x86_64-linux-gnu/ -COPY --from=psg /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages +COPY --from=psg /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages diff --git a/GB_VERSION.txt b/GB_VERSION.txt index 2312799..a936832 100644 --- a/GB_VERSION.txt +++ b/GB_VERSION.txt @@ -1 +1 @@ -10.1.1 +10.3.1 diff --git a/build_graphblas_cffi.py b/build_graphblas_cffi.py index 7548102..94594e6 100644 --- a/build_graphblas_cffi.py +++ b/build_graphblas_cffi.py @@ -13,7 +13,7 @@ # GraphBLAS_ROOT env var can point to the root directory of GraphBLAS to link against. # Expected subdirectories: include/ (contains GraphBLAS.h), lib/, and bin/ (on Windows only) # Otherwise fallback to default system folders. -graphblas_root = os.environ.get("GraphBLAS_ROOT", None) +graphblas_root = os.environ.get("GraphBLAS_ROOT") if not graphblas_root: # Windows wheels.yml configures suitesparse.sh to install GraphBLAS to "C:\\GraphBLAS". diff --git a/docker_build.sh b/docker_build.sh index 31e2b25..77d3d80 100755 --- a/docker_build.sh +++ b/docker_build.sh @@ -1,3 +1,4 @@ +#!/usr/bin/env bash if [ $# -eq 0 ] then echo "Usage: ./docker_build.sh SUITESPARSE_BRANCH VERSION [BRANCH LOCATION PUSH] @@ -21,29 +22,29 @@ COMPACT=${COMPACT:-0} if [ "$LOCATION" = "clone" ] then TMPDIR=$(mktemp -d) - if [ ! -e $TMPDIR ]; then + if [ ! -e "$TMPDIR" ]; then >&2 echo "Failed to create temp directory" exit 1 fi trap "exit 1" HUP INT PIPE QUIT TERM trap 'rm -rf "$TMPDIR"' EXIT - cd $TMPDIR - git clone --branch $BRANCH https://github.com/GraphBLAS/python-suitesparse-graphblas.git - cd python-suitesparse-graphblas + cd "$TMPDIR" || exit + git clone --branch "$BRANCH" https://github.com/GraphBLAS/python-suitesparse-graphblas.git + cd python-suitesparse-graphblas || exit fi docker build \ - --build-arg SUITESPARSE=${SUITESPARSE} \ - --build-arg VERSION=${VERSION} \ - --build-arg COMPACT=${COMPACT} \ - -t $IMAGE:$VERSION \ + --build-arg SUITESPARSE="${SUITESPARSE}" \ + --build-arg VERSION="${VERSION}" \ + --build-arg COMPACT="${COMPACT}" \ + -t "$IMAGE:$VERSION" \ . -docker tag $IMAGE:$VERSION $IMAGE:latest +docker tag "$IMAGE:$VERSION" "$IMAGE:latest" if [ "$PUSH" = "push" ] then - docker push $IMAGE:$VERSION - docker push $IMAGE:latest + docker push "$IMAGE:$VERSION" + docker push "$IMAGE:latest" fi diff --git a/pyproject.toml b/pyproject.toml index 3a47125..976de9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,13 @@ [build-system] build-backend = "setuptools.build_meta" requires = [ - # setuptools<74 until PyPy vendors cffi 1.15.1 - "setuptools >=64, <74", + "setuptools >=77", "setuptools-git-versioning", "wheel", "cffi>=1.11", - "cython", + # Free-threading in Python 3.14 requires Cython >=3.1 + "cython; python_version<'3.14'", + "cython>=3.1; python_version>='3.14'", "numpy>=2.0", ] @@ -15,8 +16,9 @@ name = "suitesparse-graphblas" dynamic = ["version"] description = "SuiteSparse:GraphBLAS Python bindings." readme = "README.md" -requires-python = ">=3.9" -license = {file = "LICENSE"} +requires-python = ">=3.11" +license = "Apache-2.0" +license-files = ["LICENSE"] authors = [ {name = "Erik Welch", email = "erik.n.welch@gmail.com"}, {name = "Jim Kitchen"}, @@ -45,18 +47,17 @@ keywords = [ ] classifiers = [ "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: POSIX :: Linux", "Operating System :: Microsoft :: Windows", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: Free Threading :: 2 - Beta", "Intended Audience :: Developers", "Intended Audience :: Other Audience", "Intended Audience :: Science/Research", @@ -67,7 +68,7 @@ classifiers = [ ] dependencies = [ "cffi>=1.15", - "numpy>=1.23", + "numpy>=1.24", ] [project.urls] homepage = "https://github.com/GraphBLAS/python-suitesparse-graphblas" @@ -93,7 +94,7 @@ dirty_template = "{tag}+{ccount}.g{sha}.dirty" [tool.black] line-length = 100 -target-version = ["py39", "py310", "py311", "py312", "py313"] +target-version = ["py311", "py312", "py313", "py314"] [tool.isort] sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] diff --git a/suitesparse.sh b/suitesparse.sh index f804f40..0b47855 100755 --- a/suitesparse.sh +++ b/suitesparse.sh @@ -10,9 +10,9 @@ elif [[ $1 =~ refs/tags/([0-9]*\.[0-9]*\.[0-9]*)\..*$ ]]; then VERSION=${BASH_REMATCH[1]} else echo "Specify a SuiteSparse version, such as: $0 refs/tags/7.4.3.0 (got: $1)" - exit -1 + exit 1 fi -echo VERSION: $VERSION +echo VERSION: "$VERSION" NPROC="$(nproc)" if [ -z "${NPROC}" ]; then @@ -27,7 +27,8 @@ if [ -n "${BREW_LIBOMP}" ]; then cmake_params+=(-DOpenMP_C_FLAGS="-Xclang -fopenmp -I$(brew --prefix libomp)/include") cmake_params+=(-DOpenMP_C_LIB_NAMES="libomp") cmake_params+=(-DOpenMP_libomp_LIBRARY="omp") - export LDFLAGS="-L$(brew --prefix libomp)/lib" + LDFLAGS="-L$(brew --prefix libomp)/lib" + export LDFLAGS if [ -n "${SUITESPARSE_MACOS_ARCH}" ]; then export CFLAGS="-arch ${SUITESPARSE_MACOS_ARCH}" @@ -50,12 +51,13 @@ if [ -n "${GRAPHBLAS_PREFIX}" ]; then cmake_params+=(-DCMAKE_INSTALL_PREFIX="${GRAPHBLAS_PREFIX}") fi -curl -L https://github.com/DrTimothyAldenDavis/GraphBLAS/archive/refs/tags/v${VERSION}.tar.gz | tar xzf - -cd GraphBLAS-${VERSION}/build +curl -L "https://github.com/DrTimothyAldenDavis/GraphBLAS/archive/refs/tags/v${VERSION}.tar.gz" | tar xzf - +cd "GraphBLAS-${VERSION}/build" || exit # Disable optimizing some rarely-used types for significantly faster builds and significantly smaller wheel size. # Also the build with all types enabled sometimes stalls on GitHub Actions. Probably due to exceeded resource limits. # These can still be used, they'll just have reduced performance (AFAIK similar to UDTs). +# shellcheck disable=SC2129 # echo "#define GxB_NO_BOOL 1" >> ../Source/GB_control.h # # echo "#define GxB_NO_FP32 1" >> ../Source/GB_control.h # # echo "#define GxB_NO_FP64 1" >> ../Source/GB_control.h # @@ -74,6 +76,7 @@ if [ -n "${SUITESPARSE_FAST_BUILD}" ]; then echo "suitesparse.sh: Fast build requested." # Disable optimizing even more types. This is for builds that don't finish in runner resource limits, # such as emulated aarm64. + # shellcheck disable=SC2129 # echo "#define GxB_NO_BOOL 1" >> ../Source/GB_control.h # echo "#define GxB_NO_FP32 1" >> ../Source/GB_control.h @@ -93,6 +96,7 @@ fi if [ -n "${SUITESPARSE_FASTEST_BUILD}" ]; then echo "suitesparse.sh: Fastest build requested." # Fastest build possible. For use in development and automated tests that do not depend on performance. + # shellcheck disable=SC2129 echo "#define GxB_NO_BOOL 1" >> ../Source/GB_control.h echo "#define GxB_NO_FP32 1" >> ../Source/GB_control.h @@ -137,7 +141,7 @@ else fi cmake .. -DCMAKE_BUILD_TYPE=Release -G 'Unix Makefiles' "${cmake_params[@]}" -make -j$NPROC +make -j"$NPROC" $SUDO make install if [ -n "${CMAKE_GNUtoMS}" ]; then diff --git a/suitesparse_graphblas/create_headers.py b/suitesparse_graphblas/create_headers.py index fbfbd0f..0ec57fb 100644 --- a/suitesparse_graphblas/create_headers.py +++ b/suitesparse_graphblas/create_headers.py @@ -279,7 +279,8 @@ def groupby(index, seq): "GRB_SUBVERSION", "GxB_NTHREADS", "GxB_CHUNK", - "GxB_GPU_ID", + "GxB_GPU_IDS", + "GxB_NGPUS", "GxB_HYPERSPARSE", "GxB_SPARSE", "GxB_BITMAP", diff --git a/suitesparse_graphblas/io/binary.py b/suitesparse_graphblas/io/binary.py index 0248e7b..4e95931 100644 --- a/suitesparse_graphblas/io/binary.py +++ b/suitesparse_graphblas/io/binary.py @@ -6,11 +6,9 @@ from suitesparse_graphblas import __version__, check_status, ffi, lib, matrix stdffi = FFI() -stdffi.cdef( - """ +stdffi.cdef(""" void *malloc(size_t size); -""" -) +""") stdlib = stdffi.dlopen(find_library("c")) # When "packing" a matrix the owner of the memory buffer is transfered diff --git a/suitesparse_graphblas/suitesparse_graphblas.h b/suitesparse_graphblas/suitesparse_graphblas.h index f0a4b44..2e3e66b 100644 --- a/suitesparse_graphblas/suitesparse_graphblas.h +++ b/suitesparse_graphblas/suitesparse_graphblas.h @@ -24,6 +24,7 @@ typedef struct GB_SelectOp_opaque *GxB_SelectOp; typedef struct GxB_Container_struct *GxB_Container; /* GxB typedefs (functions) */ +typedef int64_t (*GxB_print_function)(char *string, size_t string_size, const void *value, int verbose); typedef void (*GxB_binary_function)(void *, const void *, const void *); typedef void (*GxB_index_binary_function)(void *, const void *, GrB_Index, GrB_Index, const void *, GrB_Index, GrB_Index, const void *); typedef void (*GxB_index_unary_function)(void *z, const void *x, GrB_Index i, GrB_Index j, const void *y); @@ -166,7 +167,8 @@ typedef enum { GxB_CONTEXT_NTHREADS = 7086, GxB_CONTEXT_CHUNK = 7087, - GxB_CONTEXT_GPU_ID = 7088 + GxB_CONTEXT_NGPUS = 7102, + GxB_CONTEXT_GPU_IDS = 7101 } GxB_Context_Field; typedef enum @@ -256,7 +258,9 @@ typedef enum GxB_FREE_FUNCTION = 7040, GxB_GLOBAL_NTHREADS = 7086, GxB_GLOBAL_CHUNK = 7087, - GxB_GLOBAL_GPU_ID = 7088, + GxB_GLOBAL_NGPUS = 7102, + GxB_GLOBAL_GPU_IDS = 7101, + GxB_NGPUS_MAX = 7103, GxB_BURBLE = 7019, GxB_PRINTF = 7020, GxB_FLUSH = 7021, @@ -273,7 +277,8 @@ typedef enum GxB_JIT_C_CMAKE_LIBS = 7031, GxB_JIT_USE_CMAKE = 7032, GxB_JIT_ERROR_LOG = 7033, - GxB_JIT_CUDA_PREFACE = 7100 + GxB_JIT_CUDA_PREFACE = 7100, + GxB_PRINT_FUNCTION = 7104 } GxB_Option_Field; typedef enum @@ -3757,7 +3762,7 @@ GrB_Info GxB_unload_Vector_into_Container(GrB_Vector V, GxB_Container Container, #define GxB_END ... #define GxB_FAST_IMPORT ... #define GxB_FULL ... -#define GxB_GPU_ID ... +#define GxB_GPU_IDS ... #define GxB_HYPERSPARSE ... #define GxB_IMPLEMENTATION ... #define GxB_IMPLEMENTATION_MAJOR ... @@ -3767,6 +3772,7 @@ GrB_Info GxB_unload_Vector_into_Container(GrB_Vector V, GxB_Container Container, #define GxB_INDEX_MAX ... #define GxB_MAX_NAME_LEN ... #define GxB_NBITMAP_SWITCH ... +#define GxB_NGPUS ... #define GxB_NTHREADS ... #define GxB_RANGE ... #define GxB_SPARSE ... diff --git a/suitesparse_graphblas/suitesparse_graphblas_no_complex.h b/suitesparse_graphblas/suitesparse_graphblas_no_complex.h index 86a6798..4376bec 100644 --- a/suitesparse_graphblas/suitesparse_graphblas_no_complex.h +++ b/suitesparse_graphblas/suitesparse_graphblas_no_complex.h @@ -22,6 +22,7 @@ typedef struct GB_SelectOp_opaque *GxB_SelectOp; typedef struct GxB_Container_struct *GxB_Container; /* GxB typedefs (functions) */ +typedef int64_t (*GxB_print_function)(char *string, size_t string_size, const void *value, int verbose); typedef void (*GxB_binary_function)(void *, const void *, const void *); typedef void (*GxB_index_binary_function)(void *, const void *, GrB_Index, GrB_Index, const void *, GrB_Index, GrB_Index, const void *); typedef void (*GxB_index_unary_function)(void *z, const void *x, GrB_Index i, GrB_Index j, const void *y); @@ -162,7 +163,8 @@ typedef enum { GxB_CONTEXT_NTHREADS = 7086, GxB_CONTEXT_CHUNK = 7087, - GxB_CONTEXT_GPU_ID = 7088 + GxB_CONTEXT_NGPUS = 7102, + GxB_CONTEXT_GPU_IDS = 7101 } GxB_Context_Field; typedef enum @@ -252,7 +254,9 @@ typedef enum GxB_FREE_FUNCTION = 7040, GxB_GLOBAL_NTHREADS = 7086, GxB_GLOBAL_CHUNK = 7087, - GxB_GLOBAL_GPU_ID = 7088, + GxB_GLOBAL_NGPUS = 7102, + GxB_GLOBAL_GPU_IDS = 7101, + GxB_NGPUS_MAX = 7103, GxB_BURBLE = 7019, GxB_PRINTF = 7020, GxB_FLUSH = 7021, @@ -269,7 +273,8 @@ typedef enum GxB_JIT_C_CMAKE_LIBS = 7031, GxB_JIT_USE_CMAKE = 7032, GxB_JIT_ERROR_LOG = 7033, - GxB_JIT_CUDA_PREFACE = 7100 + GxB_JIT_CUDA_PREFACE = 7100, + GxB_PRINT_FUNCTION = 7104 } GxB_Option_Field; typedef enum @@ -3523,7 +3528,7 @@ GrB_Info GxB_unload_Vector_into_Container(GrB_Vector V, GxB_Container Container, #define GxB_END ... #define GxB_FAST_IMPORT ... #define GxB_FULL ... -#define GxB_GPU_ID ... +#define GxB_GPU_IDS ... #define GxB_HYPERSPARSE ... #define GxB_IMPLEMENTATION ... #define GxB_IMPLEMENTATION_MAJOR ... @@ -3533,6 +3538,7 @@ GrB_Info GxB_unload_Vector_into_Container(GrB_Vector V, GxB_Container Container, #define GxB_INDEX_MAX ... #define GxB_MAX_NAME_LEN ... #define GxB_NBITMAP_SWITCH ... +#define GxB_NGPUS ... #define GxB_NTHREADS ... #define GxB_RANGE ... #define GxB_SPARSE ... diff --git a/suitesparse_graphblas/utils.pyx b/suitesparse_graphblas/utils.pyx index 95d2f1b..5c9ae99 100644 --- a/suitesparse_graphblas/utils.pyx +++ b/suitesparse_graphblas/utils.pyx @@ -1,3 +1,9 @@ +# cython: freethreading_compatible=True +# +# We don't do anything special to support free-threading, but GraphBLAS C +# libraries are required to be thread-safe, so things should "just work". +# Of course, users writing multithreaded code can find many creative ways +# to fail, but python-suitesparse-graphblas shouldn't crash. import numpy as np from cpython.ref cimport Py_INCREF from libc.stdint cimport uintptr_t