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

adding raven filter memory estimator #530

Merged
merged 2 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ prep:
memory_gpu:
multiplier: None
method: module
raven_filter:
pattern: sinogram
output_dims_change: False
implementation: gpu_cupy
save_result_default: False
padding: False
memory_gpu:
- datasets: [tomo]
- multipliers: [None]
- methods: [module]
recon:
algorithm:
FBP:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@
from typing import Tuple
import numpy as np

from httomo.cufft import CufftType, cufft_estimate_2d


__all__ = [
"_calc_memory_bytes_remove_stripe_ti",
"_calc_memory_bytes_remove_all_stripe",
"_calc_memory_bytes_raven_filter",
]


Expand Down Expand Up @@ -66,3 +69,53 @@ def _calc_memory_bytes_remove_all_stripe(
tot_memory_bytes = int(input_size + output_size)

return (tot_memory_bytes, methods_memory_allocations)


def _calc_memory_bytes_raven_filter(
non_slice_dims_shape: Tuple[int, int],
dtype: np.dtype,
**kwargs,
) -> Tuple[int, int]:

pad_x = kwargs["pad_x"]
pad_y = kwargs["pad_y"]

input_size = np.prod(non_slice_dims_shape) * dtype.itemsize
output_size = np.prod(non_slice_dims_shape) * dtype.itemsize

# Padded input
padded_non_slice_dims_shape = (
non_slice_dims_shape[0] + 2 * pad_y,
non_slice_dims_shape[1] + 2 * pad_x,
)

in_slice_size_pad = (
(padded_non_slice_dims_shape[0])
* (padded_non_slice_dims_shape[1])
* dtype.itemsize
)
out_slice_size_pad = in_slice_size_pad

complex_slice_fft_data = in_slice_size_pad / dtype.itemsize * np.complex64().nbytes
complex_slice_fft_data_shifted = complex_slice_fft_data
data_out_ifft_complex = complex_slice_fft_data

# Plan size for 2D FFT
fftplan_slice = cufft_estimate_2d(
nx=padded_non_slice_dims_shape[1],
ny=padded_non_slice_dims_shape[0],
fft_type=CufftType.CUFFT_C2C,
)

tot_memory_bytes = int(
input_size
+ output_size
+ in_slice_size_pad
+ out_slice_size_pad
+ complex_slice_fft_data
+ complex_slice_fft_data_shifted
+ data_out_ifft_complex
+ 2 * fftplan_slice
)

return (tot_memory_bytes, 0)
37 changes: 36 additions & 1 deletion tests/test_backends/test_httomolibgpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
remove_stripe_based_sorting,
remove_stripe_ti,
remove_all_stripe,
raven_filter,
)
from httomolibgpu.prep.stripe import remove_stripe_based_sorting, remove_stripe_ti
from httomolibgpu.misc.corr import remove_outlier
from httomolibgpu.recon.algorithm import FBP, SIRT, CGLS
from httomolibgpu.misc.rescale import rescale_to_int
Expand Down Expand Up @@ -343,6 +343,41 @@ def test_remove_stripe_ti_memoryhook(slices, ensure_clean_memory):
assert percents_relative_maxmem <= 20


@pytest.mark.cupy
@pytest.mark.parametrize("projections", [180, 360, 720, 1080, 1440])
def test_raven_filter_memoryhook(projections, ensure_clean_memory):
vert_det = 10
horiz_det = 2560
data = cp.random.random_sample((projections, vert_det, horiz_det), dtype=np.float32)
kwargs = {}
kwargs["pad_x"] = 20
kwargs["pad_y"] = 20
hook = MaxMemoryHook()
with hook:
data_filtered = raven_filter(cp.copy(data), **kwargs).get()

# make sure estimator function is within range (80% min, 100% max)
max_mem = (
hook.max_mem
) # the amount of memory in bytes needed for the method according to memoryhook

# now we estimate how much of the total memory required for this data
(estimated_memory_bytes, subtract_bytes) = _calc_memory_bytes_raven_filter(
(projections, horiz_det), dtype=np.float32(), **kwargs
)
estimated_memory_mb = round(vert_det * estimated_memory_bytes / (1024**2), 2)
max_mem -= subtract_bytes
max_mem_mb = round(max_mem / (1024**2), 2)

# now we compare both memory estimations
difference_mb = abs(estimated_memory_mb - max_mem_mb)
percents_relative_maxmem = round((difference_mb / max_mem_mb) * 100)
# the estimated_memory_mb should be LARGER or EQUAL to max_mem_mb
# the resulting percent value should not deviate from max_mem on more than 20%
assert estimated_memory_mb >= max_mem_mb
assert percents_relative_maxmem <= 25


@pytest.mark.cupy
@pytest.mark.parametrize("angles", [900, 1800])
@pytest.mark.parametrize("dim_x_slices", [1, 3, 5])
Expand Down
Loading