This notebook compares different implementations of the Gaussian blur filter.
Note: benchmarking results vary heavily depending on image size, kernel size, used operations, parameters and used hardware. Use this notebook to adapt it to your use-case scenario and benchmark on your target hardware. If you have different scenarios or use-cases, you are very welcome to submit your notebook as pull-request!
import pyclesperanto_prototype as cle
from skimage import filters
import cupy
import cupyx.scipy.ndimage as ndi
import time
# to measure kernel execution duration properly, we need to set this flag. It will slow down exection of workflows a bit though
cle.set_wait_for_kernel_finish(True)
# selet a GPU with the following in the name. This will fallback to any other GPU if none with this name is found
cle.select_device('RTX')
<NVIDIA GeForce RTX 3050 Ti Laptop GPU on Platform: NVIDIA CUDA (1 refs)>
# test data
import numpy as np
test_image = np.random.random([100, 512, 512])
sigma = 10
# convolve with pyclesperanto
result_image = None
cl_test_image = cle.push_zyx(test_image)
for i in range(0, 10):
start_time = time.time()
result_image = cle.gaussian_blur(cl_test_image, result_image, sigma_x=sigma, sigma_y=sigma, sigma_z=sigma)
print("pyclesperanto Gaussian duration: " + str(time.time() - start_time))
pyclesperanto Gaussian duration: 0.22815942764282227 pyclesperanto Gaussian duration: 0.2140495777130127 pyclesperanto Gaussian duration: 0.2140507698059082 pyclesperanto Gaussian duration: 0.21404790878295898 pyclesperanto Gaussian duration: 0.21464228630065918 pyclesperanto Gaussian duration: 0.21403980255126953 pyclesperanto Gaussian duration: 0.2160477638244629 pyclesperanto Gaussian duration: 0.21304845809936523 pyclesperanto Gaussian duration: 0.2190532684326172 pyclesperanto Gaussian duration: 0.21404457092285156
# convolve with cupy
result_image = None
cu_test_image = cupy.asarray(test_image)
for i in range(0, 10):
start_time = time.time()
result_image = ndi.gaussian_filter(cu_test_image, output=result_image, sigma=sigma)
cupy.cuda.stream.get_current_stream().synchronize() # we need to wait here to measure time properly
print("cupy Gaussian duration: " + str(time.time() - start_time))
cupy Gaussian duration: 0.6600561141967773 cupy Gaussian duration: 0.5146195888519287 cupy Gaussian duration: 0.5141170024871826 cupy Gaussian duration: 0.5151159763336182 cupy Gaussian duration: 0.5141191482543945 cupy Gaussian duration: 0.5151159763336182 cupy Gaussian duration: 0.5151159763336182 cupy Gaussian duration: 0.5141153335571289 cupy Gaussian duration: 0.514115571975708 cupy Gaussian duration: 0.513115406036377
# convolve with scikit-image
result_image = None
for i in range(0, 10):
start_time = time.time()
result_image = filters.gaussian(test_image, output=result_image, sigma=sigma)
print("skimage Gaussian duration: " + str(time.time() - start_time))
skimage Gaussian duration: 2.6776022911071777 skimage Gaussian duration: 2.6525967121124268 skimage Gaussian duration: 2.6535966396331787 skimage Gaussian duration: 2.653596878051758 skimage Gaussian duration: 2.6505963802337646 skimage Gaussian duration: 2.6475954055786133 skimage Gaussian duration: 2.653596878051758 skimage Gaussian duration: 2.6495962142944336 skimage Gaussian duration: 2.645595073699951 skimage Gaussian duration: 2.511046886444092