Store intermediate results of cost function when solver is run in parallel

1 view (last 30 days)
Hey,
I have a cost function that is comprised of two intermediate results f1 and f2.
When I run some solver to minimize this function, I would like to keep track of f1 and f2 in each iteration. Is there any way to do that? I know that you can specify output functions but they only give you the value of J and x and not f1 and f2.
What I tried to do is to use global variables:
global f1Array f2Array
f1Array = []; f2Array = [];
opts = optimoptions('fmincon', 'UseParallel', true, 'Display', 'off');
[x, ~, ~, output] = fmincon(@fun, 1, [], [], [], [], 0.1, 2, [], opts);
fprintf('fcount according to fmincon: %d\n', output.funcCount)
fprintf('fcount as stored in object: %d\n', numel(f1Array))
function J = fun(x)
global f1Array f2Array
f1 = 1/x^2;
f2 = sqrt(x);
J = max(f1, f2)
f1Array(end+1) = f1;
f2Array(end+1) = f2;
end
However, when you run this optimization in parallel, not all function calls are being kept track of.
It works fine in serial but how do I solve this in parallel?
Thanks!

Accepted Answer

Edric Ellis
Edric Ellis on 4 Jan 2024
You could use a parallel.pool.PollableDataQueue to let the workers send the data to the client. The idea is that you create the queue at the client where you will receive the data, and give it to the workers who then call send to send across the intermediate values. Here's one way:
% This queue will receive all the messages
dq = parallel.pool.PollableDataQueue();
opts = optimoptions('fmincon', 'UseParallel', true, 'Display', 'off');
% Bind the DataQueue into the function
[x, ~, ~, output] = fmincon(@(x) fun(x,dq), 1, [], [], [], [], 0.1, 2, [], opts);
% Drain all the results from the DataQueue.
% (It might be simpler to use a parallel.pool.DataQueue together with
% afterEach rather than PollableDataQueue and poll).
f1f2 = {};
ok = true;
while ok
[data, ok] = dq.poll(0);
if ok
f1f2{end+1} = data;
end
end
fprintf('fcount according to fmincon: %d\n', output.funcCount)
fprintf('fcount as stored in object: %d\n', numel(f1f2))
function J = fun(x, dq)
f1 = 1/x^2;
f2 = sqrt(x);
% Send intermediate values to client
send(dq, {f1, f2});
J = max(f1, f2);
end
  3 Comments
Cedric Kotitschke
Cedric Kotitschke on 30 Jan 2024
Now that I implemented this in my framework, I noticed that in some cases, the number of data points in the data queue is less than the number of function evaluations. What exactly causes this? It seems like the send command does not work all the time. The problem is that I can't reproduce this with simple examples...
Edric Ellis
Edric Ellis on 30 Jan 2024
Hm, that doesn't sound right, the send should always make it through - I don't know of any reason why it wouldn't. You could try contacting MathWorks support who can help you set up Parallel Computing Toolbox diagnostic logging which might help work out what's going wrong.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!