在Matlab中检测Matlab进程

8
有没有办法在matlab程序中检测计算机上运行了多少个matlab进程?
我想要恰好有n个matlab进程正在运行。如果太少,我想要创建它们,如果太多,我想要杀死一些进程。当然,你可以手动完成这个任务,但如果可能的话,我更喜欢自动化实现,而且不要太复杂。
附加信息:目前我正在使用windowsx64(vista),但我也对其他平台感兴趣。
7个回答

12

如果你使用的是Windows系统,你可以这样做:

[s,w] = dos( 'tasklist' );
numMatlabs = length( regexp( w, '(^|\n)MATLAB.exe' ) )

5

这里有另一种方法:您可以使用Matlab的COM“Automation Server”启动工作程序,并从中央Matlab进程控制它们。

function out = start_workers(n)
myDir = pwd;
for i=1:n
    out{i} = actxserver( 'matlab.application.single' );
    out{i}.Execute(sprintf('cd(''%s'')', myDir));
end

然后您可以使用Execute()来运行它们的工作。您可以使用计时器技巧来实现类似于异步执行。

function out = evalasync(str)
%EVALASYNC Asynchronous version of eval (kind of)
%
% evalasync(str)  % evals code in str
% evalasync()     % gets results of previous call

persistent results status exception

if nargin == 0
    out = {status results exception}; % GetWorkspaceData doesn't like structs
    assignin('base', 'EVALASYNC_RESULTS', out); % HACK for Automation
    return
end

status = 'waiting';
    function wrapper(varargin)
        status = 'running';
        try
            results = eval(str);
            status = 'ok';
        catch err
            status = 'error';
            exception = err;
        end
    end

t = timer('Tag','evalasync', 'TimerFcn',@wrapper);
startat(t, now + (.2 / (60*60*24)));

end

那么

w = start_workers(3);
w{1}.Execute('evalasync(''my_workload(1)'')');
w{2}.Execute('evalasync(''my_workload(2)'')');

很遗憾,您在工作线程中只能使用单线程,因此如果再次调用evalasync()来检查结果,它将被阻塞。因此,您需要通过磁盘上的文件来监视它们的进度。因此,这可能不会带来太多优势。


3

在Linux上

!ps -ef |grep "/usr/local/matlab78/bin/glnxa64/MATLAB"|wc -l

这个技巧可以解决问题(将路径替换为您自己的路径,并减去grep进程的1)

(或者将其构建成函数,使用

[tmp, result] = system('ps -ef |grep "/usr/local/matlab78/bin/glnxa64/MATLAB"|wc -l');
str2double(result) - 1

此外,您还可以使用:
>>computer
ans = GLNXA64

查找程序当前正在执行的系统架构(win/linux等)


当你编写代码时,计算机会告诉你当前正在运行的系统(以使你的代码具有可移携性)。请参考上面的窍门。 - second
这种方法无法区分两个正在运行的MATLAB实例——如果从两个或多个会话调用,它可能会返回相同(随机)的ID。 - Alexander Kosenkov

2
关于如何检测您的计算机上当前运行了多少个MATLAB进程,我可能会选择Edric给出的答案。从那里开始,您需要停止其中一些或启动新的进程。以下是一些代码(使用Edric的方法),它将检测MATLAB进程的数量,打开新的进程并立即在其中运行代码。我还在研究杀死进程的部分...
[s,w] = dos('tasklist');
nProcesses = numel(regexp(w,'(^|\n)MATLAB.exe'));
for n = 1:(3-nProcesses),  % Starts new processes if there are less than 3
  dos('MATLAB R2009a -nosplash -r why &');  % Starts a process and runs the
                                            %   built-in function "why.m"
end

假设您有1个正在运行的进程,此代码将启动2个以上的进程,然后将控制返回给原始的MATLAB进程(由于在调用DOS函数时使用了“&”)。当它启动每一个进程时,它将自动调用内置的MATLAB函数WHY(由于在调用DOS时使用“-r why”),因此会在每个新窗口中出现以下文本:
赤裸裸且不过分秃头、不过分聪明的仓鼠服从了一只又惊恐又不过分惊恐的仓鼠。
通过将DOS调用中的“why”替换为您想要运行的任何代码/ m文件,您可以生成立即开始计算数字的新进程。
使用并行计算工具箱:
如果您正在使用并行计算工具箱创建 MATLAB 工作进程池,您需要查看 MATLABPOOL 函数。以下是一些使用方法:
>> poolSize = matlabpool('size')  % Check the current pool size

poolSize =

     0

>> matlabpool('open',2);  % Open a pool of 2 workers
Starting matlabpool using the 'local' configuration ... connected to 2 labs.
>> poolSize = matlabpool('size')  % Check the pool size again

poolSize =

     2

>> matlabpool('close');  % Close the pool of workers
Sending a stop signal to all the labs ... stopped.

并行工具箱太贵了。我不想花钱解决问题,而是绕过它。这是唯一剩下的部分 - 我只是不想手动启动进程。 - AnnaR
启动进程很容易,但终止它们则更加棘手。您不希望意外终止运行 MATLAB 代码的进程。另一种启动 MATLAB 进程的方法是: !matlab <标志和参数> & - AnnaR

1

使用Windows的TASKLIST,您还可以使用窗口标题作为过滤器获取特定运行任务的PID。如果您有多个正在运行的Matlab进程,并且您已更改了它们的标题,则这尤其有帮助。

更改Matlab主窗口标题是使用以下函数完成的(changeWindowTitle.m):

function changeWindowTitle(str)

% first get all of the Java frames present in the current JVM
frms = java.awt.Frame.getFrames();

% now, lets look through those frames for one that seems like it

root = [];
for m = 1:length(frms)
    if strcmpi(get(frms(m),'Type'),'com.mathworks.mde.desk.MLMainFrame')
        root = frms(m);
        break;
    end
end
if isempty(root)
    error('Could not find my main frame')
end
set(root,'Title',str)

如果您使用...将Matlab窗口标题修改为"MyMatlabWindow",则...
> changeWindowTitle("MyMatlabWindow");

你可以在Matlab之外使用以下方法找到该Matlab会话的PID:

c:\tasklist /FI "WindowTitle eq MyMatlabWindow" 

当然,你也可以在Matlab中使用dos()system()或感叹号来完成相同的操作。

此外,你还可以添加参数/FO CSV(将输出格式化为CSV)和/NH(抑制头部输出)。

c:\tasklist /FI "WindowTitle eq MyMatlabWindow" /FO CSV /NH

来源:


0

想写一些VBScript吗?您可以使用WMI,这是一个带有脚本绑定的Windows管理API。WMI可以列出机器上的所有进程,包括图像名称、路径和命令行。搜索MATLAB.exes。WMI的Win32_Process对象还公开了大部分Process Explorer显示的信息,如启动时间、CPU和内存使用情况。

您几乎可以从Matlab本身中使用actxserver()和COM方法调用来编写WMI脚本,但集合还不太对。但是,您可以编写一个简单的VBS来执行WMI进程列表查询并编写适用于Matlab的输出,然后将其外壳化。这比使用tasklist要多做一些工作,但如果您正在处理一堆工作进程,则可能会发现额外的信息很有用。例如,命令行、窗口标题或进程启动时间可用于区分工作进程,以决定哪个要终止。

要终止它们,您可以使用WMI的Win32_Process.Terminate,或者外壳化到taskkill命令。

这都是仅限于Windows的。如果您想使事情变得可移植,可以安装cygwin,然后在任一操作系统上使用Unix风格的ps和kill命令。

顺便说一句:如果您要使常规的Windows Matlab应用程序作为带有“-r”的工作程序,请在主脚本的最顶部使用try/catch确保它在完成时退出:

try
    do_your_work();
catch err
    warning('Got an error: %s', err.message); 
end

close force all  % prevent figures from making quit() balk
quit force

否则,在 M 代码中抛出的错误可能会冒泡到顶层并使 Matlab 进入等待用户输入的主 GUI 循环,看起来像是一个挂起的工作进程。
哦,如果你正在从 Matlab 杀死 Matlab 进程,你可能想避免杀死自己。这里有一个 MEX 函数,可以让你在 Windows64 或 Unix 上确定自己的 pid;在选择受害者时,请将其与目标进程的 pid 进行比较。更高级的 ifdef 将使其在 win32 上工作。
/* mygetpid.c - MEX function to get PID */
#ifdef _WIN64
#include <process.h>
#define GETPID _getpid
#else
/* assume we're on Unix */
#include <unistd.h>
#define GETPID getpid
#endif
#include "mex.h"

void mexFunction(int nlhs,       mxArray *plhs[],
                 int nrhs, const mxArray *prhs[]
                )
{
    /* ... a real function would have nargin/nargout checks here... */
    plhs[0] = mxCreateDoubleScalar((int) GETPID());
}

2
如果您喜欢未记录和不受支持的代码,那么总有 feature('getpid') 可以使用。 - Edric
@Edric:啊,不知道有 feature('getpid') 这个功能。这会让我省下好多工作。 - Andrew Janke

0

Edric's answer的方法很好,但如果你有很多进程在运行,它相对较慢。

如果你使用tasklist的可选输入,特别是将其限制为仅MATLAB.exe图像名称,你可以大大提高dos命令的执行速度...

[~,w] = dos( 'tasklist /fi "IMAGENAME eq MATLAB.exe" /fo "csv"' );
numMatlabs = length( regexp( w, '"MATLAB.exe"' ) );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接