MATLAB: Difference between revisions

From RCSWiki
Jump to navigation Jump to search
No edit summary
(Added compiled code example.)
Line 12: Line 12:


= <span id="license"></span>Ways to run MATLAB - License considerations =
= <span id="license"></span>Ways to run MATLAB - License considerations =
At the University of Calgary, Information Technologies has purchased a MATLAB Total Academic Headcount license that allows installation and use of MATLAB on central clusters, such as ARC, as well as on personal workstations throughout the University. Potentially thousands of instances of MATLAB can be run simultaneously, each checking out a license from a central license server. An alternative is to compile MATLAB code into a standalone application. When such an application is run, it does not need to contact the server for a license. This allows researchers to run their calculations on compatible hardware, not necessarily at the University of Calgary, such as on [https://docs.computecanada.ca/wiki/Getting_started Compute Canada (external link)] clusters.
At the University of Calgary, Information Technologies has purchased a MATLAB Total Academic Headcount license that allows installation and use of MATLAB on central clusters, such as ARC, as well as on personal workstations throughout the University. Potentially thousands of instances of MATLAB can be run simultaneously, each checking out a license from a central license server. An alternative is to compile MATLAB code into a standalone application. When such an application is run, it does not need to contact the server for a license. This allows researchers to run their calculations on compatible hardware, not necessarily at the University of Calgary, such as on [https://docs.computecanada.ca/wiki/Getting_started Compute Canada clusters (external link)].


For information about installing MATLAB on your own computer, see the Information Technologies Knowledge Base [https://ucalgary.service-now.com/it?id=kb_article&sys_id=787d708213fdbec08246f7b2e144b0d4 article on MATLAB].
For information about installing MATLAB on your own computer, see the Information Technologies Knowledge Base [https://ucalgary.service-now.com/it?id=kb_article&sys_id=787d708213fdbec08246f7b2e144b0d4 article on MATLAB].
Line 19: Line 19:
Although it is possible to run MATLAB interactively, the expectation is that most calculations with MATLAB will be completed by submitting a batch job script to the Slurm job scheduler with the sbatch command.
Although it is possible to run MATLAB interactively, the expectation is that most calculations with MATLAB will be completed by submitting a batch job script to the Slurm job scheduler with the sbatch command.


For the purposes of illustration, suppose the following serial MATLAB code, in a file sawtooth.m, is to be run.  (Parallel processing cases will be considered later). If your code does not already have them, add a function statement at the beginning and matching end statement at the end as shown in the example. Other features of this example include calling a function with both numerical and string arguments, incorporating a Slurm environment variable into the MATLAB code and producing graphical output in an non-interactive environment.
For the purposes of illustration, suppose the following serial MATLAB code, in a file sawtooth.m, is to be run.  (Parallel processing cases will be considered later). If your code does not already have them, add a function statement at the beginning and matching end statement at the end as shown in the example. Other features of this example include calling a function with both numerical and string arguments, incorporating a Slurm environment variable into the MATLAB code and producing graphical output in a non-interactive environment.
<pre>
<pre>
function sawtooth(nterms,nppcycle,ncycle,pngfilebase)
function sawtooth(nterms,nppcycle,ncycle,pngfilebase)
Line 66: Line 66:
#SBATCH --ntasks=1          # For serial code, always specify just one task.
#SBATCH --ntasks=1          # For serial code, always specify just one task.
#SBATCH --cpus-per-task=1  # For serial code, always specify just one CPU per task.
#SBATCH --cpus-per-task=1  # For serial code, always specify just one CPU per task.
#SBATCH --mem=4000m         # Adjust to match total memory required, in MB.
#SBATCH --mem=4000m         # Adjust to match total memory required, in MB.
#SBATCH --partition=pawson-bf,apophis-bf,razi-bf,lattice,parallel,cpu2013,cpu2019
#SBATCH --partition=pawson-bf,apophis-bf,razi-bf,lattice,parallel,cpu2013,cpu2019


Line 73: Line 73:


# Specify the name of the main MATLAB function to be run.
# Specify the name of the main MATLAB function to be run.
# This would normally the same as the MATLAB source code file name without a .m suffix).
# This would normally be the same as the MATLAB source code file name without a .m suffix).
MAIN="sawtooth"
MAIN="sawtooth"


Line 109: Line 109:
</pre>
</pre>


The job should produce three output files: Slurm output, MATLAB command output and a PNG file, all tagged with the Slurm Job ID.
The job should produce three output files: Slurm script output, MATLAB command output and a PNG file, all tagged with the Slurm Job ID.


= Standalone Applications =
= Standalone Applications =


When running MATLAB code as described in the preceding section, a connection to the campus MATLAB license server and checking out licenses for MATLAB and any specialized toolboxes needed is made for each job that is submitted. Currently, with the University of Calgary's current Total Academic Headcount license there are sufficient license tokens to support thousands of simultaneous MATLAB sessions (although ARC usage policy and cluster load will limit individual users to smaller numbers of jobs). However, there may be times at which the license server is slow to respond when large numbers of requests are being handled, or the server may be unavailable temporarily due to network problems. MathWorks offers an alternative way of running MATLAB code by compiling it into a standalone application.  A license is required only during the compilation process and not when the code is run.  This allows calculations to be run on ARC without concerns regarding the license server.  The compiled code can also be run on compatible (64-bit Linux) hardware, not necessarily at the University of Calgary, such as on [https://docs.computecanada.ca/wiki/Getting_started Compute Canada (external link)] clusters.
When running MATLAB code as described in the preceding section, a connection to the campus MATLAB license server, checking out licenses for MATLAB and any specialized toolboxes needed, is made for each job that is submitted. Currently, with the University of Calgary's Total Academic Headcount license, there are sufficient license tokens to support thousands of simultaneous MATLAB sessions (although ARC usage policy and cluster load will limit individual users to smaller numbers of jobs). However, there may be times at which the license server is slow to respond when large numbers of requests are being handled, or the server may be unavailable temporarily due to network problems. MathWorks offers an alternative way of running MATLAB code that can avoid license server issues by compiling it into a standalone application.  A license is required only during the compilation process and not when the code is run.  This allows calculations to be run on ARC without concerns regarding the license server.  The compiled code can also be run on compatible (64-bit Linux) hardware, not necessarily at the University of Calgary, such as on [https://docs.computecanada.ca/wiki/Getting_started Compute Canada (external link)] clusters.


== Creating a standalone application ==
== Creating a standalone application ==


The MATLAB mcc command is used to compile source code (.m files) into a standalone excecutable. There are a couple of important considerations to keep in mind when creating an executable that can be run in a batch-oriented cluster environment. One is that there is no graphical display attached to your session and the other is that the number of threads used by the standalone application has to be controlled.
The MATLAB mcc command is used to compile source code (.m files) into a standalone excecutable. There are a couple of important considerations to keep in mind when creating an executable that can be run in a batch-oriented cluster environment. One is that there is no graphical display attached to your session and another is that the number of threads used by the standalone application has to be controlled. There is also an important difference in the way arguments of the main function are handled.
 
Let's illustrate the process of creating a standalone application for the sawtooth.m code used previously. Unfortunately, if that code is compiled as it is, the resulting compiled application will fail to run properly.  The reason is that the compiled code sees all the input arguments as strings instead of interpreting them as numbers. To work around this problem, use a MATLAB function, '''isdeployed''', to determine whether or not the code is being run as a standalone application. Here is a modified version of code, called sawtooth_standalone.m that can be successfully compiled and run as a standalone application.
 
<pre>
function sawtooth_standalone(nterms,nppcycle,ncycle,pngfilebase)
 
% MATLAB file example to approximate a sawtooth
% with a truncated Fourier expansion.
 
% nterms = number of terms in expansion.
% ncycle = number of complete cycles to plot.
% nppcycle = number of points per cycle.
% pngfilebase = base of file name for graph of results.
 
% 2020-05-21
 
% Test to see if the code is running as a standalone application
% If it is, convert the arguments intended to be numeric from
% the input strings to numbers
 
if isdeployed
  nterms=str2num(nterms)
  nppcycle=str2num(nppcycle)
  ncycle=str2num(ncycle)
end
 
np=nppcycle*ncycle;
 
fourbypi=4.0/pi;
y(1:np)=pi/2.0;
x(1:np)=linspace(-pi*ncycle,pi*ncycle,np);
 
for k=1:nterms
  twokm=2*k-1;
  y=y-fourbypi*cos(twokm*x)/twokm^2;
end
 
% Prepare output
% Construct the output file name from the base file name and number of terms
% Also append the Slurm JOBID to keep file names unique from run to run.
 
job=getenv('SLURM_JOB_ID')
pngfile=strcat(pngfilebase,'_',num2str(nterms),'_',job)
disp(['Writing file: ',pngfile,'.png'])
 
fig=figure;
plot(x,y);
print(fig,pngfile,'-dpng');
 
quit
end
</pre>


For example, with code mycode.m a source directory src, with the compiled files being written to a directory called deploy, the following mcc command line (at the Linux shell prompt) could be used:
Suppose that the sawtooth_standalone.m file is in a subdirectory src below your current working directory and that the compiled files are going to be written to a subdirectory called deploy. The following commands (at the Linux shell prompt) could be used to compile the code:


<pre>
<pre>
mkdir deploy
mkdir deploy
cd src
cd src
module load matlab/r2019b
mcc -R -nodisplay \
mcc -R -nodisplay \
  -R -singleCompThread \
  -R -singleCompThread \
  -m -v -w enable \
  -m -v -w enable \
  -d ../deploy \
  -d ../deploy \
  >mycode.m
  sawtooth_standalone.m
</pre>
</pre>


Note the option -singleCompThread has been included in order to limit the executable to just one computational thread.
Note the option -singleCompThread has been included in order to limit the executable to just one computational thread.


In the deploy directory, an executable mycode will be created along with a script run_mycode.sh. These two files should be copied to the target machine where the code is to be run.
In the deploy directory, an executable, sawtooth_standalone, will be created along with a script, run_sawtooth_standalone.sh. These two files should be copied to the target machine where the code is to be run.


== Running a standalone application ==
== Running a standalone application ==


'''Note: this section is still being converted from a different web site.'''
After the standalone executable sawtooth_standalone and corresponding script run_sawtooth_standalone.sh have been transferred to a directory on the target system on which they will be run (whether to a different directory on ARC or to a completely different cluster), a batch job script needs to be created in that same directory. Here is an example batch job script, sawtooth_standalone.slurm .
 
<pre>
#!/bin/bash
#SBATCH --time=03:00:00    # Adjust this to match the walltime of your job
#SBATCH --nodes=1          # For serial code, always specify just one node.
#SBATCH --ntasks=1          # For serial code, always specify just one task.
#SBATCH --cpus-per-task=1  # For serial code, always specify just one CPU per task.
#SBATCH --mem=4000m          # Adjust to match total memory required, in MB.
#SBATCH --partition=pawson-bf,apophis-bf,razi-bf,lattice,parallel,cpu2013,cpu2019
 
# Sample batch job script for running a compiled MATLAB function
# 2020-05-21
 
# Specify the name of the compiled MATLAB standalone executable
MAIN="sawtooth_standalone"
 
# Define key parameters for the example calculation.
NTERMS=100
NPPCYCLE=20
NCYCLE=3
PNGFILEBASE=$MAIN
 
ARGS="$NTERMS $NPPCYCLE $NCYCLE $PNGFILEBASE"
 
# Choose the MCR directory according to the compiler version used
MCR=/global/software/matlab/mcr/v97


After the standalone executable mycode and corresponding script run_mycode.sh have been transferred to a directory on the target system on which they will be run, a batch job script needs to be created in the same directory. Here is an example batch job script.
echo "Starting run at $(date)"
echo "Running on compute node $(hostname)"
echo "Running from directory $(pwd)"


<nowiki>#!/bin/bash</nowiki><br /><nowiki>#PBS -S /bin/bash</nowiki><br /><br /><nowiki># Choose the MCR directory according to the compiler version used</nowiki><br />MCR=/global/software/matlab/mcr/v90<br /><br /><nowiki># If running on Grex, uncomment the following line to set </nowiki><span class="WG_Inline_Code">MCR_CACHE_ROOT</span><nowiki>:</nowiki><br /><nowiki># </nowiki><span class="WG_Inline_Code">module load mcr/m</span>cr<br /><br />echo "Running on host: `hostname`"<br />cd $PBS_O_WORKDIR <br />echo "Current working directory is `pwd`"<br /><br />echo "Starting run at: `date`" <br />./run_mycode.sh $MCR > mycode_${PBS_JOBID}.out<br />echo "Job finished at: `date`"
./run_${MAIN}.sh $MCR $ARGS > ${MAIN}_${SLURM_JOB_ID}.out 2>&1


The job is then submitted as any ordinary WestGrid batch job with the qsub command. See the [https://www.westgrid.ca/support/running_jobs Running Jobs] page for more information. If the above script is called matlab.pbs, it could be submitted using:
echo "Finished run at $(date)"
</pre>


qsub -l walltime=72:00:00,mem=6gb matlab.pbs
The job is then submitted with sbatch:


The specified walltime and total memory (mem) limits should be adjusted to appropriate values for your particular run.
<pre>
sbatch sawtooth_standalone.slurm
</pre>


An important part of the above script is the location of the MATLAB Compiler Runtime (MCR) directory. This directory contains files necessary for the standalone application to run. The version of the MCR files specified (v90 in the example, which corresponds to MATLAB R2015b) must match the version of MATLAB used to compile the code.
An important part of the above script is the definition of the variable MCR, which defines the location of the MATLAB Compiler Runtime (MCR) directory. This directory contains files necessary for the standalone application to run. The version of the MCR files specified (v97 in the example, which corresponds to MATLAB R2019b) must match the version of MATLAB used to compile the code.


A complete list of the MATLAB distributions and the corresponding compiler and MCR versions is given on the [http://www.mathworks.com/support/solutions/en/data/1-4GSNCF/?solution=1-4GSNCF Mathworks web site]. The most recent versions are listed below, along with the corresponding installation directory to which the MCR variable should be set in the example script. Not all systems have all versions installed, so, check the [/support/software/matlab/mcr/software_versions MCR versions page] or <span class="WG_Inline_Code">/global/software/matlab/mcr</span> directory on the system you are proposing to use. If the MCR version you need has not been installed please write to [mailto:support@westgrid.ca support@westgrid.ca] to request that it be installed, or use a different version of MATLAB for your compilation.
'''Note: this section is still being converted from a different web site.'''
A complete list of the MATLAB distributions and the corresponding compiler and MCR versions is given on the [http://www.mathworks.com/support/solutions/en/data/1-4GSNCF/?solution=1-4GSNCF Mathworks web site]. The most recent versions are listed below, along with the corresponding installation directory to which the MCR variable should be set in the example script. Not all systems have all versions installed, so, check the [/support/software/matlab/mcr/software_versions MCR versions page] or <span class="WG_Inline_Code">/global/software/matlab/mcr</span> directory on the system you are proposing to use. If the MCR version you need has not been installed please write to support@hpc.ucalgary.ca to request that it be installed, or use a different version of MATLAB for your compilation.


{| class="WG_Indent3" style="height: 150px; width: 576px" border="2"
{| class="WG_Indent3" style="height: 150px; width: 576px" border="2"
Line 239: Line 324:
| class="WG_Inline_Code" style="text-align: center" | /global/software/matlab/mcr/v91
| class="WG_Inline_Code" style="text-align: center" | /global/software/matlab/mcr/v91
|}
|}
<nowiki>* Please note that the MCR directories on Bugaboo are located under </nowiki><span class="WG_Inline_Code">/usr/local/matlab-mcr</span> but links are available from <span class="WG_Inline_Code">/global/software/matlab/mcr </span>so either location may be specified.
== Passing arguments to a standalone application ==
In most programs there are a number of input data values that determine the specific calculation to be performed. In order to avoid recompiling your code for each change of these key input parameters, you can pass one or more arguments to the main function (as will be illustrated in the next section on reading parameters from a file). The arguments to be passed to the code are appended to the line in your batch job script that runs your compiled code. In the example given here, a single file name, params.in, is passed as an argument to the standalone application. The idea is that multiple parameters can be specified in this parameter file, rather than parsing multiple command-line arguments. Here is an example batch job script example.
Caution: the command line arguments are interpreted as text by the compiled program, even if they appear to be numbers. So, you may need to use a str2num function call to convert character strings to numerical values.
<nowiki>#!/bin/bash</nowiki><br /><nowiki>#PBS -S /bin/bash</nowiki><br /><br /><nowiki># Choose the MCR directory according to the compiler version used</nowiki><br />MCR=/global/software/matlab/mcr/v90<br /><br />echo "Running on host: `hostname`"<br />cd $PBS_O_WORKDIR <br />echo "Current working directory is `pwd`"<br /><br />echo "Starting run at: `date`" <br />./run_mycode.sh $MCR params.in > mycode_${PBS_JOBID}.out<br />echo "Job finished at: `date`"
== Reading parameters from a file ==
To complete the example in the previous section of passing a parameter file name, params.in, as an argument to a compiled MATLAB code, here we illustrate one possible way of structuring the parameter file and using the parameters that are read. The main program used in the example will call the MATLAB built-in function bench, which runs a series of numerical and graphical tests (although the graphical part will not be meaningful here). The bench function itself takes an argument, the number of repetitions of the set of tests to run.
For the parameter file format, we assume a fairly general form that is a subset of MATLAB syntax, in which a variable is assigned a value, followed by a semicolon and an optional comment. Extra lines not matching this format are generally ignored, although the parsing logic doesn't correctly handle all cases. In particular there should be no spaces between the variable name and the equal sign when assigning values. In the file, params.in, one could have:
<nowiki># A comment line that will be ignored.</nowiki><br />% Another line that will be ignored.<br />nreps=3; % Number of repetitions of the bench command to execute.<br />output_file=bench_output; % Output file name<br />b=42; % Another variable
Here is a program that reads the params.in file, using the nreps parameter to control the number of calculations to perform.
function bench_ppn_test(command_line_arg)<br /><br />% Pass a single parameter file name as the command line argument<br />% Assume the file name does not contain any spaces.<br /><br />% Run the MATLAB bench command the number of times, nreps, specified<br />% in the parameter file.<br /><br />% 2014-01-21, 2014-02-06 DSP<br /><br />message=['Command line string: ',command_line_arg];<br />disp(message)<br /><br />% Parse the command line for the argument<br /><br />params_file=sscanf(command_line_arg,'%s')<br /><br />message=['Parameters file name: ',params_file];<br />disp(message)<br /><br />% Assign a default value to the number of repetitions<br /><br />nreps=1;<br /><br />% Read the parameters file to see if the default nreps should be<br />% over-ridden.<br /><br />fid = fopen(params_file);<br /><br />line=fgetl(fid);<br />while ischar(line)<br />% Ignore lines that do not have an equal sign.<br /> equal_index=strfind(line,'=');<br /> if isempty(equal_index)<br /> %disp('Skipping line without =:');<br /> %disp(line);<br /> else<br />% Take variable name to be the text to the left of the equal sign.<br /> name=strtrim(sscanf(line(1:equal_index-1),'%s'));<br /><br />% Find semicolon<br /> semicolon_index=strfind(line,';');<br /> if isempty(semicolon_index)<br /> disp('Semicolon missing from line:');<br /> disp(line);<br /> else<br /> %disp('Processing line:');<br /> %disp(line);<br /> value=line(equal_index+1:semicolon_index-1);<br /><br />% Make sure that eval doesn't change the type of numeric variables.<br />% Note that if(eval( ['exist ' name])) can't be used directly.<br />% http://www.mathworks.com/help/matlab/matlab_prog/variables-in-nested-and-anonymous-functions.html<br /><br /> eval( ['exist ' name ';']);<br /> if (ans)<br /> disp('Assigning new value for variable:')<br /> if (isa(eval(name), 'numeric'))<br /> eval([name ' = str2num(value)'])<br /> else<br /> eval([name ' = value'])<br /> end<br /> else<br /> disp('Initializing variable:')<br /> eval([name ' = value'])<br /> end % end test for name<br /> end % end test for semicolon<br /> end % end test for equal sign<br /> line=fgetl(fid);<br />end % end while<br /><br />fclose(fid);<br />disp('Finished reading parameters file');<br /><br />message=['Setting number of bench repetitions to ',num2str(nreps)];<br />disp(message)<br /><br />% Find the number of cores assigned to the job<br /><br />coresenv=str2num(getenv('PBS_NUM_PPN'))<br />if(isempty(coresenv))<br /> coresenv=1<br />end<br /><br />% Set number of computational threads to coresenv<br />% Note Mathworks warns that the maxNumCompThreads function will<br />% be removed in future versions of MATLAB.<br /><br />default_cores = maxNumCompThreads(coresenv)<br /><br />% Calling bench with argument nreps read from the parameters file.<br /><br />tic<br />bench(nreps)<br />toc<br /><br />quit;<br /><br />

Revision as of 15:17, 21 May 2020


Introduction

MATLAB is a general-purpose high-level programming package for numerical work such as linear algebra, signal processing and other calculations involving matrices or vectors of data. Visualization tools are also included for presentation of results. The basic MATLAB package is extended through add-on components including SIMULINK, and the Image Processing, Optimization, Neural Network, Signal Processing, Statistics and Wavelet Toolboxes, among others.

The main purpose of this page is to show how to use MATLAB on the University of Calgary ARC (Advanced Research Computing) cluster. It is presumed that you already have an account an ARC and have read the material on reserving resources and running jobs with the Slurm job management system.

Ways to run MATLAB - License considerations

At the University of Calgary, Information Technologies has purchased a MATLAB Total Academic Headcount license that allows installation and use of MATLAB on central clusters, such as ARC, as well as on personal workstations throughout the University. Potentially thousands of instances of MATLAB can be run simultaneously, each checking out a license from a central license server. An alternative is to compile MATLAB code into a standalone application. When such an application is run, it does not need to contact the server for a license. This allows researchers to run their calculations on compatible hardware, not necessarily at the University of Calgary, such as on Compute Canada clusters (external link).

For information about installing MATLAB on your own computer, see the Information Technologies Knowledge Base article on MATLAB.

Running MATLAB on the ARC cluster

Although it is possible to run MATLAB interactively, the expectation is that most calculations with MATLAB will be completed by submitting a batch job script to the Slurm job scheduler with the sbatch command.

For the purposes of illustration, suppose the following serial MATLAB code, in a file sawtooth.m, is to be run. (Parallel processing cases will be considered later). If your code does not already have them, add a function statement at the beginning and matching end statement at the end as shown in the example. Other features of this example include calling a function with both numerical and string arguments, incorporating a Slurm environment variable into the MATLAB code and producing graphical output in a non-interactive environment.

function sawtooth(nterms,nppcycle,ncycle,pngfilebase)

% MATLAB file example to approximate a sawtooth
% with a truncated Fourier expansion.

% nterms = number of terms in expansion.
% ncycle = number of complete cycles to plot.
% nppcycle = number of points per cycle.
% pngfilebase = base of file name for graph of results.

% 2020-05-14

np=nppcycle*ncycle;

fourbypi=4.0/pi;
y(1:np)=pi/2.0;
x(1:np)=linspace(-pi*ncycle,pi*ncycle,np);

for k=1:nterms
  twokm=2*k-1;
  y=y-fourbypi*cos(twokm*x)/twokm^2;
end

% Prepare output
% Construct the output file name from the base file name and number of terms
% Also append the Slurm JOBID to keep file names unique from run to run.

job=getenv('SLURM_JOB_ID')
pngfile=strcat(pngfilebase,'_',num2str(nterms),'_',job)
disp(['Writing file: ',pngfile,'.png'])

fig=figure;
plot(x,y);
print(fig,pngfile,'-dpng');

quit
end

In preparation to run the sawtooth.m code, create a batch job script, sawtooth.slurm of the form:

#!/bin/bash
#SBATCH --time=03:00:00     # Adjust this to match the walltime of your job
#SBATCH --nodes=1           # For serial code, always specify just one node.
#SBATCH --ntasks=1          # For serial code, always specify just one task.
#SBATCH --cpus-per-task=1   # For serial code, always specify just one CPU per task.
#SBATCH --mem=4000m         # Adjust to match total memory required, in MB.
#SBATCH --partition=pawson-bf,apophis-bf,razi-bf,lattice,parallel,cpu2013,cpu2019

# Sample batch job script for running a MATLAB function with both numerical and string arguments
# 2020-05-14

# Specify the name of the main MATLAB function to be run.
# This would normally be the same as the MATLAB source code file name without a .m suffix).
MAIN="sawtooth"

# Define key parameters for the example calculation.
NTERMS=100
NPPCYCLE=20
NCYCLE=3
PNGFILEBASE="sawtooth"

# Contruct a complete function call to pass to MATLAB
# Note, string arguments should appear to MATLAB enclosed in single quotes
ARGS="($NTERMS,$NPPCYCLE,$NCYCLE,'$PNGFILEBASE')"
MAIN_WITH_ARGS=${MAIN}${ARGS}

echo "Calling MATLAB function: ${MAIN_WITH_ARGS}"

echo "Starting run at $(date)"
echo "Running on compute node $(hostname)"
echo "Running from directory $(pwd)"

# Choose a version of MATLAB by loading a module:
module load matlab/r2019b
echo "Using MATLAB version: $(which matlab)"

# Use -singleCompThread below for serial MATLAB code:
matlab -singleCompThread -batch "${MAIN_WITH_ARGS}" > ${MAIN}_${SLURM_JOB_ID}.out 2>&1

echo "Finished run at $(date)"

Note that the above script uses the -batch option on the matlab command line. The MathWorks web page on running MATLAB on Linux (external link) starting with Release 2019a of MATLAB, recommends using the -batch option for non-interactive use instead of the similar -r option that is recommended in interactive sessions.

To submit the job to be executed, run:

sbatch sawtooth.slurm

The job should produce three output files: Slurm script output, MATLAB command output and a PNG file, all tagged with the Slurm Job ID.

Standalone Applications

When running MATLAB code as described in the preceding section, a connection to the campus MATLAB license server, checking out licenses for MATLAB and any specialized toolboxes needed, is made for each job that is submitted. Currently, with the University of Calgary's Total Academic Headcount license, there are sufficient license tokens to support thousands of simultaneous MATLAB sessions (although ARC usage policy and cluster load will limit individual users to smaller numbers of jobs). However, there may be times at which the license server is slow to respond when large numbers of requests are being handled, or the server may be unavailable temporarily due to network problems. MathWorks offers an alternative way of running MATLAB code that can avoid license server issues by compiling it into a standalone application. A license is required only during the compilation process and not when the code is run. This allows calculations to be run on ARC without concerns regarding the license server. The compiled code can also be run on compatible (64-bit Linux) hardware, not necessarily at the University of Calgary, such as on Compute Canada (external link) clusters.

Creating a standalone application

The MATLAB mcc command is used to compile source code (.m files) into a standalone excecutable. There are a couple of important considerations to keep in mind when creating an executable that can be run in a batch-oriented cluster environment. One is that there is no graphical display attached to your session and another is that the number of threads used by the standalone application has to be controlled. There is also an important difference in the way arguments of the main function are handled.

Let's illustrate the process of creating a standalone application for the sawtooth.m code used previously. Unfortunately, if that code is compiled as it is, the resulting compiled application will fail to run properly. The reason is that the compiled code sees all the input arguments as strings instead of interpreting them as numbers. To work around this problem, use a MATLAB function, isdeployed, to determine whether or not the code is being run as a standalone application. Here is a modified version of code, called sawtooth_standalone.m that can be successfully compiled and run as a standalone application.

function sawtooth_standalone(nterms,nppcycle,ncycle,pngfilebase)

% MATLAB file example to approximate a sawtooth
% with a truncated Fourier expansion.

% nterms = number of terms in expansion.
% ncycle = number of complete cycles to plot.
% nppcycle = number of points per cycle.
% pngfilebase = base of file name for graph of results.

% 2020-05-21

% Test to see if the code is running as a standalone application
% If it is, convert the arguments intended to be numeric from 
% the input strings to numbers

if isdeployed
  nterms=str2num(nterms)
  nppcycle=str2num(nppcycle)
  ncycle=str2num(ncycle)
end

np=nppcycle*ncycle;

fourbypi=4.0/pi;
y(1:np)=pi/2.0;
x(1:np)=linspace(-pi*ncycle,pi*ncycle,np);

for k=1:nterms
  twokm=2*k-1;
  y=y-fourbypi*cos(twokm*x)/twokm^2;
end

% Prepare output
% Construct the output file name from the base file name and number of terms
% Also append the Slurm JOBID to keep file names unique from run to run.

job=getenv('SLURM_JOB_ID')
pngfile=strcat(pngfilebase,'_',num2str(nterms),'_',job)
disp(['Writing file: ',pngfile,'.png'])

fig=figure;
plot(x,y);
print(fig,pngfile,'-dpng');

quit
end

Suppose that the sawtooth_standalone.m file is in a subdirectory src below your current working directory and that the compiled files are going to be written to a subdirectory called deploy. The following commands (at the Linux shell prompt) could be used to compile the code:

mkdir deploy
cd src
module load matlab/r2019b
mcc -R -nodisplay \
 -R -singleCompThread \
 -m -v -w enable \
 -d ../deploy \
 sawtooth_standalone.m

Note the option -singleCompThread has been included in order to limit the executable to just one computational thread.

In the deploy directory, an executable, sawtooth_standalone, will be created along with a script, run_sawtooth_standalone.sh. These two files should be copied to the target machine where the code is to be run.

Running a standalone application

After the standalone executable sawtooth_standalone and corresponding script run_sawtooth_standalone.sh have been transferred to a directory on the target system on which they will be run (whether to a different directory on ARC or to a completely different cluster), a batch job script needs to be created in that same directory. Here is an example batch job script, sawtooth_standalone.slurm .

#!/bin/bash
#SBATCH --time=03:00:00     # Adjust this to match the walltime of your job
#SBATCH --nodes=1           # For serial code, always specify just one node.
#SBATCH --ntasks=1          # For serial code, always specify just one task.
#SBATCH --cpus-per-task=1   # For serial code, always specify just one CPU per task.
#SBATCH --mem=4000m          # Adjust to match total memory required, in MB.
#SBATCH --partition=pawson-bf,apophis-bf,razi-bf,lattice,parallel,cpu2013,cpu2019

# Sample batch job script for running a compiled MATLAB function
# 2020-05-21

# Specify the name of the compiled MATLAB standalone executable
MAIN="sawtooth_standalone"

# Define key parameters for the example calculation.
NTERMS=100
NPPCYCLE=20
NCYCLE=3
PNGFILEBASE=$MAIN

ARGS="$NTERMS $NPPCYCLE $NCYCLE $PNGFILEBASE"

# Choose the MCR directory according to the compiler version used
MCR=/global/software/matlab/mcr/v97

echo "Starting run at $(date)"
echo "Running on compute node $(hostname)"
echo "Running from directory $(pwd)"

./run_${MAIN}.sh $MCR $ARGS > ${MAIN}_${SLURM_JOB_ID}.out 2>&1

echo "Finished run at $(date)"

The job is then submitted with sbatch:

sbatch sawtooth_standalone.slurm

An important part of the above script is the definition of the variable MCR, which defines the location of the MATLAB Compiler Runtime (MCR) directory. This directory contains files necessary for the standalone application to run. The version of the MCR files specified (v97 in the example, which corresponds to MATLAB R2019b) must match the version of MATLAB used to compile the code.

Note: this section is still being converted from a different web site. A complete list of the MATLAB distributions and the corresponding compiler and MCR versions is given on the Mathworks web site. The most recent versions are listed below, along with the corresponding installation directory to which the MCR variable should be set in the example script. Not all systems have all versions installed, so, check the [/support/software/matlab/mcr/software_versions MCR versions page] or /global/software/matlab/mcr directory on the system you are proposing to use. If the MCR version you need has not been installed please write to support@hpc.ucalgary.ca to request that it be installed, or use a different version of MATLAB for your compilation.

MATLAB Release Compiler Version MCR Version MCR directory*
R2009b 4.11 7.11 /global/software/matlab/mcr/v711
R2009bSP1 4.12 7.12 Not installed
R2010a 4.13 7.13 /global/software/matlab/mcr/v713
R2010b 4.14 7.14 /global/software/matlab/mcr/v714
R2011a 4.15 7.15 /global/software/matlab/mcr/v715
R2011b 4.16 7.16 /global/software/matlab/mcr/v716
R2012a 4.17 7.17 /global/software/matlab/mcr/v717
R2012b 4.18 8.0 /global/software/matlab/mcr/v80
R2013a 4.18.1 8.1 /global/software/matlab/mcr/v81
R2013b 5.0 8.2 /global/software/matlab/mcr/v82
R2014a 5.1 8.3 /global/software/matlab/mcr/v83
R2014b 5.2 8.4 /global/software/matlab/mcr/v84
R2015a 6.0 8.5 /global/software/matlab/mcr/v85
R2015b 6.1 9.0 /global/software/matlab/mcr/v90
R2016a 6.2 9.0.1 /global/software/matlab/mcr/v901
R2016b 6.3 9.1 /global/software/matlab/mcr/v91