MATLAB

The university now has a campus license for MATLAB, which makes it possible to submit jobs from MATLAB to the cluster, and run jobs on multiple nodes. For all details, see the attached manual. Note that the functionality currently only works with MATLAB 2020b; if you want to submit jobs from your own workstation, make sure to use the same MATLAB version and install the set of scripts as described in the manual.

The examples that you will find below, do not use this functionality and show how to manually submit MATLAB jobs.

In order to run a simple MATLAB script on a single core, two files should be constructed. The first file is the MATLAB script (with the .m extension), which is here called matlab_example1.m:

matlab_example1.m
% Matrix multiplication example.
A = [1,2,3;1,2,3;1,2,3];
B = [2,3,4;2,3,4;2,3,4];
% Multiplies matrix A with B 20 times.
for i=1:20
    A=A*B;
end
display(A)


The second file is the job script that is used to send the MATLAB job to the cluster. This file is called matlab_ex1.sh and should look like:

matlab_ex1.sh
#!/bin/bash
#SBATCH --time=00:05:00
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task
#SBATCH --job-name=matlab_example1
#SBATCH --output=matlab_example1.out
#SBATCH --mem=1000
 
module purge
module load MATLAB/2022b-r5
matlab -nodisplay -singleCompThread < matlab_example1.m


When both files are created and saved in the same directory, the following command can be used to submit the job from that directory:

sbatch matlab_ex1.sh


The job is now submitted, and the squeue command can be used to check the status of the job:

squeue -u $USER


A file named matlab_example1.out will also be created when the job starts running; open this file with a text viewer/editor to see the job output. If the file is empty, try again a bit later.
The expected output should be:

A =
 
    1.0e+19 *
 
        1.6210    2.4315    3.2420
        1.6210    2.4315    3.2420
        1.6210    2.4315    3.2420
 
>>

The following example shows how multiple cores are used with MATLAB.
We use the following MATLAB script named matlab_parpool_example.m:

matlab_parpool_example.m
% This code creates a random 4x4 matrix with values between 0 and 10, n times.
n = 4; % Should correspond to --cpus-per-task in the sbatch file.
parpool('local', n);
parfor i=1:n % Multithreaded part
   disp(round(rand(4)*10));
end


Then we need the following matlab_parpool_example.sh script. Note that the –cpus-per-task option is used to specify the number of cores.

matlab_parpool_example.sh
#!/bin/bash
#SBATCH --time=00:10:00
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=4 # Here we request 4 cores for this task.
#SBATCH --job-name=matlab_parpool_example
#SBATCH --output=matlab_parpool_example.out
#SBATCH --mem=8000
 
module load MATLAB/2020b
matlab -nodisplay < matlab_parpool_example.m


Then, by giving the following command, the job gets submitted:

sbatch matlab_parpool_example.sh


Note that starting a parallel pool takes some time, hence for this short example, it will not run faster than a serial execution of this example.

Here we show how to use a GPU on the cluster for your MATLAB script. Make sure that the partition is set to gpu in the batch script. The Running jobs on GPUs page shows how other settings for the GPU are set. The batch script here is named gpuExampleMatlab.sh and the MATLAB script mandelbrot.m.

gpuExampleMatlab.sh
#!/bin/bash
#SBATCH --time=00:05:00
#SBATCH --partition=gpu
#SBATCH --gres=gpu:1
#SBATCH --mem=1000
 
module load MATLAB/2020b
matlab -nodisplay -r mandelbrot


The MATLAB script:

mandelbrot.m
maxIterations = 5000;
gridSize = 1000;
xlim = [-0.748766713922161, -0.748766707771757];
ylim = [ 0.123640844894862,  0.123640851045266];
 
% Setup normal way.
 
x = linspace( xlim(1), xlim(2), gridSize );
y = linspace( ylim(1), ylim(2), gridSize );
[xGrid,yGrid] = meshgrid( x, y );
z0 = xGrid + 1i*yGrid;
count = ones( size(z0) );
 
% Calculate
t = tic();
z = z0;
for n = 0:maxIterations
    z = z.*z + z0;
    inside = abs( z )<=2;
    count = count + inside;
end
count = log( count );
 
% Show
cpuTime = toc( t );
fig = gcf;
fig.Position = [200 200 600 600];
imagesc( x, y, count );
axis image
colormap( [jet();flipud( jet() );0 0 0] );
title( sprintf( '%1.2fsecs (without GPU)', cpuTime ) );
print -dpng CPU.png
 
% Set up GPU
 
x = gpuArray.linspace( xlim(1), xlim(2), gridSize );
y = gpuArray.linspace( ylim(1), ylim(2), gridSize );
[xGrid,yGrid] = meshgrid( x, y );
z0 = complex( xGrid, yGrid );
count = ones( size(z0), 'gpuArray' );
 
% Calculate
t = tic();
z = z0;
for n = 0:maxIterations
    z = z.*z + z0;
    inside = abs( z )<=2;
    count = count + inside;
end
count = log( count );
 
% Show
count = gather( count ); % Fetch the data back from the GPU
naiveGPUTime = toc( t );
imagesc( x, y, count )
axis image
title( sprintf( '%1.3fsecs (naive GPU) = %1.1fx faster', ...
    naiveGPUTime, cpuTime/naiveGPUTime ) )
print -dpng GPU.png


Submitting this job can be done with the command: sbatch gpuExampleMatlab.sh Running this job will result in two PNG files being created in the same directory. These images show the Mandelbrot fractals and the computing time on one CPU and the computing time on one GPU.