Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scope for improvement in this code

I have written the following code in MATLAB to process large images of the order of 3000x2500 pixels. Currently the operation takes more than half hour to complete. Is there any scope to improve the code to consume less time? I heard parallel processing can make things faster, but I have no idea on how to implement it. How do I do it, given the following code?

function dirvar(subfn)
[fn,pn] = uigetfile({'*.TIF; *.tiff; *.tif; *.TIFF; *.jpg; *.bmp; *.JPG; *.png'}, ...
            'Select an image', '~/');
I = double(imread(fullfile(pn,fn)));
ld = input('Enter the lag distance = '); % prompt for lag distance
fh = eval(['@' subfn]); % Function handles
I2 = uint8(nlfilter(I, [7 7], fh));
imshow(I2); % Texture Layer Image
imwrite(I2,'result_mat.tif');

% Zero Degree Variogram
function [gamma] = ewvar(I)
    c = (size(I)+1)/2; % Finds the central pixel of moving window
    EW = I(c(1),c(2):end); % Determines the values from central pixel to margin of window
    h = length(EW) - ld; % Number of lags
    gamma = 1/(2 * h) * sum((EW(1:ld:end-1) - EW(2:ld:end)).^2);
end

The input lag distance is usually 1.

like image 824
Chethan S. Avatar asked May 18 '11 23:05

Chethan S.


People also ask

What are the scopes of coding?

Scope is a concept that refers to where values and functions can be accessed. Various scopes include: Global scope (a value/function in the global scope can be used anywhere in the entire program) File or module scope (the value/function can only be accessed from within the file)

What are code improvements?

Code improvement at the level of basic blocks is known as local optimization. It focuses on the elimination of redundant opera- tions (e.g., unnecessary loads or common subexpression calculations), and on effective instruction scheduling and register allocation.


3 Answers

You really need to use the profiler to get some improvements out of it. My first guess (as I haven't run the profiler, which you should as suggested already), would be to use as little length operations as possible. Since you are processing every image with a [7 7] window, you can precalculate some parts, such that you won't repeat these actions

function dirvar(subfn)
[fn,pn] = uigetfile({'*.TIF; *.tiff; *.tif; *.TIFF; *.jpg; *.bmp; *.JPG; *.png'}, ...
            'Select an image', '~/');
I = double(imread(fullfile(pn,fn)));
ld = input('Enter the lag distance = '); % prompt for lag distance
fh = eval(['@' subfn]); % Function handles

%% precalculations
wind = [7 7];
center = (wind+1)/2; % Finds the central pixel of moving window
EWlength = (wind(2)+1)/2;
h = EWlength - ld; % Number of lags

%% calculations
I2 = nlfilter(I, wind, fh);
imshow(I2); % Texture Layer Image
imwrite(I2,'result_mat.tif');

% Zero Degree Variogram
function [gamma] = ewvar(I)
    EW = I(center(1),center(2):end); % Determines the values from central pixel to margin of window
    gamma = 1/(2 * h) * sum((EW(1:ld:end-1) - EW(2:ld:end)).^2);
end
end

Note that by doing so, you trade performance for clearness of your code and coupling (between the function dirvar and the nested function ewvar). However, since I haven't profiled your code (you should do that yourself using your own inputs), you can find what line of your code consumes the most time.

For batch processing, I would also recommend to leave out any input, imshow, imwrite and uigetfile. Those are commands that you typically call from a more high-level function/script and that will force you to enter these inputs even when you want them to stay the same. So instead of that code, make each of the variables they produce (/process) a parameter (/return value) for your function. That way, you could leave MATLAB running during the weekend to process everything (without having manually enter to all those values), even if you are unable to speed up the code.

like image 84
Egon Avatar answered Oct 21 '22 06:10

Egon


A few general purpose tricks:

1 - use the MATLAB profiler to determine all the computational bottlenecks

2 - parallel processing can make things faster and there are a lot of tools that you can use, but it depends on how your entire code is set up and whether the code is optimized for it. By far the easiest trick to learn is parfor, where you can replace the top level for loop by parfor. This does mean you must open the MATLAB pool with matlabpool open.

3 - If you have a rather recent Nvidia GPU as well as MATLAB 2011, you can also write some CUDA code.

All in all 30 mins to me is peanuts, so don't fret it too much.

like image 3
Rasman Avatar answered Oct 21 '22 06:10

Rasman


First of all, I strongly suggest you follow the advice by @Egon: Write a separate function that collects a list of files (the excellent UIPICKFILES from the FEX is your friend here), and then runs your filtering code in a loop for each image. Note that you should definitely keep the call to imwrite in your filtering code: In case the analysis crashes at image 48 (e.g. due to power failure), you don't want to lose all the previous work.

Running thusly in batch mode has two big advantages: (1) you can start running your code and go home for the week-end, and (2) you can easily parallelize this outside loop using PARFOR. However, with only a dual-core machine, it is unlikely that you get any significant improvements from parallelization - your OS also wants to run stuff at times, and the overhead of parallelization might be more than the gain from running two workers. Also, 2.5GB of RAM is seriously limiting.

As to your specific code: in my experience using IM2COL is often faster than NLFILTER. im2col creates a nElementsInMask-by-nMasks array out of your image, so that you can apply the filtering in one single operation. With a 7x7 window, the output of im2col will be 3000*2500*49 bytes, which is close to 400MB. Thus, it should just work. All that you need to do is rewrite ewvar so that it works on a 49x1 array of pixels that make up the pixels your mask, which will require some index juggling, if I understand your code correctly.

like image 1
Jonas Avatar answered Oct 21 '22 06:10

Jonas