# Testing Julia for speed (iii)

The last example for testing speed in Julia will be a 5×5 mean filter. A mean filter is simply a way of smoothing an image, ie. suppressing irregularities in the intensities, and is common used for noise suppression. It basically works by working through each pixel in an image, obtaining the mean of the 5×5 region around that pixel, and using this value as the pixel in the filtered image. As such it is an intensive algorithm.

In this particular example, we shall apply a mean filter to a 2144×6640 pixel, 8-bit image: effectively 14 megapixels. The algorithm is analyzed using code written in C, Fortran, Python and Julia.

The 14MP 8-bit image

The image is processed using the following Julia code:

```function process(img)

dx,dy = size(img)
imgN = copy(img)
e = div(5,2)

for i=e+1:dx-e, j=e+1:dy-e
block = img[i-e:i+e,j-e:j+e]
mn = mean(block)
imgN[i,j] = round(UInt8,mn)
end
return imgN
end

@time imgN = process(img)
writedlm("panoJ.txt",imgN)```

Since Julia provides efficient means of reading an entire block of integers in from an ASCII file, the code is much shorter than it would be in C. In addition, Python, Julia and Fortran provide facilities to slice arrays, making extraction of the 5×5 neighbourhood easy.

The code has been timed based just on the process of performing the mean filtering, and avoiding extras such as file I/O. In most cases this involves a nested loop to process each pixel in the image. In the case of C, it includes a second set of nested loops to extract the 5×5 neighbourhood.

As the results show, C was able to process the image in less than a second, with Fortran in second place marginally over a second. At just over 3 seconds, the Julia code could be considered to be exceptionally fast as well. The loser in this instance is again Python which is invariably slow, even with only one pair of nested loops. In a future post, I will explore this algorithm in each of the languages cited in the context of image processing.

## 4 thoughts on “Testing Julia for speed (iii)”

1. perfectionatic says:

Looks like you are doing too much unnecessary memory allocation.
replace
block = img[i-e:i+e,j-e:j+e]
by
block = @view img[i-e:i+e,j-e:j+e]

• spqr says:

Thanks for the info. Although I appreciate that it may improve the speed slightly, I actually prefer to keep the code simple… mostly so that novice programmers can figure out what’s going on. Julia is a great language, but adding too many of these features can eventually distract from the languages usability (I mean look at C++!)

• spqr says:

P.S. I just tried it with the @view… the timing was 3.44sec vs 3.99sec without.

• perfectionatic says:

I understand your concern. However, in a lower level language like C or Fortran, a programmer will naturally find himself worrying about allocating memory for arrays and doing the necessary clearing afterwards. Julia allows you to either make a copy of subset of your array, as in your original code, to just create a “view”.
W few points I would like to add:
1. It would be great if your to share your code in all the mentioned languages for the reader to better appreciate the code complexity/speed tradeoff.
2. It is not clear if in Julia you allowed for the initial compilation time of your function
3. Increasingly @btime from Benchmarktools.jl is the preferred method for measuring performance.