Weird Behaviour of Parallel Processing when Using BlockProc

Hello, I a trying to speed up some analysis of an image (4700 v 128 pixels) that needs breaking up into smaller regions (20x128 pixels) and for each region having a calculation done such as the standard deviation (std2)
I thought the combination of Blockproc and the parallel toolbox would be ideal for this.
However, when I run my analysis, I sometmes get a fast completion time of 0.25s, but other times I run it it can take upto 3s.
1: When I start up my matlab session, i start a parallel pool:
% For parallel Processing (init parpool here)
delete(gcp('nocreate')); % but delete any that are already running
c=parcluster('local');
numwks=c.NumWorkers;
ReportMessage(app,['Parallel processing: NumWorkers = ',num2str(numwks)]);
parpool('Processes',numwks);
p=gcp;
conn=p.Connected;
ReportMessage(app,['...Connected ',num2str(conn)]);
2: I then run my fucntion from a push button callback.
My function first gets an image off a uiaxes, crops it and then performs the blockproc.
% Fast Analysis (SD)
tstart=tic;
ax=app.UIAxes;
IM=getimage(ax);
[sy,sx]=size(IM);
xl=5950; xr=10680; yb=0; yt=0; dx=xr-xl; % This is for image cropping
rect=[xl, yb, xr-xl,sy-yt-yb]; %[x, y, width, height]
IM2=imcrop(IM,rect);
IM=IM2-min(IM2(:)); % Background subtract
[sy,sx]=size(IM);
ColSize=20; % Number of pixels in each ROI - 20 default
nCols=floor(sx/ColSize);
RowSize = 128;
%BlockProc with Parallel
bss = [RowSize,ColSize]; % Each blockproc region
fh = @(bs) std2(bs.data); % perform this on each block
J = blockproc(IM, bss, fh,'UseParallel',true);
sd=J'; % Column vector
ReportMessage(app,num2str(toc(tstart)));
Is there something I am doing wrong? Do I need to close and reopen the parpool everytime or something.
Also, if I want the fh function to be a functio that has more than 1 argument, how do I do the syntax.
For example, I have a function (that works fine by itself)
Brenner=fmeasure(Image,'BREN',[]); %Focus metric
And I have tried to call it into Blockproc via:
fh = @(bs) fmeasure(bs.data,'BREN',[]);
It doesn't work properly.

1 件のコメント

Stephen23
Stephen23 37分 前
編集済み: Stephen23 26分 前
"Also, if I want the fh function to be a functio that has more than 1 argument, how do I do the syntax."
If you mean this function:
then it works without error using the syntax you showed:
im = rand(128,4700);
s1 = blockproc(im,[128,20],@(bs)fmeasure(bs.data,'BREN',[]))
s1 = 1×235
0.1589 0.1560 0.1617 0.1616 0.1503 0.1561 0.1550 0.1609 0.1597 0.1552 0.1595 0.1543 0.1585 0.1518 0.1560 0.1548 0.1673 0.1553 0.1623 0.1634 0.1598 0.1545 0.1561 0.1593 0.1552 0.1567 0.1624 0.1546 0.1563 0.1514
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>

サインインしてコメントする。

 採用された回答

Stephen23
Stephen23 約15時間 前
編集済み: Stephen23 約15時間 前

0 投票

I doubt that your example is good use of the parallel toolbox. Parallel code can be slower than serial code due to high communication overhead, small task sizes, or data serialization. It may be inefficient when workers send data back to the client frequently or when the overhead of starting a parallel pool outweighs the computation time. And your example has a small task size.
"...analysis of an image (4700 v 128 pixels) that needs breaking up into smaller regions (20x128 pixels)..."
RESHAPE and STD would be simpler and likely faster:
im = rand(128,4700);
tic
jm = reshape(im,128,20,[]);
s0 = std(jm,0,[1,2]);
toc
Elapsed time is 0.027938 seconds.
tic
s1 = blockproc(im,[128,20],@(bs)std2(bs.data));
toc
Elapsed time is 0.105474 seconds.
isequal(s0(:),s1(:))
ans = logical
1
A FOR loop could be useful too:
for k = 1:size(jm,3)
m = jm(:,:,k);
% do whatever with m
end
... which can be trivially converted to a PARFOR:

13 件のコメント

Jason
Jason 20分 前
編集済み: Jason 15分 前
Oh wow thats amazing. I did a time comparison on your S0 and S1 and get much faster times when using S0 (i.e. the reshape)
Elapsed time is 0.018587 seconds.
Elapsed time is 0.166048 seconds.
why is that, I thought Blockproc was the ultimate - obviously not.!
Could it be the use of std rather than std2?
Also, is there anything obviously wrong with my parallel toolbox approach - why do i sometimes see fast and other times slow.
Stephen23
Stephen23 12分 前
編集済み: Stephen23 8分 前
"why is that, I thought Blockproc was the ultimate - obviously not.!"
BLOCKPROC splits up data, calls functions repeatedly, works with relatively complex data types, and would have to have a lot of input/error handling. Based on that alone I would assume that it is not very fast. Convenient perhaps, but not fast.
"Could it be the use of std rather than std2?"
I doubt it. It is understanding how data is stored, avoiding splitting data up, avoiding calling functions lots of times, avoiding parallel toolbox for small tasks, using RESHAPE to make data convenient to access, maximising speed by performing multiple operations with single (inbuilt, highly optimised) function calls by using their options, and various other things that one learns. These are the native and natural ways to use MATLAB efficiently.
When a user comes onto this forum as writes "my code is slow and I tried to speed it up using the parallel toolbox" then they have usually misunderstood MATLAB as well as what parallel processing requires and when to apply it.
Jason
Jason 9分 前
Thankyou!
Jason
Jason 約1時間 前
編集済み: Jason 40分 前
Sorry, one last question, how do I get the sd values from here into a column vector (without using loops)?
s0 = std(jm,0,[1,2]);
[sy,sx,sz]=size(s0)
idx=(1:sz)'
figure
sd=s0(:,:,idx)
plot(sd)
This didn't work
Torsten
Torsten 26分 前
編集済み: Torsten 22分 前
im = rand(128,4700);
jm = reshape(im,128,20,[]);
s0 = std(jm,0,[1,2]);
size(s0)
ans = 1×3
1 1 235
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
sd = s0(:)
sd = 235×1
0.2883 0.2886 0.2886 0.2895 0.2908 0.2870 0.2869 0.2890 0.2892 0.2878 0.2852 0.2828 0.2901 0.2901 0.2901
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
hold on
plot(sd)
plot(1/sqrt(12)*ones(size(sd)))
hold off
Jason
Jason 約13時間 前
編集済み: Jason 約10時間 前
thankyou
Btw, where does this come from?
plot(1/sqrt(12)*ones(size(sd)))
Jason
Jason 約13時間 前
編集済み: Jason 約13時間 前
Actually, im really sorry but Im still running into an error using the reshape approach
My actual image is 4730 pixels wide (not 4700) and 128 pixels high.
I want each sub region to be 20 pixels wide and 128 pixels high like in the picture below
I tried this:
[sy,sx]=size(IM);
nRows=floor(sy/128);
nCols=floor(sx/20);
jm = reshape(IM,nRows,nCols,[]); % reshape = rows, then cols
Error using reshape
Product of known dimensions, 236, not divisible into total number of elements, 605568.
Torsten
Torsten 約12時間 前
編集済み: Torsten 約12時間 前
You must take nRows and nCols such that their product gives 4730.
factor(4730)
ans = 1×4
2 5 11 43
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Thus nRows = 2, nCols = 5*11*43 or nRows = 2*5, nCols = 11*43 or nRows = 5*11, nCols = 2*43 or ... is allowed.
Or you must cut some part of the image.
Jason
Jason 約11時間 前
OK, thankyou.
Stephen23
Stephen23 約10時間 前
編集済み: Stephen23 約7時間 前
The error message states:
"Product of known dimensions, 236, not divisible into total number of elements, 605568."
Note that the function RESHAPE simply changes the dimension sizes of an array, without adding or removing any data.
Now consider your image, whch contains NP many pixels (where NP does not match your comment):
im = rand(128,4730);
sz = size(im);
np = prod(sz)
np = 605440
Now lets look at what you attempted with those NP pixels:
[sy,sx] = size(im);
nRows = floor(sy/128)
nRows = 1
nCols = floor(sx/20)
nCols = 236
So you attempted to reshape NP elements into an array with 1 row, 236 columns, and some unknown number of pages. But is NP divisble by 1 and 236 ? Well, 1 is trivial, but 236 lets check if there is any remainder:
mod(np,nCols)
ans = 100
Nope, the number of rows and columns that you attempted to reshape IM into will not work because they cannot evenly divide the number of pixels of IM. That is the cause of the error: RESHAPE cannot create the size array that you requested, because it would require either inventing more data or removing it, which RESHAPE does not do.
Also note that your concept of how to specify the number of rows and columns is unlikely to help you, as should be clear when you perform some basic sanity check, e.g. by asking yourself "why am I reshaping all of the pixels into one row?". You should be counting pixels.
Jason
Jason 約10時間 前
編集済み: Jason 約10時間 前
Thankyou for an excellent explanation (and toTorsten).
Ive decided to crop my image so its exactly divisible.
I love how the std you showed uses pages. If i wanted to calculate the Brenner metric instead of the std, how would I do that. It seens std allows for "paging" but its not obvious how the fmeasure function allows for it.
Just to add, you've blown me away with your example being so much faster than blockproc.
Stephen23
Stephen23 約7時間 前
編集済み: Stephen23 約6時間 前
"If i wanted to calculate the Brenner metric instead of the std, how would I do that. It seens std allows for "paging" but its not obvious how the fmeasure function allows for it."
I would skip FMEASURE entirely. If speed is important to you then I would start with a simple FOR loop, which is likely to give reasonable speed, give you a good baseline, and be easy to implement:
im = rand(128,4700);
tic
rn = 128;
cn = 20;
jm = reshape(im,rn,cn,[]);
pn = size(jm,3);
b0 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
a = m(3:end,:)-m(1:end-2,:);
b = m(:,3:end)-m(:,1:end-2);
a(rn,1) = 0;
b(1,cn) = 0;
b0(k) = mean2(max(a,b).^2);
end
toc
Elapsed time is 0.014675 seconds.
b0
b0 = 235×1
0.1600 0.1487 0.1606 0.1542 0.1573 0.1644 0.1561 0.1576 0.1584 0.1644 0.1544 0.1584 0.1542 0.1596 0.1567
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
"where does this come from?"
It is the expected standard deviation of a continuous uniform distribution U(a,b) between a=0 and b=1. The variance of the uniform distribution is which for those a & b gives . The standard deviation is therefore just the square root of that.
Jason
Jason 約2時間 前
編集済み: Jason 約2時間 前
Wow! Could I ask 1. Why do you suggest not using fmeasure? 2. Could you explain your FOR loop please and what that end metric actually is? Thankyoy

サインインしてコメントする。

その他の回答 (0 件)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by