When you want to run Matlab code, you usually need to run the the full Matlab runtime. This comes at the price that for each run, you need a Matlab license. This could be perfectly acceptable on your workstation, but can become a problem if you want to run a lot of instances of your code (for example on unige HPC clusters), or if you want to distribute your code to someone who does not have a Matlab license.

For this type of situation, Matlab provide two tools : a compiler and a downloadable runtime named Matlab compiler runtime (MCR). The first allows to compile and package your application, the second is needed to run the compiled application.

In this article, we will review the use case where you want to compile and run multiple instances of your matlab code on unige HPC clusters (possibly with a job array). 

Compile and run multiple instances of you Matlab code on a cluster

Let's consider the following simple Matlab code, which defines a function foo(arg) printing its argument :

function foo = echo(arg)
  fprintf('Hello world! %s\n', arg);
  foo = 0;
end

We store it in a file named hello.m. On the cluster, you can check the available versions of Matlab with :

[user@login2 ~]$ module spider matlab

Let's suppose that we load version 2019b :

[user@login2 ~]$ module load matlab/2019b

We can now compile the code :

[user@login2 ~]$ mcc -m hello.m

where mcc is the Matlab compiler. After the compilation is finished, you should see a bunch of new files :

[user@login2 ~]$ ls
hello  hello.m  mccExcludedFiles.log  readme.txt  requiredMCRProducts.txt  run_hello.sh

where hello is the generated executable and run_hello.sh is a generated wrapper script that allows to run the program. We can now write a slurm script to run our Matlab code. Here is an example, we save its content in the file run_hello_with_slurm.sh :

#!/bin/bash

#SBATCH --partition=shared-cpu
#SBATCH --time=00:10:00
#SBATCH --ntasks=1
#SBATCH -o hello-matlab-%A.out

sh run_hello.sh /unige/matlab2019b bar

The last line runs the generated wrapper script, we have to pass the path of the Matlab runtime, and finally the argument of the Matlab function that is executed. We can now execute the code :

[user@login2 ~]$ sbatch run_hello_with_slurm.sh 
Submitted batch job 49498493

After the job finished its execution, you can read the output :

[user@login2~]$ cat hello-matlab-49498493.out
------------------------------------------
Setting up environment variables
---
LD_LIBRARY_PATH is .:/unige/matlab2019b/runtime/glnxa64:/unige/matlab2019b/bin/glnxa64:/unige/matlab2019b/sys/os/glnxa64:/unige/matlab2019b/sys/opengl/lib/glnxa64
Hello world! bar

You can run as many job as you want using this executable in parallel, as they do not consume Matlab licenses.

Using a job array

You can as well run your Matlab code in a job array. https://doc.eresearch.unige.ch/hpc/slurm?s[]=job&s[]=array#job_array

Let's modify slightly our submission script as follows :

#!/bin/bash

#SBATCH --partition=shared-cpu
#SBATCH --time=00:10:00
#SBATCH --ntasks=1
#SBATCH -o hello-matlab-%A_%a.out

sh run_hello.sh /unige/matlab2019b ${SLURM_ARRAY_TASK_ID}

We added the identifier of the job in the job array in the output log file name (hello-matlab-%A_%a.out) and we pass the id of the job in the array to the code. If we run this script in a job array (here with an array of 10 jobs) :

sbatch --array=1-10 run_hello_with_slurm.sh 

we end with 10 files of the form hello-matlab-\*_*.out. For example :

[user@login2 ~]$ cat hello-matlab-49498512_3.out
------------------------------------------
Setting up environment variables
---
LD_LIBRARY_PATH is .:/unige/matlab2019b/runtime/glnxa64:/unige/matlab2019b/bin/glnxa64:/unige/matlab2019b/sys/os/glnxa64:/unige/matlab2019b/sys/opengl/lib/glnxa64
Hello world! 3

With this solution, you can now run a large number of instances of you Matlab executable in a job array without worrying about the number of licenses used.