Unify batch job processing with a shared runBatch core
This commit is contained in:
@@ -4,69 +4,50 @@ arguments
|
||||
funcHandle
|
||||
wh
|
||||
options.parallel = 1;
|
||||
end
|
||||
|
||||
%%% 2) SUBMIT SIMULATION
|
||||
% Initialize job results
|
||||
if options.parallel
|
||||
curpool = gcp('nocreate');
|
||||
if isempty(curpool)
|
||||
parpool;
|
||||
else
|
||||
% stop all forgotten or unfetched jobs from queue
|
||||
if ~isempty(curpool.FevalQueue.QueuedFutures) || ~isempty(curpool.FevalQueue.RunningFutures)
|
||||
oldq = length(curpool.FevalQueue.QueuedFutures) + length(curpool.FevalQueue.RunningFutures);
|
||||
curpool.FevalQueue.cancelAll
|
||||
fprintf('Canceled %d unfetched jobs from old queue.', oldq);
|
||||
end
|
||||
end
|
||||
results = parallel.FevalFuture.empty();
|
||||
else
|
||||
results = [];
|
||||
options.waitbar = true;
|
||||
end
|
||||
|
||||
fprintf('Requested %d loops\n', wh.getLastLinIndice);
|
||||
|
||||
jobs = repmat(struct('args', {{}}, 'label', "", 'meta', struct()), 1, wh.getLastLinIndice);
|
||||
|
||||
for lin_idx = 1:wh.getLastLinIndice
|
||||
optionalVars = struct();
|
||||
|
||||
if ~isempty(wh.getDimension)
|
||||
% Build the optionalVars struct
|
||||
[parametervalues, parameternames] = wh.getPhysIndicesByLinIndex(lin_idx);
|
||||
for pidx = 1:numel(parameternames)
|
||||
optionalVars.(parameternames{pidx}) = parametervalues{pidx};
|
||||
end
|
||||
end
|
||||
|
||||
%%% SIMULATION HERE
|
||||
if options.parallel
|
||||
numOutputs = 1;
|
||||
results(lin_idx) = parfeval(funcHandle, numOutputs, optionalVars);
|
||||
else
|
||||
finalresults{lin_idx} = feval(funcHandle, optionalVars);
|
||||
wh.addValueToStorageByLinIdx(finalresults{lin_idx}, 'ber', lin_idx);
|
||||
end
|
||||
optionalVars = buildOptionalVars(lin_idx, wh);
|
||||
jobs(lin_idx).args = {optionalVars};
|
||||
jobs(lin_idx).label = sprintf('Job %d', lin_idx);
|
||||
jobs(lin_idx).meta.lin_idx = lin_idx;
|
||||
end
|
||||
|
||||
mode = processingMode.serial;
|
||||
if options.parallel
|
||||
%%% 4) Setup waitbar
|
||||
h = waitbar(0, 'Processing Simulations...');
|
||||
updateWaitbar = @(~) waitbar(mean(arrayfun(@(f) strcmp(f.State, 'finished'), results)), h);
|
||||
mode = processingMode.parallel;
|
||||
end
|
||||
|
||||
fprintf('Fetching results... \n');
|
||||
|
||||
updateWaitbarFutures = afterEach(results, updateWaitbar, 0);
|
||||
afterAll(updateWaitbarFutures, @(~) delete(h), 0);
|
||||
runBatch(funcHandle, jobs, ...
|
||||
"mode", mode, ...
|
||||
"waitbar", options.waitbar, ...
|
||||
"waitbarMessage", "Processing Simulations...", ...
|
||||
"resultHandler", @storeResult, ...
|
||||
"errorHandler", @handleError);
|
||||
|
||||
%%% 7) Fetch final results iteratively as they finish
|
||||
for i = 1:length(results)
|
||||
try
|
||||
[ridx, result] = fetchNext(results);
|
||||
wh.addValueToStorageByLinIdx(result, 'ber', ridx);
|
||||
catch ME
|
||||
fprintf('A job failed or could not be fetched. Error: %s\n', ME.message);
|
||||
function optionalVars = buildOptionalVars(lin_idx, dataStorage)
|
||||
optionalVars = struct();
|
||||
if ~isempty(dataStorage.getDimension)
|
||||
[parametervalues, parameternames] = dataStorage.getPhysIndicesByLinIndex(lin_idx);
|
||||
for pidx = 1:numel(parameternames)
|
||||
optionalVars.(parameternames{pidx}) = parametervalues{pidx};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function storeResult(result, job, ~)
|
||||
wh.addValueToStorageByLinIdx(result, 'ber', job.meta.lin_idx);
|
||||
end
|
||||
|
||||
function handleError(ME, job, ~)
|
||||
fprintf('[%s] ERROR [%s]: %s\n', job.label, ME.identifier, ME.message);
|
||||
for st = ME.stack'
|
||||
fprintf(' %s:%d (%s)\n', st.file, st.line, st.name);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user