Skip to content
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

Remove int-type bug on Windows in skimage.measure.label #72

Merged
merged 1 commit into from
Jul 28, 2021

Conversation

grlee77
Copy link
Contributor

@grlee77 grlee77 commented Jul 20, 2021

A windows user reported an issue with skimage.measure.label in the older cupyimg repository: mritools/cupyimg#21.

It seems the same issue is present here, but should be resolved by this PR. I don't think we can easily add a test case on our current linux-based CI as the issue has to do with the NumPy dtype character used to represent the numpy.int32 dtype. We may want to wait on merging until the fix is confirmed in mritools/cupyimg#21

I think I originally introduced this int_types dict with the intention of also supporting >32-bit integers, but it was incomplete and still used int32 in the actual implementation. This PR just removes this dict altogether and we can revisit the function if we get a request for int64 support.

This was causing a bug on Windows where
np.dtype(np.int32).dtype.char == 'l' instead of 'i'
@grlee77 grlee77 added bug Something isn't working non-breaking Introduces a non-breaking change labels Jul 20, 2021
@grlee77 grlee77 requested a review from a team as a code owner July 20, 2021 22:47
Copy link
Member

@jakirkham jakirkham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Greg! 😄

Had a couple quick questions below

try:
int_t = int_types[y.dtype.char]
except KeyError:
raise ValueError("y must have int32, uint16, uint32 or uint64 dtype")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am curious why this exception is no longer needed. What happens if we don't raise this?

Copy link
Contributor Author

@grlee77 grlee77 Jul 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a private function that is only called here with an input that is hard-coded to np.int32.

labels = cp.empty(input.shape, order="C", dtype=cp.int32)
num = _label(input, structure, labels, greyscale_mode=True)

The kernels in this file originate from CuPy, but have minor modifications here to match scipy.skimage.measure.label behavior rather than scipy.ndimage.label. The int checking stuff is not in upstream CuPy, I think I had originally added these so we could switch to int64 if needed, but I'm not sure there is a real use case for > 2 billion labels?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what happens if a user does pass in an int64 array?

Should add this most likely would happen just because a user requested a dtype of int, which would be handled as int64. Not so much because they need more labels.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what happens if a user does pass in an int64 array?

You will get the following compilation error:

E   /tmp/tmp0iyn3i4v/3ac4bcb15a8927c9397d795e29cb7ccd_2.cubin.cu(43): error: no instance of overloaded function "atomicCAS" matches the argument list
E               argument types are: (long long *, Y, Y)

I can add a check in _label that np.dtype(input) == np.float32 with a message like the old one if you like. That can only happen if users are calling that (private) _label function directly, though!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok. In that case would it make sense to raise in label? Also do we want to update this todo?

# TODO: currently uses int32 for the labels. should add int64 option as well
def label(input, background=None, return_num=False, connectivity=None):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no restriction on the type of input here which is the only parameter passed on to _label that comes from the user. The structure and labels array inputs to _label are generated internally, not provided by the user.

The only way the user can encounter the error cited here #72 (comment) would be if they were to import the private _label function from cucim.skimage.measure._label_kernels.

Comment on lines -29 to -31
raise NotImplementedError(
"Currently only 32-bit integer case is implemented"
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here

@jakirkham
Copy link
Member

@gpucibot merge

@rapids-bot rapids-bot bot merged commit f421e79 into rapidsai:branch-21.08 Jul 28, 2021
@jakirkham
Copy link
Member

Thanks Greg! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working non-breaking Introduces a non-breaking change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants