Run multiple MATLAB instances concurrently through a batch file - matlab

Is there a way to run multiple .m files in different instances of MATLAB concurrently through a batch file? The task that I want to accomplish is like below:
Open x instances of MATLAB;
Let different instances run different .m files simultaneously (so that my CPU power could be completely utilized);
When all instances finish, exit all MATLAB.
Could a single batch file accomplish this process? The reason I want to use a single batch file to do so is that I want to call this batch file in my MATLAB script. Essentially, I want to do parallel computation. (Since some of my scripts have to be run with MATLAB 2007, which doesn't have the parallel computing toolbox, I have to find a way around.)
Please explain the syntax of your code since I know little about the command prompt.
Currently, I only know how to do the task in sequence, just like the code shown below.
cd "C:\My_MATLAB_folder_path"
matlab r- "mfile01;exit"
matlab r- "mfile02;exit"
...
matlab r- "mfilexx;exit"
If a command prompt could not achieve this process, what alternative methods could I use? One important thing is that whatever method may be used, it must be able to be called in a MATLAB script.

When CMD executes a command or program from a batch file it waits for the launched program to exit, then executes the next command. To overcome this, you can prefix each invocation of MATLAB with start command: start "" matlab r- "mfilexx;exit"
Also making a slight delay between MATLAB invocations might be a good idea to prevent putting hard disk under excessive stress.
So the task could be done with something like this:
#echo off
setlocal
REM Delay is in seconds after /t switch
set "delay=timeout /t 1 /nobreak >nul"
REM Or this for Windows XP: (Delay is in milliseconds after -w switch)
set "delay=ping -n 1 -w 1000 127.255.255.255 >nul"
cd /d "C:\My_MATLAB_folder_path"
start "" matlab -r "this.m;exit"
%delay%
start "" matlab -r "that.m;exit"
%delay%
...
Or Alternatively it can simplified by witting the batch script this way:
cd /d "C:\My_MATLAB_folder_path"
for %%A in (
"this.m"
"that.m"
"other.m"
"add each file in a new line or on the same line separated with space.m" "one another.m"
) do (
start "" matlab -r "%%~A;exit"
%delay%
)

Related

How to run for loop in batch file step by step

I am trying to call MATLAB from the batch file several times. In this way, I used for loop to execute my MATLAB scripts several times. But what I got after running my batch file is to run all MATLAB files simultaneously. What I want is that, firstly, it runs once MATLAB, and when it is finished, it starts to run for the next time. Here is my code. Any help will be appreciated!
#echo off
for /l %%x in (1, 1, 2) do matlab -r "cd('H:\EngFiles\Ali\Backups codes\New set with multiple scenarios_Parallel');Bi_Objective_algorithm; exit"
pause
This page in the documentation describes how to call MATLAB from a Windows batch script: https://www.mathworks.com/help/matlab/ref/matlabwindows.html
The -wait option tells the matlab command to not return until MATLAB exits. For example:
matlab -wait -r "disp(1); exit"
However, since R2019a the -r switch is no longer recommended. That is the release where they introduced the much better -batch option:
matlab -batch "disp(1)"
Note that it is no longer necessary to include exit in the command.

How to run multiple scripts in sequence using command prompt

I need to do some kind of modification in post-synthesis hardware description language (HDL) files of field-progammable gate array (FPGA) design. I am using Microsemi's Libero system on chip (SoC) tool for that design process.
Totally, it has three different design processes such as
Pre-modification process
Modification process
Post-modification process on HDL codes
All three steps need to be performed in sequence using the Windows command line. I wrote a Tcl script for the first and third processes and a Perl script for the second process. In the first and third processes, some FPGA design tools for synthesis, simulation, place and route will be called through the command line.
This is the overall idea of the work. My question is how can I run all three different scripts (Tcl, Perl and Tcl) in sequence using a single script (or any other file format) in command line?
Note: In few steps, it is required to get user data through STDIN. I am working in windows platform..
Create a batch file (extension .bat) something like:
start /b tcl script1
start /b perl script1
start /b tcl script2
I'm not familar with Tcl but an example using Perl would be (from the DOS command-line):
perl hi.pl > log.txt & perl mid.pl >> log.txt & perl low.pl >> log.txt
The 3 perl script run in succession with the output of all 3 scripts put in a file called log.txt.
You can incorporate STDIN as needed.

How to make matlab block the shell in windows?

I use win7 and matlab2012a. I want to write a shell script to test my matlab scripts with different parameters. I use cygwin for this task. For example, alpha is the parameter and the matlab script is getall.m. The matlab script will read parameters from txt file 'param.txt'.
#!/bin/sh
# List=`seq 0.1 0.01 1`
List=`seq 0.1 0.1 0.2`
for alpha in $List
do
echo -ne "20\n61\n80\n1\n0.3\n${alpha}" > param.txt
matlab -nodesktop -r "getall;quit;" #time consuming
done
My problem is that script "getall.m" is time consuming, so I'd like to exec it one at a time. But I found that matlab command returns immediately. So the upper script will start a lot of matlab instances at the same time. I also tried the matlab command in cmd, but nothing changes. In ubuntu, matlab blocks the shell by default.
My question is how to make the matlab command to block the shell in windows?
There's a matlab -wait command line switch on Windows that will make it block.
http://www.mathworks.com/help/matlab/ref/matlabwindows.html
I don't know the "right" way to do this - but I do have a hack for you:
Make the matlab script create a file called "matlabDone" in the /tmp directory just before quitting; your shell script can go around a loop looking for this file. Once it exists, you know matlab is finished. Delete the file, and go around the loop again. Something like this:
List=`seq 0.1 0.1 0.2`
for alpha in $List
do
echo -ne "20\n61\n80\n1\n0.3\n${alpha}" > param.txt
matlab -nodesktop -r "getall;quit;" #time consuming
while [ ! -e /tmp/matlabDone ]
do
sleep 1
done
rm /tmp/matlabDone
done
Then make the last line of your matlab script create the file /tmp/matlabDone...
As I said - it's a hack...
PS I am not 100% sure what functions are available in cygwin. If you can't use sleep, I saw an interesting post suggesting that ping -n 2 127.0.0.1 > /dev/null (or equivalent ... depending on the version of ping you might need -c 2 -i 1 to get "one second per ping, count two") can be an alternative to sleep().

Powershell script to run multiple batch files in order

Real n00b to powershell. I was wondering if the community could help me build a pretty simple script.
Really, I can achieve everything I need in windows batch files - but these only complete one task at a time. I want a master script (a powershell script) to call each individual batch process in turn. That is, I want to run Batch_1 and then run Batch_2 only when a task from a program that Batch_1 calls has finished.
Is this possible? Is it a case of using some form of IF THEN ELSE type scenario or is there a way to make powershell wait for some event to happen?
Thanks!
GPC
You can use the FOR command, from regular windows shell (cmd.exe) to solve this problem. The following command executes every cmd file in current directory:
FOR %f IN (*.cmd) DO %f
The following command executes every file, in order, as returned by inner ´DIR´ command:
FOR /F %f IN ('DIR /b /oen *.cmd *.bat') DO %f
Normally calling out from a batch file to a console program is synchronous. A PowerShell script for this is trivial:
master-script.ps1 contents:
---------------------------
c:\batch1.bat
c:\batch2.bat
Now if the batch file is calling a Windows subsystem exe (non a console EXE) then this gets trickier because those execute async. If that's the case, update your question to indicate that.

Writing log statements to standard output with Matlab

We're starting Matlab from our Jenkins buildserver. As the build may take some time it would be nice to get some log-outputs while matlab is running. Is there a way to print text to standard output? disp, fprintf and java.lang.System.out.printline only write to the matlab console, not to standard output.
Using a logfile or a pipe won't help, as Jenkins only reads from standard-output during a build step.
How can we write log-statements to the standard output while matlab is running?
EDIT:
We're running Matlab 2010b on Windows
Depending what you are doing with Matlab you could probably launch it in command line without GUI. I used this on a server and it behaves pretty much like a shell script and writes to standards outputs.
See the startup options.
I used the following:
/path/to/matlab -nojvm -nodisplay -nosplash -nodesktop -r /path/to/mfile
EDIT: forgot to mention one very important little detail, place an exit command at the end of your mfile or Matlab will hang there waiting.
It seems that the combination of -wait and -log (not -logfile) clones the command window output to the parent console's stdout, but only if you call the MATLAB executable in [MATLABROOT]\bin, not [MATLABROOT]\bin\win64 (the subdirectory for current arch).
Tested on Windows with R2015b and R2016b:
C:\MATLAB\bin\matlab.exe -wait -log
NOT
C:\MATLAB\win64\bin\matlab.exe -wait -log
Remember to put an exit/quit in your script if you are running with -r.
The only trouble is that I can't seem to find any documentation for the -log option! Meh.
There don't seem to be any good ways to do this from within MATLAB. The easiest way I can think of doing this is by using a shell script. You could write a small shell script which would simply print any input to stdout, and then call that shell script from within matlab using the unix (or system) commands. Jenkins should be able to read the command-line output of the script and work with that.
I figured out a way to do this and am also doing it for Jenkins Matlab interface on windows.
Basic idea is that you will use diary command, but then tail -f the file, but you need a smart way to kill the tail command if you open multiple matlab instances because there will be name collisions. So the method I'm using is to name the file log.txt where the PID used is MATLAB's PID it is using when it opens.
There is an undocumented feature in MATLAB that allows you to get its PID. So now, both your batch file and MATLAB know the PID without having to read/write to a random text file that will get messy when executing multiple jobs. So the PID you use that as your unique identifier. The PID of "tail -f" is also used by MATLAB to kill tail -f to make the batch file die and is found by MATLAB using the commandline details associated with the process invocation since it uses again the unique PID log file name.
This uses some wmic commands and needs Windows Vista/7 or above. With XP you probably have to work harder to get the process ID's but should be still possible.
Here is what to do:
1) Get gnu awk for windows: http://gnuwin32.sourceforge.net/packages/gawk.htm
2) Get tail.exe from windows resource kit: http://www.microsoft.com/en-us/download/details.aspx?id=17657
3) Make sure tail and awk are in your path (the windows resourece kit I don't think automatically puts them in the path)
3) Create a batch file called matlabrun.bat as follows, (note: you need the #echo off, also the entire command is quite long, scroll right..)
#echo off
wmic process call create "c:\matlab\bin\win64\matlab.exe -r \"cd('c:\jenkins\workspace\test'); workdir=pwd; outpath=[pwd '\output'] ; try; run('C:\MATLAB\work\test_run'); end; quit; \" " | findstr ProcessId | awk "{print $3}" | awk -F";" "{ print $1 }"
4) Create another batch file called run.bat with:
for /f %%i in ('matlabrun.bat') do (
echo MATLAB Log... > log%%i.txt
tail -f log%%i.txt
set logfilename=log%%i.txt
goto next
)
:next
del /f %logfilename%
5) The run.bat file will execute matlabrun.bat and since -wait is not passed, matlab will immediately return to the command line and execute the tail -f command. That will block the batch file from completing until you kill it. matlabrun.bat returns the PID of matlab.
6) Another important note: since you are using "wmic process create" which will provide you with a PID that MATLAB is using, but will default to a working directory of c:\windows\system32. So that is why I pass the work directory to matlab. wmic process create is also a bit particular about what parameters you put into your command string for matlab to run. So it appears to have a problem with using commas in your command string. So I suggest not to use those, or figure out how to escape them (it might be that ^, works, but I just removed my commas anyway in my matlab run command).
6) The "test_run.m" file contains the following code to write to the correct log file and to kill correct tail -f instance.
matlabpid=feature('getpid');
filename=['log',num2str(matlabpid),'.txt'];
filenamefull=[workdir,'\',filename];
diary(filenamefull);
disp('Script starting...')
%%% put your code here %%%
disp('Script completed...');
diary off;
%%% FIND PID of tail.exe and kill it
%%% by using the name of the log file in the process command line
[a,b]=dos(['wmic process get Commandline,ProcessId']);
C=textscan(b,'%s','delimiter','\n');C=C{1};
for jj=1:size(C,1),
if strfind(C{jj},filename),
D=textscan(C{jj},'%s');D=D{1};
dos(['taskkill /f /pid ',D{4}]) %kills tail.exe which is the log watcher
break
end
end
7) You start it by doing run.bat. It will go and execute matlab, then start tailing the output while MATLAB runs in real-time. Then when done it will delete the log file.
8) My directory structure / files are in these locations (I'm using win7 64bit):
c:\jenkins\workspace\test\tail.exe
c:\jenkins\workspace\test\awk.exe
c:\jenkins\workspace\test\matlabrun.bat
c:\jenkins\workspace\test\run.bat
c:\matlab\work\test_run.m
c:\matlab\bin\win64\matlab.exe
If you are using 32bit matlab, point it to the win32 directory. To get the correct PID, you need to specify the actualy matlab.exe binary in the win32 or win64 directory.
You can do this by pointing the -logfile option to the Jenkins log file. Something like the following:
"C:\path\to\matlab.exe" "-r" "functionToRun" "-logfile" "%JENKINS_HOME%\jobs\%JOB_NAME%\builds\%BUILD_NUMBER%\log" /wait
You can use the diary mode. Not sure if it will fit your specific implementation.
http://www.mathworks.com/help/techdoc/ref/diary.html
I didn't find a real solution. Mathworks created some wrapper tool. But this will only output the results after matlab has exited. You won't get any ouput during execution.
http://www.mathworks.de/support/solutions/en/data/1-ACT3YN/index.html?product=ML&solution=1-ACT3YN
So I'll have live without real live-output...
Or try using '-logfile' option in matlab.
matlab.exe -nodisplay -nosplash -nodesktop -wait -logfile logfile.txt -r "try script.m ;catch err; disp(err.message); end ; exit"
I prefer using bash (Execute shell) in Jenkins, then you can tail the log-file while matlab is running.
matlab.exe <...> &
matpid=$!
tail -f logfile.txt &
tailpid=$!
wait $matpid
matexit=$?
kill $tailpid
sleep 1 # Just to make sure kill is done before Jenkins step ends and no zombie processes
exit $matexit