Skip to content

Commit

Permalink
Merge pull request #55 from neuro-ml/dev
Browse files Browse the repository at this point in the history
Add fast EDT
  • Loading branch information
vovaf709 authored Jun 5, 2024
2 parents 5f7592e + 8a58289 commit d9eaabd
Show file tree
Hide file tree
Showing 13 changed files with 317 additions and 42 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
needs: [ check_version ]
strategy:
matrix:
os: [ ubuntu-20.04, windows-2019, macOS-11 ]
os: [ ubuntu-22.04, windows-2019, macOS-11 ]

name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
Expand All @@ -59,13 +59,13 @@ jobs:
gcc --version
g++ --version
- name: Install g++-11 for ubuntu
if: matrix.os == 'ubuntu-20.04'
if: matrix.os == 'ubuntu-22.04'
id: install_cc
uses: rlalik/setup-cpp-compiler@master
with:
compiler: g++-11
- name: Check compilers for ubuntu
if: matrix.os == 'ubuntu-20.04'
if: matrix.os == 'ubuntu-22.04'
run: |
ls /usr/bin/gcc*
ls /usr/bin/g++*
Expand All @@ -80,7 +80,7 @@ jobs:
env:
CIBW_ENVIRONMENT_MACOS: >
PATH="/usr/local/opt/llvm/bin:$PATH" LDFLAGS="-L/usr/local/opt/llvm/lib" CPPFLAGS="-I/usr/local/opt/llvm/include"
CIBW_BUILD: cp36-* cp37-* cp38-* cp39-* cp310-* cp311-* cp312-*
CIBW_BUILD: cp37-* cp38-* cp39-* cp310-* cp311-* cp312-*
CIBW_BEFORE_BUILD_LINUX: 'if [ $(python -c "import sys; print(sys.version_info[1])") -ge 9 ]; then python -m pip install "numpy<2.0.0" --config-settings=setup-args="-Dallow-noblas=true"; fi'
- uses: actions/upload-artifact@v3
with:
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/test_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
build_wheels:
strategy:
matrix:
os: [ubuntu-20.04, windows-2019, macOS-11 ]
os: [ubuntu-22.04, windows-2019, macOS-11 ]

name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
Expand All @@ -33,13 +33,13 @@ jobs:
gcc --version
g++ --version
- name: Install g++-11 for ubuntu
if: matrix.os == 'ubuntu-20.04'
if: matrix.os == 'ubuntu-22.04'
id: install_cc
uses: rlalik/setup-cpp-compiler@master
with:
compiler: g++-11
- name: Check compilers for ubuntu
if: matrix.os == 'ubuntu-20.04'
if: matrix.os == 'ubuntu-22.04'
run: |
ls /usr/bin/gcc*
ls /usr/bin/g++*
Expand All @@ -54,6 +54,6 @@ jobs:
env:
CIBW_ENVIRONMENT_MACOS: >
PATH="/usr/local/opt/llvm/bin:$PATH" LDFLAGS="-L/usr/local/opt/llvm/lib" CPPFLAGS="-I/usr/local/opt/llvm/include"
CIBW_BUILD: cp39-* cp36-* cp312-*
CIBW_BUILD: cp39-* cp312-*
CIBW_SKIP: "*musllinux* *manylinux_x86_64"
CIBW_BEFORE_BUILD_LINUX: 'if [ $(python -c "import sys; print(sys.version_info[1])") -ge 9 ]; then python -m pip install "numpy<2.0.0" --config-settings=setup-args="-Dallow-noblas=true"; fi'
5 changes: 2 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ env:

jobs:
test:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
strategy:
matrix:
python-version: [ '3.6', '3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -50,7 +50,6 @@ jobs:
isort --check .
black --check .
- name: Check Cython code style
if: matrix.python-version != '3.6'
run: |
pip install cython-lint
cython-lint imops/src
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,4 @@ Available backends:

Some parts of our code for radon/inverse radon transform as well as the code for linear interpolation are inspired by
the implementations from [`scikit-image`](https://github.com/scikit-image/scikit-image) and [`scipy`](https://github.com/scipy/scipy).
Also we used [`fastremap`](https://github.com/seung-lab/fastremap) and [`cc3d`](https://github.com/seung-lab/connected-components-3d) out of the box.
Also we used [`fastremap`](https://github.com/seung-lab/fastremap), [`edt`](https://github.com/seung-lab/euclidean-distance-transform-3d) and [`cc3d`](https://github.com/seung-lab/connected-components-3d) out of the box.
53 changes: 32 additions & 21 deletions _build_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,16 @@ def get_ext_modules():
'/O3' if on_windows else '-O3',
] # FIXME: account for higher gcc versions

# Cython extension and .pyx source file names must be the same to compile
# https://stackoverflow.com/questions/8024805/cython-compiled-c-extension-importerror-dynamic-module-does-not-define-init-fu
modules = ['backprojection', 'measure', 'morphology', 'numeric', 'radon', 'zoom']
modules_to_link_against_numpy_core_math_lib = ['numeric']

src_dir = Path(__file__).parent / name / 'src'
for module in modules:
# Cython extension and .pyx source file names must be the same to compile
# https://stackoverflow.com/questions/8024805/cython-compiled-c-extension-importerror-dynamic-module-does-not-define-init-fu
shutil.copyfile(src_dir / f'_{module}.pyx', src_dir / f'_fast_{module}.pyx')

return [
Extension(
f'{name}.src._{prefix}{module}',
[f'{name}/src/_{prefix}{module}.pyx'],
include_dirs=[LazyImport('numpy')],
library_dirs=[NumpyLibImport()] if module in modules_to_link_against_numpy_core_math_lib else [],
libraries=['npymath'] + ['m'] * (not on_windows)
if module in modules_to_link_against_numpy_core_math_lib
else [],
extra_compile_args=args + additional_args,
extra_link_args=args + additional_args,
define_macros=[('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION')],
)
for module in modules
# FIXME: import of `ffast-math` compiled modules changes global FPU state, so now `fast=True` will just
# fallback to standard `-O2` compiled versions until https://github.com/neuro-ml/imops/issues/37 is resolved
# for prefix, additional_args in zip(['', 'fast_'], [[], ['-ffast-math']])
for prefix, additional_args in zip(['', 'fast_'], [[], []])
] + [
extensions = [
Extension(
f'{name}.cpp.cpp_modules',
[f'{name}/cpp/main.cpp'],
Expand All @@ -100,3 +82,32 @@ def get_ext_modules():
language='c++',
)
]
for module in modules:
libraries = []
library_dirs = []
include_dirs = [LazyImport('numpy')]

if module in modules_to_link_against_numpy_core_math_lib:
library_dirs.append(NumpyLibImport())
libraries.append('npymath')
if not on_windows:
libraries.append('m')

# FIXME: import of `ffast-math` compiled modules changes global FPU state, so now `fast=True` will just
# fallback to standard `-O2` compiled versions until https://github.com/neuro-ml/imops/issues/37 is resolved
# for prefix, additional_args in zip(['', 'fast_'], [[], ['-ffast-math']])
for prefix, additional_args in zip(['', 'fast_'], [[], []]):
extensions.append(
Extension(
f'{name}.src._{prefix}{module}',
[f'{name}/src/_{prefix}{module}.pyx'],
include_dirs=include_dirs,
library_dirs=library_dirs,
libraries=libraries,
extra_compile_args=args + additional_args,
extra_link_args=args + additional_args,
define_macros=[('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION')],
)
)

return extensions
40 changes: 39 additions & 1 deletion benchmarks/benchmark_morphology.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*[Cython(fast) for fast in [False, True]],
]

from imops.morphology import binary_closing, binary_dilation, binary_erosion, binary_opening
from imops.morphology import binary_closing, binary_dilation, binary_erosion, binary_opening, distance_transform_edt

from .common import IMAGE_TYPE_BENCHMARK, IMAGE_TYPES_BENCHMARK, NUMS_THREADS_TO_BENCHMARK, discard_arg, load_npy_gz

Expand Down Expand Up @@ -104,3 +104,41 @@ def peakmem_closing(self, backend, num_threads, image_type, boxed):
binary_closing(im, num_threads=num_threads, backend=backend, boxed=boxed)
except TypeError:
binary_closing(im, num_threads=num_threads, backend=backend)


class EDTSuite:
params = [morphology_configs, ('bool', 'int32', 'int64'), NUMS_THREADS_TO_BENCHMARK, [False, True], [False, True]]
param_names = ['backend', 'dtype', 'num_threads', 'return_distances', 'return_indices']

@discard_arg(1)
@discard_arg(-1)
@discard_arg(-1)
@discard_arg(-1)
def setup(self, dtype):
self.image = np.random.randint(0, 5 if 'int' in dtype else 2, (512, 512, 512)).astype(dtype, copy=False)

@discard_arg(2)
def time_edt(self, backend, num_threads, return_distances, return_indices):
if not return_distances and not return_indices:
return

distance_transform_edt(
self.image,
return_distances=return_distances,
return_indices=return_indices,
backend=backend,
num_threads=num_threads,
)

@discard_arg(2)
def peakmem_edt(self, backend, num_threads, return_distances, return_indices):
if not return_distances and not return_indices:
return

distance_transform_edt(
self.image,
return_distances=return_distances,
return_indices=return_indices,
backend=backend,
num_threads=num_threads,
)
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pip install imops[numba] # additionally install Numba backend

::: imops.morphology.binary_closing

::: imops.morphology.distance_transform_edt

::: imops.measure.label

::: imops.measure.center_of_mass
Expand Down
2 changes: 1 addition & 1 deletion imops/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.8.7'
__version__ = '0.8.8'
Loading

0 comments on commit d9eaabd

Please sign in to comment.