If you run MATLAB jobs routinely, you may have had the experience of denied MATLAB access or having your MATLAB batch jobs killed due to unavailable MATLAB licenses. This can be avoided if you compile your MATLAB application into an executable with the MATLAB mcc compiler. A standalone executable runs without using a MATLAB license, and has several other benefits.

Benefits of standalone executables

  1. Broader distribution: Extend the reach of your program to users who lack a MATLAB license.
  2. Access reliability: Standalone executables never fail due to license availability.
  3. Embarrassingly parallel applications: Hundreds or thousands of independent runs are common for many applications. Using a standalone makes it possible to run these tasks concurrently — e.g. on the SCC cluster — without running into licensing issues.
  4. Hide source code for intellectual property protection

To be compatible with the MATLAB mcc compiler, your program must meet a few requirements. The most important of these are listed below.

  • The starting, or “main,” program must be a function — with or without returning output. The standalone, regardless, will not return any output. You can use either the original main or you create a command function wrapper as the new “main” which in turn calls the original main. For many, a wrapper may be more appealing as it enables the original program to be kept completely separate from the corresponding standalone program.
  • All runtime input parameters are always passed to the standalone as strings. Any passed string parameter intended as double in the code must be converted with str2double. Your wrapper will perform data type conversions (if any) and pass them to the original main for further processing.

Compilation

scc1% module load matlab/2016a 
scc1% mcc -mv -o myExecR2016a myStandalone.m myApp.m 
  • -mv produces a standalone and shows actions taken
  • -o myExecR2016a specifies the executable name. Though not required, “R2016a” suffix in the output name indicates MATLAB release used for compilation.

Running Standalone executable interactively

scc1%  qrsh -pe omp 4 
scc-pi4% module load mcr/9.0.1_2016a 
scc-pi4% mcr ./myExecR2016a 2000 4 
scc-pi4% exit 

Submit a job

#!/bin/bash -l
# SGE script for MATLAB standalone
# Usage:
# scc1$ qsub run_standalone_job       
#
# Merge output and error files in one
#$ -j y
# Send email when job finished or aborted
#$ -m ae
# Request 4 cores 
#$ -pe omp 4

module load mcr/9.0.1_2016a
mcr ./myExecR2016a 2000 4

Example Source Files

function s = myApp(n, nslots)
% function s = myApp(n, nslots)
% Purpose: runs basic MATLAB commands to simulate user code for a standalone demo
%       n: size of arithmetic sequence [1+2+3+ . . . +n]
%  nslots: number of processors in parallel computing

% Compute with the Parallel Computing Toolbox
fprintf(1,'\n Test the parallel computing toolbox . . . . .\n');
fprintf(1,'Parfor will be used to compute the sum of the arithmetic sequence\n');
fprintf(1,'s = 1 + 2 + 3 + . . . + n = n(n+1)/2\n\n');
fprintf(1,'Will use %d threads for parfor operations.\n', nslots);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Especially important for running multiple batch jobs
% Without this procedure, some batch jobs may fail
% redirects ~/.matlab PCT temp files to system's TMPDIR on compute
% node to avoid inter-node (compute node <--> login node) I/O
myCluster = parcluster('local'); % cores on compute node are "local"
if getenv('ENVIRONMENT')         % true if this is a batch job
  myCluster.JobStorageLocation = getenv('TMPDIR')  % points to TMPDIR
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
parpool(myCluster, nslots);      % MATLAB R2014a or newer
%matlabpool(myCluster, nslots);    % MATLAB R2013b or older
% REPLACE BELOW EXAMPLE WITH YOUR APP
% This example uses parfor to compute arithmetic sequence sum
s = 0;             % initialize sequence sum s
parfor i=1:n
    s = s + i;     % s = 1 + 2 + 3 + . . . + n
end
%matlabpool close;  % close parallel pool for R2013 or older
delete(gcp)         % close parallel pool for R2014a or newer

fprintf(1,'\n\n Iteration count n = %d\n', n);
fprintf(1,'\nComputed s = %d   ;  Expected s =  %d \n\n', s, n*(n+1)/2);

end   % end of function% end of function

function myStandalone(n, nprocs)
% function myStandalone(n, nprocs)
% Purpose: this optionally serves as the front m-file
%          to your app so your app remain unchanged.
% n: size of arithmetic sequence [1+2+3+ . . . +n]
% nprocs: # of procs [ (matlabpool('local', nprocs) ]
% Standalone Main Program Rules
% a) It must be a function, and it must not have output
%    >> myStandalone 2000 4       % command  syntax
%    >> myStandalone(2000, 4)     % function syntax
% b) The standalone runs in command syntax only 
%    scc1$ ./myExecR2013a 2000 4
% c) Commandline input (if any) are passed as strings
%    Must be converted to double for used as double
% In command syntax, both n and nprocs are strings
if ischar(n) == 1
    disp('n needs conversion')
    n = str2double(n);  % convert string to double
end
if ischar(nprocs) == 1
    disp('nprocs needs conversion')
    nprocs = str2double(nprocs);  % convert string
end

% Call user app, myApp (script or function m-file)
s = myApp(n, nprocs);

% Handle the output (s) as intended
disp(['Sum of Arithmetic sequence 1+2+3+...+n = ' num2str(s)])

if isdeployed     % in standalone mode . . .
   exit;
else
   close all
end

end   % end of function

Additional notes

myStandalone.m is an optional application-dependent wrapper and is a command function. Note that, because myApp.m takes two input parameters — by design rather than mandatory — myStandalone.m retains the same 2 run time input.
The following command might need to be added into your matlab script to help myStandalone.m find files it needs:

>> addpath my/script/dir   % your m-files folder
  • Recompiling required whenever changes are made to one or more m-files.
  • For batch processing, mcc runtime option (e.g., -R -singleCompThread) may be required if you run a single threaded job.
scc1%  mcc -mv -o myExec myStandalone.m myApp.m -R -singleCompThread -R -nodisplay
  • -R -singleCompThread turns off multithreading while -R -nodisplay disables graphics display.
  • The standalone built with these runtime switches will always run with single thread and will not display graphics — in batch or interactive.