Skip to content

Outsource Cython backend #376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 28, 2025
Merged
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
52 changes: 11 additions & 41 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -49,48 +49,20 @@ jobs:
run: |
python -m pylint src/gstools/
- name: cython-lint check
run: |
cython-lint src/gstools/
- name: coveralls check
run: |
python -m pytest --cov gstools --cov-report term-missing -v tests/
python -m coveralls --service=github
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build_wheels:
name: wheels for ${{ matrix.os }}
build:
name: test on ${{ matrix.os }} with py ${{ matrix.ver.py }} numpy${{ matrix.ver.np }} scipy${{ matrix.ver.sp }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# macos-13 is an intel runner, macos-14 is apple silicon
os: [ubuntu-latest, windows-latest, macos-13, macos-14]

steps:
- uses: actions/checkout@v4
with:
fetch-depth: "0"

- name: Build wheels
uses: pypa/cibuildwheel@v2.22.0
with:
output-dir: dist-wheel-${{ matrix.os }}

- uses: actions/upload-artifact@v4
with:
name: dist-wheel-${{ matrix.os }}
path: ./dist-wheel-${{ matrix.os }}/*.whl

build_sdist:
name: sdist on ${{ matrix.os }} with py ${{ matrix.ver.py }} numpy${{ matrix.ver.np }} scipy${{ matrix.ver.sp }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-13, macos-14]
# https://github.com/scipy/oldest-supported-numpy/blob/main/setup.cfg
ver:
- { py: "3.8", np: "==1.20.0", sp: "==1.5.4" }
@@ -101,6 +73,8 @@ jobs:
- { py: "3.13", np: "==2.1.0", sp: "==1.14.1" }
- { py: "3.13", np: ">=2.1.0", sp: ">=1.14.1" }
exclude:
- os: ubuntu-24.04-arm
ver: { py: "3.8", np: "==1.20.0", sp: "==1.5.4" }
- os: macos-14
ver: { py: "3.8", np: "==1.20.0", sp: "==1.5.4" }
- os: macos-14
@@ -123,8 +97,6 @@ jobs:
pip install build
- name: Install GSTools
env:
GSTOOLS_BUILD_PARALLEL: 1
run: |
pip install -v --editable .[test]
@@ -133,27 +105,25 @@ jobs:
pip install "numpy${{ matrix.ver.np }}" "scipy${{ matrix.ver.sp }}"
python -m pytest -v tests/
- name: Build sdist
- name: Build dist
run: |
# PEP 517 package builder from pypa
python -m build --sdist --outdir dist-sdist .
python -m build .
- uses: actions/upload-artifact@v4
if: matrix.os == 'ubuntu-latest' && matrix.ver.py == '3.11'
with:
name: dist-sdist
path: dist-sdist/*.tar.gz
name: dist
path: dist/*

upload_to_pypi:
needs: [build_wheels, build_sdist]
needs: [build]
runs-on: ubuntu-latest

steps:
- uses: actions/download-artifact@v4
with:
pattern: dist-*
merge-multiple: true
path: dist
name: dist

- name: Publish to Test PyPI
# only if working on main
4 changes: 0 additions & 4 deletions MANIFEST.in

This file was deleted.

33 changes: 16 additions & 17 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
@@ -88,38 +88,33 @@ When using conda, the parallel version of GSTools is installed per default.

***Parallelizing Cython***

To enable the OpenMP support in Cython when using pip, you have to provide a C
compiler and OpenMP. Parallel support is controlled by an environment variable
``GSTOOLS_BUILD_PARALLEL``, that can be ``0`` or ``1`` (interpreted as ``0``
if not present). GSTools then needs to be installed from source:
For parallel support, the `GSTools-Cython <https://github.com/GeoStat-Framework/GSTools-Cython>`_
backend needs to be compiled from source the following way:

.. code-block:: none
export GSTOOLS_BUILD_PARALLEL=1
pip install --no-binary=gstools gstools
pip install --no-binary=gstools-cython gstools
Note, that the ``--no-binary=gstools`` option forces pip to not use a wheel
for GSTools.
You have to provide a C compiler and OpenMP to compile GSTools-Cython with parallel support.
The feature is controlled by the environment variable
``GSTOOLS_BUILD_PARALLEL``, that can be ``0`` or ``1`` (interpreted as ``0`` if not present).
Note, that the ``--no-binary=gstools-cython`` option forces pip to not use a wheel
for the GSTools-Cython backend.

For the development version, you can do almost the same:

.. code-block:: none
export GSTOOLS_BUILD_PARALLEL=1
pip install git+git://github.com/GeoStat-Framework/GSTools-Cython.git@main
pip install git+git://github.com/GeoStat-Framework/GSTools.git@main
***Using GSTools-Core for parallelization and even more speed***

You can install the optional dependency `GSTools-Core <https://github.com/GeoStat-Framework/GSTools-Core>`_,
which is a re-implementation of the algorithms used in GSTools. The new
package uses the language Rust and it should be faster (in some cases by orders
of magnitude), safer, and it will potentially completely replace the current
standard implementation in Cython. Once the package GSTools-Core is available
on your machine, it will be used by default. In case you want to switch back to
the Cython implementation, you can set
:code:`gstools.config.USE_GSTOOLS_CORE=False` in your code. This also works at
runtime. You can install the optional dependency e.g. by
which is a re-implementation of GSTools-Cython:

.. code-block:: none
@@ -131,8 +126,12 @@ or by manually installing the package
pip install gstools-core
GSTools-Core will automatically run in parallel, without having to use provide
OpenMP or a local C compiler.
The new package uses the language Rust and it should be safer and faster (in some cases by orders of magnitude).
Once the package GSTools-Core is available on your machine, it will be used by default.
In case you want to switch back to the Cython implementation, you can set
:code:`gstools.config.USE_GSTOOLS_CORE=False` in your code. This also works at runtime.

GSTools-Core will automatically run in parallel, without having to provide OpenMP or a local C compiler.


Citation
48 changes: 24 additions & 24 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@


[build-system]
requires = [
"setuptools>=64",
"setuptools_scm>=7",
"numpy>=2.0.0rc1,<2.3; python_version >= '3.9'",
"oldest-supported-numpy; python_version < '3.9'",
"Cython>=3.0.10,<3.1.0",
"extension-helpers>=1",
"hatchling>=1.8.0",
"hatch-vcs",
]
build-backend = "setuptools.build_meta"
build-backend = "hatchling.build"

[project]
requires-python = ">=3.8"
@@ -17,7 +15,7 @@ authors = [
{name = "Sebastian Müller, Lennart Schüler", email = "info@geostat-framework.org"},
]
readme = "README.md"
license = {text = "LGPL-3.0"}
license = "LGPL-3.0"
dynamic = ["version"]
classifiers = [
"Development Status :: 5 - Production/Stable",
@@ -47,6 +45,7 @@ classifiers = [
"Topic :: Utilities",
]
dependencies = [
"gstools-cython>=1,<2",
"emcee>=3.0.0",
"hankel>=1.0.0",
"meshio>=5.1.0",
@@ -78,7 +77,6 @@ lint = [
"black>=24",
"pylint",
"isort[colors]",
"cython-lint",
]

[project.urls]
@@ -89,14 +87,25 @@ Homepage = "https://geostat-framework.org/#gstools"
Source = "https://github.com/GeoStat-Framework/GSTools"
Tracker = "https://github.com/GeoStat-Framework/GSTools/issues"

[tool.setuptools]
license-files = ["LICENSE"]
[tool.hatch.version]
source = "vcs"
fallback_version = "0.0.0.dev0"

[tool.setuptools_scm]
write_to = "src/gstools/_version.py"
write_to_template = "__version__ = '{version}'"
[tool.hatch.version.raw-options]
local_scheme = "no-local-version"
fallback_version = "0.0.0.dev0"

[tool.hatch.build.hooks.vcs]
version-file = "src/gstools/_version.py"
template = "__version__ = '{version}'"

[tool.hatch.build.targets.sdist]
include = [
"/src",
"/tests",
]

[tool.hatch.build.targets.wheel]
packages = ["src/gstools"]

[tool.isort]
profile = "black"
@@ -160,12 +169,3 @@ target-version = [
max-attributes = 30
max-public-methods = 80
max-positional-arguments=20

[tool.cibuildwheel]
# Switch to using build
build-frontend = "build"
# Disable building PyPy wheels on all platforms, 32bit for py3.10/11/12/13, musllinux builds, py3.6/7
skip = ["cp36-*", "cp37-*", "pp*", "*-win32", "*-manylinux_i686", "*-musllinux_*"]
# Run the package tests using `pytest`
test-extras = "test"
test-command = "pytest -v {package}/tests"
34 changes: 0 additions & 34 deletions setup.py

This file was deleted.

6 changes: 3 additions & 3 deletions src/gstools/field/generator.py
Original file line number Diff line number Diff line change
@@ -20,12 +20,12 @@
from copy import deepcopy as dcp

import numpy as np
from gstools_cython.field import summate as summate_c
from gstools_cython.field import summate_fourier as summate_fourier_c
from gstools_cython.field import summate_incompr as summate_incompr_c

from gstools import config
from gstools.covmodel.base import CovModel
from gstools.field.summator import summate as summate_c
from gstools.field.summator import summate_fourier as summate_fourier_c
from gstools.field.summator import summate_incompr as summate_incompr_c
from gstools.random.rng import RNG
from gstools.tools.geometric import generate_grid

130 changes: 0 additions & 130 deletions src/gstools/field/summator.pyx

This file was deleted.

8 changes: 4 additions & 4 deletions src/gstools/krige/base.py
Original file line number Diff line number Diff line change
@@ -14,14 +14,14 @@

import numpy as np
import scipy.linalg as spl
from gstools_cython.krige import calc_field_krige as calc_field_krige_c
from gstools_cython.krige import (
calc_field_krige_and_variance as calc_field_krige_and_variance_c,
)
from scipy.spatial.distance import cdist

from gstools import config
from gstools.field.base import Field
from gstools.krige.krigesum import calc_field_krige as calc_field_krige_c
from gstools.krige.krigesum import (
calc_field_krige_and_variance as calc_field_krige_and_variance_c,
)
from gstools.krige.tools import get_drift_functions, set_condition
from gstools.tools.geometric import rotated_main_axes
from gstools.tools.misc import eval_func
84 changes: 0 additions & 84 deletions src/gstools/krige/krigesum.pyx

This file was deleted.

376 changes: 0 additions & 376 deletions src/gstools/variogram/estimator.pyx

This file was deleted.

8 changes: 4 additions & 4 deletions src/gstools/variogram/variogram.py
Original file line number Diff line number Diff line change
@@ -12,6 +12,10 @@

# pylint: disable=C0412
import numpy as np
from gstools_cython.variogram import directional as directional_c
from gstools_cython.variogram import ma_structured as ma_structured_c
from gstools_cython.variogram import structured as structured_c
from gstools_cython.variogram import unstructured as unstructured_c

from gstools import config
from gstools.normalizer.tools import remove_trend_norm_mean
@@ -23,10 +27,6 @@
generate_grid,
)
from gstools.variogram.binning import standard_bins
from gstools.variogram.estimator import directional as directional_c
from gstools.variogram.estimator import ma_structured as ma_structured_c
from gstools.variogram.estimator import structured as structured_c
from gstools.variogram.estimator import unstructured as unstructured_c

if config._GSTOOLS_CORE_AVAIL: # pylint: disable=W0212; # pragma: no cover
# pylint: disable=E0401