tags:

views:

1299

answers:

5

Is there any way of detecting how many matlab processes are running on a computer from within a matlab program?

I would like to have exactly n matlab processes running. If I have too few I want to create them and if I have to many I want to kill some. You can of course do this manually, but I'd prefer to have it automatic if it is possible and not to complicated to implement.

Additional info: Currently I'm using windowsx64 (vista), but I'm interested in other platforms too.

+3  A: 

on linux

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

would do the trick (replace path by your own and subtract 1 for the grep process)

(or to build in to a function, use

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

also, you can use

>>computer
ans = GLNXA64

to find out which system architecture (win/linux/etc ) a program is currently executing on

second
Linux I presume?
AnnaR
sure. see above for tips for windows. >>computerwill tell you what system you are currently running (to make your code portable)
second
+6  A: 

If you're on Windows, you could do this:

[s,w] = dos( 'tasklist' );
numMatlabs = length( regexp( w, '(^|\n)MATLAB.exe' ) )
Edric
Works like a charm!
AnnaR
+2  A: 

With respect to detecting how many MATLAB processes are currently running on your machine, I would probably go with the answer Edric gave. From there, you then have to either stop some of them or start new ones. Here's some code (using Edrics method) that will detect the number of MATLAB processes, open new ones, and immediately run code in them. I'm still looking into the process-killing part...

[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

Assuming you have 1 process running to start, this code will start 2 more and then return control to the original MATLAB process (due to the "&" in the call to the DOS function). When it starts each one, it will automatically call the built-in MATLAB function WHY (due to the "-r why" in the call to DOS), thus resulting in the following text appearing in each new window:

The bald and not excessively bald and not excessively smart hamster obeyed a terrified and not excessively terrified hamster.

By replacing "why" in the call to DOS with whatever code/m-file you want to run, you can spawn new processes that instantly start crunching numbers.


Using the Parallel Computing Toolbox:

(This is an old version of my answer I'm leaving here in case someone finds it helpful)

If you are using the Parallel Computing Toolbox to create a pool of MATLAB workers, you would want to look at the MATLABPOOL function. Here are some ways to use it:

>> 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.
gnovice
The parallel toolbox is way too expensive. Instead of throwing money at my problem I'm working around it. This is the only part remaining - I just don't want to start the processes manually.
AnnaR
AnnaR
A: 

Willing to write some VBScript? You can script this using WMI, a Windows administration API with scripting bindings. WMI can list all the processes on a machine, including image name, path, and command line. Search for the MATLAB.exes. WMI's Win32_Process object also exposes most of the information that Process Explorer shows, like start time, CPU, and memory usage.

You can almost script WMI from within Matlab itself using actxserver() and COM method calls, but the collections don't work quite right yet. But you can write a simple VBS to do the WMI process list query and write Matlab-friendly output, then shell out to it. This is some more work than using tasklist, but you might find the extra info useful if you're wrangling a bunch of worker processes. For example, the command lines, window titles, or process start times could be used to differentiate workers when deciding which to kill.

To kill them, you can use WMI's Win32_Process.Terminate, or shell out to the taskkill command.

This is all Windows-only. If you want to make things portable, you could install cygwin, and then shell out to the Unix-style ps and kill commands on either OS.

Side note: if you're making regular Windows Matlab apps act as workers with "-r", use a try/catch at the very top level of your main script to make sure it exits when done:

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

Otherwise, an error thrown in M-code could bubble up to the top level and drop Matlab into the main GUI loop waiting for user input, and it will look like a hung worker.

Oh, and if you're killing Matlab processes from Matlab, you probably want to avoid killing yourself. Here's a MEX function that will let you determine your own pid on Windows64 or Unix; check it against the target processes' pids when choosing victims. Fancier ifdefs will make it work on 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());
}
Andrew Janke
If you like your code undocumented and unsupported, there's always feature('getpid')
Edric
@Edric: Argh, didn't know about feature('getpid'). That would have saved me a good amount of work.
Andrew Janke
+2  A: 

Here's another approach: you could use Matlab's COM "Automation Server" to start up workers and control them from a central Matlab process.

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

Then you can use Execute() to have them run work. You could use a timer trick to get sort of asynchronous execution.

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

Then

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

Unfortunately, you're stuck with single-threading in the workers, so if you call evalasync() again to check the results, it'll block. So you'd want to monitor their progress through files on disk. So it may not be much of a win.

Andrew Janke

related questions