监视长时间运行的parfor循环的进程并不简单,因为工人无法通信。这个函数通过将进度存储在文本文件中来绕过这个限制。
使用示例:
N = 100;
parfor_progress (N);%初始化
parfor i = 1: N
暂停(rand);%用实际代码替换
parfor_progress;%数
结束
parfor_progress (0);%清理
杰里米(2021)。与parfor一起工作的进度监视器(进度条)(//www.tatmou.com/matlabcentral/fileexchange/32101-progress-monitor-progress-bar-that-works-with-parfor), MATLAB中央文件交换。检索.
启发:ParforProgress类,parwaitbar,parfor_progressbar_v1,TimedProgressBar,parfor_progressbar,matlab循环的进度条(包括。parfor),稀疏网格插值
美丽的工作!但我有个小问题。这个进度条可以写在文本文件中吗?因为我在linux集群上运行matlab。
真管用!
对文本文件进行多次读写有一定的串行限制。非常耗时,2。同时读/写可能会引起一些麻烦。只在本地池工作。
我实现了我自己的基于udp套接字的parfor进度监视器(没有读/写问题,快得多,而且不仅在本地池上工作)。
我可以显示每个工人的剩余时间和进度->https://de.mathworks.com/matlabcentral/fileexchange/71436-parfor-progress-monitor-progress-bar-v4
虽然这是有效的,但应该谨慎使用。多个工作人员以线程不安全的方式并行地从/向同一个文件读写。这可能导致文件损坏或竞争条件,在某些情况下甚至导致操作系统崩溃。如果有很多工作人员或者迭代非常快,我不推荐使用这个。
有用的工具!需要用narinchk替换nargchk,以便在R2016b中使用它。
narginchk (0, 1)
不错的贡献。然而,正如Timo已经发现的,在拟合大量数据时,我注意到进度监视器在非常长的循环中变得非常慢。在开始的时候,它并没有那么糟糕,但是随着每次循环迭代,对'fscanf'的调用变得越来越慢。
我通过读和写一个简单的二进制文件(我写预期的循环长度到前4个字节和当前的进展到下4个字节-如果你认为uint32不够,感觉使用uint64)修正了这个问题。
此外,文件名现在存储在由matlab' tempname'-function决定的文件夹中(如果删除失败,文件系统混乱更少&例如,ssd上的tempdir比网络上某处的工作目录快得多)。
如果nargin < 1
N = 1;
结束
% = 0;
w = 50;%进度条宽度
如果n> 0
F = fopen(fullfile(tempdir,'parfor_progress.bin'), 'w');
如果f < 0
错误('您对%s有写权限吗?" pwd);
结束
写入文件(f, N,“uint32”);
写入文件(f, 0, ' uint32 ');
文件关闭(f);
nargout == 0
[' 0%[>', repmat(' ', 1, w), ']']);
结束
case "锦江":N == 0
删除(fullfile (tempdir parfor_progress.bin));
% = 100;
nargout == 0
disp ([repmat (char (8), 1 (w + 9)), char(10), 100%(“,repmat (' = ' 1 w + 1), '] '));
结束
其他的
帧= fullfile (tempdir parfor_progress.bin);
如果存在~(帧,“文件”)
错误(“parfor_progress.bin没有找到。在PARFOR_PROGRESS之前运行PARFOR_PROGRESS(N),初始化PARFOR_PROGRESS .bin ');
结束
F = fopen(fname, 'r+');
一个=从文件中读(f 2“uint32”);
todo = (1);
A(2) + 1;
fseek (f 4“转炉”);
写入文件(f,进步,“uint32”);
文件关闭(f);
百分比=进展/待办事项* 100;
nargout == 0
Perc = sprintf('%3.0f%%', %);% 4字符宽,百分比
disp ([repmat (char (8), 1 (w + 9)), char (10), perc,“[”,repmat(' = ' 1轮(100)* w /百分比),“>”,repmat(“1 w -轮(百分比* w / 100 )), ']']);
结束
结束
杰里米,好主意!但是我有一个问题,在运行一个集群并行作业,没有显示在命令行窗口。由于在不同的计算机上创建不同的工作人员,如何让每个工作执行disp功能,并将内容打印到集群的主机客户端上。
两个问题:1)一些matlab程序在运行时改变工作目录。进度监视器将报告错误,因为它只检查“当前”工作目录。解决方案是使用一些绝对路径,比如~/parfor_progress.txt。2)一旦调用parfor_progress,它将输出,但有时进度不够大,不足以更新进度条的绘图。问题是:用户不知道“最后的进度”,无法判断当前的进度是否足够大到可以绘制新图。这应该由Progress监视器代码维护,使用相同的打开文件的技巧。
在西班牙语中我们会说“está chulísimo”....例如:it is so cool =)
它不像GUI中的等待栏,而是在Matlab命令窗口中显示进度。
简单,有效,谢谢!
有一个小问题:当100%的CPU被使用时,进度条的刷新不是很顺利:)
Timo—如果循环的每次迭代都非常快,那么parfor_progress的开销可能会很大。如果每次迭代都很慢,那么它就不慢。如果它大大减慢了你的速度,要么使用另一种解决方案,要么重组你的循环,让每次迭代做更多的工作。
做得很好,但是我提到过,如果我使用您的脚本,parfor循环和常见的for循环一样慢。
for循环:256年代
parfor-loop: 46
parfor_progress_: 301的Parfor-loop
我使用的是r2015a。
有人同意吗?
杰里米:谢谢。最后我做了一些类似的事情http://stackoverflow.com/a/27378993/3490931
如果超过100个SIMS,只需分割它并打印每n次迭代。完成任务。
RN:如果你编辑它,让parfor_progress.txt在共享驱动器上,它可能在分布式系统上工作,但我还没有试过。
在使用MathWorks云计算中心时,有什么方法可以使用分布式计算服务器来做类似的事情吗?
整洁的助手!
非常有用的。谢谢你!
非常高效,工作简单,完美。谢谢!
我想说:非常感谢你的剧本这么好
杰里米:首先,谢谢你写了这么方便的脚本。它非常有用。
我还发现了linux终端的显示问题,这是阿辛和亚历山德罗描述的。然而,我很快就找到了一个解决方案,尽管我根本不是MATLAB的专家用户。
我只更改了3行,将所有disp()调用更改为fprintf()。
char(8)技巧也适用于fprintf(),实际上更适用于linux终端。
希望对大家有用。
Erik:这取决于循环的每次迭代有多慢。如果每次迭代都需要一段时间来运行,那么这不会影响执行时间。如果每次迭代都非常快,它就可以。您需要对更多细节进行基准测试,我只在慢问题上使用过它。如果有必要,一个快速的修复方法是将parfor_progress.txt的路径更改为ramdisk上。
不错的工作。只是想知道,这对parfor的执行速度有什么影响?
是否有可能得到一个版本,代替打印%完成到一个txt文件,用于远程/服务器pc上的监视作业?
出色的工作!
尽管它在linux -nodesktop模式下工作很糟糕。在这种情况下,旧的(和不太完整的)条仍然显示在控制台中。
因此,屏幕上几秒钟就充斥着或多或少完整的版本条。
谢谢你的文件。它的工作原理!
正如Timo所建议的,如果有几个MATLAB实例在运行(例如,多核服务器),它将不能正常工作。
通过在文件名中添加一个随机序列,可以很容易地解决这个问题。
function parfor_progress(N)
%PARFOR_PROGRESS使用parfor的进度监视器(进度条)。
% PARFOR_PROGRESS的工作方式是创建一个名为PARFOR_PROGRESS .txt的文件
%您的工作目录,然后跟踪parfor循环的
%该文件中的进度。这个解决方案是必要的,因为parfor
工人们不能互相沟通,所以没有简单的方法
%来知道哪些迭代已经完成,哪些还没有完成。
%
% PARFOR_PROGRESS(N)初始化一组N的进度监视器
%计算。
%
% PARFOR_PROGRESS更新parfor循环中的进度
%显示更新的进度条。
%
% PARFOR_PROGRESS(0)删除PARFOR_PROGRESS .txt并完成进度
%的酒吧。
%
要抑制这些函数的输出,只需请求返回
%变量从函数调用,如PERCENT = PARFOR_PROGRESS
%返回完成的百分比。
%
%的例子:
%
% n = 100;
% parfor_progress (N);
% parfor i = 1: N
%暂停(rand);%用实际代码替换
% parfor_progress;
%结束
% parfor_progress (0);
%
%参见PARFOR。
%作者Jeremy Scheff - jdscheff@gmail.com -http://www.jeremyscheff.com/
nargchk(0, 1, nargchk, 'struct');
持续的帧;
如果nargin < 1
N = 1;
结束
% = 0;
w = 50;%进度条宽度
如果n> 0
rndseq =轮(10 ^ 6 *兰德(1));
帧= strcat (parfor_progress_, num2str (rndseq) . txt);
F = fopen(fname, 'w');
如果f < 0
错误('您对%s有写权限吗?" pwd);
结束
流(f % d \ n, n);%将N保存在progress.txt的顶部
文件关闭(f);
nargout == 0
[' 0%[>', repmat(' ', 1, w), ']']);
结束
case "锦江":N == 0
删除(帧);
% = 100;
nargout == 0
disp ([repmat (char (8), 1 (w + 9)), char(10), 100%(“,repmat (' = ' 1 w + 1), '] '));
结束
其他的
如果存在~(帧,“文件”)
([帧”,没有发现错误。在PARFOR_PROGRESS之前运行PARFOR_PROGRESS(N)来初始化',fname]);
结束
F = fopen(fname, 'a');
流(f,“1 \ n”);
文件关闭(f);
F = fopen(fname, 'r');
进度= fscanf(f, '%d');
文件关闭(f);
% =(长度(进步)1)/进展(1)* 100;
nargout == 0
Perc = sprintf('%3.0f%%', %);% 4字符宽,百分比
disp ([repmat (char (8), 1 (w + 9)), char (10), perc,“[”,repmat(' = ' 1轮(100)* w /百分比),“>”,repmat(“1 w -轮(百分比* w / 100 )), ']']);
结束
结束
这是你已经实现的一个很棒的功能,但有一点你可以改进。
问题是:
如果您在同一个文件夹中不止一次地执行任何MATLAB脚本,并且脚本包含您的函数,它们将以错误告终。
关键是,文件名总是与函数创建的文件名相同。
因此,将有多个函数尝试处理parfor_progress文件。
也许您应该选择一个附加到每个parfor_progress文件的任意文件名-id。
不管怎样,干得好!
这真是太棒了,但是我在一个运行matlab的无显示ubuntu服务器终端上运行它时遇到了一些问题(用于退格符的ascii 8不能产生正确的输出)。
如果我是你,我会重写这里的所有内容,从DISP()函数到FPRINTF()函数。而不是使用char(8)和char(10)作为退格符和回车符,分别使用断接开关\b和\n。我这样做了,它修复了我曾经遇到的进度条在多行中重复的问题(而不是在更新时被覆盖)。
阿信,
我是在Linux上开发的,从来没有见过这个问题。因此,它可能不是一般的Linux问题,而是特定于您的特定设置的问题。也许跟你系统上的字符编码有关?
作为测试,运行这个,看看它输出什么:
disp ([' aaa ', char (8)))
输出应该是aa,因为char(8)是退格符。这是我在parfor_progress中用来删除前一行的技术,所以可能backspace在您的Linux机器上由于某种原因不能工作?
有没有人知道一种更普遍的可移植的方法?
我尝试在linux环境中使用它。结果进度条看起来像这样
0% []
2% (=)
4% (= =)
.
.
.
它每次都会创建一个新行,这有点烦人。但在窗口工作很顺利。我想知道这个问题是否有一个简单的解决方法。
谢谢
阿信
谢谢——做了它应该做的事情,让你不再挠头,不知道它是不是快完成了……