Help with parfor progress bar using data queue
24 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Hello. I am trying to implement a progress par for a parfor loop, following the example shown at
I am using a script instead of a function as shown in the example, but I am unable to adapt the code in a way that works.
My code:
clear
D = parallel.pool.DataQueue;
h = waitbar(0, 'Please wait ...');
afterEach(D, @nUpdateWaitbar);
num_files = 1000;
parfor i = 1:num_files
% do stuff
send(D, [i num_files]);
end
function p = nUpdateWaitbar(input)
p = input(1)/input(2)
waitbar(p, h);
end
Executing this gives
Warning: Unrecognized function or variable 'h'.
which I assume is because the function nUpdateWaitbar doesnt know what 'h' is
but if I try to pass the waitbar handle 'h' into the dataqueue, I get another error:
Cannot convert double value 1000 to a handle
Can you please point me towards what I am doing wrong?
the parfor loop runs fine without the waitbar code so I dont think that is the issue
thanks!
5 Kommentare
Mario Malic
am 24 Nov. 2020
Bearbeitet: Mario Malic
am 25 Nov. 2020
Try this
function p = nUpdateWaitbar(input)
persistent h
if isempty(h)
h = findall(0, 'type', 'figure', 'Tag', 'TMWWaitbar');
end
p = input(1)/input(2)
waitbar(p, h);
end
Akzeptierte Antwort
Edric Ellis
am 25 Nov. 2020
The problem here is that the documentation example is using a nested function, which is able to acces variables in the containing workspace. Your function definition inside a script is a local function, which cannot automatically access the variables in the containing workspace. An alternative fix is to use an anonymous function handle to "bind" in the value of h.
clear
D = parallel.pool.DataQueue;
h = waitbar(0, 'Please wait ...');
% Note anonymous function captures the value of "h" to pass
% in to "nUpdateWaitbar"
afterEach(D, @(data) nUpdateWaitbar(data, h));
num_files = 1000;
parfor i = 1:num_files
% do stuff
send(D, [i num_files]);
end
function p = nUpdateWaitbar(input, h)
p = input(1)/input(2)
waitbar(p, h);
end
This "works", but it isn't right. If you run it you'll see the value flickering about because the parfor loop iterations are not processed in order. So, you need a different approach for nUpdateWaitbar. I would essentially make nUpdateWaitbar contain persistent data and have an "initialisation" mode. Like this:
clear
D = parallel.pool.DataQueue;
h = waitbar(0, 'Please wait ...');
num_files = 1000;
% Dummy call to nUpdateWaitbar to initialise
nUpdateWaitbar(num_files, h);
% Go back to simply calling nUpdateWaitbar with the data
afterEach(D, @nUpdateWaitbar);
parfor i = 1:num_files
% do stuff
% Note we send only an "increment" for the waitbar.
send(D, 1);
end
function p = nUpdateWaitbar(data, h)
persistent TOTAL COUNT H
if nargin == 2
% initialisation mode
H = h;
TOTAL = data;
COUNT = 0;
else
% afterEach call, increment COUNT
COUNT = 1 + COUNT;
p = COUNT / TOTAL;
waitbar(p, H);
end
end
3 Kommentare
Edric Ellis
am 30 Nov. 2020
persistent is more tightly-scoped than global - so you don't have to worry about whether other bits of code might interfere. (In general, it's good practice to try and keep your data as tightly-scoped as possible). In my 2nd example above, nUpdateWaitbar is a "local" function inside the script - this means it is only accessible to code within that script file.
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu Loops and Conditional Statements finden Sie in Help Center und File Exchange
Produkte
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!