regionprops_table output placement and format - #1088
Conversation
…put format copy_output_to_host : if True, all columns will correspond to host NumPy arrays to_table=False for batch_processing=True: do not split fixed size multidimensional arrays like centroid or inertia_tensor to one column per value
…PU regionprops API
jakirkham
left a comment
There was a problem hiding this comment.
Thanks Greg! 🙏
This looks like a nice improvement.
Was wondering if we could take some of the changes here further for more perf gains.
| column_buffer = np.empty(n, dtype=dtype) | ||
| if copy_to_host: | ||
| for i in range(n): | ||
| column_buffer[i] = cp.asnumpy(regions[i][prop]) | ||
| else: | ||
| for i in range(n): | ||
| column_buffer[i] = regions[i][prop] |
There was a problem hiding this comment.
Idk if this is possible, but would it make sense to structure regions to reverse the indexing?
IOW is it possible to do something like regions[prop][i]?
If so, this would allow this to become something like...
| column_buffer = np.empty(n, dtype=dtype) | |
| if copy_to_host: | |
| for i in range(n): | |
| column_buffer[i] = cp.asnumpy(regions[i][prop]) | |
| else: | |
| for i in range(n): | |
| column_buffer[i] = regions[i][prop] | |
| column_buffer = np.empty(n, dtype=dtype) | |
| if copy_to_host: | |
| column_buffer[...] = cp.asnumpy(regions[i][prop]) | |
| else: | |
| column_buffer[...] = regions |
...or maybe even eliminate that last copy altogether.
Admittedly this might be beyond the scope of this PR, but want to raise it since it seems like there are some efficiency gains on the table here.
There was a problem hiding this comment.
If you reach this _props_to_dict helper function code you are already on the MUCH slower path (batch_processing=False) within regionprops_table, so I don't see much point in trying to optimize this helper. For performance it is best to always call regionprops_table with batch_processing=True so a single kernel computes for all regions rather than launching kernels separately for each individual region.
There was a problem hiding this comment.
Agree we should prefer the table approach. Maybe we should consider deprecating the fallback at some point
|
/merge |
|
Thanks Greg! 🙏 |
Summary
This PR adds two options to
cucim.skimage.measure.regionprops_table:copy_output_to_host: optionally copy returned tabular values from GPU to host.to_table: optionally keep fixed-size multidimensional properties unsplit instead of expanding them into one table column per element.Motivation
regionprops_tablereturns a table-like dictionary, but the current default values are CuPy arrays on the GPU. That is efficient for GPU-side follow-up work, but inconvenient for the common case where users want to pass the result directly to pandas or other host-side tabular tools.At the same time, some GPU workflows benefit from keeping multidimensional outputs like
centroidorinertia_tensoras device arrays with their natural shapes, instead of splitting them into separate 1D columns.For cuCIM,
regionprops_table(..., batch_processing=True)is the recommended performant region property API. It computes properties for all labels in batched GPU kernels, whileregionpropsreturnsRegionPropertiesobjects whose properties are evaluated one region at a time. TheRegionPropertiesandregionpropsdocstrings now call this out, andregionpropsemits a one-time warning pointing users to the batch path.Main usage modes
Host tabular output for pandas:
In this mode, fixed-size multidimensional properties are split into table columns such as
centroid-0andcentroid-1, and returned arrays are NumPy arrays suitable for direct pandas use.GPU-native structured output:
In this mode, outputs remain on the GPU and fixed-size multidimensional properties keep their natural shapes, for example
centroidas(num_regions, ndim)andinertia_tensoras(num_regions, ndim, ndim).to_table=Falseis also supported withbatch_processing=Falsefor API symmetry, althoughbatch_processing=Trueremains the recommended performant cuCIM path.Behavior notes
coordsreturn a NumPy object array whento_table=Trueto match the scikit-image convention. The elements of the object array are either NumPy or CuPy arrays. Whento_table=Falsea tuple of arrays is used instead of an object array.regionpropsemits a one-time warning recommendingregionprops_table(..., batch_processing=True)for performant cuCIM GPU region property computation.Tests
The updated tests cover:
regionprops_tableoutput.to_table=Falsepreserving unsplitbbox,centroidandinertia_tensorshapes in both non-batch and batch paths.coordsbehavior for unsplit variable-size outputs.regionpropsperformance warning.