How to use composite objects using spmd

조회 수: 16 (최근 30일)
Hala Nagi
Hala Nagi 2022년 10월 17일
댓글: Hala Nagi 2022년 10월 18일
I am trying to implement video-on-demand using the spmd parallel computing function. I have a saved video encoded at 3 different qualities and segmented into 3second segments, and I am trying to save video frames to the video buffer (modelled as a structure) while simultaneously playing from the buffer at a constant rate of 24 frames per second. The quality of each segment must be selected based on the buffer level. However, I am getting the error "Error detected on worker 1. Subscripted assignment between dissimilar structures" from running the following code:
mov = struct; % video buffer
bufsize = length(mov); %buffer level
spmd
switch labindex
case 1
segnum = 0; %segment number
i=1;
c=1;
br = 20; %assumed channel bandwidth in Mbps
%Check last segment number and get segment names from file
res = ["low" "mid" "sample"]; %available resolutions
resnum = 1;
filename = sprintf('%sdash.m3u8',res(resnum));
s = importdata(filename);
lastseg = s{end-1,1};
[lastsegnum,n,err] = sscanf(lastseg,(res(resnum)+'dash%d.ts'));
%Get frame size for highest quality
vidobj = VideoReader("sampledash1.ts");
v = read(vidobj,1);
framesize = size(v);
%Get next segment with appropriate quality
while segnum<=lastsegnum
if bufsize<72 %24fps*3sec = 72 frames in one segment
resnum = 1;
elseif bufsize>=72 && br<216
resnum = 2;
elseif bufsize>=216
resnum = 3;
end
segment = sprintf('%sdash%d.ts',res(resnum),segnum);
vidobj = VideoReader(segment);
f = dir(segment);
fsz = f.bytes; %size of segment
x = rand;
delay = ((fsz*8)/(br*1e6)) + x; %network delay
pause(delay);
while hasFrame(vidobj)
mov(c) = im2frame(readFrame(vidobj));
mov(c).cdata = imresize(mov(c).cdata,[framesize(1) framesize(2)]);
labSend(mov(c).cdata,labindex+1,11);
bufsize = bufsize+1;
c = c+1;
end
labSend(segnum,labindex+1,12);
segnum=segnum+1;
end
case 2
depvid = vision.DeployableVideoPlayer('Size','Full-screen');
i=1;
while ~isempty(mov) %start playing the video only after the first two segments have been downloaded
frame = labReceive(labindex-1,11);
segnum = labReceive(labindex-1,12);
vid(i).cdata = frame;
i=i+1;
if segnum>1
step(depvid,vid(1).cdata)
pause(1/24)
vid(1) = [];
i = i-1;
end
end
end
end
I am a bit confused about why I am getting this error. I think it may be due to the Composite objects created by the function, but I'm not sure how.

채택된 답변

Raymond Norris
Raymond Norris 2022년 10월 17일
It's not related to your parallel code, the issue is the initialization of mov. This can be reproduced by the following
function nagi
mov = struct();
%mov.cdata = [];
%mov.colormap = [];
M.cdata = ones(240,320,3,'uint8');
M.colormap = [];
mov(1) = M;
So it's getting tripped up here
mov(c) = im2frame(readFrame(vidobj));
If you initialize mov as I've commented it out, you'll be fine.
Side note: I'm assuming at some point, labindex 1 won't have anything else to send labindex 2, correct? If so, you're going to run into the issue that labindex 2 is continuing to wait to receive from labindex 1. Keep in mind, for labindex 2, mov is never empty. For all intents and purposes, it only sees
mov = struct;
(Or however you end up initializing it). Therefore, at somepoint, MATLAB will throw
A communication mismatch error was encountered:
The other lab became idle during labReceive.
"The other lab" in this case is labindex 1.
  댓글 수: 3
Raymond Norris
Raymond Norris 2022년 10월 18일
You mentioned in a comment
%start playing the video ...
but I don't see where that was actually happening, is that the call to step? Keep in mind that technically the graphics can display (and you could even print the figures to a file), but you can't see the graphics in a spmd or parfor block. Case in point, try
parfor idx = 1:2, plot(rand(10)); end
spmd, plot(rand(10)); end
The reason is because the workers are "headless" -- they don't show their graphics. What you can use is a parallel.pool.DataQueue. Here's a simple toy example
Q = parallel.pool.DataQueue;
afterEach(Q,@updatePlot);
spmd
for idx = 1:50
if labindex==2
% Worker 2 is the workhorse, responsible for sending data back
% to the client, which in turn plots the result
% "Calculate" some data
r = round(rand*100)+5;
% Send it to the client
send(Q,r)
end
end
end
function updatePlot(r)
% Plot the results
surfc(1:r,1:r,rand(r))
axis tight, shg
end
Hala Nagi
Hala Nagi 2022년 10월 18일
That worked! Thank you so so much!!

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Parallel for-Loops (parfor)에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by