我在 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 次迭代parfor
,但每次迭代大约需要一个小时,所以这种方法对我来说不是很有帮助。
对我来说理想的解决方案是这样的
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