-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Allow rank filters to work with nogil #5399
Conversation
Thanks @klaussfreire, but I think these are already |
@grlee77 I was going through this and trying to think about how best to respond to this PR. The function declaration takes a function pointer: cdef void _core(void kernel(dtype_t_out*, Py_ssize_t, Py_ssize_t[::1], double,
dtype_t, Py_ssize_t, Py_ssize_t, double,
double, Py_ssize_t, Py_ssize_t) nogil,
dtype_t[:, ::1] image,
char[:, ::1] selem,
char[:, ::1] mask,
dtype_t_out[:, :, ::1] out,
signed char shift_x, signed char shift_y,
double p0, double p1,
Py_ssize_t s0, Py_ssize_t s1,
Py_ssize_t n_bins) except *: Finally, callers to core are not declared with nogil:
_core(....) Therefore, I think that this PR is indeeded adding multi-threaded capabilities to rank filters. |
Personally, I prefer a code organization where low level agorithmic functions are declared as In this case, I would prefer https://github.com/scikit-image/scikit-image/blob/main/skimage/filters/rank/generic_cy.pyx#L432 |
Yes, I just tried running a couple of the rank filter functions with |
Yes, I see that now. I was not looking closely enough! |
right, but I think the issue here is that |
Exactly |
I compiled this branch, but using apply_parallel still doesn't seem to result in the expected multithreaded CPU usage. I don't imediately see the issue, though. @klaussfreire, were you able to observe an improvement in your application with this change? |
Yes. I have a program that uses local entropy to do HDR stretching on several images in parallel, and it does work effectively there. Of course a single invocation isn't parallelized with this patch. Parallelization of a single invocation would require OpenMP or some other parallelization strategy inside _core, but in my use case (several invocations on several large images) it works fine. Edit: let me gather some timings... |
i also have a feeling that it won't show up with our tests that use small images (and thus things are fast). |
With patch:
Without patch
|
I tried again and did see the speedup this time, so I must have just not refreshed something properly last time. I can confirm a substantial speedup for a simple example like below that uses Computation time is 1.58 s when run with in the normal fashion, but 324 ms when run with apply parallel, so about a 5x speedup on the 10-core CPU I tested it on. import dask
import numpy as np
from skimage.filters import rank
from skimage import data, img_as_float
from skimage.util import apply_parallel
# tile a small image to be able to see the benefit of multithreading
img = img_as_float(data.camera())
img = np.tile(img, (4, 8))
# use original non-tiled shape as the chunk size
chunks = data.camera().shape
selem = np.ones((5, 5), dtype=np.uint8)
depth = selem.shape[0] // 2
img_uint = (np.clip(img, 0, 1) * 255).astype(np.uint8)
extra_keywords = dict(selem=selem)
with dask.config.set(scheduler='threads'): # scheduler='processes'):
%timeit rank_median = apply_parallel(rank.median, img_uint, chunks=chunks, depth=depth, extra_keywords=extra_keywords, dtype=img.dtype, compute=True)
# %timeit rank.median(img_uint, **extra_keywords) |
I just happened to be trying |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @klaussfreire, this looks good to me. I confirmed multithreading seems to be working properly now for both 2d and 3d (tested with rank.median
and apply_parallel
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @klaussfreire!
Description
Allow rank filters to work with nogil
For reviewers
later.
__init__.py
.doc/release/release_dev.rst
.