# Octave: Poor performance of convolution by separable 1D kernels

As a newbie, I wrote a custom function in octave to perform a 2D image convolution using separable kernels. The results of this custom function were compared with conv2() and they were consistent. But that was where the joy ended.

conv2() works at the speed of light while my custom function is slower than a steam locomotive.

How can I speed up the loops below? As you can see, the number of MACs per pixel is 6 compared to 9 that would have been the case in 2D convolution. The function takes as inputs a row vector(3x1) and a column vector(1x3).

function OutputImage = Convolve3X3(InputImage, RowCount, ColCount, Kernel_x, Kernel_y)

% Create a padded image
PaddedImage = uint8(zeros(RowCount + 2, ColCount + 2));

% Create a staging area
StagingImage = uint8(zeros(RowCount + 2, ColCount + 2));

% Create a Row Vector
RowVector = uint8(zeros(1,3));

% Create a Col Vector
ColVector = uint8(zeros(3,1));

% Copy the input image into the padded image
PaddedImage(2:RowCount + 1, 2:ColCount + 1) = InputImage;

% 1D convolution of necessary rows with Kernel_x
for i = 2: RowCount + 1
for j = 1:ColCount
RowVector = PaddedImage(i,j:j+2) .* Kernel_x;
StagingImage(i,j) = RowVector(1) + RowVector(2) + RowVector(3);
end
end

% 1D convolution of necessary columns with Kernel_y
for i = 1: RowCount
for j = 1:ColCount
ColVector = StagingImage(i:i+2,j) .* Kernel_y;
OutputImage(i,j)  = ColVector(1) + ColVector(2) + ColVector(3);
end
end

endfunction


How is conv2() so radically fast?

## 1 Answer

Because loops in MATLAB/Octave are slow (mostly because they are interpreted languages not compiled) and such operations are typically implemented in C/C++ for performance reasons. You could even further speed these up by reverting to better C/C++ implementations and writing your mex wrappers.