====== MATLAB ====== ==== MATLAB Parallel Computing ==== 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 {{ :peregrine:examples:getting_started_with_serial_and_parallel_matlab.pdf |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. ==== Single CPU ==== 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'': % 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: #!/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 >> ==== Multiple CPUs ==== The following example shows how multiple cores are used with MATLAB.\\ We use the following MATLAB script named ''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. #!/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. ==== GPU ==== 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 [[peregrine:advanced_job_management: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''. #!/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: 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.