Я запускаю много длительных симуляций в Matlab, обычно занимая от нескольких минут до нескольких часов, поэтому, чтобы ускорить работу, я решил одновременно запускать симуляции, используя цикл parfor
.
arglist = [arg1, arg2, arg3, arg4];
parfor ii = 1:size(arglist, 2)
myfun(arglist(ii));
end
Все работало отлично, за исключением одного: прогресс печати. Поскольку каждый симулятор занимает много времени, я обычно печатаю прогресс, используя что-то вроде
prevlength = 0;
for ii = 1:tot_iter
% Some calculations here
msg = sprintf('Working on %d of %d, %.2f percent done', ii, tot_iter, ii/tot_iter);
fprintf(repmat('\b', 1, prevlength))
fprintf(msg);
prevlength = numel(msg);
end
но, как и следовало ожидать, при выполнении этого внутри цикла parfor
вы получаете хаос.
Я много искал поисков решения и нашел кучу "принтеров для достижения прогресса", например этот. Тем не менее, все они печатают ход всего цикла parfor
, а не показывают, как далеко продвинулась каждая из отдельных итераций. Поскольку в цикле parfor
есть только 4-8 итераций, но каждая итерация занимает около часа, этот подход мне не очень помогает.
Идеальное решение для меня было бы чем-то вроде этого
Working on 127 of 10000, 1.27 percent done
Working on 259 of 10000, 2.59 percent done
Working on 3895 of 10000, 38.95 percent done
Working on 1347 of 10000, 13.47 percent done
то есть каждое симуляция получает одну строку, показывающую, как далеко она прошла. Я не уверен, хотя, если это вообще возможно, я, по крайней мере, не могу представить, как это сделать.
Другим способом было бы сделать что-то вроде этого
Sim 1: 1.27% Sim 2: 2.59% Sim 3: 38.95% Sim 4: 13.47%
то есть показать все прогрессии в одной строке. Чтобы сделать это, вам нужно будет отслеживать, какую позицию на каждой симуляции нужно написать и написать там, не стирая другие прогрессии. Я не могу понять, как это будет сделано, возможно ли это сделать?
Если есть какое-то другое решение моей проблемы (показывающее прогресс каждой отдельной итерации), о котором я не думал, я был бы рад услышать об этом.
Поскольку это первый раз, когда я задаю здесь вопрос о SO, вполне возможно, что я кое-что пропустил; если да, пожалуйста, не стесняйтесь комментировать ниже.
Изменить
Получив этот ответ, я подумал, что должен поделиться тем, как я использовал его для решения моей проблемы, поскольку я не использовал его точно так же, как в ответе, в случай, когда кто-то другой сталкивается с той же проблемой.
Вот небольшая тестовая программа с той же структурой, что и моя программа, используя индикатор выполнения (parfor_progress
), упомянутый в ответе:
function parfor_progress_test()
cpus = feature('numCores');
matlabpool('open', cpus);
cleaner = onCleanup(@mycleaner);
args = [1000, 1000, 1000, 1000];
m = sum(args);
parfor_progress(m);
parfor ii = 1:size(args,2)
my_fun(args(ii));
end
parfor_progress(0);
end
function my_fun(N)
for ii = 1:N
pause(rand*0.01);
parfor_progress;
end
end
function mycleaner
matlabpool close;
fclose all;
end