Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Benchmark 2D filter #88

Closed
alessandrofelder opened this issue Mar 1, 2023 · 5 comments · Fixed by #91
Closed

Benchmark 2D filter #88

alessandrofelder opened this issue Mar 1, 2023 · 5 comments · Fixed by #91
Assignees

Comments

@alessandrofelder
Copy link
Member

alessandrofelder commented Mar 1, 2023

In order to make a documented and informed decision on a good long-term solution to balance maintainability and performance #85 #73, we should compare the 2d filtering between

  • original cython implementation
  • numba implementation
  • pure python implementation

both in terms of memory usage and speed.

@alessandrofelder alessandrofelder self-assigned this Mar 1, 2023
@alessandrofelder
Copy link
Member Author

memory usage

original Cython implementation

10kx10kimage

numba

10kx10kimage_numba

pure python

10kx10kimage_py

@alessandrofelder
Copy link
Member Author

alessandrofelder commented Mar 1, 2023

Speed

original Cython implementation

13.611 <module>  filter_2d.py:1
└─ 13.601 TileProcessor.get_tile_mask  cellfinder_core/detect/filters/plane/plane_filter.py:19
   ├─ 12.600 enhance_peaks  cellfinder_core/detect/filters/plane/classical_filter.py:6
   │  ├─ 8.883 medfilt2d  scipy/signal/_signaltools.py:1828
   │  │  └─ 8.883 _medfilt2d  None
   │  ├─ 2.087 gaussian_filter  scipy/ndimage/_filters.py:279
   │  │  └─ 2.087 gaussian_filter1d  scipy/ndimage/_filters.py:211
   │  │     └─ 2.087 correlate1d  scipy/ndimage/_filters.py:84
   │  │        └─ 2.087 correlate1d  None
   │  ├─ 1.184 laplace  scipy/ndimage/_filters.py:492
   │  │  └─ 1.164 generic_laplace  scipy/ndimage/_filters.py:450
   │  │     └─ 1.062 derivative2  scipy/ndimage/_filters.py:517
   │  │        └─ 1.062 correlate1d  scipy/ndimage/_filters.py:84
   │  │           └─ 1.062 correlate1d  None
   │  ├─ 0.227 ndarray.astype  None
   │  └─ 0.166 [self]  None
   ├─ 0.291 _std  numpy/core/_methods.py:263
   │  └─ 0.277 _var  numpy/core/_methods.py:196
   │     └─ 0.214 [self]  None
   ├─ 0.245 TileWalker.__init__  cellfinder_core/detect/filters/plane/tile_walker.py:11
   │  └─ 0.245 ndarray.copy  None
   └─ 0.225 TileWalker.walk_out_of_brain_only  cellfinder_core/detect/filters/plane/tile_walker.py:56

numba

Program: benchmarks/filter_2d.py

14.688 <module>  filter_2d.py:1
└─ 14.688 TileProcessor.get_tile_mask  cellfinder_core/detect/filters/plane/plane_filter.py:19
   ├─ 12.728 enhance_peaks  cellfinder_core/detect/filters/plane/classical_filter.py:6
   │  ├─ 8.966 medfilt2d  scipy/signal/_signaltools.py:1828
   │  │  └─ 8.966 _medfilt2d  None
   │  ├─ 2.113 gaussian_filter  scipy/ndimage/_filters.py:279
   │  │  └─ 2.113 gaussian_filter1d  scipy/ndimage/_filters.py:211
   │  │     └─ 2.113 correlate1d  scipy/ndimage/_filters.py:84
   │  │        └─ 2.113 correlate1d  None
   │  ├─ 1.195 laplace  scipy/ndimage/_filters.py:492
   │  │  └─ 1.174 generic_laplace  scipy/ndimage/_filters.py:450
   │  │     └─ 1.083 derivative2  scipy/ndimage/_filters.py:517
   │  │        └─ 1.083 correlate1d  scipy/ndimage/_filters.py:84
   │  │           └─ 1.083 correlate1d  None
   │  ├─ 0.231 ndarray.astype  None
   │  └─ 0.169 [self]  None
   ├─ 1.187 TileWalker.walk_out_of_brain_only  cellfinder_core/detect/filters/plane/tile_walker.py:56
   │  ├─ 0.425 CPUDispatcher.typeof_pyval  numba/core/dispatcher.py:724
   │  │  └─ 0.366 typeof  numba/core/typing/typeof.py:32
   │  │     └─ 0.264 wrapper  functools.py:884
   │  │        └─ 0.191 typeof_impl  numba/core/typing/typeof.py:46
   │  ├─ 0.297 is_low_average  cellfinder_core/detect/filters/plane/base_tile_filter.py:37
   │  ├─ 0.218 CPUDispatcher._compile_for_args  numba/core/dispatcher.py:388
   │  │  └─ 0.213 CPUDispatcher.compile  numba/core/dispatcher.py:915
   │  │     └─ 0.213 _FunctionCompiler.compile  numba/core/dispatcher.py:124
   │  │        └─ 0.213 _FunctionCompiler._compile_cached  numba/core/dispatcher.py:131
   │  │           └─ 0.213 _FunctionCompiler._compile_core  numba/core/dispatcher.py:146
   │  │              └─ 0.213 compile_extra  numba/core/compiler.py:690
   │  └─ 0.149 [self]  None
   ├─ 0.293 _std  numpy/core/_methods.py:263
   │  └─ 0.277 _var  numpy/core/_methods.py:196
   │     └─ 0.214 [self]  None
   └─ 0.247 TileWalker.__init__  cellfinder_core/detect/filters/plane/tile_walker.py:11
      └─ 0.247 ndarray.copy  None

pure python

Program: benchmarks/filter_2d.py

34.908 <module>  filter_2d.py:1
└─ 34.897 TileProcessor.get_tile_mask  cellfinder_core/detect/filters/plane/plane_filter.py:19
   ├─ 21.426 TileWalker.walk_out_of_brain_only  cellfinder_core/detect/filters/plane/tile_walker.py:56
   │  └─ 21.413 OutOfBrainTileFilter.is_low_average  cellfinder_core/detect/filters/plane/base_tile_filter.py:37
   └─ 12.690 enhance_peaks  cellfinder_core/detect/filters/plane/classical_filter.py:6
      ├─ 8.898 medfilt2d  scipy/signal/_signaltools.py:1828
      │  └─ 8.898 _medfilt2d  None
      ├─ 2.169 gaussian_filter  scipy/ndimage/_filters.py:279
      │  └─ 2.169 gaussian_filter1d  scipy/ndimage/_filters.py:211
      │     └─ 2.169 correlate1d  scipy/ndimage/_filters.py:84
      │        └─ 2.169 correlate1d  None
      └─ 1.203 laplace  scipy/ndimage/_filters.py:492
         └─ 1.182 generic_laplace  scipy/ndimage/_filters.py:450
            └─ 1.064 derivative2  scipy/ndimage/_filters.py:517
               └─ 1.064 correlate1d  scipy/ndimage/_filters.py:84
                  └─ 1.064 correlate1d  None```

@alessandrofelder
Copy link
Member Author

alessandrofelder commented Mar 1, 2023

  • Memory usage levels are comparable across the three implementations (and very similar between cython and numba)
  • With a tweak of passing a tile to is_low_average numba is comparable in speed to cython (14.5 and 13.5 seconds) whereas pure python is much slower (~20times for the non-scipy part)

Executed on a plane containing np.random 10k x 10k 16bit integers on my SWC macbook.

@dstansby dstansby changed the title benchmark 2d filter Benchmark 2D filter Mar 1, 2023
@alessandrofelder
Copy link
Member Author

This suggests numba is a good way forward, for the 2d filter at least.

@alessandrofelder alessandrofelder mentioned this issue Mar 1, 2023
7 tasks
@dstansby dstansby moved this to Todo in Core development Mar 13, 2023
@dstansby dstansby moved this from Todo to In Progress in Core development Mar 13, 2023
@dstansby
Copy link
Member

Fixed by #91

@github-project-automation github-project-automation bot moved this from In Progress to Done in Core development Mar 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants