Slow Triple for loop
Show older comments
Hi,
I have created a program that has a tripple for loop but runs very slowly and was hoping for some tips to speed it up... Here is the code:
if WeightingVectorWells(1) > 0 || WeightingVectorWells(4) > 0
for LatCounter = 1:length(handles.Latitude)
for LongCounter = 1:length(handles.Longitude)
for WellDataCounter = 1:size(handles.WellData,1)
if sqrt(((handles.WellData{WellDataCounter,2} - handles.Latitude(LatCounter)) ^ 2 + (handles.WellData{WellDataCounter,3} - handles.Longitude(LongCounter)) ^ 2)) < .01067
handles.ScoreSheetBPDOil(LatCounter,LongCounter) = handles.WellData{WellDataCounter,12} * WeightingVectorWells(1) + ...
handles.ScoreSheetBPDOil(LatCounter,LongCounter);
handles.ScoreSheetCumOil(LatCounter,LongCounter) = handles.WellData{WellDataCounter,13} * WeightingVectorWells(4) + ...
handles.ScoreSheetCumOil(LatCounter,LongCounter);
end
end
end
if LatCounter == length(handles.Latitude)
LatCounter = LatCounter - 1;
end
progressbar(LatCounter / length(handles.Latitude))
end
end
I created a GUI for this program (first time using GUIDE and handles and handles was the easiest way I found to talk to different functions and share data so sorry if that's bad pratice). The handles.ScoreSheets are preallocated. The LatCounter and LongCounter are both about 300 in size and the handles.WellData is a 19000 by 26 matrix (19000 being the max, it can be as little as 1 but is usually around 500 or so). Whenever I stop this mid processing (ctrl-c) it always seems to be doing the sqrt function. Also, as a side note I'm trying to get my company to get parallel processing tool box because I have six of these loops. progressbar is just a function I picked up off the file exchange and takes very little processing and the if statement at the bottom inside the outer most loop is just so that progressbar doesn't bug out.
Thanks for any help, I'm an engineer, not a programmer so I really do appreciate anything.
Accepted Answer
More Answers (1)
Iain
on 17 Jul 2013
1. Do the calculations as few times as possible: The following should be in the outer loop. - Unless you want latcounter to be allowed to be the maximum value for a single calculation.
if LatCounter == length(handles.Latitude)
LatCounter = LatCounter - 1;
end
2. Minimize the amount of calcs:
sqrt(x) < y, could be x < y^2 - given that y^2 is a constant, you've removed the sqrt calc from the loop.
3. Vectorise wherever possible.
Your inner loop can be REMOVED and replaced with.
index = ((([handles.WellData{:,2}] - handles.Latitude(LatCounter)) ^ 2 + ([handles.WellData{:,3}] - handles.Longitude(LongCounter)) ^ 2)) < .01067^2;
handles.ScoreSheetBPDOil(LatCounter,LongCounter) = sum([handles.WellData{index,12}]) * WeightingVectorWells(1);
handles.ScoreSheetCumOil(LatCounter,LongCounter) = sum( [handles.WellData{index,13}]) * WeightingVectorWells(4);
3a. Its easier to vectorise if your variables are straightforward numeric arrays (handles.WellData is not) 3b. With thought, you can use elementwise operations and bsxfun, to remove all three loops.
Categories
Find more on Programming in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!