How to use composite objects using spmd

22 ビュー (過去 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 Center および File ExchangeParallel for-Loops (parfor) についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by