MATLAB Parallel Computing Toolbox User's Guide (R2025b)
MATLAB Parallel Computing Toolbox User's Guide (R2025b)
User's Guide
R2025b
How to Contact MathWorks
Phone: 508-647-7000
Getting Started
1
Parallel Computing Toolbox Product Description . . . . . . . . . . . . . . . . . . . . 1-2
v
Try Parallel Computing Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-51
vi Contents
Broadcast Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-33
Performance Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-33
vii
Evaluate Functions in the Background Using parfeval . . . . . . . . . . . . . . . 3-3
viii Contents
Distributing Arrays to Parallel Workers . . . . . . . . . . . . . . . . . . . . . . . . . . 4-12
Using Distributed Arrays to Partition Data Across Workers . . . . . . . . . . . 4-12
Load Distributed Arrays in Parallel Using datastore . . . . . . . . . . . . . . . . 4-12
Alternative Methods for Creating Distributed and Codistributed Arrays . 4-14
Use Parallel Computing to Optimize Big Data Set for Analysis . . . . . . . . 4-53
ix
Use Tall Arrays on a Parallel Pool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-96
Batch Processing
5
Choose Batch Processing Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2
Batch Parallel Job Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2
Select Batch Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-3
x Contents
Monitor Monte Carlo Batch Jobs with ValueStore . . . . . . . . . . . . . . . . . . 5-22
GPU Computing
6
Run MATLAB Functions on a GPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-3
MATLAB Functions with gpuArray Arguments . . . . . . . . . . . . . . . . . . . . . 6-3
Check gpuArray-Supported Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-4
Deep Learning with GPUs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-5
Check or Select a GPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-5
Use MATLAB Functions with the GPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6
Examples Using GPUs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-8
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-9
xi
Establish Arrays on a GPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-15
Create GPU Arrays from Existing Data . . . . . . . . . . . . . . . . . . . . . . . . . . 6-15
Create GPU Arrays Directly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-15
Examine gpuArray Characteristics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-17
Save and Load gpuArray Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-17
xii Contents
Use FFT2 on the GPU to Simulate Diffraction Patterns . . . . . . . . . . . . . 6-108
xiii
Analyze Wind Data with Large Compute Cluster . . . . . . . . . . . . . . . . . . . 7-62
Performance Profiling
8
Monitor Pool Workers with Pool Dashboard . . . . . . . . . . . . . . . . . . . . . . . . 8-2
Compare Performance of Parallel Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-3
Identify parfeval Computations in Monitoring Data . . . . . . . . . . . . . . . . . . 8-6
Analyze Distributed Array Computations . . . . . . . . . . . . . . . . . . . . . . . . . . 8-9
Measure and Improve Parallel Efficiency . . . . . . . . . . . . . . . . . . . . . . . . 8-13
xiv Contents
Programming Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-81
Program Development Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-81
Current Working Directory of a MATLAB Worker . . . . . . . . . . . . . . . . . . 8-82
Writing to Files from Workers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-82
Saving or Sending Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-82
Using clear function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-83
Running Tasks That Call Simulink Software . . . . . . . . . . . . . . . . . . . . . . 8-83
Using pause Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-83
Transmitting Large Amounts of Data . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-83
Interrupting a Job . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-83
Speeding Up a Job . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-83
Objects
9
Functions
10
xv
1
Getting Started
Parallel Computing Toolbox lets you solve compute- and data-intensive problems using multicore
processors, GPUs, and computer clusters. High-level constructs—parallel for-loops, special array
types, and parallelized numerical algorithms—enable you to scale MATLAB® applications without
CUDA® or MPI programming. Parallel Computing Toolbox also lets you use parallel-enabled functions
in MATLAB and other toolboxes and run multiple Simulink® simulations in parallel. Programs and
models can run in both interactive and batch modes.
The toolbox lets you use the full processing power of multicore and GPU-enabled desktops by
executing applications on thread and process workers (MATLAB computational engines) that run
locally. Without changing the code, you can run the same applications on clusters or clouds (using
MATLAB Parallel Server™). You can also use the toolbox with MATLAB Parallel Server to execute
matrix calculations that are too large to fit into the memory of a single machine.
Parallel Computing Toolbox lets you solve compute- and data-intensive problems using multicore
processors, GPUs, and computer clusters. High-level constructs—parallel for-loops, special array
types, and parallelized numerical algorithms—enable you to scale MATLAB applications without
CUDA or MPI programming. Parallel Computing Toolbox also lets you use parallel-enabled functions
in MATLAB and other toolboxes and run multiple Simulink simulations in parallel. Programs and
models can run in both interactive and batch modes.
The toolbox lets you use the full processing power of multicore and GPU-enabled desktops by
executing applications on thread and process workers (MATLAB computational engines) that run
locally. Without changing the code, you can run the same applications on clusters or clouds (using
MATLAB Parallel Server). You can also use the toolbox with MATLAB Parallel Server to execute
matrix calculations that are too large to fit into the memory of a single machine.
1-2
What Is Parallel Computing?
• Accelerate your code using interactive parallel computing tools, such as parfor and parfeval
• Scale up your computation using interactive Big Data processing tools, such as distributed,
tall, datastore, and mapreduce
• Use gpuArray to speed up your calculation on the GPU of your computer
• Use batch to offload your calculation to computer clusters or cloud computing facilities
• Node: standalone computer, containing one or more CPUs / GPUs. Nodes are networked to form a
cluster or supercomputer
• Thread: smallest set of instructions that can be managed independently by a scheduler. On a GPU,
multiprocessor or multicore system, multiple threads can be executed simultaneously (multi-
threading)
• Batch: off-load execution of a functional script to run in the background
• Scalability: increase in parallel speedup with the addition of more resources
• MATLAB workers: MATLAB computational engines that run in the background without a graphical
desktop. You use functions in the Parallel Computing Toolbox to automatically divide tasks and
assign them to these workers to execute the computations in parallel. You can run local workers to
take advantage of all the cores in your multicore desktop computer. You can also scale up to run
your workers on a cluster of machines, using the MATLAB Parallel Server. The MATLAB session
you interact with is known as the MATLAB client. The client instructs the workers with parallel
language functions.
• Parallel pool: a parallel pool of MATLAB workers created using parpool or functions with
automatic parallel support. By default, parallel language functions automatically create a parallel
pool for you when necessary. To learn more, see “Run Code on Parallel Pools” on page 1-28.
For the default Processes profile, the default number of workers is one per physical CPU core
using a single computational thread. This is because even though each physical core can have
several virtual cores, the virtual cores share some resources, typically including a shared floating
point unit (FPU). Most MATLAB computations use this unit because they are double-precision
floating point. Restricting to one worker per physical core ensures that each worker has exclusive
access to a floating point unit, which generally optimizes performance of computational code. If
your code is not computationally intensive, for example, it is input/output (I/O) intensive, then
consider using up to two workers per physical core. Running too many workers on too few
resources may impact performance and stability of your machine.
1-3
1 Getting Started
• Speed up: Accelerate your code by running on multiple MATLAB workers or GPUs, for example,
using parfor, parfeval, or gpuArray.
• Scale up your data: Partition your big data across multiple MATLAB workers, using tall arrays and
distributed arrays. To learn more, see “Big Data Processing”.
• Asynchronous processing: Use parfeval to execute a computing task in the background without
waiting for it to complete.
• Scale up to clusters and clouds: If your computing task is too big or too slow for your local
computer, you can offload your calculation to a cluster onsite or in the cloud using MATLAB
Parallel Server. For more information, see “Clusters and Clouds”.
See Also
Related Examples
• “Choose a Parallel Computing Solution” on page 1-5
• “Identify and Select a GPU Device” on page 6-10
• “Decide When to Use parfor” on page 2-2
• “Run Single Programs on Multiple Data Sets” on page 4-6
• “Evaluate Functions in the Background Using parfeval” on page 3-3
• “Distributing Arrays to Parallel Workers” on page 4-12
• “Run Batch Parallel Jobs” on page 5-5
1-4
Choose a Parallel Computing Solution
1-5
1 Getting Started
MATLAB Parallel
Server
If your data is large in MATLAB “Run MATLAB Functions with
multiple dimensions, use Distributed Arrays” on page 4-
distributed instead. Parallel Computing 5
Toolbox
This workflow is well
suited to linear algebra MATLAB Parallel
problems. Server
Do you want Use batch to run your MATLAB Parallel “Run Batch Parallel Jobs” on
to offload to a code on clusters and Server page 5-5
cluster? clouds.
Use batchsim to run your Simulink “Running Multiple Simulations”
simulations on clusters and (Simulink)
clouds. MATLAB Parallel
Server
1-6
Choose a Parallel Computing Solution
1-7
1 Getting Started
See Also
Related Examples
• “Profile Your Code to Improve Performance”
• “Vectorization”
• Built-in Parallel Computing Support
• “Identify and Select a GPU Device” on page 6-10
• “Interactively Run Loops in Parallel Using parfor” on page 2-43
• “Evaluate Functions in the Background Using parfeval” on page 3-3
• “Run Single Programs on Multiple Data Sets” on page 4-6
• “Choose Between spmd, parfor, and parfeval” on page 4-30
• “Big Data Workflow Using Tall Arrays and Datastores” on page 4-93
• “Use Tall Arrays on a Parallel Pool” on page 4-96
• “Use Tall Arrays on a Spark Cluster” on page 4-99
• “Distributing Arrays to Parallel Workers” on page 4-12
• “Run Batch Parallel Jobs” on page 5-5
1-8
Run MATLAB Functions with Automatic Parallel Support
To take advantage of this functionality on your desktop, you need Parallel Computing Toolbox. Run
calculations in parallel using local workers to speed up large calculations. To scale the parallel
computing to larger resources such as computer clusters, you also need a MATLAB Parallel Server
cluster.
• Some functions run automatically in parallel by default. For example, parfor, parsim, and tall.
• Many other functions run automatically in parallel if you set an option to use parallel.
When you run a function with parallel enabled, MATLAB automatically opens a parallel pool of
workers. MATLAB runs the computation across the available workers.
Automatic parallel support starts a parallel pool of workers using the default cluster profile. If you
have not touched your parallel settings, the default profile is Processes. Control parallel behavior
with the parallel settings, including scaling up to a cluster and automatic pool creation.
1-9
1 Getting Started
bar, click the Functions tab, select a product, and select the check box Automatic Parallel
Support. For example, for a filtered list of all Statistics and Machine Learning Toolbox™ functions
with automatic parallel support, see Function List (Automatic Parallel Support). If you select a
product that does not have functions with automatic parallel support, then the Automatic
Parallel Support filter is not available.
If a function you are interested in does not include automatic parallel support, here are some
alternatives:
• If you have a GPU, many MATLAB functions run automatically on a GPU. See “Run MATLAB
Functions on a GPU” on page 6-3.
• Any MATLAB code inside a for-loop can be made into a parallel for loop, provided the iterations
are independent. See parfor.
• If you are you looking for other ways to speed up your processing or to scale up your big data
calculation, see “Choose a Parallel Computing Solution” on page 1-5.
See Also
Related Examples
• “Specify Your Parallel Settings” on page 1-35
• “Run Code on Parallel Pools” on page 1-28
• “Scale Up from Desktop to Cluster” on page 7-49
More About
• “Run MATLAB Functions on a GPU” on page 6-3
• “Parallel for-Loops (parfor)”
• “Choose a Parallel Computing Solution” on page 1-5
1-10
Quick Start Parallel Computing in MATLAB
This table lists some essential parallel computing terms and their definitions.
Term Definition
Thread Smallest set of instructions that a CPU can
schedule and execute independently. A GPU,
multiprocessor, or multicore computer can
perform multithreading, or executing multiple
threads simultaneously.
Process Execution of an instance of a computer program
by one or many threads. Each process has its own
blocks of memory.
1-11
1 Getting Started
Term Definition
Node Standalone computer containing one or more
CPUs or GPUs. Nodes can be networked to form a
cluster or supercomputer.
Cluster Collection of interconnected computers that work
together as a unified system to provide high-
performance computing power for processing
complex and data-intensive tasks.
Scalability Increase in parallel speedup with the addition of
more resources.
Prerequisites
To run the examples on this page, you must have a Parallel Computing Toolbox license. To determine
whether you have Parallel Computing Toolbox installed, and whether your machine can create a
default parallel pool, enter this code in the MATLAB Command Window.
if canUseParallelPool
disp("Parallel Computing Toolbox is installed")
else
disp("Parallel Computing Toolbox is not installed")
end
Alternatively, to see which MathWorks products you have installed, in the Command Window, enter
ver.
Vectorization
MATLAB is optimized for operations involving matrices and vectors. The process of revising loop-
based, scalar-oriented code to use MATLAB matrix and vector operations is called vectorization.
Using vectorized code instead of loop-based operations often improves your code performance.
These code snippets compare the amount of time the software needs to calculate the square root of
1,000,000 values with loop-based code against vectorized code.
1-12
Quick Start Parallel Computing in MATLAB
Preallocation
In some cases, while- and for-loops that incrementally increase the size of an array each time
through the loop can adversely affect performance and memory use. You can preallocate the
maximum amount of space required for an array instead of continuously resizing arrays when you run
loop-based code.
These code snippets compare the amount of time the software needs to create a scalar variable x,
when you gradually increase the size of x in a for-loop against when you preallocate a 1-
by-1,000,000 block of memory for x.
This table shows the appropriate preallocation function for the type of array you want to initialize.
Some MATLAB functions implicitly use multithreading to parallelize their execution. These functions
automatically execute on multiple computational threads in a single MATLAB session, which means
they run faster on multicore-enabled machines. Some examples are linear algebra and numerical
functions such as fft, mldivide, eig, svd, and sort. Therefore, if you use these functions on a
machine with many cores, you can observe an increase in performance.
1-13
1 Getting Started
MATLAB and Parallel Computing Toolbox software uses MATLAB workers to explicitly parallelize your
code. MATLAB workers are MATLAB computational engines that run in the background without a
graphical desktop. The MATLAB session you interact with, also called the MATLAB client, instructs
the workers with parallel language functions. You use Parallel Computing Toolbox functions to
automatically divide tasks and assign them to these workers to execute the computations in parallel.
A parallel pool (parpool) is a group of MATLAB workers on which you can interactively run code.
1-14
Quick Start Parallel Computing in MATLAB
You can create a parallel pool of workers using parpool or functions with automatic parallel support.
By default, parallel language functions such as parfor, parfeval, and spmd automatically create a
parallel pool when you need one. When the workers start, your MATLAB session connects to them.
For example, this code automatically starts a parallel pool and runs the statement in the parfor-loop
in parallel on six workers.
parfor i = 1:100
c(i) = max(eig(rand(1000)));
end
You can also use the parallel status indicator in the lower left corner of MATLAB desktop to start a
parallel pool manually. Click the indicator icon, and then select Start Parallel Pool.
To stop a parallel pool while it is starting, press Ctrl+C or Ctrl+Break. On Apple macOS operating
systems, you also can use command+ (the command key and the plus key).
Starting a parallel pool often takes a long time, which can impact performance for code that takes
only a few seconds to execute. For longer running code, the overhead becomes less significant.
Your default parallel environment determines the parallel pool cluster. The default parallel
environment of your local machine is called Processes. This environment starts a parallel pool of
process workers. You can see the selection of available parallel environments in the Parallel menu on
the MATLAB Home tab.
Note For the default Processes profile, the default number of process workers is one per physical
CPU core using a single computational thread. This restriction ensures that each worker has
1-15
1 Getting Started
exclusive access to a floating-point unit, and generally optimizes performance of computational code.
If your code is not computationally intensive, for example, code that is input/output (I/O) intensive,
then consider using up to two workers per physical core. Running too many workers on too few
resources can impact the performance and stability of your machine.
This table summarizes the different ways you can create interactive parallel pools.
Parallel Computing Toolbox also supports running a parallel pool of workers that are backed by
computing threads instead of process workers. This parallel environment is called Threads. Thread
workers have reduced memory usage, faster scheduling, and lower data transfer costs. However
thread workers support only a subset of the MATLAB functions that are available to process workers.
MATLAB also supports an additional local parallel environment called backgroundPool. The
backgroundPool environment is backed by thread workers and supports running code in the
background while you run other code in your session at the same time. You can use one thread
worker in the backgroundPool environment when you do not have a Parallel Computing Toolbox
license. If you have a Parallel Computing Toolbox license, the maximum number of thread workers in
your backgroundPool is the value that the maxNumCompThreads function returns.
If you have access to onsite or cloud clusters, you can discover other clusters running on your
network or on Cloud Center by clicking Parallel > Discover Clusters and following the prompts.
Parallel pools on clusters are backed by process workers and support the full parallel language.
When you have an interactive parallel pool of workers, you can use parallel language functions to
split large problems into smaller tasks that workers can execute in parallel. To accelerate your
MATLAB code, use interactive parallel features such as parfor.
This example shows how to convert a for-loop into a parfor-loop and calculate the scalability of the
parfor-loop with the number of workers.
1-16
Quick Start Parallel Computing in MATLAB
You can convert for-loops to run in parallel by using a parfor-loop. Often, you can simply replace
for with parfor. However, you often need to adjust your code further to run in it parallel.
Mechanics of parfor-loops
When you run a parfor-loop, MATLAB executes the statements in the loop body in parallel. Each
execution of the parfor-loop body is an iteration. The MATLAB client issues the parfor command
and coordinates with the workers to execute the loop iterations in parallel on the workers in a
parallel pool. A parfor-loop can provide significantly better performance than its analogous for-loop
because several workers compute iterations simultaneously.
When you run a parfor-loop, the MATLAB client divides the loop iterations into subranges and
assigns them to the workers. If the number of workers is equal to the number of loop iterations, each
worker performs one iteration of the loop. If the number of iterations is greater than the number of
workers, some workers perform more than one loop iteration. In this case, a worker receives multiple
iterations at once to reduce communication time. The client also performs a static analysis of the
parfor-loop code to determine which data to transfer to each worker and which data to transfer
back to the client. The client sends the necessary data to the workers, which execute most of the
computation. The workers then send the results back to the client, which assembles those results.
MATLAB workers evaluate iterations in no particular order and independently of each other. Because
each iteration is independent, the iterations need not be synchronized, and often are not.
• Loop iterations are independent. When you convert your for-loop into a parfor-loop, you must
ensure that the loop iterations are independent. If your parfor code has dependence between the
loop iterations, the Code Analyzer in the MATLAB Editor detects the dependence. Executing the
parfor-loop generates an error.
• Loop execution are not in order. Because parfor-loop iterations have no guaranteed order, you
must ensure that your code that uses a parfor-loop does not rely on the output of the parfor-
loop being in order.
Convert a for-loop into a parfor-loop in code that calculates the maximum value of the singular-
value decomposition of 5000 200-by-200 random matrices by replacing for with parfor. Execute
the parfor-loop on six workers. Compare their execution times.
When you use parfor and you have Parallel Computing Toolbox software installed, MATLAB
automatically starts a parallel pool of workers. The parallel pool can take a long time to start. This
example shows a second run with the pool already started. You can observe that the parfor code
executed on six workers runs much faster than the for-loop code.
1-17
1 Getting Started
tic
y = zeros(5000,1);
for n = 1:5000
y(n) = max(svd(randn(200)));
end
toc
tic
y = zeros(5000,1);
parfor n = 1:5000
y(n) = max(svd(randn(200)));
end
toc
If the speed-up is less than you expect, you can calculate the scalability of your parfor-loop code.
Calculate Scalability
You can calculate the scalability of converting this for-loop into a parfor-loop. Use the scalability to
determine whether your parfor-loop code scales well with the number of workers, and whether a
limit exists.
Use a for-loop to iterate through different numbers of workers to run the parfor-loop. To specify
the number of workers, use the second input argument of parfor. You can modify the values in the
NumWorkers array to match your available resources.
numIterations = 5000;
numWorkers = [1 2 3 4 5 6];
t = zeros(size(numWorkers));
for w = 1:numel(numWorkers)
tic;
y = zeros(numIterations,1);
parfor (n = 1:numIterations,numWorkers(w))
y(n) = max(svd(randn(200)));
end
t(w) = toc;
end
Calculate the speedup by computing the ratio between the computation time of a single worker and
the computation time of each maximum number of workers. To calculate the efficiency of parallelizing
the tasks, divide the ideal speedup by the calculated speedup.
speedup = t(1)./t;
efficiency = (speedup./numWorkers).*100;
To visualize how the computations scale up with the number of workers, plot the speedup and
efficiency against the number of workers with the comparePlot on page 1-19 function defined at
the end of the example.
The speedup increases as the number of workers increases. Adding more workers shows a reduction
in computation time, but the scaling is not perfect because the efficiency decreases as the number of
workers increases. This is due to the overhead associated with parallelization. Parallel overhead
includes the time the software needs for communication, coordination, and data transfer from the
client to the workers and back.
1-18
Quick Start Parallel Computing in MATLAB
parfor-loops that do not have many iterations or computationally demanding tasks generally do not
scale well with an increasing number of workers because the time the software needs for data
transfer is significant compared with the time the software needs for computation.
comparePlot(numWorkers,speedup,efficiency);
After you finish your computation, you can delete the current parallel pool. Get the current parallel
pool with the gcp function.
delete(gcp)
Helper Functions
This function plots the speedup and efficiency of the parfor-loop against the number of workers.
function comparePlot(numWorkers,speedup,efficiency)
yyaxis left
1-19
1 Getting Started
plot(numWorkers,speedup,'-*')
grid on
title('Speedup and Efficiency with Number of Workers');
xlabel('Number of Workers');
xticks(numWorkers);
ylabel('Speedup');
yyaxis right
plot(numWorkers,efficiency,'--o');
ylabel('Efficiency')
xticks(numWorkers);
ylabel('Efficiency (%)');
legend('Speedup','Efficiency')
end
Several MathWorks products now offer built-in support for parallel computing products without
requiring extra coding. For the current list of these products and their parallel functionality, see
Parallel Computing Support in MATLAB and Simulink Products.
For more information about the parallel language functions and their applications, see “Choose a
Parallel Computing Solution” on page 1-5 and “Parallel Language Decision Tables” on page 1-22.
See Also
for | parfor | parfeval | gpuArray | distributed | tall | datastore | mapreduce | batch |
parsim | batchsim
Related Examples
• “Vectorization”
• “Preallocation”
• “Choose a Parallel Computing Solution” on page 1-5
• “Parallel Language Decision Tables” on page 1-22
• “Run Code on Parallel Pools” on page 1-28
• “Run MATLAB Functions with Automatic Parallel Support” on page 1-9
• “Decide When to Use parfor” on page 2-2
• “Evaluate Functions in the Background Using parfeval” on page 3-3
1-20
Quick Start Parallel Computing in MATLAB
1-21
1 Getting Started
• Use parallel language features to help you parallelize your MATLAB code. For examples of
common parallel features, see “Choose Parallel Computing Language Feature” on page 1-22.
• After you choose a parallel language feature, decide where to run your parallel MATLAB code. For
more information, see “Choose Workflow” on page 1-25.
• Some functions come with automatic parallel support. You can enable the UseParallel option
without choosing an external parallel language feature. For more information, see “Run MATLAB
Functions with Automatic Parallel Support” on page 1-9.
• Process
millions of
images in
parallel.
• Run multiple parsim Simulate a No Synchronous
simulations. dynamic system
• Test and multiple times in
optimize parallel or in
models. series.
• Design
experiments.
1-22
Parallel Language Decision Tables
1-23
1 Getting Started
1-24
Parallel Language Decision Tables
Choose Workflow
Interactive Workflow
Use an interactive workflow to execute parallel code on a parallel pool of workers using parpool. In
an interactive workflow, you can view results as soon as they are ready. However, you cannot retrieve
data after you close the current MATLAB client session.
To use an interactive workflow, call parfor, parfeval, parfevalOnAll, spmd, distributed, and
tall in your MATLAB code. These functions automatically start a parallel pool when you call them.
For more information, see “Run Code on Parallel Pools” on page 1-28.
Use gpuArray to convert an array in the MATLAB workspace to a gpuArray object. You can use any
gpuArray-enabled MATLAB function to work with the gpuArray object. For more information, see
“Run MATLAB Functions on a GPU” on page 6-3.
Batch Workflow
Use a batch workflow to offload work to a compute cluster and carry out other tasks, or to submit
long-running code for later execution. If you offload work to a remote compute cluster, you can close
the MATLAB client session while the job is processing. MATLAB stores information about batch jobs,
so you can retrieve results from a batch job later or in a new client session. To develop and test your
code, you can offload work to a local cluster on your client machine. If you close your MATLAB
session, any batch jobs using the local cluster also stop immediately.
Batch workflows support parfor, parfeval, gpuArray, spmd, distributed, and tall parallel
language features with any other MATLAB functions in a batch workflow. Submit your code as a
script or function with one of the batch parallel language features in this table. For more information,
see “Run Batch Parallel Jobs” on page 5-5.
1-25
1 Getting Started
Note Batch functions are not available in interactive parallel pools. To submit code that uses a pool
of workers for batch execution, use batch(__,Pool=...) or createCommunicatingJob.
See Also
parfor | parsim | parfeval | parfevalOnAll | gpuArray | spmd | distributed | tall | batch |
batchsim | createJob | createCommunicatingJob
1-26
Parallel Language Decision Tables
Related Examples
• “Run MATLAB Functions with Automatic Parallel Support” on page 1-9
• “Run Code on Parallel Pools” on page 1-28
• “Run Batch Parallel Jobs” on page 5-5
• “Choose a Parallel Computing Solution” on page 1-5
1-27
1 Getting Started
You can use the workers in a parallel pool interactively and the workers can communicate with each
other during the lifetime of the job. You can view your parpool jobs in the “Job Monitor” on page 5-
48. While these pool workers are reserved for your interactive use, they are not available to other
users.
In MATLAB, a parallel pool is represented by a [Link] object. You can only create a parallel
pool from one parallel environment or profile at a time, but you can partition the pool into multiple
pools, allowing for more flexible resource allocation. To learn more, see “Partition Parallel Pools to
Optimize Resource Use” on page 7-14.
You can have only one parallel pool at a time from a MATLAB client session.
1-28
Run Code on Parallel Pools
Cluster
Worker
Worker
Parallel Pool
parcluster
Worker
Worker
parpool
Worker
Worker
Worker
• parfor
• spmd
• distributed
• Composite
• parfeval
1-29
1 Getting Started
• parfevalOnAll
• gcp
• mapreduce
• mapreducer
• tall
• ticBytes and tocBytes
Your parallel settings specify which parallel environment the pool runs on. To access your settings, on
the Home tab, in the Environment section, select Parallel > Parallel Settings.
In your parallel settings, you can turn off the option for the pool to open or close automatically. If you
turn off the option to open a pool automatically and you use any Parallel Computing Toolbox
functionality without an open parallel pool, your code runs on the client.
You can use the parallel status indicator in the lower left corner of the MATLAB desktop to start a
parallel pool manually.
In MATLAB Online, the parallel status indicator is not visible by default. You must start a parallel pool
first by using parpool or any of the functions that automatically start a parallel pool.
Click the indicator icon, and select Start Parallel Pool. The pool parallel environment is specified by
your default parallel environment. Your default parallel environment is indicated by a check mark on
the Parallel > Select Parallel Environment menu.
1-30
Run Code on Parallel Pools
The parallel indicator menu options are different when a pool is running. You can:
• View the number of workers and the parallel environment the pool is running on
• Change the time until automatic shut-down
• Shut down the parallel pool
To stop a pool, you can also select Shut Down Parallel Pool.
Programming Interface
You can start and stop a parallel pool programmatically by using default settings or specifying
alternatives.
parpool
parpool(4)
To use a parallel environment other than your default and specify where the pool runs:
parpool('MyProfile',4)
You can run a parallel pool on different parallel environments. For more information, see “Choose
Between Thread-Based and Process-Based Environments” on page 1-43.
To get the current parallel pool and use that object when you want to shut down the pool:
p = gcp;
delete(p)
1-31
1 Getting Started
When you issue the command gcp without arguments, you might inadvertently open a pool. To avoid
this problem:
delete(gcp('nocreate'))
Note To stop a parallel pool while it is starting, press Ctrl+C or Ctrl+Break. On Apple macOS, you
also can use Command. (the Command key and the period key).
NumWorkers Property
The NumWorkers property is a hard limit on the number of workers available to the cluster or local
machine.
• For MATLAB Job Scheduler clusters, the software determines the NumWorkers property value
from the number of workers running in the cluster.
• For third-party scheduler clusters and the local machine Processes and Threads, you can specify
the NumWorkers property value in the profile.
You cannot create a parallel pool larger than the NumWorkers property value.
PreferredPoolNumWorkers Property
The PreferredPoolNumWorkers property specifies a preference for the size of the pools the
software creates with the profile. It is not a requirement or a request for a specific number of
workers. The default value for the PreferredPoolNumWorkers property depends on the parallel
environment. You can modify this value in the profile. The following is a list of parallel environments
and their default PreferredPoolNumWorkers values:
1-32
Run Code on Parallel Pools
1 The parpool resources argument overrides the default profile setting and uses the parallel
environment identified by the profile "MyProfile".
p = parpool("MyProfile");
2 The parallel environment is specified in the default profile.
p = parpool;
See Also
delete | gcp | parcluster | parfor | spmd | distributed | parfeval | parpool
Related Examples
• “Run MATLAB Functions with Automatic Parallel Support” on page 1-9
1-33
1 Getting Started
More About
• “How Parallel Computing Software Runs a Job” on page 5-50
• “Decide When to Use parfor” on page 2-2
• “Specify Your Parallel Settings” on page 1-35
• “Discover Clusters and Use Cluster Profiles” on page 7-2
• “Scale Up parfor-Loops to Cluster and Cloud” on page 2-55
1-34
Specify Your Parallel Settings
You can access your parallel settings in one of the following ways:
• On the Home tab in the Environment section, select Parallel > Parallel Settings
Click the desktop pool indicator icon and select Parallel Preferences
• In the command window, enter preferences.
preferences
In the left pane of the Settings window, select Parallel Computing Toolbox.
• Default Profile — Choose the profile you want to use. The default profile is Processes. For more
information, see “Add and Modify Cluster Profiles” on page 7-5.
• Preferred number of workers — Specify the number of workers in your parallel pool. The actual
pool size is limited by licensing, cluster size, and cluster profile settings. For more details, see
“Factors That Affect Pool Size” on page 1-32. For the Processes profile, do not choose a
preferred number of workers larger than 512. See also “Add and Modify Cluster Profiles” on page
7-5. Check your access to cloud clusters from the Parallel > Discover Clusters menu.
• Automatically create a parallel pool — If a parallel pool is not open, some functionality in
Parallel Computing Toolbox and other products will automatically create a parallel pool, including:
• parfor
• spmd
• distributed
1-35
1 Getting Started
• Composite
• parfeval
• parfevalOnAll
• afterEach
• afterAll
• gcp
• mapreduce
• mapreducer
• parsim
When these functions are used, select Automatically create a parallel pool to create a pool
automatically. If you select this option, you do not need to open a pool manually using the
parpool function. To learn more about automatic parallel support, see “Run MATLAB Functions
with Automatic Parallel Support” on page 1-9.
If this option is not selected, a pool is not open, and you use any Parallel Computing Toolbox
functionality, your code will run on the client.
• Shut down and delete a parallel pool — To shut down a parallel pool automatically if the pool
has been idle for the specified amount of time, use the IdleTimeout setting. If you use the pool
(for example, using parfor or parfeval), the timeout counter is reset. When the timeout is
about to expire, a tooltip on the desktop pool indicator warns you and allows you to reset the
timer. Note that modifying this setting changes the IdleTimeout of any already started pool.
See Also
Related Examples
• “Run MATLAB Functions with Automatic Parallel Support” on page 1-9
• “Scale Up from Desktop to Cluster” on page 7-49
More About
• “Decide When to Use parfor” on page 2-2
• “Scale Up parfor-Loops to Cluster and Cloud” on page 2-55
• “Add and Modify Cluster Profiles” on page 7-5
1-36
Choose How to Manage Data in Parallel Computing
Use this table to identify some goals for transferring data from the client to workers and discover
recommended workflows.
1-37
1 Getting Started
Create a [Link]
object at the worker, and send this object back to
the client. Then you can use the
PollableDataQueue object to send a message
to the worker. For an example of this workflow,
see “Receive Communication on Workers” on
page 3-23.
1-38
Choose How to Manage Data in Parallel Computing
Use this table to identify some goals for transferring data between workers and discover
recommended workflows.
Use this table to identify some goals for transferring data from a worker to a client and discover
recommended workflows.
1-39
1 Getting Started
Use this table to identify some goals for transferring data from a worker during execution and
discover recommended workflows.
DataQueue and ValueStore are two objects in Parallel Computing Toolbox you can use transfer
data between client and workers. The DataQueue object passes data from workers to the client in a
first-in, first-out (FIFO) order, while ValueStore stores data that multiple workers as well as the
client can access and update. You can use both objects for asynchronous data transfer to the client.
However, DataQueue is only supported on interactive parallel pools.
The choice between DataQueue and ValueStore depends on the data access pattern you require in
your parallel application. If you have many independent tasks that workers can execute in any order,
and you want to pass data to the client in a streaming fashion, then use a DataQueue object.
1-40
Choose How to Manage Data in Parallel Computing
However, if you want to store and share values to multiple workers and access or update it at any
time, then use ValueStore instead.
Use the fetchOutputs function to retrieve the output arguments of a Future object, which the
software returns when you run a parfeval or parfevalOnAll computation. fetchOutputs blocks
the client until the computation is complete, then sends the results of the parfeval or
parfevalOnAll computation to the client. In contrast, you can use ValueStore to store and
retrieve values from any parallel computation and also retrieve intermediate results as they are
produced without blocking the program. Additionally, the ValueStore object is not held in system
memory, so you can store large results in the ValueStore. However, be careful when storing large
amounts of data to avoid filling up the disk space on the cluster.
If you only need to retrieve the output of a parfeval or parfevalOnAll computation, then
fetchOutputs is the simpler option. However, if you want to store and access the results of multiple
independent parallel computations, then use ValueStore. In cases where you have multiple
parfeval computations generating large amounts of data, using the pool ValueStore object can
help avoid memory issues on the client. You can temporarily save the results in the ValueStore and
retrieve them when you need them.
load, fetchOutputs (Jobs), and ValueStore provide different ways of transferring data from
jobs back to the client.
load retrieves the variables related to a job you create when you use the batch function to run a
script or an expression. This includes any input arguments you provide and temporary variables the
workers create during the computation. load does not retrieve the variables from batch jobs that
run a function and you cannot retrieve results while the job is running. fetchOutputs (Jobs)
retrieves the output arguments contained in the tasks of a finished job you create using the batch,
createJob or createCommunicatingJob functions. If the job is still running when you call the
fetchOutputs (Jobs) function, the fetchOutputs (Jobs) function returns an error.
When you create a job on a cluster, the software automatically creates a ValueStore object for the
job, and you can use it to store data generated during job execution. Unlike the load and
fetchOutputs functions, the ValueStore object does not automatically store data. Instead, you
must manually add data as key-value pairs to the ValueStore object. Workers can store data in the
ValueStore object that the MATLAB client can retrieve during the job execution. Additionally, the
ValueStore object is not held in system memory, so you can store large results in the store.
To retrieve the results of a job after the job has finished, use the load or fetchOutputs (Jobs)
function. To access the results or track the progress of a job while it is still running, or to store
potentially high memory results, use the ValueStore object
AdditionalPaths, AttachedFiles, and AutoAttachedFiles are all parallel job properties that
you can use to specify additional files and directories that are required to run parallel code on
workers.
AdditionalPaths is a property you can use to add cluster file locations to the MATLAB path on all
workers running your job. This can be useful if you have files with large data stored on the cluster
storage, functions or libraries that are required by the workers, but are not on the MATLAB path by
default.
1-41
1 Getting Started
The AttachedFiles property allows you to specify files or directories that are required by the
workers but are not stored on the cluster storage. These files are copied to a temporary directory on
each worker before the parallel code runs. The files can be scripts, functions, or data files, and must
be located within the directory structure of the client.
Use the AutoAttachedFiles property to allow files needed by the workers to be automatically
attached to the job. When you submit a job or task, MATLAB performs dependency analysis on all the
task functions, or on the batch job script or function. Then it automatically adds the files required to
the job or task object so they are transferred to the workers. Essentially, you only want to set the
AutoAttachedFiles property to false if you know that you do not need the software to identify
the files for you. For example, if the files your job is going to use are already present on the cluster,
perhaps inside one of the AdditionalPaths locations.
Use AdditionalPaths when you have functions and libraries stored on the cluster that are required
on all workers. Use AttachedFiles when you have small files that are required to run your code. To
let MATLAB automatically determine if a job requires additional files to run, set the
AutoAttachedFiles property to true.
See Also
ValueStore | FileStore | [Link] | [Link] |
spmdSend | spmdReceive | spmdSendReceive | spmdBarrier | fetchOutputs | fetchOutputs |
load | [Link]
Related Examples
• “Share Code with Workers” on page 5-11
• “Programming Tips” on page 8-81
1-42
Choose Between Thread-Based and Process-Based Environments
Note that thread-based environments support only a subset of the MATLAB functions available for
process workers. If you are interested in a function that is not supported, let the MathWorks
Technical Support team know. For more information on support, see “Check Support for Thread-
Based Environment” on page 1-50.
1-43
1 Getting Started
1-44
Choose Between Thread-Based and Process-Based Environments
• To use parallel pool features, such as parfor or parfeval, create a parallel pool in the chosen
environment by using the parpool function.
1-45
1 Getting Started
X = rand(10000, 10000);
pool = parpool('Processes');
Time the execution and measure data transfer of some parallel code. For this example, use a
parfeval execution.
ticBytes(pool);
tProcesses = timeit(@() fetchOutputs(parfeval(@sum,1,X,'all')))
tocBytes(pool)
tProcesses = 3.9060
BytesSentToWorkers BytesReceivedFromWorkers
__________________ ________________________
1 0 0
2 0 0
3 0 0
4 0 0
5 5.6e+09 16254
6 0 0
Total 5.6e+09 16254
Note that the data transfer is significant. To avoid incurring data transfer costs, you can use thread
workers. Delete the current parallel pool and create a thread-based parallel pool.
delete(pool);
pool = parpool('Threads');
tThreads = 0.0232
1-46
Choose Between Thread-Based and Process-Based Environments
Thread workers outperform process workers because thread workers can use the data X without
copying it, and they have less scheduling overhead.
This example shows how to use a process-based and thread-based pool to solve an optimization
problem in parallel.
Thread-based pools are optimized for less data transfer, faster scheduling, and reduced memory
usage, so they can result in a performance gain in your applications.
Problem Description
The problem is to change the position and angle of a cannon to fire a projectile as far as possible
beyond a wall. The cannon has a muzzle velocity of 300 m/s. The wall is 20 m high. If the cannon is
too close to the wall, it fires at too steep an angle, and the projectile does not travel far enough. If the
cannon is too far from the wall, the projectile does not travel far enough. For full problem details, see
“Optimize ODEs in Parallel” (Global Optimization Toolbox) or the latter part of the video Surrogate
Optimization.
To solve the problem, call the patternsearch solver from Global Optimization Toolbox. The
objective function is in the cannonobjective helper function, which calculates the distance the
projectile lands beyond the wall for a given position and angle. The constraint is in the
cannonconstraint helper function, which calculates whether the projectile hits the wall, or even
reaches the wall before hitting the ground. The helper functions are in separate files that you can
view when you run this example.
Set the following inputs for the patternsearch solver. Note that, to use Parallel Computing Toolbox,
you must set 'UseParallel' to true in the optimization options.
lb = [-200;0.05];
ub = [-1;pi/2-.05];
x0 = [-30,pi/3];
opts = optimoptions('patternsearch',...
'UseCompletePoll', true, ...
'Display','off',...
'UseParallel',true);
% No linear constraints, so set these inputs to empty:
A = [];
b = [];
Aeq = [];
beq = [];
1-47
1 Getting Started
To reproduce the same computations later, seed the random generator with the default value.
rng default;
Use a loop to solve the problem several times and average the results.
tProcesses = zeros(5,1);
for repetition = 1:numel(tProcesses)
tic
[xsolution,distance,eflag,outpt] = patternsearch(@cannonobjective,x0, ...
A,b,Aeq,beq,lb,ub,@cannonconstraint,opts);
tProcesses(repetition) = toc;
end
tProcesses = mean(tProcesses)
tProcesses = 2.7677
To prepare for the comparison with a thread-based pool, delete the current parallel pool.
delete(p);
Restore the random number generator to default settings and run the same code as before.
rng default
tThreads = zeros(5,1);
for repetition = 1:numel(tThreads)
tic
[xsolution,distance,eflag,outpt] = patternsearch(@cannonobjective,x0, ...
A,b,Aeq,beq,lb,ub,@cannonconstraint,opts);
tThreads(repetition) = toc;
end
tThreads = mean(tThreads)
tThreads = 1.5790
In this example, thread workers are 1.75x faster than process workers.
Notice the performance gain due to the optimizations of the thread-based pool.
When you are done with computations, delete the parallel pool.
1-48
Choose Between Thread-Based and Process-Based Environments
delete(p);
• Because thread workers can share memory, they can access numeric data without copying, so they
are more memory efficient.
• Communication between threads is less time consuming. Therefore, the overhead of scheduling a
task or inter-worker communication is smaller.
When you use thread-based environments, keep the following considerations in mind.
• Check that your code is supported for a thread-based environment. For more information, see
“Check Support for Thread-Based Environment” on page 1-50.
• If you are using external libraries from workers, then you must ensure that the library functions
are thread-safe.
1-49
1 Getting Started
• They support all language features and are backward compatible with previous releases.
• They are more robust in the event of crashes. If a process worker crashes, then the MATLAB client
does not crash. If a process worker crashes and your code does not use spmd or distributed
arrays, then the rest of the workers can continue running.
• If you use external libraries from workers, then you do not need to pay attention to thread-safety.
• You can use cluster features, such as batch.
When you use a process-based environment, keep the following consideration in mind.
• If your code accesses files from workers, then you must use additional options, such as
'AttachedFiles' or 'AdditionalPaths', to make the data accessible.
Thread workers are supported in standalone applications created using MATLAB Compiler™ and web
apps hosted on MATLAB Web App Server™.
For more information about functions supported on thread workers, see “Run MATLAB Functions in
Thread-Based Environment”.
See Also
parpool | parcluster
Related Examples
• “Run Code on Parallel Pools” on page 1-28
1-50
Try Parallel Computing Methods
This example shows how to accelerate your MATLAB® code using parallel computing. Try the
example to see how to begin using parallel computing in MATLAB.
This graph shows the execution times for three parallel computing methods compared to serial
computing when running the algorithm used in this example. Your results will depend on your
hardware.
Develop Algorithm
Start by prototyping your algorithm. In this example, you use the computePi function to run a Monte
Carlo algorithm that estimates the value of π.
For more details estimating π using a Monte Carlo algorithm, see the Simple Monte Carlo Area
Method on page 1-55 section.
1-51
1 Getting Started
for i = 1:n
% Generate random points.
x = rand(m,1);
y = rand(m,1);
m = 3e5;
n = 1e3;
piEst = computePi(m,n)
piEst =
3.1415
Use the timeit function to measure the time required to run the computePi function.
timeSerial =
5.4936
You can accelerate this algorithm using parallel processing. In this section, you make minor changes
to the code to make it run using three parallel computing methods. You then assess which parallel
processing method is most suitable for accelerating the algorithm.
Parfor Method
If your algorithm contains a for-loop and the order of the iterations is not relevant, then converting
the for-loop to a parfor-loop is usually the easiest way to parallelize your code.
Define a new function, computePiParfor, that estimates π using a parfor-loop instead of a for-
loop.
parfor i = 1:n
% Generate random points.
x = rand(m,1);
y = rand(m,1);
1-52
Try Parallel Computing Methods
end
Start a thread-based parallel pool. By default, MATLAB starts a pool with one worker per physical
core on your local machine.
pool = parpool("Threads");
timeParfor =
1.0548
Using a parfor-loop significantly accelerates the algorithm with minimal changes to the code.
Parfeval Method
Define a function, calculatePoints, that generates m random points and determines whether the
points are inside the unit circle. This function corresponds to a single iteration of the for-loop in the
original computePi function.
Define a function, computePiParfeval, that estimates π using parfeval. This function calls
parfeval in a for-loop to execute the calculatePoints function n times on the workers in the
parallel pool. The function then uses the results to generate an estimate of π. Each worker has an
independent random number stream, so calls to rand produce a unique sequence of random numbers
on each worker. For more information about controlling random number generation on workers, see
“Control Random Number Streams on Workers” on page 5-15.
for i = 1:n
f(i) = parfeval(@calculatePoints,1,m);
end
output = fetchOutputs(f);
piEst = 4/(m*n) * sum(output);
end
1-53
1 Getting Started
timeParfeval =
1.3845
As you can see from the timing, parfeval is not well-suited to this problem as it is currently
formulated because the calculatePoints function runs too quickly, resulting in significant
communication and scheduling overheads. However, parfeval is well-suited for problems with a
known desired result but for which it is unknown how many iterations it might take to achieve the
result. For example, if you want to iteratively refine an estimate of πuntil the solution stops
improving, you could use parfeval to queue 10,000 iterations and, when the goal is reached, you
can cancel all the remaining iterations. An improved function that calculates π using parfeval,
computePiParfevalImproved, is attached to this example as a supporting file. Open this example
as a live script to access the supporting file.
GPU Method
If you have a supported GPU, you can accelerate your code by running it on the GPU. For more
information about supported GPUs, see “GPU Computing Requirements” on page 6-13.
gpu = gpuDevice;
disp([Link] + " GPU selected.")
Define a new function, computePiGPU, that estimates π on a GPU. Many functions in MATLAB and
other toolboxes run automatically on a GPU if you supply a gpuArray data argument. The
computePiGPU function generates the random points as gpuArray data, and then subsequent
calculations are performed on the GPU automatically.
function piEst = computePiGPU(m,n)
c = zeros(1,"gpuArray");
for i = 1:n
% Generate random points on the GPU.
x = rand(m,1,"gpuArray");
y = rand(m,1,"gpuArray");
piEst = 4/(m*n) * c;
end
Use the gputimeit function to measure the time required to run the computePiGPU function. The
gputimeit function is preferable to timeit for functions that use the GPU, because it ensures that
all operations on the GPU have finished before recording the time and it compensates for the
overhead.
timeGPU = gputimeit(@() computePiGPU(m,n))
timeGPU =
0.2079
You can further accelerate this code on a GPU by vectorizing the for-loop. Vectorization is the
process of revising loop-based code to use MATLAB matrix and vector operations. Vectorizing code is
1-54
Try Parallel Computing Methods
particularly effective in accelerated code that runs on a GPU, as GPUs are generally more effective
when performing a large numberof operations. An improved function that calculates π on a GPU
using vectorized code, computePiGPUVectorized, is attached to this example as a supporting file.
Open this example as a live script to access the supporting file.
Compare the execution times of the parallel methods to the serial execution.
figure
bar([timeSerial timeParfor timeParfeval timeGPU])
xlabel("Execution Type")
xticklabels(["Serial" "Parfor" "Parfeval" "GPU"])
ylabel("Execution Time (s)")
grid on
The execution times for the three parallel computing methods are significantly faster compared to
serial computing when running the algorithm used in this example. Your results will depend on your
hardware.
Given a circle with radius r inscribed within a square with sides of length 2r , the area of the circle is
related to the area of the square by π. This figure illustrates the problem.
1-55
1 Getting Started
You can derive π from the ratio of the area of the circle divided by the area of the square:
area of circle
area of square
=
1-56
Try Parallel Computing Methods
πr 2 π
2
= 4
2r
To estimate the area of the circle without using π directly, randomly generate a uniform sample of
points inside the square and count how many of the points are inside the circle. The probability that a
point can be found in the circle is the ratio of the area of the circle divided by the area of the square.
To determine whether a point is inside the circle, randomly generate two values for the x- and y-
coordinates of a point and calculate the distance between the point and the origin of the circle. The
distance d from the origin to the generated point is given by this equation:
d= x2 + y2
If d is less than the radius r of the circle, the point is inside the circle. Generate a large sample of
points and count how many are inside the circle. Use this data to obtain a ratio of points inside the
circle to the total number of points generated. This ratio is equivalent to the ratio of the area of the
circle to the area of the square. You can then estimate π using:
points in circle π
total number of points
≈ 4
points in circle
π ≈4×
total number of points
See Also
parfor | parfeval | gpuArray
Related Examples
• “Choose a Parallel Computing Solution” on page 1-5
• “Parallel Language Decision Tables” on page 1-22
1-57
1 Getting Started
• Write portable parallel code that runs in serial without Parallel Computing Toolbox.
• Write code that runs in the background without Parallel Computing Toolbox and uses more
parallel resources if you have Parallel Computing Toolbox.
• Write custom portable parallel code that runs in the background without Parallel Computing
Toolbox and uses more parallel resources if you have Parallel Computing Toolbox.
• parfor
• parfeval and parfevalOnAll
• DataQueue and PollableDataQueue
• afterEach and afterAll
• Constant
To write portable parallel code designed to use parallel pools or clusters if you have Parallel
Computing Toolbox, use parallel language syntaxes with automatic parallel support. These syntaxes
run in serial if you do not have Parallel Computing Toolbox.
To write portable parallel code that automatically runs in serial if you do not have Parallel Computing
Toolbox, do not specify a pool argument for these language features.
As a best practice, specify the pool argument for Parallel Computing Toolbox functionality only if you
need to specify an environment to run your code. If you do not specify a pool argument for parallel
functionality, the functionality runs:
If you do not have a parallel pool open and automatic pool creation is enabled, you open a pool using
the default cluster profile. For more information on setting your default cluster profile, see “Discover
Clusters and Use Cluster Profiles” on page 7-2.
Use parfeval without a pool to asynchronously run magic(3) and return one output. The function
runs in serial if you do not have Parallel Computing Toolbox.
1-58
Write Portable Parallel Code
f = parfeval(@magic,1,3)
Use a parfor-loop without a pool to run magic with different matrix sizes. The loop runs in serial if
you do not have Parallel Computing Toolbox.
parfor i = 1:10
A{i} = magic(i);
end
For information about parallel language syntaxes that run in serial without Parallel Computing
Toolbox, see “Run Parallel Language in Serial”.
For more information about your calculations in the background automatically scaling up, see “Run
MATLAB Functions in Thread-Based Environment”.
Note When you run a parfor-loop using the background pool, MATLAB suspends execution until the
loop is finished. As the code still runs in the background, you can use only functionality that is
supported in a thread-based environment.
When you run multiple functions in the background using parfeval and backgroundPool, your
code scales up to use more available cores. Use parfeval to run rand in the background 20 times.
for i = 1:20
f(i) = parfeval(backgroundPool,@rand,1);
end
To run a parfor-loop in the background, specify backgroundPool as the pool argument for
parforOptions, then use the result as the opts arguments for parfor.
• You are unable to automatically start a ThreadPool to run your parallel code
• Your code runs in serial if you do not have Parallel Computing Toolbox
The selectPool function below returns either the background pool or a parallel pool. You can use
selectPool as the pool argument with parallel language features such as parfeval and
1-59
1 Getting Started
parforOptions. If you have Parallel Computing Toolbox and have automatic parallel pool creation
enabled, the function returns a parallel pool. Otherwise, it returns the background pool.
1-60
Parallel Computing Support in MathWorks Products
Most MathWorks products enable you to run applications in parallel. For example, Simulink models
can run simultaneously in parallel, as described in “Running Multiple Simulations” (Simulink).
MATLAB Compiler and MATLAB Compiler SDK™ software let you build and deploy parallel
applications; for example, see the “Parallel Computing” section of MATLAB Compiler “Standalone
Applications” (MATLAB Compiler).
Several MathWorks products now offer built-in support for the parallel computing products, without
requiring extra coding. For the current list of these products and their parallel functionality, see
Parallel Computing Support in MATLAB and Simulink Products.
1-61
1 Getting Started
To use Parallel Computing Toolbox functionality in MATLAB Online, you must have access to a Cloud
Center cluster. You can:
• Create a cloud cluster. For more information, see “Create Cloud Cluster” on page 7-5.
• Discover an existing cluster. For more information, see “Discover Clusters” on page 7-3. You can
only discover Cloud Center clusters in your MathWorks Account.
• Import a cloud cluster profile. For more information, see “Import and Export Cluster Profiles” on
page 7-9. Note that if the profile is not in your MATLAB Drive™, you must upload it first. On the
Home tab, in the File area, click Upload.
After you set up a cloud cluster, you can use parallel language functions, such as parfor or
parfeval. Note that if you do not have any clusters set up, then parallel functions that require a
parallel pool run in serial or throw an error.
• The parallel status indicator is not visible by default. You must start a parallel pool first by using
parpool or any function that automatically start a parallel pool.
• mpiprofile viewer is not supported in MATLAB Online.
See Also
Related Examples
• “Run Code on Parallel Pools” on page 1-28
1-62
Determine Product Installation and Versions
ver
When you enter this command, MATLAB displays information about the version of MATLAB you are
running, including a list of all toolboxes installed on your system and their version numbers.
If you want to run your applications on a cluster, see your system administrator to verify that the
version of Parallel Computing Toolbox you are using is the same as the version of MATLAB Parallel
Server installed on your cluster.
1-63
2
Parallel Computing Toolbox supports interactive parallel computing and enables you to accelerate
your workflow by running on multiple workers in a parallel pool. Use parfor to execute for-loop
iterations in parallel on workers in a parallel pool. When you have profiled your code and identified
slow for-loops, try parfor to increase your throughput. Develop parfor-loops on your desktop and
scale up to a cluster without changing your code.
parfor-Loops in MATLAB
A parfor-loop in MATLAB executes a series of statements in the loop body in parallel. The MATLAB
client issues the parfor command and coordinates with MATLAB workers to execute the loop
iterations in parallel on the workers in a parallel pool. The client sends the necessary data on which
parfor operates to workers, where most of the computation is executed. The results are sent back to
the client and assembled.
A parfor-loop can provide significantly better performance than its analogous for-loop, because
several MATLAB workers can compute simultaneously on the same loop.
Each execution of the body of a parfor-loop is an iteration. MATLAB workers evaluate iterations in
no particular order and independently of each other. Because each iteration is independent, there is
no guarantee that the iterations are synchronized in any way, nor is there any need for this. If the
number of workers is equal to the number of loop iterations, each worker performs one iteration of
the loop. If there are more iterations than workers, some workers perform more than one loop
iteration; in this case, a worker might receive multiple iterations at once to reduce communication
time.
• Some loop iterations that take a long time to execute. In this case, the workers can execute the
long iterations simultaneously. Make sure that the number of iterations exceeds the number of
workers. Otherwise, you will not use all workers available.
• Many loop iterations of a simple calculation, such as a Monte Carlo simulation or a parameter
sweep. parfor divides the loop iterations into groups so that each worker executes some portion
of the total number of iterations.
• Multiple GPUs and your computations use GPU-enabled functions. For more information about
using multiple GPUs in a parfor-loop, see “Run MATLAB Functions on Multiple GPUs” on page 6-
19.
• Code that has vectorized out the for-loops. Generally, if you want to make code run faster, first try
to vectorize it. For details how to do this, see “Vectorization”. Vectorizing code allows you to
benefit from the built-in parallelism provided by the multithreaded nature of many of the
underlying MATLAB libraries. However, if you have vectorized code and you have access only to
local workers, then parfor-loops may run slower than for-loops. Do not devectorize code to
allow for parfor; in general, this solution does not work well.
2-2
Decide When to Use parfor
• Loop iterations that take a short time to execute. In this case, parallel overhead dominates your
calculation.
• Loop iterations that all use the same GPU. GPUs contain many microprocessors that can perform
computations in parallel and trying to further parallelize GPU computations using a parfor-loop
is unlikely to speed up your code.
You cannot use a parfor-loop when an iteration in your loop depends on the results of other
iterations. Each iteration must be independent of all others. For help dealing with independent loops,
see “Ensure That parfor-Loop Iterations Are Independent” on page 2-10. The exception to this rule
is to accumulate values in a loop using “Reduction Variables” on page 2-35.
In deciding when to use parfor, consider parallel overhead. Parallel overhead includes the time
required for communication, coordination and data transfer — sending and receiving data — from
client to workers and back. If iteration evaluations are fast, this overhead could be a significant part
of the total time. Consider two different types of loop iterations:
• for-loops with a computationally demanding task. These loops are generally good candidates for
conversion into a parfor-loop, because the time needed for computation dominates the time
required for data transfer.
• for-loops with a simple computational task. These loops generally do not benefit from conversion
into a parfor-loop, because the time needed for data transfer is significant compared with the
time needed for computation.
This example calculates the spectral radius of a matrix and converts a for-loop into a parfor-loop.
Find out how to measure the resulting speedup and how much data is transferred to and from the
workers in the parallel pool.
1 In the MATLAB Editor, enter the following for-loop. Add tic and toc to measure the
computation time.
tic
n = 200;
A = 500;
2-3
2 Parallel for-Loops (parfor)
a = zeros(1,n);
for i = 1:n
a(i) = max(abs(eig(rand(A))));
end
toc
2 Run the script, and note the elapsed time.
Elapsed time is 31.935373 seconds.
3 In the script, replace the for-loop with a parfor-loop. Add ticBytes and tocBytes to
measure how much data is transferred to and from the workers in the parallel pool.
tic
ticBytes(gcp);
n = 200;
A = 500;
a = zeros(1,n);
parfor i = 1:n
a(i) = max(abs(eig(rand(A))));
end
tocBytes(gcp)
toc
4 Run the new script on four workers, and run it again. Note that the first run is slower than the
second run, because the parallel pool takes some time to start and make the code available to the
workers. Note the data transfer and elapsed time for the second run.
By default, MATLAB automatically opens a parallel pool of workers on your local machine.
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
...
BytesSentToWorkers BytesReceivedFromWorkers
__________________ ________________________
1 15340 7024
2 13328 5712
3 13328 5704
4 13328 5728
Total 55324 24168
The parfor run on four workers is about three times faster than the corresponding for-loop
calculation. The speed-up is smaller than the ideal speed-up of a factor of four on four workers.
This is due to parallel overhead, including the time required to transfer data from the client to
the workers and back. Use the ticBytes and tocBytes results to examine the amount of data
transferred. Assume that the time required for data transfer is proportional to the size of the
data. This approximation allows you to get an indication of the time required for data transfer,
and to compare your parallel overhead with other parfor-loop iterations. In this example, the
data transfer and parallel overhead are small in comparison with the next example.
The current example has a low parallel overhead and benefits from conversion into a parfor-loop.
Compare this example with the simple loop iteration in the next example, see “Example of parfor with
High Parallel Overhead” on page 2-4.
For another example of a parfor-loop with computationally demanding tasks, see “Nested parfor and
for-Loops and Other parfor Requirements” on page 2-13
2-4
Decide When to Use parfor
long to execute and you do not notice an increase in execution speed. This example has a high
parallel overhead and does not benefit from conversion into a parfor-loop.
1 Write a loop to create a sine wave. Use tic and toc to measure the time elapsed.
tic
n = 1024;
A = zeros(n);
for i = 1:n
A(i,:) = (1:n) .* sin(i*2*pi/1024);
end
toc
tic
ticBytes(gcp);
n = 1024;
A = zeros(n);
parfor (i = 1:n)
A(i,:) = (1:n) .* sin(i*2*pi/1024);
end
tocBytes(gcp)
toc
3 Run the script on four workers and run the code again. Note that the first run is slower than the
second run, because the parallel pool takes some time to start and make the code available to the
workers. Note the data transfer and elapsed time for the second run.
BytesSentToWorkers BytesReceivedFromWorkers
__________________ ________________________
1 13176 2.0615e+06
2 15188 2.0874e+06
3 13176 2.4056e+06
4 13176 1.8567e+06
Total 54716 8.4112e+06
Note that the elapsed time is much smaller for the serial for-loop than for the parfor-loop on
four workers. In this case, you do not benefit from turning your for-loop into a parfor-loop. The
reason is that the transfer of data is much greater than in the previous example, see “Example of
parfor with Low Parallel Overhead” on page 2-3. In the current example, the parallel overhead
dominates the computing time. Therefore the sine wave iteration does not benefit from
conversion into a parfor-loop.
This example illustrates why high parallel overhead calculations do not benefit from conversion into a
parfor-loop. To learn more about speeding up your code, see “Convert for-Loops into parfor-Loops”
on page 2-7
See Also
parfor | ticBytes | tocBytes
2-5
2 Parallel for-Loops (parfor)
Related Examples
• “Interactively Run Loops in Parallel Using parfor” on page 2-43
• “Convert for-Loops into parfor-Loops” on page 2-7
• “Ensure That parfor-Loop Iterations Are Independent” on page 2-10
• “Nested parfor and for-Loops and Other parfor Requirements” on page 2-13
• “Scale Up parfor-Loops to Cluster and Cloud” on page 2-55
2-6
Convert for-Loops into parfor-Loops
for x = 0:0.1:1
for y = 2:10
A(y) = A(y-1) + y;
end
end
To speed up the code, try to convert the for-loops to parfor-loops. Observe that this code produces
errors.
parfor x = 0:0.1:1
parfor y = 2:10
A(y) = A(y-1) + y;
end
end
In this case you cannot simply convert the for-loops to parfor-loops without modification. To make
this work, you must change the code in several places. To diagnose the problems, look for Code
Analyzer messages in the MATLAB Editor.
This code shows common problems when you try to convert for-loops to parfor-loops.
2-7
2 Parallel for-Loops (parfor)
To solve these problems, you must modify the code to use parfor. The body of the parfor-loop is
executed in a parallel pool using multiple MATLAB workers in a nondeterministic order. Therefore,
you have to meet these requirements for the body of the parfor-loop:
1 The body of the parfor-loop must be independent. One loop iteration cannot depend on a
previous iteration, because the iterations are executed in parallel in a nondeterministic order. In
the example,
A(y) = A(y-1) + y;
is not independent, and therefore you cannot use parfor. For next steps in dealing with
independence issues, see “Ensure That parfor-Loop Iterations Are Independent” on page 2-10.
2 You cannot nest a parfor-loop inside another parfor-loop. The example has two nested for-
loops, and therefore you can replace only one for-loop with a parfor-loop. Instead, you can call
a function that uses a parfor-loop inside the body of the other parfor-loop. However, such
nested parfor-loops give you no computational benefit, because all workers are used to
parallelize the outermost loop. For help dealing with nested loops, see “Nested parfor and for-
Loops and Other parfor Requirements” on page 2-13.
3 parfor-loop variables must be consecutive increasing integers. In the example,
parfor x = 0:0.1:1
has non-integer loop variables, and therefore you cannot use parfor here. You can solve this
problem by changing the value of the loop variable to integer values required by the algorithm.
For next steps in troubleshooting parfor-loop variables, see “Ensure That parfor-Loop Variables
Are Consecutive Increasing Integers” on page 2-21.
4 You cannot break out of a parfor-loop early, as you can in a for-loop. Do not include a return or
break statement in the body of your parfor-loop. Without communication, the other MATLAB
instances running the loop do not know when to stop. As an alternative, consider parfeval.
If you still have problems converting for-loops to parfor-loops, see “Troubleshoot Variables in
parfor-Loops” on page 2-21.
Tip You can profile a parfor-loops using tic and toc to measure the speedup compared to the
corresponding for-loop. Use ticBytes and tocBytes to measure how much data is transferred to
and from the workers in the parallel pool. For more information and examples, see “Profiling parfor-
loops” on page 2-46.
2-8
Convert for-Loops into parfor-Loops
See Also
parfor | ticBytes | tocBytes
Related Examples
• “Decide When to Use parfor” on page 2-2
• “Ensure That parfor-Loop Iterations Are Independent” on page 2-10
• “Nested parfor and for-Loops and Other parfor Requirements” on page 2-13
• “Troubleshoot Variables in parfor-Loops” on page 2-21
2-9
2 Parallel for-Loops (parfor)
The following example produces equivalent results, using a for-loop on the left and a parfor-loop
on the right. Try the example in your MATLAB Command Window:
clear A clear A
for i = 1:8 parfor i = 1:8
A(i) = i; A(i) = i;
end end
A A
A = A =
1 2 3 4 5 6 7 81 2 3 4 5 6 7 8
Each element of A is equal to its index. The parfor-loop works because each element is determined
by the indexed loop variable only and does not depend on other variables. for-loops with
independent tasks are ideal candidates for parfor-loops.
Note By default, parfor automatically starts a parallel pool of workers, if you have not started one
already. parfor creates a pool using your default cluster profile, if you have set your parallel settings
accordingly.
In the example, the array elements are available in the client workspace after the parfor-loop,
exactly as with a for-loop.
Now use a nonindexed variable inside the loop, or a variable whose indexing does not depend on the
loop variable i. Try these examples, and note the values of d and i afterward:
2-10
Ensure That parfor-Loop Iterations Are Independent
clear A clear A
d = 0; i = 0; d = 0; i = 0;
for i = 1:4 parfor i = 1:4
d = i*2; d = i*2;
A(i) = d; A(i) = d;
end end
A A
d d
i i
A = A =
2 4 6 8 2 4 6 8
d = d =
8 0
i = i =
4 0
Although the elements of A are the same in both examples, the value of d is not. In the for-loop, the
iterations are executed sequentially, so afterward d has the value it held in the last iteration of the
loop. In the parfor-loop, however, the iterations execute in parallel, so it is impossible to assign d a
defined value at the end of the loop. This situation also applies to the loop variable i. Therefore,
parfor-loop behavior is defined so that it does not affect the values d and i outside the loop. Their
values remain the same before and after the loop. If the variables in your parfor-loop are not
independent, then you might get different answers from those in the for-loop. In summary, a
parfor-loop requires that each iteration be independent of the other iterations. All code that follows
the parfor statement should not depend on the loop iteration sequence.
Code Analyzer can help diagnose whether the loop iterations are dependent. The code in the example
shows iterations defined in terms of the previous iteration:
parfor k = 2:10
x(k) = x(k-1) + k;
end
Look for Code Analyzer messages in the MATLAB Editor. In this case, Code Analyzer reports the
dependency problem.
For help with other common parfor problems, see “Nested parfor and for-Loops and Other parfor
Requirements” on page 2-13.
See Also
parfor
2-11
2 Parallel for-Loops (parfor)
Related Examples
• “Decide When to Use parfor” on page 2-2
• “Convert for-Loops into parfor-Loops” on page 2-7
• “Nested parfor and for-Loops and Other parfor Requirements” on page 2-13
• “Troubleshoot Variables in parfor-Loops” on page 2-21
• “Reduction Variables” on page 2-35
More About
• “Evaluate Functions in the Background Using parfeval” on page 3-3
2-12
Nested parfor and for-Loops and Other parfor Requirements
Nested parfor-Loops
You cannot use a parfor-loop inside another parfor-loop. As an example, the following nesting of
parfor-loops is not allowed:
parfor i = 1:10
parfor j = 1:5
...
end
end
Tip You cannot nest parfor directly within another parfor-loop. A parfor-loop can call a function
that contains a parfor-loop, but you do not get any additional parallelism.
Code Analyzer in the MATLAB Editor flags the use of parfor inside another parfor-loop:
You cannot nest parfor-loops because parallelization can be performed at only one level. Therefore,
choose which loop to run in parallel, and convert the other loop to a for-loop.
Consider the following performance issues when dealing with nested loops:
• Parallel processing incurs overhead. Generally, you should run the outer loop in parallel, because
overhead only occurs once. If you run the inner loop in parallel, then each of the multiple parfor
executions incurs an overhead. See “Convert Nested for-Loops to parfor-Loops” on page 2-14 for
an example how to measure parallel overhead.
• Make sure that the number of iterations exceeds the number of workers. Otherwise, you do not
use all available workers.
• Try to balance the parfor-loop iteration times. parfor tries to compensate for some load
imbalance.
Tip Always run the outermost loop in parallel, because you reduce parallel overhead.
You can also use a function that uses parfor and embed it in a parfor-loop. Parallelization occurs
only at the outer level. In the following example, call a function MyFun.m inside the outer parfor-
loop. The inner parfor-loop embedded in MyFun.m runs sequentially, not in parallel.
parfor i = 1:10
MyFun(i)
2-13
2 Parallel for-Loops (parfor)
end
function MyFun(i)
parfor j = 1:5
...
end
end
The following code shows a simple example. Use tic and toc to measure the computing time
needed.
A = 100;
tic
for i = 1:100
for j = 1:100
a(i,j) = max(abs(eig(rand(A))));
end
end
toc
You can parallelize either of the nested loops, but you cannot run both in parallel. The reason is that
the workers in a parallel pool cannot start or access further parallel pools.
If the loop counted by i is converted to a parfor-loop, then each worker in the pool executes the
nested loops using the j loop counter. The j loops themselves cannot run as a parfor on each
worker.
Because parallel processing incurs overhead, you must choose carefully whether you want to convert
either the inner or the outer for-loop to a parfor-loop. The following example shows how to
measure the parallel overhead.
First convert only the outer for-loop to a parfor-loop. Use tic and toc to measure the computing
time needed. Use ticBytes and tocBytes to measure how much data is transferred to and from the
workers in the parallel pool.
Run the new code, and run it again. The first run is slower than subsequent runs, because the parallel
pool takes some time to start and make the code available to the workers.
A = 100;
tic
2-14
Nested parfor and for-Loops and Other parfor Requirements
ticBytes(gcp);
parfor i = 1:100
for j = 1:100
a(i,j) = max(abs(eig(rand(A))));
end
end
tocBytes(gcp)
toc
BytesSentToWorkers BytesReceivedFromWorkers
__________________ ________________________
1 32984 24512
2 33784 25312
3 33784 25312
4 34584 26112
Total 1.3514e+05 1.0125e+05
Next convert only the inner loop to a parfor-loop. Measure the time needed and data transferred as
in the previous case.
A = 100;
tic
ticBytes(gcp);
for i = 1:100
parfor j = 1:100
a(i,j) = max(abs(eig(rand(A))));
end
end
tocBytes(gcp)
toc
BytesSentToWorkers BytesReceivedFromWorkers
__________________ ________________________
1 1.3496e+06 5.487e+05
2 1.3496e+06 5.4858e+05
3 1.3677e+06 5.6034e+05
4 1.3476e+06 5.4717e+05
Total 5.4144e+06 2.2048e+06
If you convert the inner loop to a parfor-loop, both the time and amount of data transferred are
much greater than in the parallel outer loop. In this case, the elapsed time is almost the same as in
the nested for-loop example. The speedup is smaller than running the outer loop in parallel, because
you have more data transfer and thus more parallel overhead. Therefore if you execute the inner loop
in parallel, you get no computational benefit compared to running the serial for-loop.
If you want to reduce parallel overhead and speed up your computation, run the outer loop in
parallel.
If you convert the inner loop instead, then each iteration of the outer loop initiates a separate
parfor-loop. That is, the inner loop conversion creates 100 parfor-loops. Each of the multiple
parfor executions incurs overhead. If you want to reduce parallel overhead, you should run the
outer loop in parallel instead, because overhead only occurs once.
2-15
2 Parallel for-Loops (parfor)
Tip If you want to speed up your code, always run the outer loop in parallel, because you reduce
parallel overhead.
Required (static): You must define the range of a for-loop nested in a parfor-loop by constant
numbers or broadcast variables.
In the following example, the code on the left does not work because you define the upper limit of the
for-loop by a function call. The code on the right provides a workaround by first defining a broadcast
or constant variable outside the parfor-loop:
Invalid Valid
A = zeros(100, 200); A = zeros(100, 200);
parfor i = 1:size(A, 1) n = size(A, 2);
for j = 1:size(A, 2) parfor i = 1:size(A,1)
A(i, j) = i + j; for j = 1:n
end A(i, j) = i + j;
end end
end
Required (static): The index variable for the nested for-loop must never be explicitly assigned
other than by its for statement.
Following this restriction is required. If the nested for-loop variable is changed anywhere in a
parfor-loop other than by its for statement, the region indexed by the for-loop variable is not
guaranteed to be available at each worker.
The code on the left is not valid because it tries to modify the value of the nested for-loop variable j
in the body of the loop. The code on the right provides a workaround by assigning the nested for-
loop variable to a temporary variable t, and then updating t.
Invalid Valid
A = zeros(10); A = zeros(10);
parfor i = 1:10 parfor i = 1:10
for j = 1:10 for j = 1:10
A(i, j) = 1; A(i, j) = 1;
j = j+1; t = j;
end t = t + 1;
end end
end
Following this restriction is required. If a nested for-loop variable is indexed, iterations are not
guaranteed to be independent.
2-16
Nested parfor and for-Loops and Other parfor Requirements
The example on the left is invalid because it attempts to index the nested for-loop variable j. The
example on the right removes this indexing.
Invalid Valid
A = zeros(10); A = zeros(10);
parfor i = 1:10 parfor i = 1:10
for j = 1:10 for j = 1:10
j(1); j;
end end
end end
Required (static): When using the nested for-loop variable for indexing a sliced array, you must
use the variable in plain form, not as part of an expression.
For example, the following code on the left does not work, but the code on the right does:
Invalid Valid
A = zeros(4, 11); A = zeros(4, 11);
parfor i = 1:4 parfor i = 1:4
for j = 1:10 for j = 2:11
A(i, j + 1) = i + j; A(i, j) = i + j - 1;
end end
end end
Required (static): If you use a nested for-loop to index into a sliced array, you cannot use that
array elsewhere in the parfor-loop.
In the following example, the code on the left does not work because A is sliced and indexed inside
the nested for-loop. The code on the right works because v is assigned to A outside of the nested
loop:
Invalid Valid
A = zeros(4, 10); A = zeros(4, 10);
parfor i = 1:4 parfor i = 1:4
for j = 1:10 v = zeros(1, 10);
A(i, j) = i + j; for j = 1:10
end v(j) = i + j;
disp(A(i, j)) end
end disp(v(j))
A(i, :) = v;
end
parfor-Loop Limitations
Nested Functions
The body of a parfor-loop cannot reference a nested function. However, it can call a nested function
by a function handle. Try the following example. Note that A(idx) = nfcn(idx) in the parfor-
loop does not work. You must use feval to invoke the fcn handle in the parfor-loop body.
function A = pfeg
function out = nfcn(in)
out = 1 + in;
2-17
2 Parallel for-Loops (parfor)
end
fcn = @nfcn;
>> pfeg
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
ans =
2 3 4 5 6 7 8 9 10 11
Tip If you use function handles that refer to nested functions inside a parfor-loop, then the values
of externally scoped variables are not synchronized among the workers.
Nested parfor-Loops
The body of a parfor-loop cannot contain a parfor-loop. For more information, see “Nested parfor-
Loops” on page 2-13.
The body of a parfor-loop cannot contain an spmd statement, and an spmd statement cannot contain
a parfor-loop. The reason is that workers cannot start or access further parallel pools.
The body of a parfor-loop cannot contain break or return statements. Consider parfeval or
parfevalOnAll instead, because you can use cancel on them.
The body of a parfor-loop cannot contain global or persistent variable declarations. The reason
is that these variables are not synchronized between workers. You can use global or persistent
variables within functions, but their value is visible only to the worker that creates them. Instead of
global variables, it is a better practice to use function arguments to share values.
To learn more about variable requirements, see “Troubleshoot Variables in parfor-Loops” on page 2-
21.
Scripts
If a script introduces a variable, you cannot call this script from within a parfor-loop or spmd
statement. The reason is that this script would cause a transparency violation. For more details, see
“Ensure Transparency in parfor-Loops or spmd Statements” on page 2-51.
Anonymous Functions
You can define an anonymous function inside the body of a parfor-loop. However, sliced output
variables inside anonymous functions are not supported. You can work around this by using a
temporary variable for the sliced variable, as shown in the following example.
2-18
Nested parfor and for-Loops and Other parfor Requirements
x = 1:10;
parfor i=1:10
temp = x(i);
anonymousFunction = @() 2*temp;
x(i) = anonymousFunction() + i;
end
disp(x);
For more information on sliced variables, see “Sliced Variables” on page 2-28.
inputname Functions
Using inputname to return the workspace variable name corresponding to an argument number is
not supported inside parfor-loops. The reason is that parfor workers do not have access to the
workspace of the MATLAB desktop. To work around this, call inputname before parfor, as shown in
the following example.
a = 'a';
myFunction(a)
function X = myFunction(a)
name = inputname(1);
parfor i=1:2
X(i).(name) = i;
end
end
load Functions
The syntaxes of load that do not assign to an output structure are not supported inside parfor-
loops. Inside parfor, always assign the output of load to a structure.
The reason is that workers do not have access to the workspace of the MATLAB desktop. To work
around this, call these functions before parfor, as shown in the following example.
myFunction('a','b')
function X = myFunction(a,b)
nin = nargin;
parfor i=1:2
X(i) = i*nin;
end
end
P-Code Scripts
You can call P-code script files from within a parfor-loop, but P-code scripts cannot contain a
parfor-loop. To work around this, use a P-code function instead of a P-code script.
2-19
2 Parallel for-Loops (parfor)
See Also
parfor | parfeval | parfevalOnAll
Related Examples
• “Decide When to Use parfor” on page 2-2
• “Convert for-Loops into parfor-Loops” on page 2-7
• “Ensure That parfor-Loop Iterations Are Independent” on page 2-10
• “Troubleshoot Variables in parfor-Loops” on page 2-21
2-20
Troubleshoot Variables in parfor-Loops
In this section...
“Ensure That parfor-Loop Variables Are Consecutive Increasing Integers” on page 2-21
“Avoid Overflows in parfor-Loops” on page 2-21
“Solve Variable Classification Issues in parfor-Loops” on page 2-22
“Structure Arrays in parfor-Loops” on page 2-24
“Converting the Body of a parfor-Loop into a Function” on page 2-25
“Unambiguous Variable Names” on page 2-25
“Transparent parfor-loops” on page 2-25
“Global and Persistent Variables” on page 2-25
You can fix these errors by converting the loop variables into a valid range. For example, you can fix
the noninteger example as follows:
iValues = 0:0.2:1;
parfor idx = 1:numel(iValues)
i = iValues(idx);
...
end
2-21
2 Parallel for-Loops (parfor)
When MATLAB recognizes a name in a parfor-loop as a variable, the variable is classified in one of
several categories, shown in the following table. Make sure that your variables are uniquely classified
and meet the category requirements. parfor-loops that violate the requirement return an error.
Classification Description
“Loop Variables” on Loop indices
page 2-27
“Sliced Variables” on Arrays whose segments are operated on by different iterations of the loop
page 2-28
“Broadcast Variables defined before the loop whose value is required inside the loop, but
Variables” on page 2- never assigned inside the loop
33
“Reduction Variables that accumulates a value across iterations of the loop, regardless of
Variables” on page 2- iteration order
35
“Temporary Variables created inside the loop, and not accessed outside the loop
Variables” on page 2-
41
To find out which variables you have, examine the code fragment. All variable classifications in the
table are represented in this code:
2-22
Troubleshoot Variables in parfor-Loops
If you run into variable classification problems, consider these approaches before you resort to the
more difficult method of converting the body of a parfor-loop into a function.
• If you use a nested for-loop to index into a sliced array, you cannot use that array elsewhere in
the parfor-loop. The code on the left does not work because A is sliced and indexed inside the
nested for-loop. The code on the right works because v is assigned to A outside the nested loop.
You can compute an entire row, and then perform a single assignment into the sliced output.
Invalid Valid
A = zeros(4, 10); A = zeros(4, 10);
parfor i = 1:4 parfor i = 1:4
for j = 1:10 v = zeros(1, 10);
A(i, j) = i + j; for j = 1:10
end v(j) = i + j;
disp(A(i, 1)) end
end disp(v(1))
A(i, :) = v;
end
• The code on the left does not work because the variable x in parfor cannot be classified. This
variable cannot be classified because there are multiple assignments to different parts of x.
Therefore parfor cannot determine whether there is a dependency between iterations of the
loop. The code on the right works because you completely overwrite the value of x. parfor can
now determine unambiguously that x is a temporary variable.
Invalid Valid
parfor idx = 1:10 parfor idx = 1:10
x(1) = 7; x = [7, 8];
x(2) = 8; out(idx) = sum(x);
out(idx) = sum(x); end
end
• This example shows how to slice the field of a structured array. See struct for details. The code
on the left does not work because the variable a in parfor cannot be classified. This variable
cannot be classified because the form of indexing is not valid for a sliced variable. The first level of
indexing is not the sliced indexing operation, even though the field x of a appears to be sliced
correctly. The code on the right works because you extract the field of the struct into a separate
variable tmpx. parfor can now determine correctly that this variable is sliced. In general, you
2-23
2 Parallel for-Loops (parfor)
cannot use fields of structs or properties of objects as sliced input or output variables in
parfor.
Invalid Valid
a.x = []; tmpx = [];
parfor idx = 1:10 parfor idx = 1:10
a.x(idx) = 7; tmpx(idx) = 7;
end end
a.x = tmpx;
You cannot create a structure in a parfor-loop using dot notation assignment. In the code on the left,
both lines inside the loop generate a classification error. In the code on the right, as a workaround
you can use the struct function to create the structure in the loop or in the first field.
Invalid Valid
parfor i = 1:4 parfor i = 1:4
temp.myfield1 = rand(); temp = struct();
temp.myfield2 = i; temp.myfield1 = rand();
end temp.myfield2 = i;
end
parfor i = 1:4
temp = struct('myfield1',rand(),'myfield2',i);
end
You cannot use structure fields as sliced input or output arrays in a parfor-loop. In other words, you
cannot use the loop variable to index the elements of a structure field. In the code on the left, both
lines in the loop generate a classification error because of the indexing. In the code on the right, as a
workaround for sliced output, you employ separate sliced arrays in the loop. Then you assign the
structure fields after the loop is complete.
Invalid Valid
parfor i = 1:4 parfor i = 1:4
outputData.outArray1(i) = 1/i; outArray1(i) = 1/i;
outputData.outArray2(i) = i^2; outArray2(i) = i^2;
end end
outputData = struct('outArray1',outArray1,'outArray2'
The workaround for sliced input is to assign the structure field to a separate array before the loop.
You can use that new array for the sliced input.
inArray1 = inputData.inArray1;
inArray2 = inputData.inArray2;
parfor i = 1:4
temp1 = inArray1(i);
temp2 = inArray2(i);
end
2-24
Troubleshoot Variables in parfor-Loops
Invalid Valid
function parfor_loop_body_bad function parfor_loop_body_good
data = rand(5,5); data = rand(5,5);
means = zeros(1,5); means = zeros(1,5);
parfor i = 1:5 parfor i = 1:5
% Code Analyzer flags problem % Call a function instead
% with variable y below means(i) = computeMeans(data(:,i));
[Link] = mean(data(:,i)); end
means(i) = [Link]; disp(means);
end end
disp(means);
end % This function now contains the body
% of the parfor-loop
function means = computeMeans(data)
[Link] = mean(data);
means = [Link];
end
Starting parallel pool (parpool) using the 'Processes' profile ... connecte
0.6786 0.5691 0.6742 0.6462 0.6307
parfor i = 1:n
...
a = f(5);
...
end
Transparent parfor-loops
The body of a parfor-loop must be transparent: all references to variables must be “visible” in the
text of the code. For more details about transparency, see “Ensure Transparency in parfor-Loops or
spmd Statements” on page 2-51.
2-25
2 Parallel for-Loops (parfor)
See Also
More About
• “Decide When to Use parfor” on page 2-2
• “Convert for-Loops into parfor-Loops” on page 2-7
• “Ensure That parfor-Loop Iterations Are Independent” on page 2-10
• “Nested parfor and for-Loops and Other parfor Requirements” on page 2-13
• “Ensure Transparency in parfor-Loops or spmd Statements” on page 2-51
• “Use parfor-Loops for Reduction Assignments” on page 2-64
• “Run Parallel Simulations” (Simulink)
2-26
Loop Variables
Loop Variables
The loop variable defines the loop index value for each iteration. You set it in the first line of a
parfor statement.
parfor p=1:12
For values across all iterations, the loop variable must evaluate to ascending consecutive integers.
Each iteration is independent of all others, and each has its own loop index value.
This restriction is required, because changing p in the parfor body cannot guarantee the
independence of iterations.
This example attempts to modify the value of the loop variable p in the body of the loop, and thus is
invalid.
parfor p = 1:n
p = p + 1;
a(p) = i;
end
Required (static): You cannot index or subscript the loop variable in any way.
This restriction is required, because referencing a field of a loop variable cannot guarantee the
independence of iterations.
The following code attempts to reference a field (b) of the loop variable (p) as if it were a structure.
Both lines within the loop are invalid.
parfor p = 1:n
p.b = 3
x(p) = fun(p.b)
end
Similarly, the following code is invalid because it attempts to index the loop variable as a 1-by-1
matrix:
parfor p = 1:n
x = p(1)
end
See Also
parfor
More About
• “Troubleshoot Variables in parfor-Loops” on page 2-21
2-27
2 Parallel for-Loops (parfor)
Sliced Variables
A sliced variable is one whose value can be broken up into segments, or slices, which are then
operated on separately by different workers. Each iteration of the loop works on a different slice of
the array. Using sliced variables can reduce communication between the client and workers.
parfor i = 1:length(A)
B(i) = f(A(i));
end
• Type of First-Level Indexing — The first level of indexing is either parentheses, (), or braces, {}.
• Fixed Index Listing — Within the first-level parentheses or braces, the list of indices is the same
for all occurrences of a given variable.
• Form of Indexing — Within the list of indices for the variable, exactly one index involves the loop
variable.
• Shape of Array — The array maintains a constant shape. In assigning to a sliced variable, the right
side of the assignment cannot be [] or '', because these operators attempt to delete elements.
For a sliced variable, the first level of indexing is enclosed in either parentheses, (), or braces, {}.
Here are the forms for the first level of indexing for arrays that are sliced and not sliced.
After the first level, you can use any type of valid MATLAB indexing in the second and subsequent
levels.
The variable A shown here on the left is not sliced; that shown on the right is sliced.
A.q{i,12} A{i,12}.q
Within the first-level indexing of a sliced variable, the list of indices is the same for all occurrences of
a given variable.
The variable A on the left is not sliced because A is indexed by i and i+1 in different places. In the
code on the right, variable A is sliced correctly.
2-28
Sliced Variables
The example on the right shows occurrences of first-level indexing using both parentheses and braces
in the same loop, which is acceptable.
The following example on the left does not slice A because the indexing of A is not the same in all
places. The example on the right slices both A and B. The indexing of A is not the same as the
indexing of B. However, the indexing of both A and B are individually consistent.
Form of Indexing
Within the first-level of indexing for a sliced variable, exactly one indexing expression is of the form i,
i+k, i-k, or k+i. The index i is the loop variable and k is a scalar integer constant or a simple (non-
indexed) broadcast variable. Every other indexing expression is a positive integer constant, a simple
(non-indexed) broadcast variable, a nested for-loop index variable, colon, a colon expression
involving simple broadcast variables or scalar integer constants, or end.
With i as the loop variable, the A variables shown on the left are not sliced, while the A variables on
the right are sliced.
You can work around the unsupported indexing expressions by declaring them as broadcast variables.
In this example, the code on the left does not work because it directly uses unsupported indexing
expressions to index the slice variables. The code on the right provides a workaround by declaring
the expressions as broadcast variables before the loop body.
2-29
2 Parallel for-Loops (parfor)
When you use other variables along with the loop variable to index an array, you cannot set these
variables inside the loop. In effect, such variables are constant over the execution of the entire
parfor statement. You cannot combine the loop variable with itself to form an index expression.
Shape of Array
A sliced variable must maintain a constant shape. The variable A shown here is not sliced:
A(i,:) = [];
A is not sliced because changing the shape of a sliced array would violate assumptions governing
communication between the client and workers.
However, if MATLAB determines that, in each iteration, the sliced variable elements are set before
any use, then MATLAB does not transmit the variable to the workers. In this example, all elements of
A are set before any use.
parfor ii = 1:n
if someCondition
A(ii) = 32;
else
A(ii) = 17;
end
% loop code that uses A(ii)
end
Sliced-output variables can grow dynamically through indexed assignments with default values
inserted at intermediate indices. In this example, you can see that the default value of 0 has been
inserted at several places in A.
A = [];
parfor idx = 1:10
if rand < 0.5
A(idx) = idx;
end
end
disp(A);
0 2 0 4 5 0 0 8 9 10
Even if a sliced variable is not explicitly referenced as an input, implicit usage can make it so. In the
following example, not all elements of A are necessarily set inside the parfor-loop. Therefore the
original values of the array are received, held, and then returned from the loop.
2-30
Sliced Variables
A = 1:10;
parfor ii = 1:10
if rand < 0.5
A(ii) = 0;
end
end
Under some circumstances, parfor-loops must assume that a worker may need all segments of a
sliced variable. In this example, it is not possible to determine which elements of the sliced variable
will be read before execution, so parfor sends all possible segments.
A = 1:10;
parfor ii=1:11
if ii <= randi([10 11])
A(ii) = A(ii) + 1;
end
end
Note that in these circumstances, the code can attempt to index a sliced variable outside of the array
bounds and generate an error.
In this example, the code on the left does not work because it indexes the sliced variable A outside
the nested for-loop that defines j.
• The range of the for-loop variable must be a row vector of positive constant numbers or
variables.
In this example, the code on the left does not work because it defines the upper limit of the nested
for-loop with a function call. The code on the right provides a workaround by defining the upper
limit in a constant variable outside the parfor-loop.
• The for-loop variable must not be assigned other than by its for statement.
2-31
2 Parallel for-Loops (parfor)
In this example, the code on the left does not work because it reassigns the for-loop variable
inside the for-loop. The code on the right provides a workaround by assigning i to the temporary
variable t.
• dictionary
• table
• When you use sliced arrays of handle objects, MATLAB constructs default elements. For more
information, see “Create and Initialize Object Arrays”.
See Also
More About
• “Troubleshoot Variables in parfor-Loops” on page 2-21
2-32
Broadcast Variables
Broadcast Variables
A broadcast variable is any variable, other than the loop variable or a sliced variable, that does not
change inside a loop. At the start of a parfor-loop, MATLAB sends the values of any broadcast
variables to all the workers. In this example, MATLAB sends the values of A and B to all the workers.
A = 5;
B = 10;
C = 0;
parfor i = 1:10
if i == A
C = C + B;
end
end
Performance Considerations
Having large broadcast variables or many broadcast variables can cause significant communication
between a client and its associated workers and increase overhead. Where communication overhead
due to broadcast variables is large, consider creating and assigning temporary variables inside the
loop instead. Conversely, where computational overhead due to creating and assigning temporary
variables is large, consider using broadcast variables instead.
For more details, see “Temporary Variables” on page 2-41 and “Deciding When to Use parfor” on
page 2-2.
Note When multiple parfor-loops need to access the same constant set of data, you can improve the
performance of your code by using [Link] which transfers data to the workers
only once instead of at the start of each parfor-loop.
To improve the performance of your code, look for opportunities to reduce the number of unnecessary
broadcast variables. For example, this code contains a broadcast variable M.
M = magic(10);
parfor i = 1:numel(M)
out(i) = M(i)./numel(M);
end
This code can be rewritten to evaluate numel(M) before the parfor-loop. Removing numel(M) from
the parfor-loop prevents MATLAB from sending all elements of M to each worker. Instead MATLAB
sends the value of N and a subset of the sliced variable M to each worker.
M = magic(10);
N = numel(M);
parfor i = 1:N
out(i) = M(i)./N;
end
See Also
[Link]
2-33
2 Parallel for-Loops (parfor)
More About
• “Troubleshoot Variables in parfor-Loops” on page 2-21
• “Improve parfor Performance” on page 2-45
• “Deciding When to Use parfor” on page 2-2
• “Temporary Variables” on page 2-41
2-34
Reduction Variables
Reduction Variables
MATLAB supports an important exception, called reduction, to the rule that loop iterations must be
independent. A reduction variable accumulates a value that depends on all the iterations together,
but is independent of the iteration order. MATLAB allows reduction variables in parfor-loops.
Reduction variables appear on both sides of an assignment statement, such as any of the following,
where expr is a MATLAB expression.
X = X + expr X = expr + X
X = X - expr See Associativity in Reduction Assignments in
“Requirements for Reduction Assignments” on page
2-37
X = X .* expr X = expr .* X
X = X * expr X = expr * X
X = X & expr X = expr & X
X = X | expr X = expr | X
X = [X, expr] X = [expr, X]
X = [X; expr] X = [expr; X]
X = min(X, expr) X = min(expr, X)
X = max(X, expr) X = max(expr, X)
X = union(X, expr) X = union(expr, X)
X = intersect(X, expr) X = intersect(expr, X)
Each of the allowed statements listed in this table is referred to as a reduction assignment. By
definition, a reduction variable can appear only in assignments of this type.
This loop is equivalent to the following, where you calculate each d(i) by a different iteration.
X = X + d(1) + ... + d(n)
In a regular for-loop, the variable X would get its value either before entering the loop or from the
previous iteration of the loop. However, this concept does not apply to parfor-loops.
In a parfor-loop, the value of X is never transmitted from client to workers or from worker to
worker. Rather, additions of d(i) are done in each worker, with i ranging over the subset of 1:n
being performed on that worker. The results are then transmitted back to the client, which adds the
partial sums of the workers into X. Thus, workers do some of the additions, and the client does the
rest.
2-35
2 Parallel for-Loops (parfor)
Required (static): For any reduction variable, the same reduction function or operation must be
used in all reduction assignments for that variable.
The parfor-loop on the left is not valid because the reduction assignment uses + in one instance, and
[,] in another. The parfor-loop on the right is valid.
Invalid Valid
parfor i = 1:n parfor i = 1:n
if testLevel(k) if testLevel(k)
A = A + i; A = A + i;
else else
A = [A, 4+i]; A = A + i + 5*k;
end end
% loop body continued % loop body continued
end end
Required (static): If the reduction assignment uses *, [,], or [;], then X must be consistently
specified as the first or second argument in every reduction assignment.
The parfor-loop on the left is not valid because the order of items in the concatenation is not
consistent throughout the loop. The parfor-loop on the right is valid.
Invalid Valid
parfor i = 1:n parfor i = 1:n
if testLevel(k) if testLevel(k)
A = [A, 4+i]; A = [A, 4+i];
else else
A = [r(i), A]; A = [A, r(i)];
end end
% loop body continued % loop body continued
end end
The code on the left is not valid because it tries to index a, and so MATLAB cannot classify it as a
reduction variable. To fix it, the code on the right uses a non-indexed variable.
2-36
Reduction Variables
Invalid Valid
a.x = 0 tmpx = 0
parfor i = 1:10 parfor i = 1:10
a.x = a.x + 1; tmpx = tmpx + 1;
end end
a.x = tmpx;
Required (static): f can be a function or a variable. If f is a variable, then you cannot change f in
the parfor body (in other words, it is a broadcast variable).
If f is a variable, then for all practical purposes its value at run time is a function handle. However, as
long as the right side can be evaluated, the resulting value is stored in X.
The parfor-loop on the left does not execute correctly because the statement f = @times causes f
to be classified as a temporary variable. Therefore f is cleared at the beginning of each iteration. The
parfor-loop on the right is correct, because it does not assign f inside the loop.
Invalid Valid
f = @(x,k)x * k; f = @(x,k)x * k;
parfor i = 1:n parfor i = 1:n
a = f(a,i); a = f(a,i);
% loop body continued % loop body continued
f = @times; % Affects f end
end
The operators && and || are not listed in the table in “Reduction Variables” on page 2-35. Except for
&& and ||, all the matrix operations of MATLAB have a corresponding function f, such that u op v
is equivalent to f(u,v). For && and ||, such a function cannot be written because u&&v and u||v
might or might not evaluate v. However, f(u,v) always evaluates v before calling f. Therefore &&
and || are excluded from the table of allowed reduction assignments for a parfor-loop.
Every reduction assignment has an associated function f. The properties of f that ensure
deterministic behavior of a parfor statement are discussed in the following sections.
Associativity in Reduction Assignments. The following practice is recommended for the function f, as
used in the definition of a reduction variable. However, this rule does not generate an error if not
adhered to. Therefore, it is up to you to ensure that your code meets this recommendation.
To be associative, the function f must satisfy the following for all a, b, and c.
f(a,f(b,c)) = f(f(a,b),c)
2-37
2 Parallel for-Loops (parfor)
The classification rules for variables, including reduction variables, are purely syntactic. They cannot
determine whether the f you have supplied is truly associative or not. Associativity is assumed, but if
you violate this rule, each execution of the loop might result in different answers.
Note The addition of mathematical real numbers is associative. However, the addition of floating-
point numbers is only approximately associative. Different executions of this parfor statement might
produce values of X with different round-off errors. You cannot avoid this cost of parallelism.
For example, the statement on the left yields 1, while the statement on the right returns 1 + eps:
(1 + eps/2) + eps/2 1 + (eps/2 + eps/2)
Except for the minus operator (-), all special cases listed in the table in “Reduction Variables” on
page 2-35 have a corresponding (approximately) associative function. MATLAB calculates the
assignment X = X - expr by using X = X + (-expr). (So, technically, the function for calculating
this reduction assignment is plus, not minus.) However, the assignment X = expr - X cannot be
written using an associative function, which explains its exclusion from the table.
Commutativity in Reduction Assignments. Some associative functions, including +, .*, min, and max,
intersect, and union, are also commutative. That is, they satisfy the following for all a and b.
f(a,b) = f(b,a)
Noncommutative functions include * (because matrix multiplication is not commutative for matrices
in which both dimensions have size greater than one), [,], and [;]. Noncommutativity is the reason
that consistency in the order of arguments to these functions is required. As a practical matter, a
more efficient algorithm is possible when a function is commutative as well as associative, and
parfor is optimized to exploit commutativity.
Recommended: Except in the cases of *, [,], and [;], the function f of a reduction assignment
must be commutative. If f is not commutative, different executions of the loop might result in
different answers.
Violating the restriction on commutativity in a function used for reduction could result in unexpected
behavior, even if it does not generate an error.
Recommended: An overload of the minus operator (-) must obey the mathematical law that X -
(y + z) is equivalent to (X - y) - z.
2-38
Reduction Variables
iteration, store the value of the computation and the loop index in a 2-element row vector. Use a
custom reduction function to compare this vector to a stored vector. If the value from the
computation is greater than the stored value, replace the old vector with the new vector.
Create a reduction function compareValue. The function takes two vectors as inputs:
valueAndIndexA and valueAndIndexB. Each vector contains a value and an index. The reduction
function compareValue returns the vector with the greatest value (first element).
maxValueAndIndex = [0 0];
Run a parfor-loop. In each iteration, use rand to create a random value. Then, use the reduction
function compareValue to compare maxValueAndIndex to the random value and loop index. When
you store the result as maxValueAndIndex, you use maxValueAndIndex as a reduction variable.
parfor ii = 1:100
% Simulate some actual computation
thisValueAndIndex = [rand() ii];
% Compare value
maxValueAndIndex = compareValue(maxValueAndIndex, thisValueAndIndex);
end
After the parfor-loop finishes running, the reduction variable maxValueAndIndex is available on
the client. The first element is the largest random value computed in the parfor-loop, and the
second element is the corresponding loop index.
maxValueAndIndex
maxValueAndIndex =
0.9706 89.0000
In this example, MATLAB classifies X as a reduction variable because the assignment is equivalent to
X = X + (1 * 2).
X = 0;
parfor i=1:10
2-39
2 Parallel for-Loops (parfor)
X = X + 1 * 2;
end
In this example, MATLAB classifies X as a temporary variable because the assignment, equivalent to X
= (X * 1) + 2, is not of the form X = (expr) op X or X = X op (expr).
X = 0;
parfor i=1:10
X = X * 1 + 2;
end
As a best practice, use parentheses to explicitly specify operator precedence for chained reduction
assignments.
See Also
More About
• “Troubleshoot Variables in parfor-Loops” on page 2-21
• “Use parfor-Loops for Reduction Assignments” on page 2-64
2-40
Temporary Variables
Temporary Variables
A temporary variable is any variable that is the target of a direct, nonindexed assignment, but is not a
reduction variable. In the following parfor-loop, a and d are temporary variables:
a = 0;
z = 0;
r = rand(1,10);
parfor i = 1:10
a = i; % Variable a is temporary
z = z + i;
if i <= 5
d = 2*a; % Variable d is temporary
end
end
In contrast to the behavior of a for-loop, MATLAB clears any temporary variables before each
iteration of a parfor-loop. To help ensure the independence of iterations, the values of temporary
variables cannot be passed from one iteration of the loop to another. Therefore, temporary variables
must be set inside the body of a parfor-loop, so that their values are defined separately for each
iteration.
MATLAB does not send temporary variables back to the client. A temporary variable in a parfor-loop
has no effect on a variable with the same name that exists outside the loop. This behavior is different
from ordinary for-loops.
Uninitialized Temporaries
Temporary variables in a parfor-loop are cleared at the beginning of every iteration. MATLAB can
sometimes detect cases in which loop iterations use a temporary variable before it is set in that
iteration. In this case, MATLAB issues a static error rather than a run-time error. There is little point
in allowing execution to proceed if a run-time error is guaranteed to occur. This kind of error often
arises because of confusion between for and parfor, especially regarding the rules of classification
of variables. For example:
b = true;
parfor i = 1:n
if b && some_condition(i)
do_something(i);
b = false;
end
...
end
2-41
2 Parallel for-Loops (parfor)
s = 0;
parfor i = 1:n
s = s + f(i);
...
if (s > whatever)
...
end
end
If the only occurrences of s are the two in the first statement of the body, s would be classified as a
reduction variable. But in this example, s is not a reduction variable because it has a use outside of
reduction assignments in the line s > whatever. Because s is the target of an assignment (in the
first statement), it is a temporary. Therefore MATLAB issues an error, but points out the possible
connection with reduction.
If you change parfor to for, the use of s outside the reduction assignment relies on the iterations
being performed in a particular order. In a parfor-loop, it matters that the loop “does not care”
about the value of a reduction variable as it goes along. It is only after the loop that the reduction
value becomes usable.
ans Variable
Inside the body of a parfor-loop, the ans variable is classified as a temporary variable. All
considerations and restrictions for temporary variables apply to ans. For example, assignments to
ans inside a parfor-loop have no effect on ans outside the loop.
See Also
More About
• “Troubleshoot Variables in parfor-Loops” on page 2-21
• “Reduction Variables” on page 2-35
• “Ensure Transparency in parfor-Loops or spmd Statements” on page 2-51
2-42
Interactively Run Loops in Parallel Using parfor
This example calculates the spectral radius of a matrix and converts a for-loop into a parfor-loop.
Find out how to measure the resulting speedup.
1 In the MATLAB Editor, enter the following for-loop. Add tic and toc to measure the time
elapsed.
tic
n = 200;
A = 500;
a = zeros(n);
for i = 1:n
a(i) = max(abs(eig(rand(A))));
end
toc
2 Run the script, and note the elapsed time.
tic
n = 200;
A = 500;
a = zeros(n);
parfor i = 1:n
a(i) = max(abs(eig(rand(A))));
end
toc
4 Run the new script, and run it again. Note that the first run is slower than the second run,
because the parallel pool takes some time to start and make the code available to the workers.
Note the elapsed time for the second run.
By default, MATLAB automatically opens a parallel pool of workers on your local machine.
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
...
Elapsed time is 10.760068 seconds.
2-43
2 Parallel for-Loops (parfor)
The parfor run on four workers is about three times faster than the corresponding for-loop
run. The speed-up is smaller than the ideal speed-up of a factor of four on four workers. This is
due to parallel overhead, including the time required to transfer data from the client to the
workers and back. This example shows a good speed-up with relatively small parallel overhead,
and benefits from conversion into a parfor-loop. Not all for-loop iterations can be turned into
faster parfor-loops. To learn more, see “Decide When to Use parfor” on page 2-2.
One key requirement for using parfor-loops is that the individual iterations must be independent.
Independent problems suitable for parfor processing include Monte Carlo simulations and
parameter sweeps. For next steps, see “Convert for-Loops into parfor-Loops” on page 2-7.
In this example, you managed to speed up the calculation by converting the for-loop into a parfor-
loop on four workers. You might reduce the elapsed time further by increasing the number of workers
in your parallel pool, see “Scale Up parfor-Loops to Cluster and Cloud” on page 2-55.
You can modify your cluster profiles to control how many workers run your loops, and whether the
workers are local or on a cluster. For more information on profiles, see “Discover Clusters and Use
Cluster Profiles” on page 7-2.
Modify your parallel settings to control whether a parallel pool is created automatically, and how long
it remains available before timing out. For more information on settings, see “Specify Your Parallel
Settings” on page 1-35.
You can run Simulink models in parallel with the parsim command instead of using parfor-loops.
For more information and examples of using Simulink in parallel, see “Running Multiple Simulations”
(Simulink).
See Also
parfor | parpool | tic | toc
More About
• “Decide When to Use parfor” on page 2-2
• “Convert for-Loops into parfor-Loops” on page 2-7
• “Scale Up parfor-Loops to Cluster and Cloud” on page 2-55
2-44
Improve parfor Performance
Consider all factors in this list when you are considering to convert for-loops to parfor-loops. For
more details, see “Convert for-Loops into parfor-Loops” on page 2-7.
In this example, you first create a big data set D and execute a parfor-loop accessing D. Then you
use D to build a [Link] object, which allows you to reuse the data by copying D
to each worker. Measure the elapsed time using tic and toc for each case and note the difference.
function constantDemo
D = rand(1e7, 1);
tic
for i = 1:20
a = 0;
parfor j = 1:60
a = a + sum(D);
end
end
toc
tic
D = [Link](D);
for i = 1:20
b = 0;
parfor j = 1:60
b = b + sum([Link]);
end
2-45
2 Parallel for-Loops (parfor)
end
toc
end
>> constantDemo
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
Elapsed time is 63.839702 seconds.
Elapsed time is 10.194815 seconds.
In the second case, you send the data only once. You can enhance the performance of the parfor-
loop by using the [Link] object.
Profiling parfor-loops
You can profile a parfor-loop by measuring the time elapsed using tic and toc. You can also
measure how much data is transferred to and from the workers in the parallel pool by using
ticBytes and tocBytes. Note that this is different from profiling MATLAB code in the usual sense
using the MATLAB profiler, see “Profile Your Code to Improve Performance”.
This example calculates the spectral radius of a matrix and converts a for-loop into a parfor-loop.
Measure the resulting speedup and the amount of transferred data.
1 In the MATLAB Editor, enter the following for-loop. Add tic and toc to measure the time
elapsed. Save the file as MyForLoop.m.
function a = MyForLoop(A)
tic
for i = 1:200
a(i) = max(abs(eig(rand(A))));
end
toc
end
2 Run the code, and note the elapsed time.
a = MyForLoop(500);
ticBytes(gcp);
parfor i = 1:200
a(i) = max(abs(eig(rand(A))));
end
tocBytes(gcp)
4 Run the new code, and run it again. Note that the first run is slower than the second run,
because the parallel pool has to be started and you have to make the code available to the
workers. Note the elapsed time for the second run.
By default, MATLAB automatically opens a parallel pool of workers on your local machine.
a = MyParforLoop(500);
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
...
BytesSentToWorkers BytesReceivedFromWorkers
__________________ ________________________
2-46
Improve parfor Performance
1 15340 7024
2 13328 5712
3 13328 5704
4 13328 5728
Total 55324 24168
The elapsed time is 31.9 seconds in serial and 10.8 seconds in parallel, and shows that this code
benefits from converting to a parfor-loop.
Slicing Arrays
If a variable is initialized before a parfor-loop, then used inside the parfor-loop, it has to be passed
to each MATLAB worker evaluating the loop iterations. Only those variables used inside the loop are
passed from the client workspace. However, if all occurrences of the variable are indexed by the loop
variable, each worker receives only the part of the array it needs.
As an example, you first run a parfor-loop using a sliced variable and measure the elapsed time.
% Sliced version
M = 100;
N = 1e6;
data = rand(M, N);
tic
parfor idx = 1:M
out2(idx) = sum(data(idx, :)) ./ N;
end
toc
Now suppose that you accidentally use a reference to the variable data instead of N inside the
parfor-loop. The problem here is that the call to size(data, 2) converts the sliced variable into a
broadcast (non-sliced) variable.
clear
M = 100;
N = 1e6;
data = rand(M, N);
tic
parfor idx = 1:M
out2(idx) = sum(data(idx, :)) ./ size(data, 2);
end
toc
Note that the elapsed time is greater for the accidentally broadcast variable.
In this case, you can easily avoid the non-sliced usage of data, because the result is a constant, and
can be computed outside the loop. In general, you can perform computations that depend only on
2-47
2 Parallel for-Loops (parfor)
broadcast data before the loop starts, since the broadcast data cannot be modified inside the loop. In
this case, the computation is trivial, and results in a scalar result, so you benefit from taking the
computation out of the loop.
With local workers, because all the MATLAB worker sessions are running on the same machine, you
might not see any performance improvement from a parfor-loop regarding execution time. This can
depend on many factors, including how many processors and cores your machine has. The key point
here is that a cluster might have more cores available than your local machine. If your code can be
multithreaded by MATLAB, then the only way to go faster is to use more cores to work on the
problem, using a cluster.
You might experiment to see if it is faster to create the arrays before the loop (as shown on the left
below), rather than have each worker create its own arrays inside the loop (as shown on the right).
Try the following examples running a parallel pool locally, and notice the difference in time execution
for each loop. First open a local parallel pool:
parpool('Processes')
Run the following examples, and execute again. Note that the first run for each case is slower than
the second run, because the parallel pool has to be started and you have to make the code available
to the workers. Note the elapsed time, for each case, for the second run.
tic; tic;
n = 200; n = 200;
M = magic(n); parfor i = 1:n
R = rand(n); M = magic(n);
parfor i = 1:n R = rand(n);
A(i) = sum(M(i,:).*R(n+1-i,:)); A(i) = sum(M(i,:).*R(n+1-i,:));
end end
toc toc
Running on a remote cluster, you might find different behavior, as workers can simultaneously create
their arrays, saving transfer time. Therefore, code that is optimized for local workers might not be
optimized for cluster workers, and vice versa.
See Also
[Link]
More About
• “Ensure Transparency in parfor-Loops or spmd Statements” on page 2-51
• “Use parfor-Loops for Reduction Assignments” on page 2-64
2-48
Use Objects and Handles in parfor-Loops
Objects
When you run a parfor-loop, you can send broadcast variables or sliced input variables from the
client to workers, or send sliced output variables from workers back to the client. The save and load
functions must be supported for each object that you send to or from workers. For more information,
see “Default Save and Load Process for Objects”.
Assigning a value to the sliced property of an object or the sliced field of a structure is not supported
in a parfor-loop.
Invalid Valid
s = struct; parfor i = 1:4
parfor i = 1:4 x(i) = i;
[Link](i) = i; end
end s = struct('SomeField',x);
For more information about first-level indexing constraints, see “Sliced Variables” on page 2-28.
Handle Classes
You can send handle objects as inputs to the body of a parfor-loop. However, any changes that you
make to handle objects on the workers during loop iterations are not automatically propagated back
to the client. That is, changes made inside the loop are not automatically reflected after the loop.
To make the client reflect the changes after the loop, explicitly assign the modified handle objects to
output variables of the parfor-loop. In the following example, maps is a sliced input/output variable.
m1 = [Link];
m2 = [Link];
m3 = [Link];
maps = {m1,m2,m3};
parfor ii = 1:numel(maps)
mymap = maps{ii}; % input slice assigned to local copy
for jj = 1:1000
mymap(num2str(jj)) = rand;
end
maps{ii} = mymap; % modified local copy assigned to output slice
end
isequal(maps{1},m1) % false - maps{1} is no longer the same handle as m1.
You cannot directly call a function handle with the loop index as an input argument, because this
variable cannot be distinguished from a sliced input variable. If you must call a function handle with
the loop index variable as an argument, use feval.
2-49
2 Parallel for-Loops (parfor)
B = @sin;
for ii = 1:100
A(ii) = B(ii);
end
A corresponding parfor-loop does not allow B to reference a function handle. As a workaround, use
feval.
B = @sin;
parfor ii = 1:100
A(ii) = feval(B,ii);
end
See Also
More About
• “Troubleshoot Variables in parfor-Loops” on page 2-21
• “Sliced Variables” on page 2-28
2-50
Ensure Transparency in parfor-Loops or spmd Statements
In the following examples, the variable X is not transferred to the workers. Only the character vector
'X' is passed to eval, and X is not visible as an input variable in the loop or block body. As a result,
MATLAB issues an error at run time.
X = 5; X = 5;
parfor ii = 1:4 spmd
eval('X'); eval('X');
end end
Similarly, you cannot clear variables from a workspace by executing the clear function inside a
parfor-loop or spmd statement:
Alternatively, you can free up memory used by a variable by setting its value to empty when it is no
longer needed.
parfor ii = 1:4
<statements...>
X = [];
<statements...>
end
In the case of spmd blocks, you can clear its Composite from the client workspace.
In general, the requirement for transparency restricts all dynamic access to variables, because the
entire variable might not be present in any given worker. In a transparent workspace, you cannot
create, delete, modify, access, or query variables if you do not explicitly specify these variables in the
code.
Note Transparency applies only to the direct body of the parfor or spmd construct, and not to any
functions called from there. One workaround for save and load is to hide the calls to save and load
inside a function. An alternative workaround is to call save with the "-fromstruct" option. For
more information, see “Save Variables in parfor-Loops” on page 2-53.
2-51
2 Parallel for-Loops (parfor)
MATLAB does successfully execute eval and evalc statements that appear in functions called from
the parfor body.
• If your Simulink model requires access to variables contained in a .mat file, you must load these
parameters in the workspace of each worker. You must do this before the parfor-loop, and after
opening parpool. To achieve this, you can use spmd or parfevalOnAll, as shown in the
examples.
spmd
evalin('base', 'load(''path/to/file'')')
end
See Also
parfor | spmd
More About
• “Troubleshoot Variables in parfor-Loops” on page 2-21
• “Run Single Programs on Multiple Data Sets” on page 4-6
• “Run Parallel Simulations” (Simulink)
2-52
Save Variables in parfor-Loops
This example shows how to use the save function in a parfor-loop to save one or more variables to a
file.
To use the save function in the body of a parfor-loop, you must use the "-fromstruct" option. If
you do not use this option, MATLAB® produces an error due to a transparency violation.
You must also ensure that each worker or parfor iteration has unique access to any files it writes or
saves data to. When multiple workers attempt to write to the same file, MATLAB can produce an
error or corrupted data, or one worker might overwrite the data from another worker. These issues
are more likely to occur when:
• There is more than one worker per machine, and the workers attempt to write to the same file.
• The workers have a shared file system and use the same path to identify a file for writing.
pool = parpool("Processes");
Use a parfor-loop to generate data and save it to separate MAT files in each iteration. Temporarily
store the results variable in a scalar structure. Use the "-fromstruct" option of the save function
to save the field and value from the structure to a file as a variable.
By default, parpool sets the working folder on the workers to match that of the MATLAB client
session. So, the client current working folder becomes the default folder where the workers save the
files.
View the contents of one of the files using the whos function.
whos("-file","output_1.mat");
To save multiple variables, create a structure with multiple fields and then save the fields and values
as individual variables.
2-53
2 Parallel for-Loops (parfor)
whos("-file","output_2.mat");
delete output*
delete(pool);
See Also
save | parfor
Related Examples
• “Ensure Transparency in parfor-Loops or spmd Statements” on page 2-51
2-54
Scale Up parfor-Loops to Cluster and Cloud
edit MyCode
2 In the MATLAB Editor, enter the new parfor-loop and add tic and toc to measure the time
elapsed.
function a = MyCode(A)
tic
parfor i = 1:200
a(i) = max(abs(eig(rand(A))));
end
toc
end
3 Save the file, and close the Editor.
4 On the Parallel > Parallel Settings menu, check that your Default Cluster is Processes (your
desktop machine).
5 In the MATLAB Command Window, define a parallel pool of size 1, and run your function on one
worker to calculate the elapsed time. Note the elapsed time for a single worker and shut down
your parallel pool.
parpool(1);
a = MyCode(1000);
delete(gcp);
6 Open a new parallel pool of two workers, and run the function again.
parpool(2);
a = MyCode(1000);
Note the elapsed time; you should see that this now has decreased compared to the single
worker case.
7 Try 4, 8, 12 and 16 workers. Measure the parallel scalability by plotting the elapsed time for each
number of workers on a log-log scale.
2-55
2 Parallel for-Loops (parfor)
The figure shows the scalability for a typical multicore desktop PC (blue circle data points). The
strong scaling test shows almost linear speedup and significant parallel scalability for up to eight
workers. Observe from the figure that, in this case, we do not achieve further speedup for more
than eight workers. This result means that, on a local desktop machine, all cores are fully used
for 8 workers. You can get a different result on your local desktop, depending on your hardware.
To further speed up your parallel application, consider scaling up to cloud or cluster computing.
8 If you have exhausted your local workers, as in the previous example, you can scale up your
calculation to cloud computing. Check your access to cloud computing from the Parallel >
Discover Clusters menu.
Open a parallel pool in the cloud and run your application without changing your code.
parpool(16);
a = MyCode(1000);
Note the elapsed time for increasing numbers of cluster workers. Measure the parallel scalability
by plotting the elapsed time as a function of number of workers on a log-log scale.
2-56
Scale Up parfor-Loops to Cluster and Cloud
The figure shows typical performance for workers in the cloud (red plus data points). This strong
scaling test shows linear speedup and 100% parallel scalability up to 16 workers in the cloud.
Consider further scaling up of your calculation by increasing the number of workers in the cloud
or on a compute cluster. Note that the parallel scalability can be different, depending on your
hardware, for a larger number of workers and other applications.
9 If you have direct access to a cluster, you can scale up your calculation using workers on the
cluster. Check your access to clusters from the Parallel > Discover Clusters menu. If you have
an account, select cluster, open a parallel pool and run your application without changing your
code.
parpool(64);
a = MyCode(1000);
2-57
2 Parallel for-Loops (parfor)
The figure shows typical strong scaling performance for workers on a cluster (black x data
points). Observe that you achieve 100% parallel scalability, persisting up to at least 80 workers
on the cluster. Note that this application scales linearly - the speedup is equal to the number of
workers used.
This example shows a speedup equal to the number of workers. Not every task can achieve a
similar speedup, see for example “Interactively Run Loops in Parallel Using parfor” on page 2-43.
You might need different approaches for your particular tasks. To learn more about alternative
approaches, see “Choose a Parallel Computing Solution” on page 1-5.
Tip You can further profile a parfor-loop by measuring how much data is transferred to and from
the workers in the parallel pool by using ticBytes and tocBytes. For more information and
examples, see “Profiling parfor-loops” on page 2-46.
See Also
Related Examples
• “Discover Clusters” on page 7-3
• “Discover Clusters and Use Cluster Profiles” on page 7-2
• “Profiling parfor-loops” on page 2-46
2-58
Scale Up parfor-Loops to Cluster and Cloud
2-59
2 Parallel for-Loops (parfor)
Perform a parameter sweep in parallel and plot progress during parallel computations.
You can use a DataQueue to monitor results during computations on a parallel pool. You can also use
a DataQueue with parallel language features such as parfor, parfeval and spmd.
The example shows how to perform a parameter sweep on a classical system, the Van der Pol
oscillator. This system can be expressed as a set of ODEs dependent on the two Van der Pol oscillator
parameters, μ and ν:
ẋ = νy
ẏ = μ 1 − x2 y − x
You can perform a parallel parameter sweep over the parameters μ and ν using a parfor loop to find
out the mean period of y when varying them. The following animation shows an execution of this
example in a local cluster.
Define the range of values for the parameters to be explored. Create a meshgrid to account for the
different combinations of the parameters.
gridSize = 6;
mu = linspace(100, 150, gridSize);
2-60
Plot During Parameter Sweep with parfor
nu = linspace(0.5, 2, gridSize);
[M,N] = meshgrid(mu,nu);
Declare a variable to store the results of the sweep. Use nan for preallocation to avoid plotting an
initial surface. Create a surface plot to visualize the results of the sweep for each combination of the
parameters. Prepare settings such as title, labels, and limits.
Z = nan(size(N));
c = surf(M, N, Z);
xlabel('\mu Values','Interpreter','Tex')
ylabel('\nu Values','Interpreter','Tex')
zlabel('Mean Period of y')
view(137, 30)
axis([100 150 0.5 2 0 500]);
Create a DataQueue to send intermediate results from the workers to the client. Use the afterEach
function to define a callback in the client that updates the surface each time a worker sends the
current result.
D = [Link];
[Link](@(x) updateSurface(c, x));
2-61
2 Parallel for-Loops (parfor)
Use parfor to perform a parallel parameter sweep. Instruct the workers to solve the system for each
combination of the parameters in the meshgrid, and compute the mean period. Immediately send the
result of each iteration back to the client when the worker finishes computations.
parfor ii = 1:numel(N)
[t, y] = solveVdp(M(ii), N(ii));
l = islocalmax(y(:, 2));
send(D, [ii mean(diff(t(l)))]);
end
Scale Up to a Cluster
If you have access to a cluster, you can scale up your computation. To do this, delete the previous
parpool, and open a new one using the profile for your larger cluster. The code below shows a
cluster profile named 'MyClusterInTheCloud'. To run this code yourself, you must replace
'MyClusterInTheCloud' with the name of your cluster profile. Adjust the number of workers. The
example shows 4 workers. Increase the size of the overall computation by increasing the size of the
grid.
gridSize = 25;
delete(gcp('nocreate'));
parpool('MyClusterInTheCloud',4);
If you run the parameter sweep code again after setting the cluster profile, then the workers in the
cluster compute and send the results to the MATLAB® client when they become available. The
following animation shows an execution of this example in a cluster.
2-62
Plot During Parameter Sweep with parfor
Helper Functions
Create a helper function to define the system of equations, and apply the solver on it.
Declare a function for the DataQueue to update the graph with the results that come from the
workers.
function updateSurface(s, d)
[Link](d(1)) = d(2);
drawnow('limitrate');
end
See Also
gcp | [Link]
More About
• “Plot During Parameter Sweep with parfeval” on page 3-31
2-63
2 Parallel for-Loops (parfor)
x = 0; x2 = [];
parfor i = 1:10 n = 10;
x = x + i; parfor i = 1:n
end x2 = [x2, i];
x end
x2
x =
x2 =
55
1 2 3 4 5 6 7 8
If the loop iterations operate in a nondeterministic sequence, you might expect the concatenation
sequence in the example on the right to be nonconsecutive. However, MATLAB recognizes the
concatenation operation and yields deterministic results.
The next example, which attempts to compute Fibonacci numbers, is not a valid parfor-loop because
the value of an element of f in one iteration depends on the values of other elements of f calculated
in other iterations.
f = zeros(1,50);
f(1) = 1;
f(2) = 2;
parfor n = 3:50
f(n) = f(n-1) + f(n-2);
end
When you are finished with your loop examples, clear your workspace and delete your parallel pool of
workers:
clear
delete(gcp)
See Also
More About
• “Reduction Variables” on page 2-35
• “Ensure That parfor-Loop Iterations Are Independent” on page 2-10
2-64
Repeat Random Numbers in parfor-Loops
In a parfor-loop, you cannot control what sequence the iterations execute in, nor can you control
which worker runs which iterations. So even if you reset the random number generators, the parfor-
loop can generate the same values in a different sequence.
To reproduce the same set of random numbers in a parfor-loop each time the loop runs, you must
control random generation by assigning a particular substream for each iteration.
First, create the stream you want to use, using a generator that supports substreams. Creating the
stream as a [Link] allows all workers to access the stream.
sc = [Link](RandStream('Threefry'))
Inside the parfor-loop, you can set the substream index by the loop index. This ensures that each
iteration uses its particular set of random numbers, regardless of which worker runs that iteration or
what sequence iterations run in.
r = zeros(1,16);
parfor i = 1:16
stream = [Link]; % Extract the stream from the Constant
[Link] = i;
r(i) = rand(stream);
end
r
r =
Columns 1 through 8
Columns 9 through 16
See Also
RandStream | rng
More About
• “Control Random Number Streams on Workers” on page 5-15
• “Creating and Controlling a Random Number Stream”
2-65
2 Parallel for-Loops (parfor)
This example shows how to speed up Monte-Carlo code by using parfor-loops. Monte-Carlo methods
are found in many fields, including physics, mathematics, biology, and finance. Monte-Carlo methods
involve executing a function many times with randomly distributed inputs. With Parallel Computing
Toolbox™, you can replace a for-loop with a parfor-loop to easily speed up code.
This example runs a simple stochastic simulation based on the dollar auction. Run multiple
simulations to find the market value for a one dollar bill using a Monte-Carlo method. In this example,
the dollar auction is treated as a black-box function that produces outputs that depend on random
processes. To find out more about the model, see The Dollar Auction on page 2-66. To see how to
speed up Monte-Carlo code in general, see Use a parfor-loop to Estimate Market Value on page 2-
69.
The dollar auction is a non-zero-sum game first introduced by Martin Shubik in 1971. In the game,
players bid for a one dollar bill. After a player makes a bid, every other player can choose to make a
bid higher than the previous bidder. The auction ends when no more players decide to place a bid.
The highest bidder receives the one dollar bill, however, unlike a typical auction both the highest and
second-highest bidder give their bid to the auctioneer.
Stochastic Model
You can model games similar to the dollar auction using a stochastic model. The state (current bid
and number of active players) can be modeled using Markov processes, and therefore outcomes
(market value) can be expected to have well-defined statistics. The outcomes are drawn from a
conditional distribution, and therefore the dollar auction is ideal for Monte-Carlo analysis. The
market value is influenced by the following factors:
In this example, the following algorithm determines what actions players take (bidding or dropping
out) depending on the state.
2-66
Use parfor to Speed Up Monte-Carlo Code
The supporting function dollarAuction simulates a dollar auction. To view the code, see
dollarAuction.m. The function takes three inputs: nPlayers, incr, and dropoutRate. Set each
of the values.
nPlayers = ;
incr = ;
dropoutRate = ;
Run a random scenario by executing the dollarAuction function. Store the outputs bids and
dropouts.
[bids,dropouts] = dollarAuction(nPlayers,incr,dropoutRate);
As the game continues, some players place bids and some drop out. If the bid exceeds 1, the players
are locked in a "bidding war" until only one player remains.
The table dropouts contains two variables: Player, a unique number assigned to each player;
Epoch, the round of bidding when Player dropped out. Use findgroups to group
[Link], and use splitapply to get the number of players who drop out in each of the
unique rounds in [Link].
[G,epochs] = findgroups([Link]);
numberDropouts = splitapply(@numel,[Link],G);
Initially, there are no dropouts. Add this information to epochs and numberDropouts by prepending
1 and 0.
epochs = [1;epochs];
numberDropouts = [0;numberDropouts];
Use nPlayers and cumsum to calculate the number of players remaining from numberDropouts.
Calculate the bids using incr and epochs. Use stairs to plot the bid against the cumulative sum of
numberDropouts.
2-67
2 Parallel for-Loops (parfor)
You can estimate the market value of the bill with value origValue by using Monte-Carlo methods.
Here, you produce a Monte-Carlo model and compare the speed with and without Parallel Computing
Toolbox. Set the number of trials nTrials used to randomly sample the outcomes.
nTrials = 10000;
You can sample the possible outcomes by executing the supporting function dollarAuction
multiple times. Use a for-loop to produce nTrials samples, storing the last bid from each trial in B.
Each time you run the dollarAuction function, you get different results. However, when you run
the function many times, the results you produce from all of the runs will have well-defined statistics.
Record the time taken to compute nTrials simulations. To reduce statistical noise in the elapsed
time, repeat this process five times, then take the minimum elapsed time.
t = zeros(1,5);
for j = 1:5
tic
B = zeros(1,nTrials);
for i = 1:nTrials
bids = dollarAuction(nPlayers,incr,dropoutRate);
B(i) = [Link](end);
end
t(j) = toc;
end
forTime = min(t)
2-68
Use parfor to Speed Up Monte-Carlo Code
forTime = 21.4323
Use histogram to plot a histogram of the final bids B. Use xline to overlay the plot with the
original value (one dollar) and the average market value given by mean.
histogram(B);
origLine = xline(1,'k','LineWidth',3);
marketLine = xline(mean(B),'k--','LineWidth',3);
xlabel('Market value')
ylabel('Frequency')
legend([origLine, marketLine],{'Original value','Market value'},'Location','NorthEast')
With the given algorithm and input parameters, the average market value is greater than the original
value.
You can use Parallel Computing Toolbox to easily speed up your Monte-Carlo code. First, create a
parallel pool with four workers using the 'Processes' profile.
p = parpool('Processes',4);
Replace the for-loop with a parfor-loop. Record the time taken to compute nTrials simulations.
To reduce statistical noise in the elapsed time, repeat this process 5 times then take the minimum
elapsed time.
2-69
2 Parallel for-Loops (parfor)
t = zeros(1,5);
for j = 1:5
tic
parfor i = 1:nTrials
bids = dollarAuction(nPlayers,incr,dropoutRate);
B(i) = [Link](end);
end
t(j) = toc;
end
parforTime = min(t)
parforTime = 5.9174
With four workers, the results indicate that the code can runs over three times faster when you use a
parfor-loop.
When you generate random numbers in a parfor-loop, each run of the loop can produce different
results. To create reproducible results, each iteration of the loop must have a deterministic state for
the random number generator. For more information, see “Repeat Random Numbers in parfor-Loops”
on page 2-65.
When you create a stream, substreams of that stream are statistically independent. For more
information, see RandStream. To ensure that your code produces the same distribution of results
each time, create a random number generator stream in each iteration of the loop, then set the
Substream property to the loop index. Replace dollarAuction with dollarAuctionStream, then
use s to run dollarAuctionStream on a worker.
Record the time taken to compute nTrials simulations. To reduce statistical noise in the elapsed
time, repeat this process five times, then take the minimum elapsed time.
t = zeros(1,5);
for j = 1:5
tic
parfor i = 1:nTrials
s = RandStream('Threefry');
[Link] = i;
bids = dollarAuctionStream(nPlayers,incr,dropoutRate,s);
B(i) = [Link](end);
end
t(j) = toc;
end
parforTime = min(t)
parforTime = 8.7355
You can scale your code from your desktop to a cluster with more workers. For more information
about scaling up from desktop to a cluster, see “Scale Up from Desktop to Cluster” on page 7-49.
2-70
Use parfor to Speed Up Monte-Carlo Code
delete(p);
Compute the supporting function dollarAuctionStream in a parfor-loop. Run the same parfor-
loop with different numbers of workers, and record the elapsed times. To reduce statistical noise in
the elapsed time, run the parfor-loop five times, then take the minimum elapsed time. Record the
minimum times in the array elapsedTimes. In the following code, replace MyCluster with the
name of your cluster profile.
workers = [1 2 4 8 16 32];
elapsedTimes = zeros(1,numel(workers));
for k = 1:numel(workers)
t = zeros(1,5);
for j = 1:5
tic
parfor (i = 1:nTrials, workers(k))
s = RandStream('Threefry');
[Link] = i;
bids = dollarAuctionStream(nPlayers,incr,dropoutRate,s);
B(i) = [Link](end);
end
t(j) = toc;
end
elapsedTimes(k) = min(t);
end
2-71
2 Parallel for-Loops (parfor)
2-72
Compare Performance of Multithreading and ProcessPool
Compare how fast functions run on the client and on a ProcessPool. Some MATLAB® functions by
default already make use of multithreading on machines with many cores. Computations that use
these functions perform better when multiple threads are available than on a single thread.
Therefore, for multiple computations of one of these functions, parallel execution on a local parallel
pool with computationally single threaded workers can perform no better than execution on
multithreaded cores on the client. This effect can be exacerbated by the overheads associated with
parallelization.
The supporting function compareClientAndPool on page 2-76 listed at the end of this example
performs multiple executions of the specified function:
The syntax is similar to parfeval: use a function handle as the first argument, the number of
outputs as the second argument, and then give all required arguments for the function.
First, create a local ProcessPool to remove the overheads associated with starting a parallel pool.
p = parpool("Processes");
Compare the single threaded, multithreaded and pool execution times for the eig function using the
compareClientAndPool supporting function. Use @(N) eig(N) as the function handle.
2-73
2 Parallel for-Loops (parfor)
The parallel pool computes the answer faster than the client. When you compare the single threaded
time against the multithreaded time on the client, the results indicate eig is slower when run on
multithreaded cores. Therefore the eig function does not benefit from multithreading.
Calculate the speedup of running the eig function on a parallel pool by computing the ratio between
eigMulti and eigPool.
eigSpeedup = eigMulti/eigPool
eigSpeedup = 3.7398
The eig function achieved more than five times speedup on the pool because parfor executes the
iterations in parallel on workers that are single threaded by default.
Next, check how fast the mtimes function runs by using the compareClientAndPool supporting
function.
2-74
Compare Performance of Multithreading and ProcessPool
The parallel pool typically computes the answer faster than the client if your local machine has four
or more cores.
When you compare the single threaded time against the multithreaded time on the client, mtimes is
faster on multithreaded cores than single threaded. Therefore the mtimes function benefits from
multithreading.
mtimesSpeedup = 1.2938
The mtimes function achieved less speedup than the eig function because the mtimes function
performs better when multiple threads are available.
When you are done with your computations, you can delete the current parallel pool.
delete(p);
2-75
2 Parallel for-Loops (parfor)
The supporting function compareClientAndPool performs multiple computations on the client and
on the current parallel pool. It takes as input a function handle fcn and a variable number of input
arguments (in1, in2, ...). The compareClientAndPool function executes fcn(in1,
in2, ...) on the client with a single thread, client with multiple threads and the active parallel
pool. As an example, if you want to test rand(500), use compareClientAndPool(fcn,500) where
the function handle has the form:
% Use the number of workers in the pool to make the problem size proportional to the number of wo
numIterations = 40 * gcp().NumWorkers;
% Client - multithreaded
clear xCompThreads % Sets maxNumCompThreads("automatic")
timer = tic();
for i = 1:numIterations
out = fcn(in);
end
tMulti = toc(timer);
% Parallel pool
timer = tic();
parfor i = 1:numIterations
out = fcn(in);
end
tPool = toc(timer);
% Plot Results
x = categorical({'Single Threaded','Multithreaded','Parallel Pool'});
x = reordercats(x,{'Single Threaded','Multithreaded','Parallel Pool'});
y = [tSingle,tMulti,tPool];
comparePlot = bar(x,y);
xlabel("Execution Environment")
ylabel("Time (s)")
title(strcat("Comparison of ",func2str(fcn)," Execution Times"))
end
See Also
Related Examples
• Run MATLAB on multicore and multiprocessor machines
2-76
Compare Performance of Multithreading and ProcessPool
2-77
2 Parallel for-Loops (parfor)
If you use a UNIX® system (Linux® or Macintosh), it is recommended that you adjust your operating
system limits. Check and set limits with the ulimit or limit command, depending on your
installation. Note that these commands might require root access.
For example, these commands set the maximum number of user processes.
ulimit -u 23741
limit maxproc 23741
Changing a limit inside a shell affects only that shell and any subsequent MATLAB sessions you start
there. To make this setting persistent system-wide, you must modify the relevant file.
For more information on ulimit, limit, or [Link], see their man pages.
Without these settings, large parallel pools can error, hang, or lose workers during creation. These
problems occur when MATLAB attempts to create more user processes or file handles than your
operating system allows.
If you use a cluster of machines, you must set the maximum number of user processes for each
machine.
See Also
More About
• “What Is a Parallel Pool?” on page 1-28
2-78
3
You can evaluate a function in the background without waiting for it to complete, using parfeval. In
many cases, it can be convenient to break out of a for loop early. For example, in an optimization
procedure, you can stop the loop early when the result is good enough. You can do this on one or all
parallel pool workers, using parfeval or parfevalOnAll. This can be useful if you want to be able
to plot intermediate results. Note that this is different from using parfor, where you have to wait for
the loop to complete.
Use send and poll together to send and poll for messages or data from different workers using a
data queue. You can use afterEach to add a function to call when new data is received from a data
queue.
Use afterEach and afterAll to automatically invoke functions after each or after all elements of a
Future array complete. This array can contain futures returned by parfeval, parfevalOnAll,
afterEach or afterAll.
3-2
Evaluate Functions in the Background Using parfeval
This example shows how to solve a simple optimization problem by using parfeval to evaluate
functions in the background. When you use parfeval to evaluate functions in the background, you
create Future objects. You can collect the results as they become available and break out of the
optimization loop early when the result is good enough.
To reproduce the same computations later, seed the random generator with the default value.
rng("default")
The objective function objFun takes a row vector x as input and returns a scalar value representing
the output of the function. Define the objective function and the number of iterations for the
optimization loop. Randomly generate candidates for the x values to evaluate the objective function.
Initialize the minimum value and index variables.
Use parfeval to evaluate the objective function for each set of x candidates in the background.
When you use parfeval to run computations in the background, the function creates and adds a
Future object for each computation to the pool queue. Futures remain in the queue until a worker
becomes idle. When a worker becomes idle, it starts to compute a future if the queue is not empty.
When a worker completes a future, the future is removed from the queue and the worker becomes
idle.
f(1:numIterations) = [Link];
for i = 1:numIterations
f(i) = parfeval(objFun,1,xCandidates(i,:));
end
When a future completes, its State property becomes 'finished' and its Read property becomes
false. You can use the fetchNext function to retrieve the results from the futures as they finish.
After fetchNext retrieves the output from the next unread future in array f, MATLAB sets the Read
property of that future to true.
Run a for-loop with the same number of iterations as before. In each iteration, use fetchNext to
retrieve the next completed future's index and value. Next, compare the new value to the existing
minimum value, and update the minimum value and its index if a smaller value is found.
If a value less than or equal to 0.01 is found, display the solution and exit the loop early.
3-3
3 Asynchronous Parallel Programming
minFval = fval;
minIndex = completedIndex;
end
if minFval <= 0.01
fprintf("Best solution found: x = [%f,%f], fval = %f\n", ...
xCandidates(minIndex,1),xCandidates(minIndex,2),minFval);
break;
end
end
cancel(f);
clear f;
See Also
parfeval | backgroundPool
Related Examples
• “Query and Cancel parfeval Futures” on page 3-5
• “Plot During Parameter Sweep with parfeval” on page 3-31
3-4
Query and Cancel parfeval Futures
When you use parfeval or parfevalOnAll to run computations in the background, you create
objects called futures. You can use the State property of a future to find out whether it is running,
queued or finished. You can also use the FevalQueue property of a parallel pool to access running
and queued futures. To cancel futures, you can use the cancel function. In this example, you:
When you use parfeval to run computations in the background, the function creates and adds a
future for each computation to the pool queue. Tasks remain in the queue until a worker becomes
idle. When a worker becomes idle, it starts to compute a task if the queue is not empty. When a
worker completes a task, the task is removed from the queue and the worker becomes idle.
For efficiency, preallocate an array of future objects. Use parfeval to instruct the workers to
execute the function pause in the background. Use an argument of 1 for the third future, and an
argument of Inf for all other futures.
f(1:5) = [Link];
for n = 1:5
if n == 3
f(n) = parfeval(@pause,0,1);
else
f(n) = parfeval(@pause,0,Inf);
end
end
Each use of parfeval returns a future object that represents the execution of a function on a
worker. Except for the third future, every future will take an infinite amount of time to compute. The
future created by parfeval(@pause,0,Inf) is an extreme case of a future which can slow down a
queue.
You can use the State property to obtain the status of futures. Construct a cell array of the state of
each future in f.
{[Link]}
3-5
3 Asynchronous Parallel Programming
cancel(f(2));
{[Link]}
After you cancel the second future, the third future runs. Wait until the third future completes, then
examine the states again.
wait(f(3));
{[Link]}
When a future completes, its State property becomes 'finished'. To distinguish between futures
which are canceled and complete normally, use the Error property.
f(3):
The code cancels the second future, as the message property indicates. The second future was
canceled, as stated in the message property. The third future completes without error, and therefore
does not have an error message.
You can use the FevalQueue property to access the futures in the pool queue.
[Link]
ans =
FevalQueue with properties:
The queue has two properties: RunningFutures and QueuedFutures. The RunningFutures
property is an array of futures corresponding to tasks that are currently running.
disp([Link])
3-6
Query and Cancel parfeval Futures
--------------------------------------------------------
1 22 running @pause
2 25 running @pause
The QueuedFutures property is an array of futures corresponding to tasks that are currently queued
and not running.
disp([Link])
ID: 26
Function: @pause
CreateDateTime: 24-Oct-2023 17:28:51
StartDateTime:
RunningDuration: 0 days 0h 0m 0s
State: queued
Error: none
You can cancel a single future or an array of futures. Cancel all the futures in QueuedFutures.
cancel([Link]);
{[Link]}
RunningFutures and QueuedFutures are sorted from newest to oldest, regardless of whether f is
in order from newest to oldest. Each future has a unique ID property for the lifetime of the client.
Check the ID property of each of the futures in f.
disp(f)
for j = 1:length([Link])
rf = [Link](j);
fprintf("[Link](%i): ID = %i\n", j, [Link])
end
[Link](1): ID = 22
[Link](2): ID = 25
Here, RunningFutures is an array containing f(1) and f(4). If you cancel RunningFutures(2),
you cancel the fourth future f(4).
3-7
3 Asynchronous Parallel Programming
Sometimes, futures are not available in the workspace, for example, if you execute the same piece of
code twice before it finishes, or if you use parfeval in a function. You can cancel futures that are not
available in the workspace.
clear f
You can use RunningFutures and QueuedFutures to access futures that have not yet completed.
Use RunningFutures to cancel f(4).
rf2 = [Link](2);
cancel(rf2)
[Link]
ans =
'finished'
To cancel all the futures still in the queue, use this code.
cancel([Link]);
cancel([Link]);
3-8
Use afterEach and afterAll to Run Callback Functions
You create a Future when you run functions in the background or on a parallel pool using
parfeval, parfevalOnAll, afterEach, or afterAll. You can use afterEach and afterAll to
automatically run a callback function after one or more Future objects finish.
• If you use the afterEach function, MATLAB runs the callback function after each Future object
finishes. If the Future array has M elements, the MATLAB client runs the callback function M
times.
• If you use the afterAll function, MATLAB runs the callback function after all Future objects
finish. If the Future array has M elements, the MATLAB client runs the callback function only runs
once.
You can use afterEach to automatically invoke functions on each of the results of parfeval
computations.
Use parfeval to compute random vectors in the workers. With default settings, parfeval creates a
parpool automatically if there is not one already created.
Display the maximum element in each of those vectors after they are created. afterEach executes
the function handle on the output of each future when they become ready.
0.9975
0.9990
0.9982
0.9991
0.9982
0.9998
0.9999
3-9
3 Asynchronous Parallel Programming
0.9986
0.9996
0.9990
You can use afterAll to automatically invoke functions on all of the combined outputs of your
parfeval computations.
Use parfeval to compute random vectors in the workers. With default settings, parfeval creates a
parpool automatically if there is not one already created.
Display the maximum element among all of those vectors after they are created. afterAll executes
the function handle on the combined output of all the futures when they all become ready.
You can combine afterEach and afterAll to automatically invoke more functions on the results of
futures. Both afterEach and afterAll generate future variables that can be used again in
afterEach and afterAll.
Use parfeval to compute random vectors in the workers. With default settings, parfeval creates a
parpool automatically if there is not one already created.
Compute the largest element in each of those vectors when they become ready. afterEach executes
the function handle on the output of each future when they become ready and creates another future
to hold the results.
To compute the minimum value among them, call afterAll on this new future. afterAll executes a
function on the combined output arguments of all the futures after they all complete. In this case,
afterAll executes the function min on the outputs of maxFuture after completing and creates
another future to hold the result.
You can fetch the result using fetchOutputs. fetchOutput waits until the future completes to
gather the results.
3-10
Use afterEach and afterAll to Run Callback Functions
fetchOutputs(minFuture)
ans = 0.9970
You can check the result of afterEach by calling fetchOutputs on its future variable.
fetchOutputs(maxFuture)
ans = 10×1
0.9984
0.9996
1.0000
0.9999
0.9999
0.9970
0.9999
0.9998
0.9998
0.9997
This example shows how to update a user interface as computations complete. When you offload
computations to workers using parfeval, all user interfaces are responsive while workers perform
the computations. You can use waitbar to create a simple user interface.
• Use afterEach to update the user interface after each computation completes.
• Use afterAll to update the user interface after all the computations complete.
Use waitbar to create a figure handle, h. When you use afterEach or afterAll, the waitbar
function updates the figure handle. For more information about handle objects, see “Handle Object
Behavior”.
h = waitbar(0,'Waiting...');
Use parfeval to calculate the real part of the eigenvalues of random matrices. With default settings,
parfeval creates a parallel pool automatically if one has not already been created. For efficiency,
preallocate an array of Future objects.
f(1:100) = [Link];
for idx = 1:100
3-11
3 Asynchronous Parallel Programming
You can use afterEach to automatically invoke functions on each of the results of the parfeval
computations. Use afterEach to schedule another set of future objects to compute the largest value
in each of the output arrays after each future in the f completes.
maxFuture = afterEach(f,@max,1);
You can use the State property to obtain the status of futures. Define an anonymous function that
updates the fractional wait bar length of h to the fraction of Future objects that have finished
executing. The updateWaitbar anonymous function computes the mean of a logical array in which
an element is true if the State property of the corresponding Future object in f is "finished".
Use afterEach and updateWaitbar to update the fractional wait bar length after each future in
maxFuture completes. Use afterAll and delete to close the wait bar after all the computations
are complete.
updateWaitbarFutures = afterEach(f,updateWaitbar,0);
afterAll(updateWaitbarFutures,@(~) delete(h),0)
Use afterAll and histogram to show a histogram of the results in maxFuture after all the futures
complete.
showsHistogramFuture = afterAll(maxFuture,@histogram,0);
3-12
Use afterEach and afterAll to Run Callback Functions
When computations for future variables result in an error, by default, afterEach does not evaluate
its function on the elements that failed. If you want to handle any errors, for example, you have a user
interface that you want to update, you can use the name-value pair PassFuture. When set to true,
the future variable is passed to the callback function. You can call fetchOutputs on it, process the
outputs, and handle any possible errors.
3-13
3 Asynchronous Parallel Programming
Send computations to the workers using parfeval. With default settings, parfeval creates a
parpool automatically if there is not one already created. If your parfeval computations result in
an error, the future variable errors, and its Error property reflects it.
ans =
ParallelException with properties:
identifier: 'MATLAB:NonIntegerInput'
message: 'Size inputs must be integers.'
cause: {}
remotecause: {[1×1 MException]}
stack: [1×1 struct]
Correction: []
If you use afterEach on that future, the callback function is not evaluated on those elements in the
future that errored. In the code below, the msgbox is not executed because the future errors.
To handle futures that result in errors, use the name-value pair PassFuture when calling
afterEach. The future variable is passed to the callback function instead of its outputs. Call
fetchOutputs on the future variable, and process its outputs. If the future results in an error,
fetchOutputs throws an error that you can catch and handle. The following code shows an error
dialog box.
function handleError(f)
try
output = fetchOutputs(f);
% Do something with the output
catch
errordlg('Operation failed');
end
end
See Also
parfeval | parfevalOnAll | Future | afterEach | afterAll
3-14
Update User Interface Asynchronously Using afterEach and afterAll
This example shows how to update a user interface as computations complete. When you offload
computations to workers using parfeval, all user interfaces are responsive while workers perform
the computations. You can use waitbar to create a simple user interface.
• Use afterEach to update the user interface after each computation completes.
• Use afterAll to update the user interface after all the computations complete.
Use waitbar to create a figure handle, h. When you use afterEach or afterAll, the waitbar
function updates the figure handle. For more information about handle objects, see “Handle Object
Behavior”.
h = waitbar(0,'Waiting...');
Use parfeval to calculate the real part of the eigenvalues of random matrices. With default settings,
parfeval creates a parallel pool automatically if one has not already been created. For efficiency,
preallocate an array of Future objects.
f(1:100) = [Link];
for idx = 1:100
f(idx) = parfeval(@(n) real(eig(randn(n))),1,5e2);
end
You can use afterEach to automatically invoke functions on each of the results of the parfeval
computations. Use afterEach to schedule another set of future objects to compute the largest value
in each of the output arrays after each future in the f completes.
maxFuture = afterEach(f,@max,1);
You can use the State property to obtain the status of futures. Define an anonymous function that
updates the fractional wait bar length of h to the fraction of Future objects that have finished
executing. The updateWaitbar anonymous function computes the mean of a logical array in which
an element is true if the State property of the corresponding Future object in f is "finished".
updateWaitbar = @(~) waitbar(mean({[Link]} == "finished"),h);
Use afterEach and updateWaitbar to update the fractional wait bar length after each future in
maxFuture completes. Use afterAll and delete to close the wait bar after all the computations
are complete.
updateWaitbarFutures = afterEach(f,updateWaitbar,0);
afterAll(updateWaitbarFutures,@(~) delete(h),0)
3-15
3 Asynchronous Parallel Programming
Use afterAll and histogram to show a histogram of the results in maxFuture after all the futures
complete.
showsHistogramFuture = afterAll(maxFuture,@histogram,0);
See Also
“Asynchronous Parallel Programming”
3-16
Perform Webcam Image Acquisition in Parallel with Postprocessing
This example shows how to perform frame acquisition from a webcam in parallel with data
postprocessing.
In the example, you use a parallel worker to perform image acquisition and then stream the data back
to the client for postprocessing by using a DataQueue object.
To perform postprocessing using workers instead of your MATLAB® client, see “Perform Image
Acquisition and Parallel Image Processing” on page 3-19.
parpool('Processes',1);
To send information back from the worker to the MATLAB client, create a DataQueue object.
D = [Link];
Create a figure object, and set 'Visible' to 'on' so that it opens outside of the live script. To
display images every time they arrive from the DataQueue object, use afterEach.
fig = figure('Visible','on');
afterEach(D,@processDisp);
Define the frequency of acquisition, that is, how many frames per second you want to pull out from
the camera.
freq = 5;
Select a value that takes into account how long postprocessing takes. Otherwise the video stream can
significantly lag over time.
To start data acquisition on the parallel worker, call parfeval and pass the acquisition function, the
DataQueue object, and the acquisition rate as arguments.
f = parfeval(@getFrameFromCamera,0,D,freq);
Acquire frames for a period of 30 seconds. This example applies a blurring filter as the
postprocessing step and shows the original and processed frames side by side.
pause(30);
3-17
3 Asynchronous Parallel Programming
cancel(f);
For a more detailed example showing postprocessing on workers, see “Perform Image Acquisition and
Parallel Image Processing” on page 3-19.
The getFrameFromCamera function connects to the webcam, then acquires image frames and sends
them to the DataQueue object in an infinite loop.
function getFrameFromCamera(D,freq)
cam = webcam;
while true
img = snapshot(cam);
send(D,img);
pause(1/freq);
end
end
The processDisp function postprocesses frames and displays the original and processed frames
each time data arrives to the DataQueue object.
function processDisp(img)
imgBlur = imgaussfilt(img,3);
imshow([img, imgBlur],'Parent',gca)
end
See Also
parpool | [Link] | afterEach | parfeval | imshow
Related Examples
• “Perform Image Acquisition and Parallel Image Processing” on page 3-19
3-18
Perform Image Acquisition and Parallel Image Processing
This example shows how to perform image acquisition from a webcam and postprocess data in
parallel.
In this example, the MATLAB® client acquires frames from the video device and then offloads the
postprocessing to parallel workers, which filter off the noise from each frame using a denoising
neural network. The frames are then written into a video.
In this example, you use parfeval to perform postprocessing in the workers and
[Link] to instantiate the denoising network in the workers to be used during
postprocessing. To send the frames back from the workers and ensure that they are written in order,
this example uses an OrderedDataQueue object.
Clear previous image acquisition objects and extract information about the video device currently
connected to the machine.
objects = imaqfind;
delete(objects);
imaqreset;
deviceInfo = imaqhwinfo('winvideo')
Check if a folder for the output video already exists in the current directory. If no folder for output
video exists, create one.
if ~isfolder('OutputFolder')
mkdir OutputFolder
end
To write video data to an AVI file in the output folder, create a VideoWriter object.
videoOut = VideoWriter('OutputFolder/[Link]');
To enable the offloading of postprocessing to the workers, first start a parallel pool.
p = parpool('Processes');
Create a [Link] object to create a denoising network only once in the workers
and use it to filter the noise out from the frames.
C = [Link](@() denoisingNetwork('dncnn'));
3-19
3 Asynchronous Parallel Programming
To send the postprocessed frames back from the workers and write them in order, use an
OrderedDataQueue. Set a callback to write the frames to disk by using afterEach.
Q = OrderedDataQueue;
afterEach(Q,@(frame) writeVideo(videoOut,frame));
The OrderedDataQueue object is defined in a supporting file to this example. If you want to use it in
your own code, copy and place it with the rest of your files.
Create a video input object. Set the object to perform acquisition in the client frame by frame.
videoIn = videoinput('winvideo',1,'YUY2_800x600')
[Link] = 'RGB';
[Link] = Inf;
[Link] = 1;
Set the video writing frame rate to the same rate as for video reading, and open the video output
object.
src = [Link];
[Link] = str2double([Link]);
open(videoOut);
[Link] = {@postProcessAndWrite,C,Q};
start(videoIn);
Create a preview window. You can stop the video as soon as the preview is manually closed by using
waitfor on the figure handle hPreviewFig. For this example, stop video acquisition after 2
seconds.
hPreviewImg = preview(videoIn);
hPreviewFig = ancestor(hPreviewImg,'figure');
pause(2);
stop(videoIn);
3-20
Perform Image Acquisition and Parallel Image Processing
The postprocessing function stores a future variable in the UserData property of the video object.
This variable represents a future execution of the video write operations. To close the video writer
after all the data is written to the output file, use afterAll on this future variable.
postProcessFutures = [Link];
closeVideoFuture = afterAll(postProcessFutures,@() close(videoOut),0);
The postprocessing operation in this example is can take a few minutes. On a Windows 10, Intel®
Xeon® W-2133 3.60 GHz CPU, with 6 cores, postprocessing took 4 minutes.
You can use a waitbar to track the postprocessing progress. To update the waitbar after each
postprocessing operation finishes, use afterEach. To close the waitbar after all operations finish,
use afterAll. For more information, see “Update User Interface Asynchronously Using afterEach
and afterAll” on page 3-15.
h = waitbar(0,'Postprocessing...');
updateWaitbarFuture = afterEach(postProcessFutures, ...
@(~) waitbar(sum(strcmp('finished',{[Link]}))/numel(postProcessFutures),h),
afterAll(closeVideoFuture, @() close(h),0);
Block execution in the client session until the writing finishes by waiting for the future variable.
wait(closeVideoFuture);
delete(videoIn);
Visualize Results
After the video file has been created, you can visualize the results.
vidObj = VideoReader('OutputFolder/[Link]');
images = cell(1,5);
times = .4:.4:2;
for ii = 1:numel(times)
[Link] = times(ii);
images{ii} = readFrame(vidObj);
end
montage(images,'Size',[1 5])
3-21
3 Asynchronous Parallel Programming
Define the main postprocessing routine, which is executed after each frame acquisition. This function
postProcessAndWrite fetches the data from the video input object and calls parfeval to start the
frame denoising in a parallel worker.
function postProcessAndWrite(videoIn,~,C,Q)
[frame,~,metadata] = getdata(videoIn,1);
postProcessFuture = parfeval(@postProcess,0,frame,C,Q,[Link]);
[Link] = [[Link] postProcessFuture];
end
Define the postprocessing function to be executed in the worker. For this example, to simplify
computation, convert each frame to gray, and then denoise it by using the denoiseImage function.
The function postProcess takes the frame and the denoising network object stored in the Value
field of the [Link] object as inputs. For more information on denoising images
with a denoising neural network, see “Get Pretrained Image Denoising Network” (Image Processing
Toolbox).
function postProcess(frame,C,Q,frameNumber)
grayFrame = im2double(rgb2gray(frame));
denoisedGrayFrame = denoiseImage(grayFrame,[Link]);
denoisedGrayFrame = im2uint8(denoisedGrayFrame);
send(Q,frameNumber,denoisedGrayFrame)
end
See Also
parfeval | [Link] | imaqfind | videoinput | VideoWriter | afterAll |
afterEach | denoiseImage
Related Examples
• “Perform Webcam Image Acquisition in Parallel with Postprocessing” on page 3-17
More About
• “Get Started with Image Processing Toolbox” (Image Processing Toolbox)
• “Get Started with Image Acquisition Toolbox” (Image Acquisition Toolbox)
3-22
Receive Communication on Workers
This example shows how to set up a data queue on the workers to receive data.
You can use a PollableDataQueue to transfer data or messages between the client and workers. By
default, a PollableDataQueue object sends data only to the client or worker that creates it. To
enable workers to receive messages from the client using this default type, you create the
PollableDataQueue object on a workers and send it to the client. Starting in R2025a, you can
create another type of PollableDataQueue that allows the client or any worker in the pool to poll it
to receive data. For an example that uses this type of PollableDataQueue, see “Send Messages to
Workers Using Pollable Data Queues” on page 3-36.
This example generates instrument data on the workers and sends the data back to the client. To
start and stop the signal generation, the client can send a message to the workers using a data
queue. This approach provides a smoother way to stop a parfeval computation on a worker.
Prepare and initialize plots to visualize the instrument data from the workers. The createPlots on
page 3-25 function is defined at the end of the example.
[fig,p] = createPlots;
Create a DataQueue and use afterEach to specify the function to execute each time the queue
receives data. The receiveDataOnClient on page 3-26 function plots the data received from the
workers and is defined at the end of the example.
clientQueue = [Link];
afterEach(clientQueue,@(data) receiveDataOnClient(p,data));
Use parfeval to establish data queues on the three workers in the parallel pool. The
connectToWorker on page 3-25 helper function assigns a unique ID to each worker, creates a
PollableDataQueue on each worker, and sends the data queue to the client using the
helperClientQueue queue. The workers then wait for instructions from the client to start data
generation.
wkrF(1:3) = [Link];
for ID = 1:3
wkrF(ID) = parfeval(@connectToWorker,0,clientQueue,helperClientQueue,ID);
end
At the client, receive the labeled worker queues. You can now use these queues to send data to each
worker.
3-23
3 Asynchronous Parallel Programming
allWkrQueues = struct('ID',{},'Queue',{});
for i = 1:3
wkrQueue = poll(helperClientQueue,inf);
allWkrQueues([Link]) = wkrQueue;
end
for ID = 1:3
send(allWkrQueues(ID).Queue,"Start generating data");
end
This figure shows the instrument data each worker generates and sends to the client.
[Link]="on";
pause(10)
To stop gathering data on worker 2, send a message to the worker using the queue created on worker
2. You can observe that the line for Instrument 2 stops around 0.9 seconds.
send(allWkrQueues(2).Queue,"stop");
3-24
Receive Communication on Workers
[status, ~] = poll(helperClientQueue,inf);
disp(status)
Helper Functions
The connectToWorker function creates a PollableDataQueue on the workers, sends them to the
client, then polls the wkrQueue queue to wait for instructions from the client.
When the worker receives a message from the client, the function generates a dummy signal on the
workers that mimics continuous data from an instrument. At each time step, the worker sends one
point of the signal to the client with the clientQueue queue, then polls the wkrQueue queue to
check if the queue has data. If there is data to receive, the worker stops generating data and sends a
message to the client to confirm that it has stopped generating data.
function connectToWorker(clientQueue,helperClientQueue,ID)
% Assign an ID to this worker.
[Link] = ID;
% Create a PollableDataQueue on this specific worker.
[Link] = [Link];
% Send the queue to the client.
send(helperClientQueue,wkrQueue);
Define a function to prepare and initialize plots to visualize the data from the workers. Specify
different line properties for each worker.
3-25
3 Asynchronous Parallel Programming
Define a function to update the plots when the workers send data to the client.
function receiveDataOnClient(p,data)
addpoints(p(data{1,1}),data{1,2},data{1,3})
drawnow limitrate;
end
See Also
[Link] | [Link] | afterEach
Related Examples
• “Update User Interface Asynchronously Using afterEach and afterAll” on page 3-15
• “Perform Data Acquisition and Processing on Pool Workers” on page 3-47
3-26
Interactively Import and Process Data in Parallel
This example shows how to import and process data simultaneously in an interactive parallel pool. To
streamline your workflow, you can overlap parfeval and parfor computations on the same parallel
pool.
In this example, you import audio signals in the background with parfeval and simultaneously
perform some basic signal processing with parfor. The data import and processing approach
described in this example is generally applicable and is not reliant on the specific details of the
import and process functions.
Set Up
To simulate importing audio from a database, the example generates audio data using the
acquireAudio function, which is defined in a supporting file. The acquireAudio function also
partitions the audio into frames to facilitate parallelized audio processing. Before you start, specify
the number of audio files to import, as well as the duration and sample rate of the audio. Partition the
audio into 30 frames.
numAudio = 3;
audioDuration = 300;
sampleRate = 44100;
numFrames = 30;
The example stores the processed data in the parallel pool ValueStore object. To provide a visual
representation of the computation progress, use the waitbar function to create a simple user
interface. Set up an update function called handleValueStoreEntry to run each time an entry is
added to the ValueStore object. The handleValueStoreEntry on page 3-29 function, defined at
the end of the example, uses persistent to store information about the parfor iterations. To
initialize the persistent variables, run the handleValueStoreEntry function.
3-27
3 Asynchronous Parallel Programming
store = [Link];
[Link] = @(store,key) handleValueStoreEntry(store,key);
handleValueStoreEntry(numAudio,numFrames,analysisWaitBar);
Acquire and automatically process the audio data iteratively. To import the data, schedule the
acquireAudio function to run asynchronously with parfeval. To process the data in parallel, use
the processAudio function in a parfor-loop. The processAudio function is defined in a
supporting file to this example.
To minimize the waiting time for workers to receive data, stagger the computations. Submit a
parfeval computation to acquire the first audio before you start the for-loop.
importFuture = parfeval(@acquireAudio,1,audioDuration,numFrames,sampleRate);
for idx = 1:numAudio
% Retrieve audio data from the parfeval computation.
audio = fetchOutputs(importFuture);
% Schedule the next parfeval computation to run in the background.
if idx < numAudio
importFuture = parfeval(@acquireAudio,1,audioDuration,numFrames,sampleRate);
end
% Process the audio data.
parfor frame = 1:numFrames
store = getCurrentValueStore;
key = strcat("Audio_",num2str(idx),"_Frame_",num2str(frame));
% Perform some signal processing.
inputSignal = audio{1,frame};
store(key) = processAudio(inputSignal,sampleRate);
end
end
You can retrieve the processed audio from the ValueStore object for further computations. For
example, retrieve and plot the first frame of each audio using the plotFrame on page 3-30 function
defined at the end of the example.
3-28
Interactively Import and Process Data in Parallel
Clean Up
delete(analysisWaitBar);
delete(pool);
Helper Functions
Update a wait bar when an entry is added to the pool ValueStore by using persistent variables to
perform the counting.
function handleValueStoreEntry(numAudio,numFrames,analysisWaitBar)
persistent count currentAudio nAudio nFrames bar
if nargin == 3
% Initialize counting variables.
count = 0;
currentAudio = 1;
nAudio = numAudio;
nFrames = numFrames;
3-29
3 Asynchronous Parallel Programming
bar = analysisWaitBar;
fprintf("Wait bar counter reset to 0.")
else
count = count + 1;
progress = count/nFrames;
waitbar(progress,bar, ...
sprintf("Processing audio %d of %d",currentAudio,nAudio))
if count == nFrames
currentAudio = currentAudio + 1;
count = 0;
end
end
end
function plotFrames(t,plotData)
fig = figure(Name="First Frame of Each Audio");
tl = tiledlayout(fig,3,1);
for i=1:3
nexttile(tl);
plot(t,plotData(:,i));
title(sprintf("Audio %d",i))
end
title(tl,"First Frame of Each Audio")
xlabel(tl,"Time (s)");
ylabel(tl,"Amplitude");
end
See Also
parfor | parfeval
Related Examples
• “Perform Image Acquisition and Parallel Image Processing” on page 3-19
• “Send Messages to Workers Using Pollable Data Queues” on page 3-36
3-30
Plot During Parameter Sweep with parfeval
This example shows how to perform a parallel parameter sweep with parfeval and send results
back during computations with a DataQueue object.
parfeval does not block MATLAB, so you can continue working while computations take place.
The example performs a parameter sweep on the Lorenz system of ordinary differential equations, on
the parameters σ and ρ, and shows the chaotic nature of this system.
d
x=σ y−z
dt
d
y =x ρ−z −y
dt
d
z = xy − βx
dt
parpool("Threads");
Define the range of parameters that you want to explore in the parameter sweep.
gridSize = 40;
sigma = linspace(5,45,gridSize);
rho = linspace(50,100,gridSize);
beta = 8/3;
[rho,sigma] = meshgrid(rho,sigma);
After you define the parameters, you can perform the parallel parameter sweep.
To visualize the interim results of the parameter sweep, create a surface plot. Note that initializing
the Z component of the surface with NaN creates an empty plot.
figure;
surface = surf(rho,sigma,NaN(size(sigma)));
xlabel('\rho','Interpreter','Tex')
ylabel('\sigma','Interpreter','Tex')
3-31
3 Asynchronous Parallel Programming
To send interim data from the workers, create a DataQueue object. Set up a function that updates
the surface plot each time a worker sends data by using the afterEach function. The updatePlot
function is a supporting function defined at the end of the example.
Q = [Link];
afterEach(Q,@(data) updatePlot(surface,data));
parfeval works more efficiently when you distribute the workload. To distribute the workload,
group the parameters to explore into partitions. For this example, split into uniform partitions of size
step by using the colon operator (:). The resulting array partitions contains the boundaries of the
partitions. Note that you must add the end point of the last partition.
step = 100;
partitions = [1:step:numel(sigma),numel(sigma)+1]
partitions = 1×17
3-32
Plot During Parameter Sweep with parfeval
• Large enough that the computation time is large compared to the overhead of scheduling the
partition.
• Small enough that there are enough partitions to keep all workers busy.
To represent function executions on parallel workers and hold their results, use future objects.
f(1:numel(partitions)-1) = [Link];
for ii = 1:numel(partitions)-1
f(ii) = parfeval(@parameterSweep,1,partitions(ii),partitions(ii+1),sigma,rho,beta,Q);
end
parfeval does not block MATLAB, so you can continue working while computations take place. The
workers compute in parallel and send intermediate results through the DataQueue as soon as they
become available.
If you want to block MATLAB until parfeval completes, use the wait function on the future objects.
Using the wait function is useful when subsequent code depends on the completion of parfeval.
wait(f);
After parfeval finishes the computations, wait finishes and you can execute more code. For
example, plot a selection of the Lorenz system solutions. Use the fetchOutputs function to retrieve
the results stored in the future objects.
results = fetchOutputs(f);
idxs = randperm(numel(results),4);
figure
for n = 1:numel(idxs)
nexttile
a = results{idxs(n)};
plot3(a(:,1),a(:,2),a(:,3))
grid on
xlabel("x")
ylabel("y")
zlabel("z")
title("Lorenz System Solution", ...
"\rho = "+ num2str(rho(idxs(n)),'%5.2f') + " \sigma = "+ num2str(sigma(idxs(n)),'%5.2f'),
end
3-33
3 Asynchronous Parallel Programming
If your parameter sweep needs more computational resources and you have access to a cluster, you
can scale up your parfeval computations. For more information, see “Scale Up from Desktop to
Cluster” on page 7-49.
Define a helper function that solves the Lorenz system on a partition of the parameters to explore.
Send intermediate results to the MATLAB client by using the send function on the DataQueue
object.
function results = parameterSweep(first,last,sigma,rho,beta,Q)
results = cell(last-first,1);
for ii = first:last-1
lorenzSystem = @(t,a) [sigma(ii)*(a(2) - a(1)); a(1)*(rho(ii) - a(3)) - a(2); a(1)*a(2) -
[t,a] = ode45(lorenzSystem,[0 100],[1 1 1]);
send(Q,[ii,a(end,3)]);
results{ii-first+1} = a;
end
end
Define another helper function that updates the surface plot when new data arrives.
3-34
Plot During Parameter Sweep with parfeval
function updatePlot(surface,data)
[Link](data(1)) = data(2);
drawnow('limitrate');
end
See Also
parpool | [Link] | afterEach | parfeval
Related Examples
• “Plot During Parameter Sweep with parfor” on page 2-60
• “Scale Up from Desktop to Cluster” on page 7-49
3-35
3 Asynchronous Parallel Programming
This example shows how to use pollable data queues to send data or instructions to workers during
asynchronous function evaluations with parfeval.
You can use PollableDataQueue objects to transfer data and messages between the client and
workers in an interactive parallel pool. By default, a PollableDataQueue object sends the data only
to the client or worker that creates the PollableDataQueue object. However, starting in R2025a,
you can also create a type of PollableDataQueue object that allows the client or any worker in the
pool to poll and receive data.
This example demonstrates how to prepare workers to receive data or instructions you send from the
client using a PollableDataQueue object. You also use the PollableDataQueue object to
smoothly stop a parfeval computation on a worker. You can adapt this approach for any application
that requires sending additional instructions to a worker during an asynchronous parfeval
computation. To see an example of controlling a hardware device using a PollableDataQueue
object, see “Control Hardware and Acquire Data in Parallel” on page 3-39.
To enable communication from the worker to the client, create a PollableDataQueue object with
the Destination argument set to "any". This type of PollableDataQueue object allows both the
client and worker to send and receive messages.
To simplify the communication between the client and worker, create two PollableDataQueue
objects. The workerToClient queue sends messages from the worker to the client, while the
clientToWorker queue sends messages from the client to the worker.
workerToClient = [Link](Destination="any");
clientToWorker = [Link](Destination="any");
Define the function processData, which runs on the worker. The processData function waits for
data from the client, processes it, and sends status updates back to the client. The function stops
when it receives the "stop" message.
function out = processData(workerToClient,clientToWorker)
out = 0;
send(workerToClient,"Ready to receive data.");
while true
% Wait for a message
data = poll(clientToWorker,Inf);
if strcmp(data,"stop")
send(workerToClient,"Stopped processing data on worker.")
return
else
response = sprintf("Data %d received.",data(1));
send(workerToClient,response);
out = out+data(2);
pause(1);
end
3-36
Send Messages to Workers Using Pollable Data Queues
end
end
Use parfeval to execute the processData function and prepare the worker to start waiting for
messages from the client. parfeval computes the processData function asynchronously on a
worker and does not block the client.
future = parfeval(@processData,1,workerToClient,clientToWorker);
Poll the workerToClient queue to receive the initial status message from the worker.
status = poll(workerToClient,inf)
status =
"Ready to receive data."
In a loop, send data to the worker using the clientToWorker queue and poll the workerToClient
queue for confirmation before sending the next data point.
status =
"Data 1 received."
status =
"Data 2 received."
status =
"Data 3 received."
status =
"Data 4 received."
status =
"Data 5 received."
To stop the parfeval computation and terminate the processing loop on the worker, send a "stop"
message to the clientToWorker queue. If more than one worker is receiving data from the queue,
close the queue using the close function instead of sending multiple "stop" signals.
send(clientToWorker,"stop");
Poll for the final status message, wait for the parfeval computation to complete, and retrieve the
accumulated result using fetchOutputs.
status = poll(workerToClient,inf)
status =
"Stopped processing data on worker."
wait(future)
out = fetchOutputs(future)
out =
3.2311
3-37
3 Asynchronous Parallel Programming
See Also
Functions
poll | send | afterEach | parfeval
Objects
[Link] | [Link]
Related Examples
• “Receive Communication on Workers” on page 3-23
• “Control Hardware and Acquire Data in Parallel” on page 3-39
• “Perform Data Acquisition and Processing on Pool Workers” on page 3-47
3-38
Control Hardware and Acquire Data in Parallel
This example shows how to simultaneously control hardware and perform data acquisition on parallel
workers.
You can use the parfeval function to asynchronously control hardware and acquire data with
workers in a parallel pool. parfeval does not block the client, so you can continue to run
computations on the client or, like in this example, send instructions to the workers.
This example demonstrates how to set up workers for simultaneous hardware control and data
acquisition using a simulated test rig for a quarter-car suspension model. One worker controls an
actuator on the test rig, and the other workers acquire data from four sensors on the test rig and
send it to the client for visualization. To control the actuator, you send messages to a worker using a
PollableDataQueue object.
You can adapt this approach for any application that requires simultaneous control and monitoring or
data acquisition.
pool = parpool("Threads",5);
The actuator on the test rig follows a road profile to simulate road disturbances. Define the road
profile function and its parameters. The profile function models a road surface as a cosine wave, and
the parameters are frequency, disturbance duration, and time-step.
Create a figure and set up animated plots for visualizing the road displacement, suspension
deflection, body travel, and body acceleration.
[fig,p] = createPlot;
Create a DataQueue and use afterEach to specify the function to execute each time the queue
receives data. The displayOnClient function plots the data from the workers and is defined at the
end of the example.
resultsDq = [Link];
afterEach(resultsDq,@(readings) displayOnClient(p,readings));
To enable communication between the client and worker connected to the hardware device, create
PollableDataQueue objects with the Destination argument set to "any". This type of
PollableDataQueue object allows both the client and worker to send and receive messages.
3-39
3 Asynchronous Parallel Programming
workerToClientPdq = [Link](Destination="any");
clientToWorkerPdq = [Link](Destination="any");
To start collecting data from the different sensors, use parfeval to execute the readAndSend
function for each sensor. The readAndSend function is defined at the end of the example.
To perform real-time hardware control, you define the worker function, connect to the hardware and
send instructions to it, and then update the hardware parameters before stopping the process.
Define a function for the worker that allows dynamic control of a hardware device in real time. The
connectToActuator function performs initial hardware setup and signals readiness to the client
using the workerToClientPdq queue. The function waits for initial parameters from the
clientToWorkerPdq queue and begins generating and sending road profiles to the actuator based
on these parameters. In a loop, the function continues to send profiles while actively checking for
client instructions to update parameters or stop operations. The generateRoadProfile and
sendToActuator functions are included as supporting files to this example.
function connectToActuator(workerToClientPdq,clientToWorkerPdq)
% Perform additional hardware setup.
send(workerToClientPdq,"Ready");
% Wait for instructions.
params = poll(clientToWorkerPdq,inf);
send(workerToClientPdq,sprintf("Started sending road profiles to actuator."));
while true
3-40
Control Hardware and Acquire Data in Parallel
roadProfile = generateRoadProfile(params);
sendToActuator(roadProfile);
[change,OK] = poll(clientToWorkerPdq,[Link](end)-1);
if OK
if isstruct(change)
params = change;
send(workerToClientPdq,sprintf("Updated road profile parameters."));
else
strcmp(change,"stop")
send(workerToClientPdq,sprintf("Stopped sending profiles to actuator."));
return
end
end
end
end
Connect to Hardware
To instruct the worker to connect to the actuator, submit a parfeval computation to run the
connectToActuator function on a worker. Poll the workerToClientPdq queue to receive
confirmation, waiting indefinitely to ensure the actuator is ready to begin.
actuatorFuture = parfeval(@connectToActuator,0,workerToClientPdq,clientToWorkerPdq);
poll(workerToClientPdq,inf)
ans =
"Ready"
Next, use the clientToWorkerPdq queue to instruct the worker to start sending the road profiles to
the actuator. Receive confirmation from the worker.
send(clientToWorkerPdq,params);
poll(workerToClientPdq,inf)
ans =
"Started sending road profiles to actuator."
The parfeval function does not block the client, so you can continue working while the workers
continue their computations. For this example, use pause to allow the worker to send data to the
actuator for four seconds.
pause(4)
Use the clientToWorkerPdq queue to update the road profile parameters for the actuator. Change
the road profile function and send the updated parameters to the worker. You can see a change in the
road displacement plot after five seconds when the actuator receives the next road profile. Wait to
receive confirmation from the worker.
ans =
"Updated road profile parameters."
3-41
3 Asynchronous Parallel Programming
To stop sending profiles to the actuator and terminate the parfeval computation, send a "stop"
message to the worker. The road displacement plot shows a displacement of 0 after about 15 seconds.
Again, wait to receive confirmation.
pause(4)
send(clientToWorkerPdq,"stop");
poll(workerToClientPdq,2)
ans =
"Stopped sending profiles to actuator."
Wait for the sensor futures to complete and retrieve the sensor readings from the parfeval futures.
wait(sensorFutures);
[tAll,dAll] = fetchOutputs(sensorFutures);
Supporting Functions
readAndSend
The readAndSend helper function reads sensor data in one-second increments and sends it to the
client. The connectToSensor function simulates the reading of data from different sensors in a
quarter-car test rig and is attached to this example as a supporting file.
function [tAll,dAll] = readAndSend(sensorID,readDuration,resultDq)
tAll = [];
dAll = [];
for duration = 1:readDuration
[t,d] = connectToSensor(sensorID,1);
[Link] = sensorID;
readings.x = t;
readings.y = d;
tAll = [tAll,t];
dAll = [dAll,d];
send(resultDq,readings)
end
clear connectToSensor
end
displayOnClient
The displayOnClient function updates the animated plots with new data points received from the
sensors.
function displayOnClient(p,readings)
idx = [Link];
addpoints(p(idx),readings.x,readings.y)
drawnow limitrate;
end
createPlot
The createPlot function sets up the figure and animated lines for displaying the sensor readings.
function [fig,p] = createPlot
fig = figure(Name="Quarter Car Test Rig",Visible="off",Position=[263 429 1124 417]);
3-42
Control Hardware and Acquire Data in Parallel
See Also
Functions
poll | send | afterEach | parfeval
Objects
[Link] | [Link]
Related Examples
• “Send Messages to Workers Using Pollable Data Queues” on page 3-36
• “Receive Communication on Workers” on page 3-23
• “Perform Data Acquisition and Processing on Pool Workers” on page 3-47
3-43
3 Asynchronous Parallel Programming
This example shows how to use a pollable data queue to transfer data between workers during
asynchronous function evaluations with parfeval.
You can use PollableDataQueue objects to transfer data and messages between the client and
workers in an interactive parallel pool. By default, a PollableDataQueue object sends the data only
to the client or worker that creates the PollableDataQueue object. However, starting in R2025a,
you can also create a type of PollableDataQueue object that allows the client or any worker in the
pool to poll and receive data.
This example demonstrates how to set up workers to send and receive data from each other using a
PollableDataQueue object. You also use the PollableDataQueue object to smoothly stop a
parfeval computation on a worker. You can adapt this approach for any application that requires
communication between workers during an asynchronous parfeval computation. To see an example
that shows how to use this approach in a data acquisition and processing workflow, see “Perform
Data Acquisition and Processing on Pool Workers” on page 3-47.
Define a function for the first worker. The firstWorkerFcn function processes each element of the
input data by doubling it and then sends the result to the next worker through the queue. After
processing all data, the function sends a "stop" signal. If more than one worker is receiving data
from the queue, close the queue using the close function instead of sending multiple "stop"
signals.
function firstWorkerFcn(workerQueue,inData)
for idx = 1:numel(inData)
initialResult = inData(idx)*2;
send(workerQueue,initialResult);
end
send(workerQueue,"stop");
end
Define a function for the second worker. The secondWorkerFcn function continuously polls the
queue for data, processes each received value, and stores the results. The function stops processing
after receiving the "stop" signal.
function finalResults = secondWorkerFcn(workerQueue)
count = 0;
while true
data = poll(workerQueue,Inf);
if strcmp(data,"stop")
break;
3-44
Transfer Data Between Workers Using Pollable Data Queues
end
count = count+1;
finalResults(count,:) = [data data+1];
end
end
Create input data and use parfeval to execute the worker functions asynchronously. The first
worker processes the input data, and the second worker receives and further processes the results.
inData = 1:5;
futures(1) = parfeval(@firstWorkerFcn,0,queue,inData);
futures(2) = parfeval(@secondWorkerFcn,1,queue);
Wait for both workers to complete their tasks using wait, and then retrieve the final results from the
second worker using fetchOutputs.
wait(futures);
finalResults = fetchOutputs(futures(2));
plotWorkerOutput(inData,finalResults);
Helper Functions
Define a function to visualize the movement of data through the workers. The plotWorkerOutput
function plots the input data and the results from both workers, showing the transformation at each
step.
3-45
3 Asynchronous Parallel Programming
function plotWorkerOutput(inData,finalResults)
c = ["r","g","b","c","m"];
figure;
hold on;
for idx = 1:numel(inData)
plot([1, 2, 3],[inData(idx),finalResults(idx,1),finalResults(idx,2)],"-o"+c(idx),MarkerFaceCo
end
hold off;
ylabel("Output");
xticklabels(["","Client","Worker 1","Worker 2"]);
title("Data Movement Through Workers");
legend
grid on;
xticks(0:4);
xlim([0 4]);
end
See Also
Functions
poll | send | afterEach | parfeval
Objects
[Link] | [Link]
Related Examples
• “Perform Data Acquisition and Processing on Pool Workers” on page 3-47
• “Send Messages to Workers Using Pollable Data Queues” on page 3-36
• “Control Hardware and Acquire Data in Parallel” on page 3-39
3-46
Perform Data Acquisition and Processing on Pool Workers
This example shows how to implement a parallel data acquisition and processing pipeline on an
interactive parallel pool. The pipeline uses PollableDataQueue objects to facilitate data transfer
between workers in the parallel pool.
Starting in R2025a, you can create PollableDataQueue objects that the client or any worker can
poll for data. Use this type of PollableDataQueue object to transfer data or messages between
workers in pipeline workflows or in applications where multiple workers need access to a single
PollableDataQueue object.
This example demonstrates how to parallelize an image acquisition and processing pipeline. You can
adapt this approach to accelerate any pipeline workflow.
In this example, you capture streaming images of a simulated pendulum in motion. You then perform
real-time image processing and analysis on each frame to determine the center of the pendulum. In
this setup, one worker from the parallel pool acquires image data from a simulation and passes the
data to a PollableDataQueue object. Two other workers poll this queue to receive and process the
data and then send it to another PollableDataQueue object. A fourth worker polls this second
queue to receive and analyze the data, finally sending it to a DataQueue object with a callback
function that displays the results on the client.
pool = parpool("Processes",4);
Prepare and initialize plots to visualize data from the workers. The prepareDisplay function is
defined at the end of this example.
[fig,p,himage] = prepareDisplay;
To enable data transfer between the workers, create PollableDataQueue objects with the
Destination argument set to "any". When you set the Destination argument to "any", the
client or any worker can poll the resulting queue for data.
Create two PollableDataQueue objects with Destination set to "any" for the data acquisition
and processing stages of the pipeline.
3-47
3 Asynchronous Parallel Programming
acquisitionToProcessingPdq = [Link](destination="any");
processingToAnalysisPdq = [Link](destination="any");
Create an additional PollableDataQueue object to enable the client to send messages to the
worker performing the data acquisition.
stopSignalPdq = [Link](destination="any");
To visualize the processed images and result data on the client, create a DataQueue object,
displayResultsDq. Use the afterEach function to run the displayOnClient function when
workers send data to the displayResultsDq object. The displayOnClient function is defined at
the end of this example.
displayResultsDq = [Link];
afterEach(displayResultsDq,@(results) displayOnClient(p,himage,results));
To manage data flow and smoothly stop computations in the pipeline, define a different function for
each stage: data acquisition, data processing, and data analysis. Each function uses specific queues
to facilitate data transfer and communication between workers.
function acquireData(stopSignalPdq,acquisitionToProcessingPdq)
while isempty(poll(stopSignalPdq))
rawData = generateFrames(10);
send(acquisitionToProcessingPdq,rawData);
end
close(acquisitionToProcessingPdq);
clear generateFrames
send(stopSignalPdq,"Data acquisition stopped")
end
In the processData function, a worker polls the acquisitionToProcessingPdq queue for new
data, processes it, and sends the results to the processingToAnalysisPdq queue. The loop
continues until the worker running the data acquisition stage closes the
acquisitionToProcessingPdq queue. When the acquisitionToProcessingPdq queue is
closed and no data is available in the queue, poll returns the status indicator OK as false. The
worker then stops waiting for data and closes the processingToAnalysisPdq queue. The
processFrames function is attached to this example as a supporting file.
function processData(acquisitionToProcessingPdq,processingToAnalysisPdq)
OK = true;
while OK
[rawFrame,OK] = poll(acquisitionToProcessingPdq,Inf);
if OK
processedFrames = processFrames(rawFrame);
3-48
Perform Data Acquisition and Processing on Pool Workers
send(processingToAnalysisPdq,processedFrames);
end
end
close(processingToAnalysisPdq);
end
In the analyzeData function, a worker polls the processingToAnalysisPdq queue for processed
data, analyzes it, and sends the results to the displayResultsDq queue. The loop continues until a
worker running the previous stage closes the processingToAnalysisPdq queue and the worker
drains the queue. When the processingToAnalysisPdq queue is closed and no data is available in
the queue, poll returns the status indicator OK as false. The worker then stops waiting for data.
The findPendulumCenters function is attached to this example as a supporting file.
To execute a different function on each worker, use the parfeval function. parfeval allows you to
run tasks asynchronously without blocking MATLAB®.
captureF = parfeval(@acquireData,0,stopSignalPdq,acquisitionToProcessingPdq);
processFOne = parfeval(@processData,0,acquisitionToProcessingPdq,processingToAnalysisPdq);
processFTwo = parfeval(@processData,0,acquisitionToProcessingPdq,processingToAnalysisPdq);
Instruct the final worker to perform data analysis and send the results to the client.
analyzeF = parfeval(@analyzeData,1,processingToAnalysisPdq,displayResultsDq);
This figure displays the input frame, processed frame, and analysis results from the workers.
[Link]="on";
3-49
3 Asynchronous Parallel Programming
The parfeval function does not block MATLAB, so you can continue working while computations
take place. The workers process the different stages of the pipeline in parallel and send intermediate
results to the client as soon as they become available.
Send a message to the stopSignalPdq queue. The worker running the data acquisition periodically
polls this queue for messages. When the worker receives a message, the worker stops data
acquisition and closes the acquisitionToProcessingPdq queue.
send(stopSignalPdq,"stop");
Wait for the last worker in the pipeline to complete its parfeval computation.
wait(analyzeF);
Confirm that the data acquisition worker successfully stopped acquiring data.
status = poll(stopSignalPdq)
status =
"Data acquisition stopped"
Use the fetchOutputs function to retrieve the results from the analyzeF future object. Calculate
the pendulum length by fitting a circle through the pendulum centers and plot the results. For more
details, see the calculateAndPlotLength function attached to this example as a supporting file.
3-50
Perform Data Acquisition and Processing on Pool Workers
allCentroids = fetchOutputs(analyzeF);
calculateAndPlotLength(allCentroids);
Supporting Functions
displayOnClient
The displayOnClient function updates a figure plotting the detected pendulum centroids and
updating the image frames. It appends the new centroid coordinates to the plot and refreshes the
pendulum images with the latest input frame, region of interest (ROI), and processed frame.
function displayOnClient(p,himage,results)
centroids = [Link];
[Link] = [[Link] centroids(1)];
[Link] = [[Link] centroids(2)];
himage(1).CData = [Link];
himage(2).CData = [Link];
himage(3).CData = [Link];
drawnow limitrate nocallbacks;
end
prepareDisplay
The prepareDisplay function sets up a figure window with a tiled layout to display images and
plots related to pendulum tracking. The function creates a plot for tracking pendulum centers and
initializes image placeholders for displaying various stages of image processing.
3-51
3 Asynchronous Parallel Programming
himage = gobjects(1,3);
titleStr = ["Pendulum Simulation","Cropped Region","Segmented Pendulum"];
for n = 1:3
nexttile(n)
himage(n) = imshow(rand(480,640));
title(titleStr(n))
end
end
See Also
Functions
poll | send | afterEach | parfeval
Objects
[Link] | [Link]
Related Examples
• “Transfer Data Between Workers Using Pollable Data Queues” on page 3-44
• “Send Messages to Workers Using Pollable Data Queues” on page 3-36
• “Control Hardware and Acquire Data in Parallel” on page 3-39
More About
• “Get Started with Image Processing Toolbox” (Image Processing Toolbox)
3-52
4
You can use Parallel Computing Toolbox to distribute large arrays in parallel across multiple MATLAB
workers, so that you can run big-data applications that use the combined memory of your cluster. You
operate on the entire array as a single entity, however, workers operate only on their part of the
array, and automatically transfer data between themselves when necessary. Parallel Computing
Toolbox also enables you to execute MATLAB tall array and datastore calculations in parallel, so
that you can analyze big data sets that do not fit in the memory of your cluster. You can use MATLAB
Parallel Server to run tall array and datastore calculations in parallel on Spark enabled Hadoop
clusters. Doing so significantly reduces the execution time of very large data calculations.
If your data is currently in the memory of your local machine, you can use the distributed function
to distribute an existing array from the client workspace to the workers of a parallel pool. Distributed
arrays use the combined memory of multiple workers in a parallel pool to store the elements of an
array. For alternative ways of partitioning data, see “Distributing Arrays to Parallel Workers” on page
4-12. You operate on the entire array as a single entity, however, workers operate only on their part
of the array, and automatically transfer data between themselves when necessary. You can use
distributed arrays to scale up your big data computation. Consider distributed arrays when you have
access to a cluster, as you can combine the memory of multiple machines in your cluster.
A distributed array is a single variable, split over multiple workers in your parallel pool. You can
work with this variable as one single entity, without having to worry about its distributed nature. To
explore the functionalities available for distributed arrays in the Parallel Computing Toolbox, see
“Run MATLAB Functions with Distributed Arrays” on page 4-5.
When you create a distributed array, you cannot control the details of the distribution. On the
other hand, codistributed arrays allow you to control all aspects of distribution, including
dimensions and partitions. In the following, you learn how to create both distributed and
codistributed arrays.
• Use the distributed function to distribute an existing array from the client workspace to the
workers of a parallel pool.
• You can directly construct a distributed array on the workers. You do not need to first create the
array in the client, so that client workspace memory requirements are reduced. The functions
available include eye(___,"distributed"), rand(___,"distributed"), etc. For a full list,
see the Alternative Functionality section of the distributed object reference page.
• To create a codistributed array inside an spmd statement, see “Single Program Multiple Data
(spmd)” on page 4-113. Then access it as a distributed array outside the spmd statement. This
lets you use distribution schemes other than the default.
In this example, you create an array in the client workspace, then turn it into a distributed array.
Create a magic 4-by-4 matrix on the client and distribute the matrix to the workers. View the results
on the client and display information about the variables.
A = magic(4);
B = distributed(A);
B
whos
4-2
Create and Use Distributed Arrays
You have created B as a distributed array, split over the workers in your parallel pool. This is
shown in the figure below. The distributed array is ready for further computations.
Close the pool after you have finished using the distributed array.
delete(gcp)
• “Partitioning a Larger Array” on page 4-40 — Start with a large array that is replicated on all
workers, and partition it so that the pieces are distributed across the workers. This is most useful
when you have sufficient memory to store the initial replicated array.
• “Building from Smaller Arrays” on page 4-40 — Start with smaller replicated arrays stored on
each worker, and combine them so that each array becomes a segment of a larger codistributed
array. This method reduces memory requirements as it lets you build a codistributed array from
smaller pieces.
• “Using MATLAB Constructor Functions” on page 4-41 — Use any of the MATLAB constructor
functions like rand or zeros with a codistributor object argument. These functions offer a quick
means of constructing a codistributed array of any size in just one step.
In this example, you create a codistributed array inside an spmd statement, using a nondefault
distribution scheme.
In an spmd statement, define a 1-D distribution along the third dimension, with 4 parts on worker 1,
and 12 parts on worker 2. Then create a 3-by-3-by-16 array of zeros. View the codistributed array
on the client and display information about the variables.
spmd
codist = codistributor1d(3,[4,12]);
Z = zeros(3,3,16,codist);
Z = Z + spmdIndex;
end
Z
whos
Close the pool after you have finished using the codistributed array.
delete(gcp)
4-3
4 Big Data Processing
For more details on codistributed arrays, see “Working with Codistributed Arrays” on page 4-38.
See Also
Related Examples
• “Distributing Arrays to Parallel Workers” on page 4-12
• “Big Data Workflow Using Tall Arrays and Datastores” on page 4-93
• “Single Program Multiple Data (spmd)” on page 4-113
4-4
Run MATLAB Functions with Distributed Arrays
n = 1000;
D = distributed(gallery("lehmer",n));
e = eig(D);
If any of the input arguments to these distributed-enabled functions is a distributed array, their
output arrays are distributed, unless returning MATLAB data is more appropriate (for example,
numel).
Distributed arrays are well suited for large mathematical computations, such as large problems of
linear algebra. You can also use distributed arrays for big data processing. For more information on
distributing arrays, see “Distributing Arrays to Parallel Workers” on page 4-12.
Tip For a filtered list of all MATLAB functions that support distributed arrays, see Function List
(Distributed Arrays).
You can browse functions that support distributed arrays from all MathWorks products at the
following link: All Functions List (Distributed Arrays). Alternatively, you can filter by product. On the
Help bar, click Functions. In the function list, browse the left pane to select a product, for example,
MATLAB. At the bottom of the left pane, select Distributed Arrays. If you select a product that does
not have distributed-enabled functions, then the Distributed Arrays filter is not available.
For information about updates to individual distributed-enabled functions, see the release notes.
To check support for sparse distributed arrays, consult the following section.
4-5
4 Big Data Processing
In this section...
“Introduction” on page 4-6
“When to Use spmd” on page 4-6
“Define an spmd Statement” on page 4-6
“Display Output” on page 4-8
“MATLAB Path” on page 4-8
“Error Handling” on page 4-8
“spmd Limitations” on page 4-8
Introduction
The single program multiple data (SPMD) language construct allows seamless interleaving of serial
and parallel programming. The spmd statement lets you define a block of code to run simultaneously
on multiple workers. Variables assigned inside the spmd statement on the workers allow direct access
to their values from the client by reference via Composite objects.
This chapter explains some of the characteristics of spmd statements and Composite objects.
The “multiple data” aspect means that even though the spmd statement runs identical code on all
workers, each worker can have different, unique data for that code. So multiple data sets can be
accommodated by multiple workers.
Typical applications appropriate for spmd are those that require running simultaneous execution of a
program on multiple data sets, when communication or synchronization is required between the
workers. Some common cases are:
• Programs that take a long time to execute — spmd lets several workers compute solutions
simultaneously.
• Programs operating on large data sets — spmd lets the data be distributed to multiple workers.
For more information, see “Choose Between spmd, parfor, and parfeval” on page 4-30.
spmd
<statements>
end
4-6
Run Single Programs on Multiple Data Sets
Note If a parallel pool is not running, with default parallel settings, spmd creates a pool using your
default cluster profile.
The block of code represented by <statements> executes in parallel simultaneously on all workers
in the parallel pool. If you want to limit the execution to only a portion of these workers, specify
exactly how many workers to run on:
spmd (n)
<statements>
end
This statement requires that n workers run the spmd code. n must be less than or equal to the
number of workers in the open parallel pool. If the pool is large enough, but n workers are not
available, the statement waits until enough workers are available. If n is 0, the spmd statement uses
no workers, and runs locally on the client, the same as if there were not a pool currently running.
spmd (m,n)
<statements>
end
In this case, the spmd statement requires a minimum of m workers, and it uses a maximum of n
workers.
If it is important to control the number of workers that execute your spmd statement, set the exact
number in the cluster profile or with the spmd statement, rather than using a range.
spmd (3)
R = rand(4,4);
end
Note All subsequent examples in this chapter assume that a parallel pool is open and remains open
between sequences of spmd statements.
Unlike a parfor-loop, the workers used for an spmd statement each have a unique value for
spmdIndex. This lets you specify code to be run on only certain workers, or to customize execution,
usually for the purpose of accessing unique data.
spmd (3)
if spmdIndex==1
R = rand(9,9);
else
R = rand(4,4);
end
end
Load unique data on each worker according to spmdIndex, and use the same function on each
worker to compute a result from the data:
4-7
4 Big Data Processing
spmd (3)
labdata = load(['datafile_' num2str(spmdIndex) '.ascii'])
result = MyFunction(labdata)
end
The workers executing an spmd statement operate simultaneously and are aware of each other. As
with a communicating job, you are allowed to directly control communications between the workers,
transfer data between them, and use codistributed arrays among them.
spmd (3)
RR = rand(30, codistributor());
end
Each worker has a 30-by-10 segment of the codistributed array RR. For more information about
codistributed arrays, see “Working with Codistributed Arrays” on page 4-38.
Display Output
When running an spmd statement on a parallel pool, all command-line output from the workers
displays in the client Command Window. Because the workers are MATLAB sessions without displays,
any graphical output (for example, figure windows) from the pool does not display at all.
MATLAB Path
All workers executing an spmd statement must have the same MATLAB search path as the client, so
that they can execute any functions called in their common block of code. Therefore, whenever you
use cd, addpath, or rmpath on the client, it also executes on all the workers, if possible. For more
information, see the parpool reference page. When the workers are running on a different platform
than the client, use the function pctRunOnAll to properly set the MATLAB path on all workers.
Error Handling
When an error occurs on a worker during the execution of an spmd statement, the error is reported
to the client. The client tries to interrupt execution on all workers, and throws an error to the user.
Errors and warnings produced on workers are annotated with the worker ID (spmdIndex) and
displayed in the client's Command Window in the order in which they are received by the MATLAB
client.
The behavior of lastwarn is unspecified at the end of an spmd if used within its body.
spmd Limitations
Nested Functions
Inside a function, the body of an spmd statement cannot reference a nested function. However, it can
call a nested function by means of a variable defined as a function handle to the nested function.
Because the spmd body executes on workers, variables that are updated by nested functions called
inside an spmd statement are not updated in the workspace of the outer function.
4-8
Run Single Programs on Multiple Data Sets
The body of an spmd statement cannot directly contain another spmd. However, it can call a function
that contains another spmd statement. The inner spmd statement does not run in parallel in another
parallel pool, but runs serially in a single thread on the worker running its containing function.
Nested parfor-Loops
An spmd statement cannot contain a parfor-loop, and the body of a parfor-loop cannot contain an
spmd statement.
The body of an spmd statement cannot contain break, continue, or return statements. Consider
parfeval or parfevalOnAll instead of spmd, because you can use cancel on them.
The body of an spmd statement cannot contain global or persistent variable declarations. The
reason is that these variables are not synchronized between workers. You can use global or
persistent variables within functions, but their value is only visible to the worker that creates
them. Instead of global variables, it is a better practice to use function arguments to share values.
Anonymous Functions
The body of an spmd statement cannot define an anonymous function. However, it can reference an
anonymous function by means of a function handle.
inputname Functions
Using inputname to return the workspace variable name corresponding to an argument number is
not supported inside spmd. The reason is that spmd workers do not have access to the workspace of
the MATLAB desktop. To work around this, call inputname before spmd, as shown in the following
example.
a = 'a';
myFunction(a)
function X = myFunction(a)
name = inputname(1);
spmd
X.(name) = spmdIndex;
end
X = [X{:}];
end
load Functions
The syntaxes of load that do not assign to an output structure are not supported inside spmd
statements. Inside spmd, always assign the output of load to a structure.
4-9
4 Big Data Processing
The reason is that workers do not have access to the workspace of the MATLAB desktop. To work
around this, call these functions before spmd.
myFunction('a','b')
function myFunction(a,b)
nin = nargin;
spmd
X = spmdIndex*nin;
end
end
P-Code Scripts
You can call P-code script files from within an spmd statement, but P-code scripts cannot contain an
spmd statement. To work around this, use a P-code function instead of a P-code script.
ans Variable
References to the ans variable defined outside an spmd statement are not supported inside the spmd
statement. Inside the body of an spmd statement, you must assign the ans variable before you use it.
Composites and distributed arrays must appear as their own top-level variables within an spmd
statement and must not be hidden inside other data containers such as structures, cell arrays, or
objects.
In this example, you store the Composite object C in a cell array Y, which you then use as an input
variable in an spmd statement. As a result, MATLAB issues a warning at run time:
spmd; C = 5; end
Y = {C};
spmd
disp(Y)
end
Similarly, you cannot use Composite or distributed arrays stored in an object such as a dictionary
in an spmd statement. In this example, dd is an invalid distributed array and CC is an invalid
Composite:
spmd; C = 5; d = ones(7,"codistributed"); end
X = dictionary(["dist","comp"],{d,C});
spmd
dd = X{"dist"}
CC = X{"comp"}
end
As a workaround, extract the Composite or distributed array from the data structure and assign it to
a separate variable before the spmd statement:
spmd; C = 5; d = ones(7,"codistributed"); end
X = dictionary(["dist","comp"],{d,C});
4-10
Run Single Programs on Multiple Data Sets
dd = X{"dist"};
CC = X{"comp"};
spmd
disp(dd)
disp(CC)
end
See Also
spmd | parfor | parfeval | parfevalOnAll | distributed | Composite
More About
• “Ensure Transparency in parfor-Loops or spmd Statements” on page 2-51
• “Choose Between spmd, parfor, and parfeval” on page 4-30
4-11
4 Big Data Processing
• If your data is currently in the memory of your local machine, you can use the distributed
function to distribute an existing array from the client workspace to the workers of a parallel pool.
This option can be useful for testing or before performing operations which significantly increase
the size of your arrays, such as repmat.
• If your data does not fit in the memory of your local machine, but does fit in the memory of your
cluster, you can use datastore with the distributed function to read data into the memory of
the workers of a parallel pool.
• If your data does not fit in the memory of your cluster, you can use datastore with tall arrays
to partition and process your data in chunks. See also “Big Data Workflow Using Tall Arrays and
Datastores” on page 4-93.
This example shows how to create and load distributed arrays using datastore. Create a datastore
using a tabular file of airline flight data. This data set is too small to show equal partitioning of the
data over the workers. To simulate a large data set, artificially increase the size of the datastore using
repmat.
[Link] = {'DepTime','DepDelay'};
[Link] = 'NA';
Create a distributed table by reading the datastore in parallel. Partition the datastore with one
partition per worker. Each worker then reads all data from the corresponding partition. The files must
be in a shared location that is accessible by the workers.
dt = distributed(ds);
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
summary(dt)
4-12
Distributing Arrays to Parallel Workers
Variables:
min 1
max 2505
NaNs 23,510
min -1036
max 1438
NaNs 23,510
size(dt)
ans =
1235230 2
head(dt)
ans =
DepTime DepDelay
_______ ________
642 12
1021 1
2055 20
1332 12
629 -1
1446 63
928 -2
859 -1
1833 3
1041 1
Worker 1:
Worker 2:
4-13
4 Big Data Processing
Worker 3:
Worker 4:
Note that the data is partitioned equally over the workers. For more details on datastore, see
“What Is a Datastore?”
For more details about workflows for big data, see “Choose a Parallel Computing Solution” on page 1-
5.
• Use the distributed function to distribute an existing array from the client workspace to the
workers of a parallel pool.
• Use any of the distributed functions to directly construct a distributed array on the workers.
This technique does not require that the array already exists in the client, thereby reducing client
workspace memory requirements. Functions include eye(___,'distributed') and
rand(___,'distributed'). For a full list, see the distributed object reference page.
• Create a codistributed array inside an spmd statement, and then access it as a distributed array
outside the spmd statement. This technique lets you use distribution schemes other than the
default.
The first two techniques do not involve spmd in creating the array, but you can use spmd to
manipulate arrays created this way. For example:
Create an array in the client workspace, and then make it a distributed array.
parpool('Processes',2) % Create pool
W = ones(6,6);
W = distributed(W); % Distribute to the workers
spmd
T = W*2; % Calculation performed on workers, in parallel.
% T and W are both codistributed arrays here.
end
4-14
Distributing Arrays to Parallel Workers
Alternatively, you can use the codistributed function, which allows you to control more options
such as dimensions and partitions, but is often more complicated. You can create a codistributed
array by executing on the workers themselves, either inside an spmd statement or inside a
communicating job. When creating a codistributed array, you can control all aspects of
distribution, including dimensions and partitions.
The relationship between distributed and codistributed arrays is one of perspective. Codistributed
arrays are partitioned among the workers from which you execute code to create or manipulate them.
When you create a distributed array in the client, you can access it as a codistributed array inside an
spmd statement. When you create a codistributed array in an spmd statement, you can access it as a
distributed array in the client. Only spmd statements let you access the same array data from two
different perspectives.
Create a codistributed array inside an spmd statement using a nondefault distribution scheme. First,
define 1-D distribution along the third dimension, with 4 parts on worker 1, and 12 parts on worker 2.
Then create a 3-by-3-by-16 array of zeros.
For more details on codistributed arrays, see “Working with Codistributed Arrays” on page 4-38.
See Also
distributed | codistributed | tall | datastore | spmd | repmat | eye | rand
Related Examples
• “Run MATLAB Functions with Distributed Arrays” on page 4-5
• “Big Data Workflow Using Tall Arrays and Datastores” on page 4-93
• “What Is a Datastore?”
4-15
4 Big Data Processing
More About
• “Datastore”
• “Tall Arrays for Out-of-Memory Data”
4-16
Access Worker Variables with Composites
Introduction to Composites
Composite objects in the MATLAB client session let you directly access data values on the workers.
Most often you assigned these variables within spmd statements. In their display and usage,
Composites resemble cell arrays. There are two ways to create Composites:
• Use the Composite function on the client. Values assigned to the Composite elements are stored
on the workers.
• Define variables on workers inside an spmd statement. After the spmd statement, the stored
values are accessible on the client as Composites.
After the spmd statement, those data values are accessible on the client as Composites. Composite
objects resemble cell arrays, and behave similarly. On the client, a Composite has one element per
worker. For example, suppose you create a parallel pool of three local workers and run an spmd
statement on that pool:
parpool("Processes",3)
ans =
8 1 6
3 5 7
4 9 2
MM{2}
ans =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A variable might not be defined on every worker. For the workers on which a variable is not defined,
the corresponding Composite element has no value. Trying to read that element throws an error.
4-17
4 Big Data Processing
spmd
if spmdIndex > 1
HH = rand(4);
end
end
HH
HH =
Worker 1: No data
Worker 2: class = double, size = [4 4]
Worker 3: class = double, size = [4 4]
You can also set values of Composite elements from the client. This causes a transfer of data, storing
the value on the appropriate worker even though it is not executed within an spmd statement:
MM{3} = eye(4);
In this case, MM must already exist as a Composite, otherwise MATLAB interprets it as a cell array.
Now when you do enter an spmd statement, the value of the variable MM on worker 3 is as set:
spmd
if spmdIndex == 3, MM, end
end
Worker 3:
MM =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Data transfers from worker to client when you explicitly assign a variable in the client workspace
using a Composite element:
M =
8 1 6
3 5 7
4 9 2
Assigning an entire Composite to another Composite does not cause a data transfer. Instead, the
client merely duplicates the Composite as a reference to the appropriate data stored on the workers:
However, accessing a Composite's elements to assign values to other Composites does result in a
transfer of data from the workers to the client, even if the assignment then goes to the same worker.
In this case, NN must already exist as a Composite:
delete(gcp)
4-18
Access Worker Variables with Composites
The values are retained on the workers until the corresponding Composites are cleared on the client,
or until the parallel pool is deleted. The following example illustrates data value lifespan with spmd
blocks, using a pool of four workers:
parpool('Processes',4)
spmd
AA = spmdIndex; % Initial setting
end
AA(:) % Composite
ans =
{[1]}
{[2]}
{[3]}
{[4]}
spmd
AA = AA * 2; % Multiply existing value
end
AA(:) % Composite
ans =
{[2]}
{[4]}
{[6]}
{[8]}
spmd
AA = AA * 2;
end % Generates error
delete(gcp)
Analyzing and transferring files to the workers ...done.
Error detected on workers 2 3 4.
Caused by:
An UndefinedFunction error was thrown on the workers for 'AA'.
This may be because the file containing 'AA' is not accessible on the workers.
Specify the required files for this parallel pool
using the command: addAttachedFiles(pool, ...).
See the documentation for parpool for more details.
Unrecognized function or variable 'AA'.
4-19
4 Big Data Processing
PP = Composite()
By default, this creates a Composite with an element for each worker in the parallel pool. You can
also create Composites on only a subset of the workers in the pool. See the Composite reference page
for more details. The elements of the Composite can now be set as usual on the client, or as variables
inside an spmd statement. When you set an element of a Composite, the data is immediately
transferred to the appropriate worker:
for ii = 1:numel(PP)
PP{ii} = ii;
end
See Also
Composite | spmd
Related Examples
• “Working with Codistributed Arrays” on page 4-38
4-20
Use spmdReduce to Achieve MPI_Allreduce Functionality
In this example, we look at the spmdReduce function and the functions that build on it: spmdPlus
and spmdCat. These seemingly simple functions turn out to be very powerful tools in parallel
programming.
The spmdReduce function allows us to perform any associative binary operation on a variable that is
defined on all workers. This allows us not only to sum a variable across all workers, but also to find its
minimum and maximum across all the workers, concatenate them, and perform many other useful
operations.
function paralleltutorial_gop
Introduction
When doing parallel programming, we often run into the situation of having a variable defined on all
workers, and we want to perform an operation on the variable as it exists on all workers. For
example, if we enter an spmd statement and define
spmd
x = spmdIndex;
end
on all workers, we might want to calculate the sum of the values of x across the workers. This is
exactly what the spmdPlus operation does, it sums the x across the workers and duplicates the
result on all workers:
spmd
s = spmdPlus(x);
end
The variables assigned to inside an spmd statement are represented on the client as Composite. We
can bring the resulting values from the workers to the client by indexing into the Composite much
like that of cell arrays:
s{1} % Display the value of s on worker 1. All workers store the same value.
ans =
21
Also, spmdReduce, spmdPlus, and spmdCat allow us to specify a single worker to which the function
output should be returned, and they return an empty vector on the other workers.
spmd
s = spmdPlus(x, 1);
end
s{1}
ans =
4-21
4 Big Data Processing
21
This example shows how to perform a host of operations similar to addition across all workers. In
MPI, these are known as collective operations, such as MPI_SUM, MPI_PROD, MPI_MIN, MPI_MAX,
etc.
The data we use for all our examples is very simple: a 1-by-2 variant array that is only slightly more
complicated than the x we defined in the beginning:
spmd
x = spmdIndex + (1:2)
end
Now that we have initialized our vector x to different values on the workers, we can ask questions
such as what is the element-by-element sum of the values of x across the workers? What about the
product, the minimum, and the maximum? As to be expected from our introduction,
spmd
s = spmdPlus(x);
end
s{1}
ans =
27 33
returns the element-by-element addition of the values of x. However, spmdPlus is only a special case
of the spmdReduce operation. The spmdReduce function allows us to perform any associative
operation across the workers on the elements of a variant array. The most basic example of an
associative operation is addition; it is associative because addition is independent of the grouping
which is used:
(a + b) + c = a + (b + c)
In MATLAB®, addition can be denoted by the @plus function handle, so we can also write
spmdPlus(x) as
spmd
s = spmdReduce(@plus, x);
end
s{1}
ans =
27 33
We can concatenate the vector x across the workers by using the spmdCat function, and we can
choose the dimension to concatenate along.
4-22
Use spmdReduce to Achieve MPI_Allreduce Functionality
spmd
y1 = spmdCat(x, 1); % Concatenate along rows.
y2 = spmdCat(x, 2); % Concatenate along columns.
end
y1{1}
y2{1}
ans =
2 3
3 4
4 5
5 6
6 7
7 8
ans =
2 3 3 4 4 5 5 6 6 7 7 8
It is simple to calculate the element-by-element product of the values of x across the workers:
spmd
p = spmdReduce(@times, x);
end
p{1}
ans =
5040 20160
spmd
M = spmdReduce(@max, x);
m = spmdReduce(@min, x);
end
M{1}
m{1}
ans =
7 8
ans =
2 3
4-23
4 Big Data Processing
Logical Operations
MATLAB has even more built-in associative operations. The logical AND, OR, and XOR operations are
represented by the @and, @or, and @xor function handles. For example, look at the logical array
spmd
y = (x > 4)
end
We can then easily perform these logical operations on the elements of y across the workers:
spmd
yand = spmdReduce(@and, y);
yor = spmdReduce(@or, y);
yxor = spmdReduce(@xor, y);
end
yand{1}
yor{1}
yxor{1}
ans =
0 0
ans =
1 1
ans =
1 0
Bitwise Operations
To conclude our tour of the associative operations that are built into MATLAB, we look at the bitwise
AND, OR, and XOR operations. These are represented by the @bitand, @bitor, and @bitxor
function handles.
spmd
xbitand = spmdReduce(@bitand, x);
xbitor = spmdReduce(@bitor, x);
xbitxor = spmdReduce(@bitxor, x);
end
xbitand{1}
xbitor{1}
xbitxor{1}
ans =
4-24
Use spmdReduce to Achieve MPI_Allreduce Functionality
0 0
ans =
7 15
ans =
1 11
We need to do just a little bit of programming to find the spmdIndex corresponding to where the
element-by-element maximum of x across the workers occurs. We can do this in just a few lines of
code:
type pctdemo_aux_gop_maxloc
and when the function has been implemented, it can be applied just as easily as any of the built-in
operations:
spmd
[maxval, maxloc] = pctdemo_aux_gop_maxloc(x);
end
[maxval{1}, maxloc{1}]
ans =
7 8 6 6
4-25
4 Big Data Processing
Similarly, we only need a few lines of code to find the spmdIndex where the element-by-element
minimum of x across the workers occurs:
type pctdemo_aux_gop_minloc
spmd
[minval, minloc] = pctdemo_aux_gop_minloc(x);
end
[minval{1}, minloc{1}]
ans =
2 3 1 1
See Also
spmd | spmdReduce | spmdPlus | spmdCat
Related Examples
• “Numerical Estimation of Pi Using Message Passing” on page 4-27
4-26
Numerical Estimation of Pi Using Message Passing
This example shows the basics of working with spmd statements, and how they provide an interactive
means of performing parallel computations. We do this by performing relatively simple computations
to approximate pi.
function paralleldemo_quadpi_mpi
Introduction
We intend to have the parallel pool perform the calculations in parallel, and to use the spmd keyword
to mark the parallel blocks of code. We first look at the size of the parallel pool that is currently open.
p = gcp;
[Link]
ans =
type pctdemo_aux_quadpi.m
function y = pctdemo_aux_quadpi(x)
%PCTDEMO_AUX_QUADPI Return data to approximate pi.
% Helper function used to approximate pi. This is the derivative
% of 4*atan(x).
We divide the work between the workers by having each worker calculate the integral of the function
over a subinterval of [0, 1] as shown in the picture.
4-27
4 Big Data Processing
We define the variables a and b on all the workers, but let their values depend on spmdIndex so that
the intervals [a, b] correspond to the subintervals shown in the figure. We then verify that the
intervals are correct. Note that the code in the body of the spmd statement is executed in parallel on
all the workers in the parallel pool.
spmd
a = (spmdIndex - 1)/spmdSize;
b = spmdIndex/spmdSize;
fprintf('Subinterval: [%-4g, %-4g]\n', a, b);
end
We let all the workers now use a MATLAB quadrature method to approximate each integral. They all
operate on the same function, but on the different subintervals of [0,1] shown in the figure above.
spmd
myIntegral = integral(@pctdemo_aux_quadpi, a, b);
fprintf('Subinterval: [%-4g, %-4g] Integral: %4g\n', ...
a, b, myIntegral);
end
The workers have all calculated their portions of the integral of the function, and we add the results
together to form the entire integral over [0, 1]. We use the spmdPlus function to add myIntegral
across all the workers and return the sum on all the workers.
4-28
Numerical Estimation of Pi Using Message Passing
spmd
piApprox = spmdPlus(myIntegral);
end
Since the variable piApprox was assigned to inside an spmd statement, it is accessible on the client
as a Composite. Composite objects resemble cell arrays with one element for each worker. Indexing
into a Composite brings back the corresponding value from the worker to the client.
pi : 3.141592653589793116
Approximation: 3.141592653589793116
Error : 0
See Also
spmd | spmdPlus
Related Examples
• “Use spmdReduce to Achieve MPI_Allreduce Functionality” on page 4-21
4-29
4 Big Data Processing
Use spmd if you require fine-grained worker-to-worker communication and collaboration between
workers during a computation. parfor, parfeval, and parfevalOnAll do not allow
communication between workers. Computations with spmd can involve communication between
workers using the spmdSend, spmdReceive, and spmdSendReceive functions.
If you are unsure, ask yourself the following: within my parallel code, can each computation be
completed without any communication between workers? If yes, use parfor or parfeval.
Otherwise, use spmd.
Use spmd if your computations involve large arrays distributed across workers. You can perform
simultaneous calculations on all workers or perform customized calculations on specific workers.
When workers run an spmd block, each worker is assigned a unique index, the spmdIndex. This lets
you specify code to be run only on certain workers, and target sections of distributed arrays.
When choosing between parfor, parfeval, and spmd, consider whether your calculation requires
synchronization with the client.
parfor and spmd require synchronization, and therefore block you from running any new
computations on the MATLAB client. parfeval does not require synchronization, so you can
continue to use the client.
spmd and parfeval have other capabilities you can use after you have submitted your computations.
• With spmd, you can collect results computed inside the spmd statement without transferring the
results to the client. Access the values of the variables assigned inside the spmd statement as
Composite objects from the client. For more information, see “Access Worker Variables with
Composites” on page 4-17.
• When you submit a parfeval task, MATLAB schedules the task to run asynchronously and
returns Future objects before the submitted task finishes running. A Future object represents
the task that MATLAB has scheduled. You can interact with Future objects in different ways:
4-30
Choose Between spmd, parfor, and parfeval
• Use fetchNext to retrieve results as they become available or check if results are ready.
• Stop parfeval calculations from running using the cancel function.
• Use Future objects in other computation on the client.
Using spmd can be slower or faster than using parfor-loops or parfeval, depending on the type of
computation. Overhead affects the relative performance of parfor-loops, parfeval, and spmd.
For a set of tasks, parfor and parfeval typically perform better than spmd under these conditions:
In this example, you examine the speed at which the software performs matrix operations when using
a parfor-loop, parfeval, and spmd.
p = parpool("Processes");
Examine the speed at which the software can generate random matrices by using a parfor-loop,
parfeval, and spmd. Set the number of trials (n) and the matrix size (for an m-by-m matrix).
Increasing the number of trials improves the statistics used in later analysis, but does not affect the
calculation itself.
m = ;
n = ;
Then, use a parfor-loop to execute rand(m) once for each worker. Time each of the n trials.
parforTime = zeros(n,1);
for i = 1:n
tic;
mats = cell(1,[Link]);
parfor N = 1:[Link]
mats{N} = rand(m);
end
parforTime(i) = toc;
end
4-31
4 Big Data Processing
Next, use parfeval to execute rand(m) once for each worker. Time each of the n trials.
parfevalTime = zeros(n,1);
for i = 1:n
tic;
f(1:[Link]) = [Link];
for N = 1:[Link]
f(N) = parfeval(@rand,1,m);
end
mats = fetchOutputs(f);
parfevalTime(i) = toc;
clear f
end
Finally, use spmd to execute rand(m) once for each worker. You can use spmdCat to concatenate the
values of mat on each worker into array mats and store it on worker 1. For details on workers and
how to execute commands on them with spmd, see “Run Single Programs on Multiple Data Sets” on
page 4-6. Time each of the n trials.
spmdTime = zeros(n,1);
for i = 1:n
tic;
spmd
mat = rand(m);
mats = spmdCat({mat}, 1, 1);
end
allMats = mats{1};
spmdTime(i) = toc;
end
Use rmoutliers to remove the outliers from each of the trials. Then, use boxplot to compare the
times.
% Hide outliers
boxData = rmoutliers([parforTime parfevalTime spmdTime]);
% Plot data
boxplot(boxData, 'labels',{'parfor','parfeval','spmd'}, 'Symbol','')
ylabel('Time (seconds)')
title('Make n Random Matrices (m-by-m)')
4-32
Choose Between spmd, parfor, and parfeval
Typically, spmd requires more overhead per evaluation than parfor or parfeval. Therefore, in this
case, using a parfor-loop or parfeval is more efficient.
Next, compute the sum of random matrices. You can do this by using a reduction variable with a
parfor-loop, a sum after computations with parfeval, or spmdPlus with spmd. Again, set the
number of trials (n) and the matrix size (for an m-by-m matrix).
m = ;
n = ;
Then, use a parfor-loop to execute rand(m) once for each worker. Compute the sum with a
reduction variable. Time each of the n trials.
parforTime = zeros(n,1);
for i = 1:n
tic;
result = 0;
4-33
4 Big Data Processing
parfor N = 1:[Link]
result = result + rand(m);
end
parforTime(i) = toc;
end
Next, use parfeval to execute rand(m) once for each worker. Use fetchOutputs to fetch all of the
matrices, then use sum. Time each of the n trials.
parfevalTime = zeros(n,1);
for i = 1:n
tic;
f(1:[Link]) = [Link];
for N = 1:[Link]
f(N) = parfeval(@rand,1,m);
end
result = sum(fetchOutputs(f));
parfevalTime(i) = toc;
clear f
end
Finally, use spmd to execute rand(m) once for each worker. Use spmdPlus to sum all of the
matrices. To send the result only to the first worker, set the optional target worker argument to 1.
Time each of the n trials.
spmdTime = zeros(n,1);
for i = 1:n
tic;
spmd
r = spmdPlus(rand(m), 1);
end
result = r{1};
spmdTime(i) = toc;
end
Use rmoutliers to remove the outliers from each of the trials. Then, use boxplot to compare the
times.
% Hide outliers
boxData = rmoutliers([parforTime parfevalTime spmdTime]);
% Plot data
boxplot(boxData, 'labels',{'parfor','parfeval','spmd'}, 'Symbol','')
ylabel('Time (seconds)')
title('Sum of n Random Matrices (m-by-m)')
4-34
Choose Between spmd, parfor, and parfeval
For this calculation, spmd is faster than a parfor-loop or parfeval. When you use reduction
variables in a parfor-loop, each worker performs a local reduction before sending its partial result
back to the client to compute the final result.
By contrast, spmd calls spmdPlus only once to do a global reduction operation, requiring less
overhead. As such, the overhead for the reduction part of the calculation is O(n2) for spmd, and
O(mn2) for parfor.
See Also
spmd | parfor | parfeval
More About
• “Run Single Programs on Multiple Data Sets” on page 4-6
• “Distribute Arrays and Run SPMD” on page 4-113
4-35
4 Big Data Processing
Introduction
Many built-in data types and data structures supported by MATLAB software are also supported in
the MATLAB parallel computing environment. This includes arrays of any number of dimensions
containing numeric, character, logical values, cells, or structures. In addition to these basic building
blocks, the MATLAB parallel computing environment also offers different types of arrays.
Nondistributed Arrays
When you create a nondistributed array, MATLAB constructs a separate array in the workspace of
each worker, using the same variable name on all workers. Any operation performed on that variable
affects all individual arrays assigned to it. If you display from worker 1 the value assigned to this
variable, all workers respond by showing the array of that name that resides in their workspace.
The state of a nondistributed array depends on the value of that array in the workspace of each
worker:
Replicated Arrays
A replicated array resides in the workspaces of all workers, and its size and content are identical on
all workers. When you create the array, MATLAB assigns it to the same variable on all workers. If you
display in spmd the value assigned to this variable, all workers respond by showing the same array.
Variant Arrays
A variant array also resides in the workspaces of all workers, but its content differs on one or more
workers. When you create the array, MATLAB assigns a different value to the same variable on all
workers. If you display the value assigned to this variable, all workers respond by showing their
version of the array.
4-36
Nondistributed Versus Distributed Arrays
A replicated array can become a variant array when its value becomes unique on each worker.
spmd
B = magic(3); %replicated on all workers
B = B + spmdIndex; %now a variant array, different on each worker
end
Private Arrays
A private array is defined on one or more, but not all workers. You could create this array by using
spmdIndex in a conditional statement, as shown here:
spmd
if spmdIndex >= 3, A = magic(3) + spmdIndex - 1, end
end
Codistributed Arrays
With replicated and variant arrays, the full content of the array is stored in the workspace of each
worker. Codistributed arrays, on the other hand, are partitioned into segments, with each segment
residing in the workspace of a different worker. Each worker has its own array segment to work with.
Reducing the size of the array that each worker has to store and process means a more efficient use
of memory and faster processing, especially for large data sets.
This example distributes a 3-by-10 replicated array A across four workers. The resulting array D is
also 3-by-10 in size, but only a segment of the full array resides on each worker.
spmd
A = [11:20; 21:30; 31:40];
D = codistributed(A);
getLocalPart(D)
end
For more details on using codistributed arrays, see “Working with Codistributed Arrays” on page 4-
38.
4-37
4 Big Data Processing
For example, to distribute an 80-by-1000 array to four workers, you can partition it either by columns,
giving each worker an 80-by-250 segment, or by rows, with each worker getting a 20-by-1000
segment. If the array dimension does not divide evenly over the number of workers, MATLAB
partitions it as evenly as possible.
The following example creates an 80-by-1000 replicated array and assigns it to variable A. In doing
so, each worker creates an identical array in its own workspace and assigns it to variable A, where A
is local to that worker. The second command distributes A, creating a single 80-by-1000 array D that
spans all four workers. Worker 1 stores columns 1 through 250, worker 2 stores columns 251 through
500, and so on. The default distribution is by the last nonsingleton dimension, thus, columns in this
case of a 2-dimensional array.
spmd
A = zeros(80, 1000);
D = codistributed(A)
end
Each worker has access to all segments of the array. Access to the local segment is faster than to a
remote segment, because the latter requires sending and receiving data between workers and thus
takes more time.
4-38
Working with Codistributed Arrays
For each worker, the MATLAB Parallel Command Window displays information about the
codistributed array, the local portion, and the codistributor. For example, an 8-by-8 identity matrix
codistributed among four workers, with two columns on each worker, displays like this:
>> spmd
II = eye(8,"codistributed")
end
Worker 1:
This worker stores II(:,1:2).
LocalPart: [8x2 double]
Codistributor: [1x1 codistributor1d]
Worker 2:
This worker stores II(:,3:4).
LocalPart: [8x2 double]
Codistributor: [1x1 codistributor1d]
Worker 3:
This worker stores II(:,5:6).
LocalPart: [8x2 double]
Codistributor: [1x1 codistributor1d]
Worker 4:
This worker stores II(:,7:8).
LocalPart: [8x2 double]
Codistributor: [1x1 codistributor1d]
To see the actual data in the local segment of the array, use the getLocalPart function.
In distributing an array of N rows, if N is evenly divisible by the number of workers, MATLAB stores
the same number of rows (N/spmdSize) on each worker. When this number is not evenly divisible by
the number of workers, MATLAB partitions the array as evenly as possible.
MATLAB provides codistributor object properties called Dimension and Partition that you can use
to determine the exact distribution of an array. See “Indexing into a Codistributed Array” on page 4-
45 for more information on indexing with codistributed arrays.
You can distribute arrays of any MATLAB built-in data type, and also numeric arrays that are complex
or sparse, but not arrays of function handles or object types.
• “Partitioning a Larger Array” on page 4-40 — Start with a large array that is replicated on all
workers, and partition it so that the pieces are distributed across the workers. This is most useful
when you have sufficient memory to store the initial replicated array.
• “Building from Smaller Arrays” on page 4-40 — Start with smaller variant or replicated arrays
stored on each worker, and combine them so that each array becomes a segment of a larger
codistributed array. This method reduces memory requirements as it lets you build a codistributed
array from smaller pieces.
4-39
4 Big Data Processing
• “Using MATLAB Constructor Functions” on page 4-41 — Use any of the MATLAB constructor
functions like rand or zeros with a codistributor object argument. These functions offer a quick
means of constructing a codistributed array of any size in just one step.
If you have a large array already in memory that you want MATLAB to process more quickly, you can
partition it into smaller segments and distribute these segments to all of the workers using the
codistributed function. Each worker then has an array that is a fraction the size of the original,
thus reducing the time required to access the data that is local to each worker.
As a simple example, the following line of code creates a 4-by-8 replicated matrix on each worker
assigned to the variable A:
The next line uses the codistributed function to construct a single 4-by-8 matrix D that is
distributed along the second dimension of the array:
spmd
D = codistributed(A);
getLocalPart(D)
end
Arrays A and D are the same size (4-by-8). Array A exists in its full size on each worker, while only a
segment of array D exists on each worker.
Examining the variables in the client workspace, an array that is codistributed among the workers
inside an spmd statement, is a distributed array from the perspective of the client outside the spmd
statement. Variables that are not codistributed inside the spmd are Composites in the client outside
the spmd.
whos
Name Size Bytes Class Attributes
See the codistributed function reference page for syntax and usage information.
The codistributed function is less useful for reducing the amount of memory required to store
data when you first construct the full array in one workspace and then partition it into distributed
segments. To save on memory, you can construct the smaller pieces (local part) on each worker first,
4-40
Working with Codistributed Arrays
and then use [Link] to combine them into a single array that is distributed across
the workers.
This example creates a 4-by-250 variant array A on each of four workers and then uses
codistributor to distribute these segments across four workers, creating a 16-by-250
codistributed array. Here is the variant array, A:
spmd
A = [1:250; 251:500; 501:750; 751:1000] + 250 * (spmdIndex - 1);
end
Now combine these segments into an array that is distributed by the first dimension (rows). The array
is now 16-by-250, with a 4-by-250 segment residing on each worker:
spmd
D = [Link](A, codistributor1d(1,[4 4 4 4],[16 250]))
end
Worker 1:
This worker stores D(1:4,:).
LocalPart: [4x250 double]
Codistributor: [1x1 codistributor1d]
whos
Name Size Bytes Class Attributes
You could also use replicated arrays in the same fashion, if you wanted to create a codistributed array
whose segments were all identical to start with. See the codistributed function reference page for
syntax and usage information.
MATLAB provides several array constructor functions that you can use to build codistributed arrays
of specific values, sizes, and classes. These functions operate in the same way as their nondistributed
counterparts in the MATLAB language, except that they distribute the resultant array across the
workers using the specified codistributor object, codist.
Constructor Functions
The codistributed constructor functions are listed here. Use the codist argument (created by the
codistributor function: codist=codistributor()) to specify over which dimension to
distribute the array. See the individual reference pages for these functions for further syntax and
usage information.
eye(___,codist)
false(___,codist)
Inf(___,codist)
NaN(___,codist)
ones(___,codist)
rand(___,codist)
4-41
4 Big Data Processing
randi(___,codist)
randn(___,codist)
true(___,codist)
zeros(___,codist)
[Link](m,n,...,codist)
[Link](a,d,b)
[Link](m,n,...,codist)
[Link](m,n,...,codist)
sparse(m,n,codist)
[Link](m,...,codist)
[Link](m,n,density,codist)
[Link](m,n,density,codist)
Local Arrays
That part of a codistributed array that resides on each worker is a piece of a larger array. Each
worker can work on its own segment of the common array, or it can make a copy of that segment in a
variant or private array of its own. This local copy of a codistributed array segment is called a local
array.
The getLocalPart function copies the segments of a codistributed array to a separate variant array.
This example makes a local copy L of each segment of codistributed array D. The size of L shows that
it contains only the local part of D for each worker. Suppose you distribute an array across four
workers:
spmd(4)
A = [1:80; 81:160; 161:240];
D = codistributed(A);
size(D)
L = getLocalPart(D);
size(L)
end
3 80
3 20
Each worker recognizes that the codistributed array D is 3-by-80. However, notice that the size of the
local part, L, is 3-by-20 on each worker, because the 80 columns of D are distributed over four
workers.
Use the [Link] function to perform the reverse operation. This function, described
in “Building from Smaller Arrays” on page 4-40, combines the local variant arrays into a single array
distributed along the specified dimension.
Continuing the previous example, take the local variant arrays L and put them together as segments
to build a new codistributed array X.
spmd
codist = codistributor1d(2,[20 20 20 20],[3 80]);
4-42
Working with Codistributed Arrays
X = [Link](L,codist);
size(X)
end
3 80
The iscodistributed function returns a logical 1 (true) if the input array is codistributed, and
logical 0 (false) otherwise. The syntax is
The codistributor object determines how an array is partitioned and its dimension of distribution. To
access the codistributor of an array, use the getCodistributor function. This returns two
properties, Dimension and Partition:
Dimension: 2
Partition: [20 20 20 20]
The Dimension value of 2 means the array X is distributed by columns (dimension 2); and the
Partition value of [20 20 20 20] means that twenty columns reside on each of the four workers.
spmd
C = getCodistributor(X);
part = [Link]
dim = [Link]
end
Other functions that provide information about standard arrays also work on codistributed arrays and
use the same syntax.
4-43
4 Big Data Processing
• is* — Many functions that have names beginning with 'is', such as ischar and issparse.
Construct an 8-by-16 codistributed array D of random values distributed by columns on four workers:
spmd
D = rand(8,16,codistributor());
size(getLocalPart(D))
end
8 4
Create a new codistributed array distributed by rows from an existing one already distributed by
columns:
spmd
X = redistribute(D, codistributor1d(1));
size(getLocalPart(X))
end
2 16
4-44
Working with Codistributed Arrays
Restore the undistributed segments to the full array form by gathering the segments:
With codistributed arrays, these values are not so easily obtained. For example, the second segment
of an array (that which resides in the workspace of worker 2) has a starting index that depends on the
array distribution. For a 200-by-1000 array with a default distribution by columns over four workers,
the starting index on worker 2 is 251. For a 1000-by-200 array also distributed by columns, that same
index would be 51. As for the ending index, this is not given by using the end keyword, as end in this
case refers to the end of the entire array; that is, the last subscript of the final segment. The length of
each segment is also not given by using the length or size functions, as they only return the length
of the entire array.
The MATLAB colon operator and end keyword are two of the basic tools for indexing into
nondistributed arrays. For codistributed arrays, MATLAB provides a version of the colon operator,
called [Link]. This actually is a function, not a symbolic operator like colon.
Note When using arrays to index into codistributed arrays, you can use only replicated or
codistributed arrays for indexing. The toolbox does not check to ensure that the index is replicated,
as that would require global communications. Therefore, the use of unsupported variants (such as
spmdIndex) to index into codistributed arrays might create unexpected results.
Suppose you have a row vector of 1 million elements, distributed among several workers, and you
want to locate its element number 225,000. That is, you want to know what worker contains this
element, and in what position in the local part of the vector on that worker. The globalIndices
function provides a correlation between the local and global indexing of the codistributed array.
4-45
4 Big Data Processing
If you run this code on a pool of four workers you get this result:
Worker 1:
Element is in position 225000 on worker 1.
If you run this code on a pool of five workers you get this result:
Worker 2:
Element is in position 25000 on worker 2.
Notice if you use a pool of a different size, the element ends up in a different location on a different
worker, but the same code can be used to locate the element.
2-Dimensional Distribution
As an alternative to distributing by a single dimension of rows or columns, you can distribute a matrix
by blocks using '2dbc' or two-dimensional block-cyclic distribution. Instead of segments that
comprise a number of complete rows or columns of the matrix, the segments of the codistributed
array are 2-dimensional square blocks.
For example, consider a simple 8-by-8 matrix with ascending element values. You can create this
array in an spmd statement or communicating job.
spmd
A = reshape(1:64, 8, 8)
end
1 9 17 25 33 41 49 57
2 10 18 26 34 42 50 58
3 11 19 27 35 43 51 59
4 12 20 28 36 44 52 60
5 13 21 29 37 45 53 61
6 14 22 30 38 46 54 62
7 15 23 31 39 47 55 63
8 16 24 32 40 48 56 64
Suppose you want to distribute this array among four workers, with a 4-by-4 block as the local part
on each worker. In this case, the worker grid is a 2-by-2 arrangement of the workers, and the block
4-46
Working with Codistributed Arrays
size is a square of four elements on a side (i.e., each block is a 4-by-4 square). With this information,
you can define the codistributor object:
spmd
DIST = codistributor2dbc([2 2], 4);
end
Now you can use this codistributor object to distribute the original matrix:
spmd
AA = codistributed(A, DIST)
end
This distributes the array among the workers according to this scheme:
If the worker grid does not perfectly overlay the dimensions of the codistributed array, you can still
use '2dbc' distribution, which is block cyclic. In this case, you can imagine the worker grid being
repeatedly overlaid in both dimensions until all the original matrix elements are included.
Using the same original 8-by-8 matrix and 2-by-2 worker grid, consider a block size of 3 instead of 4,
so that 3-by-3 square blocks are distributed among the workers. The code looks like this:
spmd
DIST = codistributor2dbc([2 2], 3)
AA = codistributed(A, DIST)
end
The first “row” of the worker grid is distributed to worker 1 and worker 2, but that contains only six
of the eight columns of the original matrix. Therefore, the next two columns are distributed to worker
1. This process continues until all columns in the first rows are distributed. Then a similar process
applies to the rows as you proceed down the matrix, as shown in the following distribution scheme:
4-47
4 Big Data Processing
The diagram above shows a scheme that requires four overlays of the worker grid to accommodate
the entire original matrix. The following code shows the resulting distribution of data to each of the
workers.
spmd
getLocalPart(AA)
end
Worker 1:
ans =
1 9 17 49 57
2 10 18 50 58
3 11 19 51 59
7 15 23 55 63
8 16 24 56 64
Worker 2:
ans =
25 33 41
26 34 42
27 35 43
31 39 47
32 40 48
Worker 3:
ans =
4 12 20 52 60
5 13 21 53 61
6 14 22 54 62
Worker 4:
ans =
4-48
Working with Codistributed Arrays
28 36 44
29 37 45
30 38 46
• '2dbc' distribution might not offer any performance enhancement unless the block size is at least
a few dozen. The default block size is 64.
• The worker grid should be as close to a square as possible.
• Not all functions that are enhanced to work on '1d' codistributed arrays work on '2dbc'
codistributed arrays.
4-49
4 Big Data Processing
Note Using a for-loop over a distributed range (drange) is intended for explicit indexing of the
distributed dimension of codistributed arrays (such as inside an spmd statement or a communicating
job). For most applications involving parallel for-loops you should first try using parfor loops. See
“Parallel for-Loops (parfor)”.
Parallelizing a for-Loop
In some occasions you already have a coarse-grained application to perform, i.e. an application for
which the run time is significantly greater than the communication time needed to start and stop the
program. If you do not want to bother with the overhead of defining jobs and tasks, you can take
advantage of the ease-of-use that spmd provides. Where an existing program might take hours or
days to process all its independent data sets, you can shorten that time by distributing these
independent computations over your cluster.
The following changes make this code operate in parallel, either interactively in spmd or in a
communicating job:
Note that the length of the for iteration and the length of the codistributed array results need to
match in order to index into results within a for drange loop. This way, no communication is
required between the workers. If results was simply a replicated array, as it would have been when
running the original code in parallel, each worker would have assigned into its part of results,
leaving the remaining parts of results 0. At the end, results would have been a variant, and
without explicitly calling spmdSend and spmdReceive or spmdCat, there would be no way to get the
total results back to one (or all) workers.
4-50
Looping over a Distributed Range (for-drange)
When using the load function, you need to be careful that the data files are accessible to all workers
if necessary. The best practice is to use explicit paths to files on a shared file system.
Correspondingly, when using the save function, you should be careful to only have one worker save
to a particular file (on a shared file system) at a time. Thus, wrapping the code in if spmdIndex ==
1 is recommended.
Because results is distributed across the workers, this example uses gather to collect the data
onto worker 1.
A worker cannot plot a visible figure, so the print function creates a viewable file of the plot.
To illustrate this characteristic, you can try the following example, in which one for loop works, but
the other does not.
With spmd, create two codistributed arrays, one an identity matrix, the other set to zeros, distributed
across four workers.
D = eye(8, 8, codistributor())
E = zeros(8, 8, codistributor())
By default, these arrays are distributed by columns; that is, each of the four workers contains two
columns of each array. If you use these arrays in a for-drange loop, any calculations must be self-
contained within each worker. In other words, you can only perform calculations that are limited
within each worker to the two columns of the arrays that the workers contain.
For example, suppose you want to set each column of array E to some multiple of the corresponding
column of array D:
This statement sets the j-th column of E to j times the j-th column of D. In effect, while D is an
identity matrix with 1s down the main diagonal, E has the sequence 1, 2, 3, etc., down its main
diagonal.
This works because each worker has access to the entire column of D and the entire column of E
necessary to perform the calculation, as each worker works independently and simultaneously on two
of the eight columns.
Suppose, however, that you attempt to set the values of the columns of E according to different
columns of D:
4-51
4 Big Data Processing
This method fails, because when j is 2, you are trying to set the second column of E using the third
column of D. These columns are stored in different workers, so an error occurs, indicating that
communication between the workers is not allowed.
Restrictions
To loop over all elements in the array, you can use for-drange on the dimension of distribution, and
regular for-loops on all other dimensions. The following example executes in an spmd statement
running on a parallel pool of 4 workers:
spmd
PP = zeros(6,8,12,"codistributed");
RR = rand(6,8,12,codistributor())
% Default distribution:
% by third dimension, evenly across 4 workers.
for ii = 1:6
for jj = 1:8
for kk = drange(1:12)
PP(ii,jj,kk) = RR(ii,jj,kk) + spmdIndex;
end
end
end
end
PP
4-52
Use Parallel Computing to Optimize Big Data Set for Analysis
This example shows how to optimize data preprocessing for analysis using parallel computing.
By optimizing the organization, storage of time series data, you can simplify and accelerate any
downstream applications like predictive maintenance, digital twins, signal-based AI, and fleet
analytics.
In this example, you transform large raw data into a state ready for future analysis and save it to
Parquet files using parallel workers. Parquet files offer efficient access to data because they
efficiently store column-oriented heterogeneous data, allowing you to conditionally filter the files by
row and only load the data you need. Next, you can use the out-of-memory data to train a simple AI
model.
If you have data stored on a cluster, you can use this code for similar data optimization without
downloading the data. To see an example that performs analysis on data stored in the cloud, see
“Process Big Data in the Cloud” on page 4-66.
pool = parpool("Processes");
This example uses sample aircraft sensor data provided by NASA [1].
If you want to try these data preprocessing techniques yourself, you must download the aircraft
sensor data. NASA provides data for approximately 180,000 flights, with one MAT file representing
each flight. For more information, see Sample Flight Data.
This code creates a folder in your current folder and downloads data for the first year of aircraft tail
number 652, which occupies approximately 1.6 GB of disk space. Downloading the data can take
several minutes. To confirm that you want to download the data, select "true" from the drop-down
list before you run the example.
downloadIfTrue = ;
if downloadIfTrue
downloadNASAFlightData(pwd,"small");
dataRoot = fullfile(pwd,"data");
else
disp("Confirm and download flight data to proceed.");
return
end
The downloadNASAFlightData function downloads and organizes the files for tail 652 into
subfolders for each month.
4-53
4 Big Data Processing
Examine a sample of the flight data. Each MAT file comprises of 186 structure arrays, with each
structure array representing a sensor. Each structure array stores the metadata associated with the
sensor, along with the sensor readings in a nested array. Additionally, the file name contains
important metadata such as the flight ID, tail number, and start time.
sampleData = matfile(fullfile(dataRoot,"mat","Tail_652\200101\[Link]"));
[Link]
It is not efficient to store the data for each sensor as a separate structure variable or to embed the
metadata within the filename. Instead, you can organize the data into a nested schema. This
approach enables you to easily search the metadata and reduce the number of rows in the table by
nesting the sensor values. Use the struct2table function to organize the sample structure array.
struct2table([Link],AsArray=true)
ans=1×5 table
data Rate Units Description Alpha
_______________ ____ _______ _____________________ ________
The returnNestedTable helper function applies the struct2table function to each sensor data in
the sample MAT file and vertically concatenates the results.
head(returnNestedTable(fullfile(dataRoot,"mat","Tail_652\200101\[Link]")))
A datastore is a repository for collections of data that are too large to fit in memory. You can read and
process data stored in multiple files as a single entity. To learn more, see “Getting Started with
Datastore”.
Create a FileDatastore object with the data files from the first year of tail 652. You must use the
returnNestedTable custom read function to read the data in the MAT files.
4-54
Use Parallel Computing to Optimize Big Data Set for Analysis
Preview the datastore. The table output is the same as the table output when you call the
returnNestedTable read function without the datastore.
preview(dsFlight)
ans=186×8 table
StartTime TailNumber FlightId Rate Alpha Des
_______________________ __________ _______________ ____ _________ ____________
Clean Data
Next, prepare the data for future analysis by cleaning it. Use the transform function to perform
some table manipulation and change the data types of table variables. The datastore defers
performing the transformation until you read or write from it.
Convert all variables that are cell arrays of character vectors into string arrays. To categorize the
data later, convert the Units variable to a categorical array, and SampleRate variable into a
single array. Preview a sample of the results of the transformed datastore.
ans=8×8 table
StartTime TailNumber FlightId SampleRate SensorName
_______________________ __________ _______________ __________ __________ _____
4-55
4 Big Data Processing
Standardize the missing values for the units variable. MATLAB® uses the <undefined> token to
mark missing data in categorical values, but some rows of the Unit variable also show <units> or
UNITS, which you can treat as missing in this data set. Use a transformation function to standardize
this so every missing value in the units variable uses a uniform missing token. Preview a sample of
the results from the transformed datastore.
ans=8×8 table
StartTime TailNumber FlightId SampleRate SensorName
_______________________ __________ _______________ __________ __________ _____
Now that the data is optimized and ready for future analysis, save the data in the final transformed
datastore as Parquet files using the writeall function. The Parquet file format supports the efficient
compression, encoding and extraction of column-oriented heterogeneous data. When you set
UseParallel to true, the writeall function automatically uses the workers of the open parallel
pool to apply the transformations functions and write the contents of the transformed datastore to
files.
This code creates one Parquet file for each MAT file in the datastore and saves the Parquet files in the
parquet_sample folder, preserving the folder structure of the original MAT files. This process writes
2.6 GB of data to disk. To confirm that you want to save the data, select "true" from the drop-down
list before you run the example.
saveIfTrue = ;
if saveIfTrue
outdir = fullfile(dataRoot,"parquet_sample");
if isfolder(outdir)
rmdir(outdir,"s");
end
writeall(tdsFlight5,outdir,FolderLayout="duplicate", ...
OutputFormat="parquet",UseParallel=true)
disp("Parquet files saved to the parquet_sample folder.")
else
4-56
Use Parallel Computing to Optimize Big Data Set for Analysis
The writeall function saves the Parquet files into subfolders for each month.
Deep learning leverages neural networks to extract useful patterns and features directly from data.
To learn more, see “Deep Learning in MATLAB” (Deep Learning Toolbox).
Now that the data is clean and organized, you can use a subset of the sensor data to train a neural
network. You can predict a flight's future true airspeed at cruising altitude, using time series sensor
data such as altitude pressure, fuel flow, fan speed, current true airspeed, wind direction, and wind
speed. To train a neural network to predict the true airspeed, you can use a long short-term memory
(LSTM) network. LSTM networks excel in sequence-to-sequence predictions, which makes them ideal
for time series data. They recognize patterns in the sequence of data and predict future values at
each time step.
For this example, use each flight's sensor time series as a sequence of training data. To predict the
future true airspeed, train the network with targets that are the true airspeed values offset by one
time step into the future. This approach means that at every time step of the input sequence, the
LSTM predicts the next time step's true airspeed value.
Extract Data
Start by extracting the flight data from January through to April 2001 as well as June 2001. The data
from May 2001 is not available.
Create a parquetDatastore and use the SelectedVariableNames property to import only the
StartTime, SampleRate, SensorName and Data variables. Each file contains all the data for a
single flight, so set the ReadSize property to file to read and process one file at time. The
ReadSize property also determines how the software partitions the data before sending it to each
parallel worker.
pdsFlight = parquetDatastore(fullfile(dataRoot,"parquet_sample","Tail_652"), ...
IncludeSubfolders=true,ReadSize="file", ...
SelectedVariableNames=["StartTime","SampleRate","SensorName","Data"]);
4-57
4 Big Data Processing
To import data that corresponds to January through April 2001 as well as June 2001, create a row
filter using the ParquetDatastore object. Then, use the row filter to select rows with StartTime
values greater than or equal to January 2001 and StartTime values less than July 2001. Preview the
filtered datastore.
rf = rowfilter(pdsFlight);
[Link] = [Link] >= datetime("2001-01-01")...
& [Link] < datetime("2001-07-01");
preview(pdsFlight)
ans=8×4 table
StartTime SampleRate SensorName Data
____________________ __________ __________ _______________
Extract the cruise phase for each flight. Pivot the nested sensor data into individual variables using
the nested2wide helper function and extract the altitude pressure (ALT), fuel flow (FF.1), fan speed
(N1.1 and N2.1) true airspeed (TAS), wind direction (WD), wind speed (WS) and weight on wheel
(WOW) variables. To resolve the different sample rates, the nested2wide function fills in any missing
values with the previous nonmissing value.
The extractCruise helper function identifies the cruise phase of a flight and returns only the
section that contains the cruise portion as a timetable. If the function does not detect a cruise phase,
or if it detects multiple separate cruises, the function returns an empty timetable.
Use one transform to pivot the nested sensor data into variables, identify and return timetables from
the files that contain cruise portions.
Not all of the files return data, as only about 60% of flights contain a cruise phase. The rest are short
flights or flights that never left the ground. To find the indices of the files with cruise portions, use a
transformation to identify the files in the tpdsFlight datastore that did not return empty tables and
the readall function to collect the indices in parallel. To return a datastore that includes only files
that have a cruise portion, use the subset function with the tpdsFlight datastore and the indices
corresponding to these files.
ans=3043×8 timetable
timestamp ALT FF.1 N1.1 N2.1 TAS WD WOW
_______________________ _____ ____ ______ ______ ______ ______ ___ __
4-58
Use Parallel Computing to Optimize Big Data Set for Analysis
Randomly partition the tpdsFlightCruise datastore into a training set containing 70% of the files,
a validation set containing 15% of the files and a test set containing the remaining 15% of the files
using the trainingPartitions helper function.
numCruiseFlights = sum(indices);
[indexTrain,indexValidation,indexTest] = trainingPartitions(numCruiseFlights,[0.70 0.15 0.15]);
pdsTrain = subset(tpdsFlightCruise,indexTrain);
For a better fit and to prevent the training from diverging, you must normalize the training, validation
and test data. In this example, you rescale the sensor variables in the training, validation and test
data to the range [0,1] using the minimum and maximum values from all the data in the training
datastore.
To easily calculate the minimum and maximum of all training data, create a tall timetable with the
data from the pdsTrain datastore. Extract the variables required for training from the tall timetable,
and compute the minimum and maximum. When you use the gather function to gather the results
into memory, MATLAB automatically executes the computations in parallel on the workers of the open
parallel pool.
testDataTT = tall(pdsTrain);
tallTrainDs = testDataTT{:,["ALT","FF.1","N1.1","N2.1","TAS","WD","WS"]};
[[Link],[Link]] = gather(min(tallTrainDs),max(tallTrainDs));
Create a transformed datastore that removes the timestamp and WOW variables and returns the data
ready for training using the prepareMLData helper function.
For a single input layer, the neural network expects the datastore to output a table with rows
corresponding to the number of sequences in the training data and two variables specifying the
predictors and targets, respectively. Each sequence of predictors or targets must be represented as a
t-by-c numeric array, where t and c represent the number of time steps and features in each
4-59
4 Big Data Processing
sequence, respectively. In this example, each file is one sequence of training data, so you must
transform the training datastore to output a table with two variables for the predictor and target
data, and one row per file.
The prepareMLData helper function first normalizes the data based on the minimum and maximum
values in the stats structure. To create the predictor data for each file, the prepareMLData helper
function combines all seven sensor variables from the sequence into a single t-by-7 array, excluding
the sensor data for the final time step. Additionally, the function creates the target true airspeed
values by removing the first time step's data and combining the values from the remaining time steps
into a single t-by-1 array.
preview(tpdsTrain)
ans=1×2 table
Predictors Targets
_______________ _______________
{1379×7 double} {1379×1 double}
Partition 15% of the data from the tpdsFlightCruise datastore for use as the validation data
pdsValid datastore.
pdsValid = subset(tpdsFlightCruise,indexValidation);
Use the prepareMLData helper function in a transform to remove the timestamp and WOW variables
and return the validation data ready for training. The prepareMLData function transforms the
validation data into the same format as the training data.
ans=1×2 table
Predictors Targets
_______________ _______________
4-60
Use Parallel Computing to Optimize Big Data Set for Analysis
Partition 15% of the data from the tpdsFlightCruise datastore for use as the test datastore.
tpdsTest = subset(tpdsFlightCruise,indexTest);
Use the prepareMLData helper function to remove the timestamp and WOW variables and return all
seven sensor variables, excluding the sensor data for the final time step in the sequence, combined
into a single array.
Use the prepareMLData helper function to remove the timestamp and WOW variables and return the
test target true airspeed values shifted by one time step. The prepareMLData function does not
normalize the test target data.
• Sequence input layer with size matching the number of input features, in this example, seven
(ALT, FF.1, N1.1, N2.1, TAS, WD, and WS).
• An LSTM layer with 64 hidden units that outputs the full sequence.
• Fully connected layer with output size set to 136 corresponding to 136 hidden neurons.
• Dropout layer with dropout probability 0.60211.
• Fully connected layer with output size matching the number of outputs, in this example, one
(TAS).
numFeatures = 7;
numHiddenUnits = 64;
numResponses = 1;
layers = [ ...
sequenceInputLayer(numFeatures,Normalization="none")
lstmLayer(numHiddenUnits,OutputMode="sequence")
fullyConnectedLayer(136)
dropoutLayer(0.60211)
fullyConnectedLayer(numResponses)];
• Train using the "ADAM" optimizer and for 20 epochs with mini-batches of size 1.
• Specify the learning rate to 0.01 and the gradient threshold to 1.
• To validate the network at regular intervals during training, specify the validation datastore as
tpdsValid and set the validation frequency to 30.
• Set ExecutionEnvironment to "parallel-auto" to use the parallel pool for training. If there
is no current parallel pool, the software starts one using the default cluster profile. If the pool has
4-61
4 Big Data Processing
access to GPUs, then only workers with a unique GPU perform training computation and excess
workers become idle.
• Monitor the mean squared error (MSE) metric and display the training progress in a plot.
maxEpochs = 20;
miniBatchSize = 1;
options = trainingOptions("adam", ...
MaxEpochs=maxEpochs, ...
MiniBatchSize=miniBatchSize, ...
InitialLearnRate=0.01, ...
GradientThreshold=1, ...
ValidationData=tpdsValid, ...
ValidationFrequency=30, ...
ExecutionEnvironment="parallel-auto", ...
Metrics="rmse", ...
Plots="training-progress", ...
Verbose=0);
Train the neural network. Because this is a regression task, use mean squared error loss.
net = trainnet(tpdsTrain,layers,"mse",options);
Test Network
You can use the trained neural network to predict the true airspeed of each flight sequence in the test
datastore. After the prediction is complete, convert the normalized predicted values to the real
values.
yPred = minibatchpredict(net,tpdsTestPredictors,MiniBatchSize=1,UniformOutput=false);
minTAS = [Link](5);
maxTAS = [Link](5);
predictedTrueAirspeeds = cellfun(@(x) (maxTAS-minTAS)*(x+minTAS),yPred,UniformOutput=false);
Extract the target true airspeed values for comparison. Set UseParallel to true to use the workers
of the open parallel pool.
4-62
Use Parallel Computing to Optimize Big Data Set for Analysis
targetY = readall(tpdsTestTargets,UseParallel=true);
targetTrueAirspeeds = targetY.("Test Targets");
idx = randperm(length(predictedTrueAirspeeds),4);
figure
tiledlayout(2,2)
for i = 1:numel(idx)
nexttile
plot(targetTrueAirspeeds{idx(i)},"--")
hold on
plot(predictedTrueAirspeeds{idx(i)},".-")
hold off
title("Test Flight " + idx(i))
xlabel("Time Step")
ylabel("TAS (knots)")
legend(["Test Data","Predicted"],Location="best")
end
4-63
4 Big Data Processing
Calculate the mean of the maximum absolute error, the maximum relative error (as a fraction of the
target value) and the mean RMSE between the target and predicted true airspeed values.
meanRMSE = mean(rootMeanSE);
fprintf("Mean RMSE = %5.4f knots",meanRMSE)
Plot the maximum absolute error for the test flight data.
figure
nexttile
histogram(rootMeanSE)
xlabel("RMSE (knots)")
ylabel("Frequency")
title("RMSE")
nexttile
histogram(maxRelativeError*100)
xlabel("Absolute Error (%)")
ylabel("Frequency")
title("Max Absolute Errors as Percentage of Target")
4-64
Use Parallel Computing to Optimize Big Data Set for Analysis
Clean Up
Remove the flight data files and delete the parallel pool.
rmdir(dataRoot,"s");
delete(pool);
References
[1] “Flight Data For Tail 652 | NASA Open Data Portal.” Accessed October 6, 2023. https://
[Link]/dataset/Flight-Data-For-Tail-652/fxpu-g6k3.
See Also
parfor | fileDatastore | transform | writeall
Related Examples
• “Process Big Data in the Cloud” on page 4-66
• “Use Tall Arrays on a Parallel Pool” on page 4-96
4-65
4 Big Data Processing
This example shows how to access a large data set in the cloud and process it in a cloud cluster using
MATLAB® capabilities for big data.
The public data set in this example is part of the Wind Integration National Dataset Toolkit, or WIND
Toolkit [1], [2], [3], [4]. For more information, see Wind Integration National Dataset Toolkit.
Requirements
To run this example, you must set up access to a cluster in Amazon® AWS®. In MATLAB, you can
create clusters in Amazon AWS directly from the MATLAB desktop. On the Home tab, in the Parallel
menu, select Create and Manage Clusters. In the Cluster Profile Manager, click Create Cloud
Cluster. Alternatively, you can use MathWorks Cloud Center to create and access compute clusters in
Amazon AWS. For more information, see Getting Started with Cloud Center.
The data set used in this example is the Techno-Economic WIND Toolkit. It contains 2 TB (terabyte) of
data for wind power estimates and forecasts along with atmospheric variables from 2007 to 2013
within the continental U.S.
The Techno-Economic WIND Toolkit is available via Amazon Web Services, in the location s3://nrel-
pds-wtk/wtk-techno-economic/pywtk-data. It contains two data sets:
To work with remote data in Amazon S3, you must define environment variables for your AWS
credentials. For more information on setting up access to remote data, see “Work with Remote Data”.
In the following code, replace YOUR_AWS_ACCESS_KEY_ID and YOUR_AWS_SECRET_ACCESS_KEY
with your own Amazon AWS credentials. If you are using temporary AWS security credentials, also
set the environment variable AWS_SESSION_TOKEN.
setenv("AWS_ACCESS_KEY_ID","YOUR_AWS_ACCESS_KEY_ID");
setenv("AWS_SECRET_ACCESS_KEY","YOUR_AWS_SECRET_ACCESS_KEY");
This data set requires you to specify its geographic region, and so you must set the corresponding
environment variable.
setenv("AWS_DEFAULT_REGION","us-west-2");
To give the workers in your cluster access to the remote data, add these environment variable names
to the EnvironmentVariables property of your cluster profile. To edit the properties of your
cluster profile, use the Cluster Profile Manager, in Parallel > Create and Manage Clusters. For
more information, see “Set Environment Variables on Workers” on page 7-12.
4-66
Process Big Data in the Cloud
The 2 TB data set is quite large. This example shows you how to find a subset of the data set that you
want to analyze. The example focuses on data for the state of Massachusetts.
First obtain the IDs that identify the metrological stations in Massachusetts, and determine the files
that contain their metrological information. Metadata information for each station is in a file named
three_tier_site_metadata.csv. Because this data is small and fits in memory, you can access it
from the MATLAB client with readtable. You can use the readtable function to access open data
in S3 buckets directly without needing to write special code.
tMetadata = readtable("s3://nrel-pds-wtk/wtk-techno-economic/pywtk-data/three_tier_site_metadata.
"ReadVariableNames",true,"TextType","string");
To find out which states are listed in this data set, use unique.
states = unique([Link])
4-67
4 Big Data Processing
"South Carolina"
"South Dakota"
"Tennessee"
"Texas"
"Utah"
"Vermont"
"Virginia"
"Washington"
"West Virginia"
"Wisconsin"
"Wyoming"
The data for a given station is contained in a file that follows this naming convention: s3://nrel-
pds-wtk/wtk-techno-economic/pywtk-data/met_data/folder/site_id.nc, where folder
is the nearest integer less than or equal to site_id/500. Using this convention, compose a file
location for each station.
folder = floor(siteId/500);
fileLocations = compose("s3://nrel-pds-wtk/wtk-techno-economic/pywtk-data/met_data/%d/%[Link]",fold
You can use datastores and tall arrays to access and process data that does not fit in memory. When
performing big data computations, MATLAB accesses smaller portions of the remote data as needed,
so you do not need to download the entire data set at once. With tall arrays, MATLAB automatically
breaks the data into smaller blocks that fit in memory for processing.
If you have Parallel Computing Toolbox, MATLAB can process the many blocks in parallel. The
parallelization enables you to run an analysis on a single desktop with local workers, or scale up to a
cluster for more resources. When you use a cluster in the same cloud service as the data, the data
stays in the cloud and you benefit from improved data transfer times. Keeping the data in the cloud is
also more cost-effective. This example ran in less than 20 minutes using 18 workers on a c4.8xlarge
machine in Amazon AWS.
If you use a parallel pool in a cluster, MATLAB processes this data using workers in the cluster.
Create a parallel pool in the cluster. In the following code, use the name of your cluster profile
instead. Attach the script to the pool, because the parallel workers need to access a helper function in
it.
p = parpool("myAWSCluster");
addAttachedFiles(p,mfilename("fullpath"));
Create a datastore with the metrology data for the stations in Massachusetts. The data is in the form
of Network Common Data Form (NetCDF) files, and you must use a custom read function to interpret
them. In this example, this function is named ncReader and reads the NetCDF data into timetables.
You can explore its contents at the end of this script.
4-68
Process Big Data in the Cloud
dsMetrology = fileDatastore(fileLocations,"ReadFcn",@ncReader,"UniformRead",true);
Create a tall timetable with the metrology data from the datastore.
ttMetrology = tall(dsMetrology)
ttMetrology =
Get the mean temperature per month using groupsummary, and sort the resulting tall table. For
performance, MATLAB defers most tall operations until the data is needed. In this case, plotting the
data triggers evaluation of deferred calculations.
meanTemperature = groupsummary(ttMetrology,"Time","month","mean","temperature");
meanTemperature = sortrows(meanTemperature);
figure;
plot(meanTemperature.mean_temperature,"*-");
ylim([260 300]);
xlim([1 12*7+1]);
xticks(1:12:12*7+1);
xticklabels(["2007","2008","2009","2010","2011","2012","2013","2014"]);
title("Average Temperature in Massachusetts 2007-2013");
xlabel("Year");
ylabel("Temperature (K)")
4-69
4 Big Data Processing
Many MATLAB functions support tall arrays, so you can perform a variety of calculations on big data
sets using familiar syntax. For more information on supported functions, see “Supporting Functions”.
The data in the Techno-Economic WIND Toolkit is saved in NetCDF files. Define a custom read
function to read its data into a timetable. For more information on reading NetCDF files, see
“NetCDF Files”.
function t = ncReader(filename)
% NCREADER Read NetCDF File (.nc), extract data set and save as a timetable
4-70
Process Big Data in the Cloud
fileLength = [Link];
% Extract initial timestamp, sample period and create the time axis
tAttributes = struct2table([Link]);
startTime = datetime(cell2mat([Link](contains([Link],"start_time"))),"Conver
samplePeriod = seconds(cell2mat([Link](contains([Link],"sample_period"))));
References
[1] Draxl, C., B. M. Hodge, A. Clifton, and J. McCaa. Overview and Meteorological Validation of the
Wind Integration National Dataset Toolkit (Technical Report, NREL/TP-5000-61740). Golden, CO:
National Renewable Energy Laboratory, 2015.
[2] Draxl, C., B. M. Hodge, A. Clifton, and J. McCaa. "The Wind Integration National Dataset (WIND)
Toolkit." Applied Energy. Vol. 151, 2015, pp. 355-366.
[3] King, J., A. Clifton, and B. M. Hodge. Validation of Power Output for the WIND Toolkit (Technical
Report, NREL/TP-5D00-61714). Golden, CO: National Renewable Energy Laboratory, 2014.
[4] Lieberman-Cribbin, W., C. Draxl, and A. Clifton. Guide to Using the WIND Toolkit Validation Code
(Technical Report, NREL/TP-5000-62595). Golden, CO: National Renewable Energy Laboratory, 2014.
See Also
tall | datastore | readtable | parpool
Related Examples
• “Work with Remote Data”
• “Discover Clusters and Use Cluster Profiles” on page 7-2
More About
• “Work with Deep Learning Data in AWS” (Deep Learning Toolbox)
• “Deep Learning with Big Data” (Deep Learning Toolbox)
4-71
4 Big Data Processing
This example shows how to solve a system of linear equations of the form Ax = b in parallel with a
direct method using distributed arrays.
Distributed arrays are well-suited for large mathematical computations, such as large problems of
linear algebra. In the same way as for arrays stored in the client memory, you can use mldivide to
solve can systems of linear equations defined using distributed arrays, so you do not need to change
your code.
Distributed arrays distribute data from your client workspace to a parallel pool in your local machine
or in a cluster. Each worker stores a portion of the array in its memory, but can also communicate
with the other workers to access all segments of the array. Distributed arrays can contain different
types of data including full and sparse matrices.
Direct methods of solving linear equations typically factorize the coefficient matrix A to compute the
solution. mldivide selects one of a set of direct solver methods depending on the structure of A and
whether A is full or sparse.
This example demonstrates how to solve a simple system of linear equations of the form Ax = b with
an exact, known solution x. The system is defined by the matrix A and the column vector b. The
solution x is also a column vector. In this example, the system is defined using full and sparse
matrices. The required code is the same for systems defined using distributed arrays or arrays on the
client memory.
For a related example that shows how to use iterative solvers and distributed arrays, see “Use
Distributed Arrays to Solve Systems of Linear Equations with Iterative Methods” on page 4-77.
First define the coefficient matrix A as variable in the client memory, A, and then pass this matrix to
the “Creation” on page 9-35 function to create a distributed version of the same matrix, ADist.
When you use the distributed function, MATLAB automatically starts a parallel pool using your
default cluster settings.
n = 1e3;
A = randi(100,n,n);
ADist = distributed(A);
You can now define the right hand vector b. In this example, b is defined as the row sum of A, which
T
leads to an exact solution to Ax = b of the form xexact = [1, . . . , 1] .
b = sum(A,2);
bDist = sum(ADist,2);
Since sum acts on a distributed array, bDist is also distributed and its data is stored in the memory
of the workers of your parallel pool. Finally, define the exact solutions for comparison with the
solutions obtained using direct numerical methods.
xEx = ones(n,1);
xDistEx = ones(n,1,'distributed');
4-72
Use Distributed Arrays to Solve Systems of Linear Equations with Direct Methods
Now that you have defined your system of linear equations, you can use mldivide to solve the
system directly. In MATLAB, you can call mldivide using the special operator \. You do not have to
change your code to solve the distributed system as mldivide has automatic support for distributed
arrays.
Once you have calculated the solution, you can check the error between each element of the obtained
result x and the expected values of xexact.
x = A\b;
err = abs(xEx-x);
xDist = ADist\bDist;
errDist = abs(xDistEx-xDist);
figure
subplot(2,1,1)
semilogy(err,'o');
title('System of Linear Equations with Full Matrices');
ylabel('Absolute Error');
xlabel('Element in x');
ylim([10e-17,10e-13])
subplot(2,1,2)
semilogy(errDist,'o');
title('System of Linear Equations with Distributed Full Matrices');
ylabel('Absolute Error');
xlabel('Element in x');
ylim([10e-17,10e-13])
4-73
4 Big Data Processing
For both the distributed arrays and the arrays stored on the client, the absolute error between the
calculated results for x and the exact result xexact is small. The accuracy of the solution is
approximately the same for both array types.
mean(err)
ans = 1.6031e-13
mean(errDist)
ans =
1.2426e-13
Distributed arrays can also contain sparse data. To create the coefficient matrix A, use sprand and
speye to directly generate a sparse matrix of random numbers plus the sparse identity matrix.
Adding the identity matrix helps to prevent creating A as a singular or near-singular matrix, both of
which are difficult to factorize.
n = 1e3;
density = 0.2;
A = sprand(n,n,density) + speye(n);
ADist = distributed(A);
Choosing the right hand vector b as the row sum of A yields an exact solution of the same form as the
solution to the full matrix system.
b = sum(A,2);
bDist = sum(ADist,2);
xEx = ones(n,1);
xDistEx = ones(n,1,'distributed');
In the same way as with full matrices, you can now solve this system of linear equations directly using
mldivide and check the error between the obtained result and its expected value.
x = A\b;
err = abs(xEx-x);
xDist = ADist\bDist;
errDist = abs(xDistEx-xDist);
figure
subplot(2,1,1)
semilogy(err,'o');
title('System of Linear Equations with In-Client Sparse Matrices');
ylabel('Absolute Error');
xlabel('Element in x');
ylim([10e-17,10e-13])
subplot(2,1,2)
semilogy(errDist,'o');
title('System of Linear Equations with Distributed Sparse Matrices');
ylabel('Absolute Error');
xlabel('Element in x');
ylim([10e-17,10e-13])
4-74
Use Distributed Arrays to Solve Systems of Linear Equations with Direct Methods
As with the full matrix system, solving the system of linear equations using both on-client arrays and
distributed arrays produces solutions with comparable accuracy.
mean(err)
ans = 1.6031e-13
mean(errDist)
ans =
1.2426e-13
After you are done with your computations, you can delete your parallel pool. The gcp function
returns the current parallel pool object so you can delete the current pool.
delete(gcp('nocreate'));
For certain types of large and sparse coefficient matrix A, there are more efficient methods than
direct factorization for solving your systems. In these cases, iterative methods might be more efficient
at solving your system of linear equations. Iterative methods generate a series of approximate
solutions that converge to a final result. For an example of how to use iterative methods to solve
4-75
4 Big Data Processing
linear equations with large, sparse input matrices, see “Use Distributed Arrays to Solve Systems of
Linear Equations with Iterative Methods” on page 4-77.
See Also
distributed | sparse | mldivide
Related Examples
• “Use Distributed Arrays to Solve Systems of Linear Equations with Iterative Methods” on page
4-77
4-76
Use Distributed Arrays to Solve Systems of Linear Equations with Iterative Methods
For large-scale mathematical computations, iterative methods can be more efficient than direct
methods. This example shows how you can solve systems of linear equations of the form Ax = b in
parallel using distributed arrays with iterative methods.
This example continues the topics covered in “Use Distributed Arrays to Solve Systems of Linear
Equations with Direct Methods” on page 4-72. The direct solver methods implemented in mldivide
can be used to solve distributed systems of linear equations in parallel but may not be efficient for
certain large and sparse systems. Iterative methods generate a series of solutions from an initial
guess, converging to a final result after several steps. These steps can be less computationally
intensive than calculating the solution directly.
Distributed arrays distribute data from your client workspace to a parallel pool in your local machine
or in a cluster. Each worker stores a portion of the array in its memory, but can also communicate
with the other workers to access all segments of the array. Distributed arrays can contain different
types of data including full and sparse matrices.
This example uses the pcg function to demonstrate how to solve large systems of linear equations
using the conjugate gradient and the preconditioned conjugate gradient methods. Iterative methods
can be used with both dense and sparse matrices but are most efficient for sparse matrix systems.
When you use the “Creation” on page 9-35 function, the software automatically starts a parallel pool
using your default cluster settings. This example uses the Wathen matrix from the gallery function.
This matrix is a sparse, symmetric, and random matrix with overall dimension N = 3n2 + 4n + 1.
n = 400;
A = distributed(gallery('wathen',n,n));
N = 3*n^2+4*n+1
N = 481601
You can now define the right hand vector b. In this example, b is defined as the row sum of A, which
T
leads to an exact solution to Ax = b of the form xexact = [1, . . . , 1] .
b = sum(A,2);
Since sum acts on a distributed array, b is also distributed and its data is stored in the memory of the
workers of your parallel pool. Finally, you can define the exact solution for comparison with the
solutions obtained using iterative methods.
xExact = ones(N,1,'distributed');
Solve your System of Linear Equations with the Conjugate Gradient Method
The pcg MATLAB function provides the conjugate gradient (CG) method, which iteratively generates
a series of approximate solutions for x, improving the solution with each step.
4-77
4 Big Data Processing
[xCG_1,flagCG_1,relres_CG1,iterCG_1,resvecCG_1] = pcg(A,b);
When the system is solved, you can check the error between each element of the obtained result
xCG_1 and the expected values of xExact. The error in the computed result is relatively high.
errCG_1 = abs(xExact-xCG_1);
figure(1)
hold off
semilogy(errCG_1,'o');
title('System of Linear Equations with Sparse Matrix');
ylabel('Absolute Error');
xlabel('Element in x');
The iterative computation ends when the series of approximate solutions converges to a specific
tolerance or after the maximum number of iteration steps. For both distributed and on-client arrays,
pcg uses the same default settings:
4-78
Use Distributed Arrays to Solve Systems of Linear Equations with Iterative Methods
• The default maximum number of iteration steps is 20 or the order of coefficient matrix A if less
than 20.
As a second output argument, the pcg function also returns a convergence flag that gives you more
information about the obtained result, including whether the computed solution converged to the
desired tolerance. For example, a value of 0 indicates the solution has properly converged.
flagCG_1
flagCG_1 = 1
In this example, the solution does not converge within the default maximum number of iterations,
which results in the high error.
To increase the likelihood of convergence, you can customize the settings for tolerance and maximum
number of iteration steps.
tolerance = 1e-12;
maxit = N;
tCG = tic;
[xCG_2,flagCG_2,relresCG_2,iterCG_2,resvecCG_2] = pcg(A,b,tolerance,maxit);
tCG = toc(tCG);
flagCG_2
flagCG_2 = 0
With the custom settings, the solution converges. This solution has an improved absolute error
compared to the previous solution.
errCG_2 = abs(xExact-xCG_2);
figure(2)
hold off
semilogy(errCG_1,'o');
hold on
semilogy(errCG_2,'d');
title('Comparison of Absolute Error');
ylabel('Absolute Error');
xlabel('Element in x');
legend('Default tolerance and iterations','Improved tolerance and iterations');
hold off
4-79
4 Big Data Processing
The pcg method also returns a vector of the residual norm at each iteration step, norm(b-A*x)/
norm(b). The relative residual norm shows the ratio of accuracies between consecutive iteration
steps. The evolution of the residuals during the iterative process can help you understand why the
solution did not converge without custom settings.
figure(3)
f=semilogy(resvecCG_2./resvecCG_2(1));
hold on
semilogy([Link],[1e-6 1e-6],'--')
semilogy([20 20], [Link],'--')
semilogy([Link],[1e-12 1e-12],'--')
title('Evolution of Relative Residual');
ylabel('Relative Residual');
xlabel('Iteration Step');
legend('Residuals of CG','Default Tolerance','Default Number of Steps','Custom Tolerance')
hold off
4-80
Use Distributed Arrays to Solve Systems of Linear Equations with Iterative Methods
It is clear that the default number of steps is not enough to achieve a good solution for this system.
Solve Your System of Linear Equations with the Preconditioned Conjugate Gradient Method
You can improve the efficiency of solving your system using the preconditioned conjugate gradient
(PCG) method. First, precondition your system of linear equations using a preconditioner matrix M.
Next, solve your preconditioned system using the CG method. The PCG method can take much fewer
iterations than the CG method.
The pcg function is also used for the PCG method. You can supply a suitable preconditioner matrix M
as an additional input.
An ideal preconditioner matrix is a matrix whose inverse M−1 is a close approximation to the inverse
of the coefficient matrix, A−1, but is easier to compute. This example uses the diagonal of A to
precondition the system of linear equations.
M = spdiags(spdiags(A,0),0,N,N);
tPCG = tic;
[xPCG,flagPCG,relresPCG,iterPCG,resvecPCG]=pcg(A,b,tolerance,maxit,M);
tPCG = toc(tPCG);
4-81
4 Big Data Processing
figure(4)
hold off;
semilogy(resvecCG_2./resvecCG_2(1))
hold on;
semilogy(resvecPCG./resvecPCG(1))
title('Evolution of Relative Residual');
ylabel('Relative Residual');
xlabel('Iteration Step');
legend('Residuals of CG','Residuals of PCG with M \approx diag(A)')
4-82
Use Distributed Arrays to Solve Systems of Linear Equations with Iterative Methods
The previous figure shows that the PCG method needs drastically fewer steps to converge compared
to the nonpreconditioned system. This result is also reflected in the execution times.
fprintf([...
'\nTime to solve system with CG: %d s', ...
'\nTime to solve system with PCG: %d s'],tCG,tPCG);
As well as solving this example system in fewer iteration steps, the PCG method also returns a more
accurate solution.
errPCG = abs(xExact-xPCG);
figure(5)
hold off
semilogy(errCG_1,'o');
hold on
semilogy(errCG_2,'d');
semilogy(errPCG,'x');
title('Comparison of absolute error');
4-83
4 Big Data Processing
ylabel('Absolute error');
xlabel('Element in x');
legend('CG default','CG custom','PCG');
After you are done with your computations, you can delete your parallel pool. The gcp function
returns the current parallel pool object so you can delete the current pool.
delete(gcp('nocreate'))
The Wathen matrix used in this example is a good demonstration of how a good preconditioner can
dramatically improve the efficiency of the solution. The Wathen matrix has relatively small off-
diagonal components, so choosingM = diag(A) gives a suitable preconditioner. For an arbitrary matrix
A, finding a preconditioner might not be so straightforward.
For an example of how to approximate a differential equation by a linear system and solve it using a
distributed iterative solver with a multigrid preconditioner, see “Solve Differential Equation Using
Multigrid Preconditioner on Distributed Discretization” on page 4-86.
See Also
distributed | sparse | pcg
4-84
Use Distributed Arrays to Solve Systems of Linear Equations with Iterative Methods
Related Examples
• “Use Distributed Arrays to Solve Systems of Linear Equations with Direct Methods” on page 4-
72
4-85
4 Big Data Processing
This example shows how to solve Poisson's equation using a preconditioned iterative solver and
distributed arrays. By using distributed arrays, you can scale up the calculation using the memory of
a cluster of machines, not just the memory of a single machine. You can scale up without changing
your code.
This example continues the topics covered in “Use Distributed Arrays to Solve Systems of Linear
Equations with Iterative Methods” on page 4-77. Based on [1], the example models heat distribution
in a room by using Poisson's equation, in a form known as the homogeneous steady-state heat
equation. Steady state means that the heat does not vary with time and homogeneous means that
there is no external heat source.
∂2 u ∂2 u ∂2 u
−Δu = − + + =0
∂x2 ∂y2 ∂z2
In the equation, u represents the temperature at every point x, y, z of the room. To solve the
equation, you first approximate it by a system of linear equations using a finite difference
discretization method. Then, you use the preconditioned conjugate gradients (pcg) method to solve
the system. Preconditioning transforms the problem to improve the performance of the numerical
solver. By using distributed arrays, you can leverage the combined memory of a cluster of machines
and allow finer discretizations.
In this example, a cube of side 1 models the room. The first step is to discretize it using a 3-D grid.
The preconditioning method in this example uses several grids with different levels of granularity.
Each level coarsens the grid by a factor of 2 in each dimension. Define the number of multigrid levels.
multigridLevels = 2;
Define the number of points in each dimension, X, Y, and Z, of the finest grid. The preconditioning
method requires that the number of points in this grid be divisible by 2^multigridLevels. In this
case, the number of points must be divisible by 4, because the number of multigrid levels is 2.
numPoints.X = 32;
numPoints.Y = 32;
numPoints.Z = 32;
Discretize the spatial dimensions with a 3-D grid by using the meshgrid function. Divide each
dimension uniformly according to the number of points by using linspace. Note that, to include the
boundaries of the cube, you must add two additional points.
4-86
Solve Differential Equation Using Multigrid Preconditioner on Distributed Discretization
Suppose the room has a window and a door. The walls and ceiling have a constant temperature of 0
degrees, the window has a constant temperature of 16 degrees, and the door has a constant
temperature of 15 degrees. The floor is at 0.5 degrees. The goal is to determine the temperature
distribution across the interior of the room.
Define the coordinates of the floor, window, and door using relational operators, and define the
temperature on these boundary elements. The boundaries are the facets of the cube and, therefore,
one of X,Y, or Z must be 0 or 1. Set the rest of the boundary and the interior of the cube to 0.
floor = (0.0 <= X & X <= 1.0) & (0.0 <= Y & Y <= 1) & (Z == 0.0);
window = (X == 1) & (0.2 <= Y & Y <= 0.8) & (0.4 <= Z & Z <= 0.6);
door = (0.4 <= X & X <= 0.6) & (Y == 1.0) & (0.0 <= Z & Z <= 0.6);
u = zeros(size(X));
u(floor) = 0.5;
u(window) = 16;
u(door) = 15;
These boundary conditions specify the constant values that a solution must take along the boundary
of the domain. This type of boundary condition is known as the Dirichlet boundary condition.
Visualize the boundary conditions using the slice function. Use slices positioned at the boundary of
the cube that show the nonzero boundary conditions.
xSlices = 1;
ySlices = 1;
zSlices = 0;
f = slice(X,Y,Z,u,xSlices,ySlices,zSlices,'nearest');
title('Constant nonzero boundary conditions'), xlabel('x'), ylabel('y'), zlabel('z');
colorbar, colormap cool;
shading interp;
set(f,'EdgeColor',[0 0 0]);
4-87
4 Big Data Processing
This example discretizes the differential equation into a linear system using a finite differences
approximation method, and uses a multigrid preconditioner to improve the performance of the
iterative solver. For this example, use the discretization and the preconditioner in the
discretizePoissonEquation and multigridPreconditioner on page 4-91 supporting
functions. The discretizePoissonEquation function is attached to this example as a supporting
file. To access this file, open the example as a live script.
For other problems, choose a discretization and a preconditioner that are appropriate for your
application.
Among other techniques, this preconditioner applies smoothing to minimize errors with a series of
approximations. Define the number of smoothing steps. Using a greater number of steps makes
approximations more accurate, but also more computationally intensive. Then, discretize the
differential equation and set up the preconditioner.
numberOfSmootherSteps = 1;
[A,b,multigridData] = discretizePoissonEquation(numPoints,multigridLevels,numberOfSmootherSteps,u
4-88
Solve Differential Equation Using Multigrid Preconditioner on Distributed Discretization
preconditioner = setupPreconditioner(multigridData);
If you need more computational resources, such as memory, you can scale up using distributed arrays
without needing to change your code. Distributed arrays distribute your data across multiple workers
and they can leverage the computational performance and memory of a cluster of machines.
Start a pool of parallel workers. By default, parpool uses your default cluster. Check your default
cluster profile on the MATLAB Home tab, in the Environment area, in Parallel > Select a Default
Cluster.
parpool;
Distribute the temperature variable u across the memory of the workers in your cluster by using the
distributed function.
distU = distributed(u);
You can use the same code as before; no changes are required because the discretization and
preconditioner functions create distributed arrays if the input is a distributed array. Many MATLAB
functions are enhanced for distributed arrays, so you can work with them in the same way you work
with in-memory arrays.
Use pcg inside an spmd block to solve the linear system in a distributed manner.
spmd
x = pcg(A,b,tol,maxit,preconditioner);
end
4-89
4 Big Data Processing
Lab 1:
pcg converged at iteration 45 to a solution with relative residual 5.4e-13.
Plot Results
The solution from the solver is a vector that fits in memory. Send the data from the workers to the
client by using gather. Reshape the data back into a 3-D array and reorder the dimensions to
produce the final solution. Set the inner part of u to this solution. The outer part, the boundary,
already contains the value of the boundary conditions.
x3D = reshape(gather(x),numPoints.X,numPoints.Y,numPoints.Z);
u(2:end-1,2:end-1,2:end-1) = permute(x3D, [2, 1, 3]);
Visualize the solution using the slice function. Add additional slices to plot the temperature inside
the cube. You can use the Rotate tool, or vary the position of the slices, to explore the solution.
xSlices = [.5,1];
ySlices = [.5,1];
zSlices = [0,.5];
f = slice(X,Y,Z,u,xSlices,ySlices,zSlices,'nearest');
title('Heat distribution'), xlabel('x'), ylabel('y'), zlabel('z');
colorbar, colormap cool;
shading interp;
You can try different values of numPoints in this example to test different levels of discretization.
Using a larger value increases the resolution, but requires more memory. In addition, the larger
multigridLevels is, the more memory efficient the preconditioner is. However, a larger
4-90
Solve Differential Equation Using Multigrid Preconditioner on Distributed Discretization
Define Preconditioner
Define a multigrid preconditioner for use with the preconditioned conjugate gradients method. This
type of preconditioner uses several discretization grids with different levels of granularity to
approximate the solution of a system of linear equations more efficiently. The preconditioning method
in this example is based on [2], and follows these main stages:
function x = multigridPreconditioner(mgData,r,level)
end
Create a function that takes the multigrid data and returns a function handle that applies the
preconditioner to input data. In this example, this function handle is the preconditioner input to pcg.
You must create this function because it is not possible to define anonymous functions inside spmd
blocks.
4-91
4 Big Data Processing
if ~isempty(multigridData)
preconditioner = @(x,varargin) multigridPreconditioner(multigridData,x,1);
else
preconditioner = [];
end
end
References
[1] Dongarra, J., M. A. Heroux, and P. Luszczek. HPCG Benchmark: A New Metric for Ranking High
Performance Computing Systems. Knoxville, TN: University of Tennessee, 2015.
[2] Elman, H. C., D. J. Silvester, and A. J. Wathen. Finite Elements and Fast Iterative Solvers: With
Applications in Incompressible Fluid Dynamics. Oxford, UK: Oxford University Press, 2005, Section
2.5.
See Also
pcg | distributed | spmd | gather
Related Examples
• “Use Distributed Arrays to Solve Systems of Linear Equations with Iterative Methods” on page
4-77
• “Use Distributed Arrays to Solve Systems of Linear Equations with Direct Methods” on page 4-
72
4-92
Big Data Workflow Using Tall Arrays and Datastores
The illustration shows a typical workflow that uses tall arrays to analyze a large data set. In this
workflow, you analyze a small subset of the data before scaling up to analyze the entire data set.
Parallel computing can help you scale up from steps six to seven. That is, after checking that your
code works on the small data set, run it on the whole data set. You can use MATLAB to enhance this
workflow.
4-93
4 Big Data Processing
MATLAB Parallel
Server
One of the benefits of developing your algorithms with tall arrays is that you only need to write the
code once. You can develop your code locally, then use mapreducer to scale up and take advantage
of the capabilities offered by Parallel Computing Toolbox and MATLAB Parallel Server.
See Also
gather | tall | datastore | mapreducer
Related Examples
• “Use Tall Arrays on a Parallel Pool” on page 4-96
• “Use Tall Arrays on a Spark Cluster” on page 4-99
• “Tall Arrays for Out-of-Memory Data”
• “Choose a Parallel Computing Solution” on page 1-5
4-94
Big Data Workflow Using Tall Arrays and Datastores
More About
• “Datastore”
4-95
4 Big Data Processing
ds = datastore('[Link]');
varnames = {'ArrDelay', 'DepDelay'};
[Link] = varnames;
[Link] = 'NA';
If you have Parallel Computing Toolbox installed, when you use the tall function, MATLAB
automatically starts a parallel pool of workers, unless you turn off the default parallel pool
preference. The default cluster uses local workers on your machine.
Note If you want to turn off automatically opening a parallel pool, change your parallel settings. If
you turn off the Automatically create a parallel pool option, then you must explicitly start a pool if
you want the tall function to use it for parallel processing. See “Specify Your Parallel Settings” on
page 1-35.
If you have Parallel Computing Toolbox, you can run the same code as the MATLAB tall table example
and automatically execute it in parallel on the workers of your local machine.
tt = tall(ds)
tt =
ArrDelay DepDelay
________ ________
8 12
8 1
21 20
13 12
4 -1
59 63
3 -2
11 -1
: :
: :
4-96
Use Tall Arrays on a Parallel Pool
The display indicates that the number of rows, M, is not yet known. M is a placeholder until the
calculation completes.
Extract the arrival delay ArrDelay from the tall table. This action creates a new tall array variable to
use in subsequent calculations.
a = [Link];
You can specify a series of operations on your tall array, which are not executed until you call
gather. Doing so enables you to batch up commands that might take a long time. For example,
calculate the mean and standard deviation of the arrival delay. Use these values to construct the
upper and lower thresholds for delays that are within 1 standard deviation of the mean.
m = mean(a,'omitnan');
s = std(a,'omitnan');
one_sigma_bounds = [m-s m m+s];
Use gather to calculate one_sigma_bounds, and bring the answer into memory.
sig1 = gather(one_sigma_bounds)
sig1 =
You can specify multiple inputs and outputs to gather if you want to evaluate several things at once.
Doing so is faster than calling gather separately on each tall array. As an example, calculate the
minimum and maximum arrival delay.
max_delay =
1014
min_delay =
-64
If you want to develop in serial and not use local workers or your specified cluster, enter the following
command.
mapreducer(0);
If you use mapreducer to change the execution environment after creating a tall array, then the tall
array is invalid and you must recreate it. To use local workers or your specified cluster again, enter
the following command.
mapreducer(gcp);
Note One of the benefits of developing algorithms with tall arrays is that you only need to write the
code once. You can develop your code locally, and then use mapreducer to scale up to a cluster,
4-97
4 Big Data Processing
without needing to rewrite your algorithm. For an example, see “Use Tall Arrays on a Spark Cluster”
on page 4-99.
See Also
gather | tall | datastore | table | mapreducer | parpool
Related Examples
• “Big Data Workflow Using Tall Arrays and Datastores” on page 4-93
• “Use Tall Arrays on a Spark Cluster” on page 4-99
• “Tall Arrays for Out-of-Memory Data”
More About
• “Datastore”
4-98
Use Tall Arrays on a Spark Cluster
In this section...
“Connect to Spark Cluster Using Cluster Profile” on page 4-99
“Manually Connect to Spark Cluster and Spark Enabled Hadoop Cluster” on page 4-99
“Creating and Using Tall Tables” on page 4-100
This example shows how to modify a MATLAB example of creating a tall table to run on a Spark
cluster or a Spark enabled Hadoop cluster. You can use this tall table to create tall arrays and
calculate statistical properties. You can develop code locally and then scale up, to take advantage of
the capabilities offered by Parallel Computing Toolbox and MATLAB Parallel Server without having to
rewrite your algorithm. See also “Big Data Workflow Using Tall Arrays and Datastores” on page 4-93,
“Configure for Spark Clusters” (MATLAB Parallel Server), and “Configure for Hadoop Clusters”
(MATLAB Parallel Server)
To learn how to create a profile for your Spark cluster, see “Client Configuration” (MATLAB Parallel
Server).
Create the cluster object by specifying the Spark installation location on your machine. Use the
mapreducer function to set the Spark cluster as the execution environment.
cluster = [Link](SparkInstallFolder="/path/to/spark/install");
mapreducer(cluster);
Create a cluster object to connect to a Spark enabled Hadoop cluster from a MATLAB client.
4-99
4 Big Data Processing
Use environment variables to specify the Hadoop cluster installation location and the Spark
installation location on your machine. Create the cluster object and set the Spark enabled Hadoop
cluster as the execution environment.
setenv('HADOOP_HOME', '/path/to/hadoop/install')
setenv('SPARK_HOME', '/path/to/spark/install');
cluster = [Link];
mapreducer(cluster);
Note In the setup step, you use mapreducer to set the cluster execution environment. In the next
step, you create a tall array. If you modify or delete the cluster execution environment after creating a
tall array, then the tall array is invalid and you must recreate it.
Note If you want to develop in serial and not use local workers, enter the following command.
mapreducer(0);
These instructions show how to create and use tall tables on a Spark enabled Hadoop cluster,
although this procedure can be used for any Spark cluster.
Create a datastore that points to a tabular file of airline flight data. Clean the data by treating 'NA'
values as missing data so that the datastore function replaces them with NaN values.
ds = datastore('[Link]');
varnames = {'ArrDelay', 'DepDelay'};
[Link] = varnames;
[Link] = "NA";
Create a tall table tt from the datastore. MATLAB automatically starts a Spark job to run subsequent
calculations on the tall table.
tt = tall(ds)
tt =
ArrDelay DepDelay
________ ________
8 12
4-100
Use Tall Arrays on a Spark Cluster
8 1
21 20
13 12
4 -1
59 63
3 -2
11 -1
: :
: :
The display indicates that the number of rows, M, is not yet known. M is a placeholder until the
calculation completes.
Extract the arrival delay ArrDelay from the tall table. This action creates a new tall array variable to
use in subsequent calculations.
a = [Link];
You can specify a series of operations on your tall array, which are not executed until you call the
gather function. Doing so allows you to batch up commands that might take a long time. As an
example, calculate the mean and standard deviation of the arrival delay. Use these values to construct
the upper and lower thresholds for delays that are within 1 standard deviation of the mean.
m = mean(a,'omitnan');
s = std(a,'omitnan');
one_sigma_bounds = [m-s m m+s];
Use gather to calculate one_sigma_bounds, and bring the answer into memory.
sig1 = gather(one_sigma_bounds)
sig1 =
You can specify multiple inputs and outputs to gather if you want to evaluate several things at once.
Doing so is faster than calling gather separately on each tall array. For example, calculate the
minimum and maximum arrival delay.
max_delay =
1014
min_delay =
-64
Note These examples take more time to complete the first time if MATLAB is starting on the cluster
workers.
4-101
4 Big Data Processing
When using tall arrays on a Spark cluster, compute resources from the cluster will be reserved for the
lifetime of the mapreducer execution environment. To clear these resources, you must delete the
mapreducer:
delete(gcmr);
mapreducer(0);
See Also
gather | tall | datastore | table | mapreducer | [Link] |
[Link]
Related Examples
• “Big Data Workflow Using Tall Arrays and Datastores” on page 4-93
• “Use Tall Arrays on a Parallel Pool” on page 4-96
• “Configure for Spark Clusters” (MATLAB Parallel Server)
• “Configure for Hadoop Clusters” (MATLAB Parallel Server)
• “Tall Arrays for Out-of-Memory Data”
More About
• “Datastore”
4-102
Run mapreduce on a Parallel Pool
You can set your parallel settings so that a pool does not automatically open. In this case, you must
explicitly start a pool if you want mapreduce to use it for parallelization of its work. To learn more
about parallel settings, see “Specify Your Parallel Settings” on page 1-35.
For example, this conceptual code starts a pool with 12 workers. Then it sets the execution
environment to the pool using mapreducer, which creates the MapReducer object mr. Finally, it uses
mr to run mapreduce on the transformed datastore tds.
p = parpool('Processes',12);
mr = mapreducer(p);
outds = mapreduce(tds,@MeanDistMapFun,@MeanDistReduceFun,mr)
Note mapreduce can run on any cluster that supports parallel pools. The examples in this topic use
a local cluster, which works for all Parallel Computing Toolbox installations.
Create two MapReducer objects for specifying the different execution environments for mapreduce.
inMatlab = mapreducer(0);
inPool = mapreducer(p);
Create and preview the datastore. The data set used in this example is available in matlabroot/
toolbox/matlab/demos.
ds = datastore('[Link]','TreatAsMissing','NA',...
'SelectedVariableNames','ArrDelay','ReadSize',1000);
preview(ds)
ArrDelay
________
4-103
4 Big Data Processing
8
8
21
13
4
59
3
11
Next, run the mapreduce calculation in the MATLAB client session. The map and reduce functions
are available in matlabroot/toolbox/matlab/demos.
meanDelay = mapreduce(ds,@meanArrivalDelayMapper,...
@meanArrivalDelayReducer,inMatlab);
********************************
* MAPREDUCE PROGRESS *
********************************
Map 0% Reduce 0%
Map 10% Reduce 0%
Map 20% Reduce 0%
Map 30% Reduce 0%
Map 40% Reduce 0%
Map 50% Reduce 0%
Map 60% Reduce 0%
Map 70% Reduce 0%
Map 80% Reduce 0%
Map 90% Reduce 0%
Map 100% Reduce 100%
readall(meanDelay)
Key Value
__________________ ________
'MeanArrivalDelay' [7.1201]
Then, run the calculation on the current parallel pool. Note that the output text indicates a parallel
mapreduce.
meanDelay = mapreduce(ds,@meanArrivalDelayMapper,...
@meanArrivalDelayReducer,inPool);
readall(meanDelay)
Key Value
__________________ ________
'MeanArrivalDelay' [7.1201]
4-104
Run mapreduce on a Parallel Pool
With this relatively small data set, a performance improvement with the parallel pool is not likely.
This example is to show the mechanism for running mapreduce on a parallel pool. As the data set
grows, or the map and reduce functions themselves become more computationally intensive, you
might expect to see improved performance with the parallel pool, compared to running mapreduce in
the MATLAB client session.
Note When running parallel mapreduce on a cluster, the order of the key-value pairs in the output is
different compared to running mapreduce in MATLAB. If your application depends on the
arrangement of data in the output, you must sort the data according to your own requirements.
See Also
Functions
datastore | mapreduce | mapreducer
Related Examples
• “Getting Started with MapReduce”
• “Run mapreduce on a Hadoop Cluster” on page 4-106
More About
• “MapReduce”
• “Datastore”
4-105
4 Big Data Processing
In this section...
“Cluster Preparation” on page 4-106
“Output Format and Order” on page 4-106
“Calculate Mean Delay” on page 4-106
Cluster Preparation
Before you can run mapreduce on a Hadoop cluster, make sure that the cluster and client machine
are properly configured. Consult your system administrator, or see “Configure for Hadoop Clusters”
(MATLAB Parallel Server).
When running mapreduce on a Hadoop cluster, the order of the key-value pairs in the output is
different compared to running mapreduce in other environments. If your application depends on the
arrangement of data in the output, you must sort the data according to your own requirements.
First, you must set environment variables and cluster properties as appropriate for your specific
Hadoop configuration. See your system administrator for the values for these and other properties
necessary for submitting jobs to your cluster.
setenv('HADOOP_HOME', '/path/to/hadoop/install')
cluster = [Link];
Note The specified outputFolder must not already exist. The mapreduce output from a Hadoop
cluster cannot overwrite an existing folder.
Create a MapReducer object to specify that mapreduce should use your Hadoop cluster.
mr = mapreducer(cluster);
Create and preview the datastore. The data set is available in matlabroot/toolbox/matlab/
demos.
4-106
Run mapreduce on a Hadoop Cluster
ds = datastore('[Link]','TreatAsMissing','NA',...
'SelectedVariableNames','ArrDelay','ReadSize',1000);
preview(ds)
ArrDelay
________
8
8
21
13
4
59
3
11
Next, specify your output folder, output outds and call mapreduce to execute on the Hadoop cluster
specified by mr. The map and reduce functions are available in matlabroot/toolbox/matlab/
demos.
outputFolder = 'hdfs:///home/myuser/out1';
outds = mapreduce(ds,@myMapperFcn,@myReducerFcn,...
'OutputFolder',outputFolder);
meanDelay = mapreduce(ds,@meanArrivalDelayMapper,...
@meanArrivalDelayReducer,mr,...
'OutputFolder',outputFolder)
Parallel mapreduce execution on the Hadoop cluster:
********************************
* MAPREDUCE PROGRESS *
********************************
Map 0% Reduce 0%
Map 66% Reduce 0%
Map 100% Reduce 66%
Map 100% Reduce 100%
meanDelay =
Files: {
' .../tmp/myuser/tpc00621b1_4eef_4abc_8078_646aa916e7d9/[Link]'
}
ReadSize: 1 key-value pairs
FileType: 'seq'
readall(meanDelay)
Key Value
__________________ ________
'MeanArrivalDelay' [7.1201]
Although for demonstration purposes this example uses a local data set, it is likely when using
Hadoop that your data set is stored in an HDFS™ file system. Likewise, you might be required to
store the mapreduce output in HDFS. For details about accessing HDFS in MATLAB, see “Work with
Remote Data”.
4-107
4 Big Data Processing
See Also
Functions
datastore | mapreduce | mapreducer | [Link]
Related Examples
• “Getting Started with MapReduce”
• “Run mapreduce on a Parallel Pool” on page 4-103
More About
• “MapReduce”
• “Datastore”
4-108
Partition a Datastore in Parallel
• Perform some action on only one part of the whole datastore, or on several defined parts
simultaneously.
• Search for specific values in the data store, with all workers acting simultaneously on their own
partitions.
• Perform a reduction calculation on the workers across all partitions.
This example shows how to use the partition function to parallelize the reading of data from a
datastore. It uses a small datastore of airline data provided in MATLAB®, and finds the mean of the
non-NaN values from its 'ArrDelay' column.
Serial Execution
A simple way to calculate the mean is to divide the sum of all the non-NaN values by the number of
non-NaN values. The code in the sumAndCountArrivalDelay on page 4-111 helper function does
this for the datastore first in a non-parallel way.
delete(gcp('nocreate'));
Create a datastore from the collection of worksheets in airlinesmall_subset.xlsx and select the
ArrDelay variables to import.
Use the function sumAndCountArrivalDelay to calculate the mean without any parallel execution.
Use the tic and toc functions to time the execution, here and in the later parallel cases.
ds = spreadsheetDatastore(repmat({'airlinesmall_subset.xlsx'},20,1));
[Link] = 'ArrDelay';
reset(ds);
tic
[total,count] = sumAndCountArrivalDelay(ds)
total = 3098060
count = 394940
sumtime = toc
sumtime = 36.6618
mean = total/count
mean = 7.8444
4-109
4 Big Data Processing
Parallel Execution
The partition function allows you to partition the datastore into smaller parts, each represented as
a datastore itself. These smaller datastores work completely independently of each other, so that you
can work with them inside of parallel language features such as parfor loops and spmd blocks.
You can use the numpartitions function to specify the number of partitions, which is based on the
datastore itself and the parallel pool size. This does not necessarily equal the number of workers in
the pool. Set the number of loop iterations to the number of partitions (N).
The following code starts a parallel pool on a local cluster, then partitions the datastore among
workers for iterating over the loop. This code calls the helper function
parforSumAndCountArrivalDelay on page 4-111, which includes a parfor loop to amass the
count and sum totals in parallel loop iterations.
p = parpool('Processes',4);
reset(ds);
tic
[total,count] = parforSumAndCountArrivalDelay(ds)
total = 3098060
count = 394940
parfortime = toc
parfortime = 11.6383
mean = total/count
mean = 7.8444
Rather than let the software calculate the number of partitions, you can explicitly set this value, so
that the data can be appropriately partitioned to fit your algorithm. For example, to parallelize data
from within an spmd block, you can specify the number of workers (spmdSize) as the number of
partitions to use. The spmdSumAndCountArrivalDelay on page 4-111 helper function uses an spmd
block to perform a parallel read, and explicitly sets the number of partitions equal to the number of
workers.
reset(ds);
tic
[total,count] = spmdSumAndCountArrivalDelay(ds)
total = 3098060
count = 394940
spmdtime = toc
spmdtime = 11.7520
4-110
Partition a Datastore in Parallel
mean = total/count
mean = 7.8444
When you are done with your computation, you can delete the current parallel pool.
delete(p);
Helper Functions
Create a helper function to amass the count and sum in a non-parallel way.
Create a helper function to amass the count and sum in parallel using parfor.
[localTotal,localCount] = sumAndCountArrivalDelay(subds);
total = total + localTotal;
count = count + localCount;
end
end
Create a helper function to amass the count and sum in parallel using spmd.
See Also
datastore | spreadsheetDatastore
4-111
4 Big Data Processing
Related Examples
• “Getting Started with MapReduce”
• “Run mapreduce on a Parallel Pool” on page 4-103
More About
• “MapReduce”
• “Datastore”
4-112
Distribute Arrays and Run SPMD
Now MM is a distributed array, equivalent to M, and you can manipulate or access its elements in the
same way as any other array.
M2 = 2*MM; % M2 is also distributed, calculation performed on workers
x = M2(1,1) % x on the client is set to first element of M2
This code creates an individual 4-by-4 matrix, R, of random numbers on each worker in the pool.
Composites
Following an spmd statement, in the client context, the values from the block are accessible, even
though the data is actually stored on the workers. On the client, these variables are called Composite
objects. Each element of a composite is a symbol referencing the value (data) on a worker in the pool.
Note that because a variable might not be defined on every worker, a Composite might have
undefined elements.
Continuing with the example from above, on the client, the Composite R has one element for each
worker:
X = R{3}; % Set X to the value of R from worker 3.
The line above retrieves the data from worker 3 to assign the value of X. The following code sends
data to worker 3:
X = X + 2;
R{3} = X; % Send the value of X from the client to worker 3.
If the parallel pool remains open between spmd statements and the same workers are used, the data
on each worker persists from one spmd statement to another.
spmd
R = R + spmdIndex % Use values of R from previous spmd.
end
4-113
4 Big Data Processing
A typical use for spmd is to run the same code on a number of workers, each of which accesses a
different set of data. For example:
spmd
INP = load(['somedatafile' num2str(spmdIndex) '.mat']);
RES = somefun(INP)
end
Then the values of RES on the workers are accessible from the client as RES{1} from worker 1,
RES{2} from worker 2, etc.
There are two forms of indexing a Composite, comparable to indexing a cell array:
Although data persists on the workers from one spmd block to another as long as the parallel pool
remains open, data does not persist from one instance of a parallel pool to another. That is, if the pool
is deleted and a new one created, all data from the first pool is lost.
For more information about using distributed arrays, spmd, and Composites, see “Distributed
Arrays”.
See Also
distributed | spmd | Composite
Related Examples
• “Create and Use Distributed Arrays” on page 4-2
• “Run Single Programs on Multiple Data Sets” on page 4-6
• “Access Worker Variables with Composites” on page 4-17
4-114
5
Batch Processing
Use batch jobs to off-load the execution of long-running computations in the background. For batch
jobs, MATLAB can be closed on the client, and the client can be shut down when the batch job is
submitted to another computer or cluster. You can carry out other tasks while the batch job is
processing. Batch jobs are particularly suitable when you are working on a compute cluster. Learn
more about batch processing and detailed job control in the following sections.
To develop and test your code, you can offload work to a local cluster on your client machine. If you
close your MATLAB session, any batch jobs using the local cluster also stop immediately.
There are two types of jobs you can run in a batch workflow:
Typically, if your code does not require a parallel pool, then you can use an independent job.
• Communicating Jobs – one worker acts as the client and the other workers run the noninteractive
pool. The workers can communicate with each other during the execution of their tasks.
Typically, if your code calls functions that require a parallel pool such as parfor, parfeval,
spmd, or distributed, then it is a communicating job.
Parallel Computing Toolbox provides the following functions to run your MATLAB code in a batch
process:
• batch
• createJob
• createCommunicatingJob
Tip For a simpler function to run communicating jobs, use the batch function instead of the
createCommunicatingJob function.
The following diagram shows when to use the batch and createJob functions.
5-2
Choose Batch Processing Function
5-3
5 Batch Processing
See Also
batch | createJob | createCommunicatingJob | createTask
Related Examples
• “Run Script as Batch Job” on page 5-20
• “Run Batch Parallel Jobs” on page 5-5
• “Run Batch Job and Access Files from Workers” on page 5-8
• “Create and Run Job” on page 10-77
• “Parallel Language Decision Tables” on page 1-22
• “Run MATLAB Functions with Automatic Parallel Support” on page 1-9
5-4
Run Batch Parallel Jobs
5 batch does not block MATLAB and you can continue working while computations take place. If
you need to block MATLAB until the job finishes, use the wait function on the job object.
wait(job)
6 After the job finishes, you can retrieve and view its results. The load command transfers
variables created on the worker to the client workspace, where you can view the results:
load(job,'A')
plot(A)
7 When the job is complete, permanently delete its data and remove its reference from the
workspace:
delete(job)
clear job
batch runs your code on a local worker or a cluster worker, but does not require a parallel pool.
You can use batch to run either scripts or functions. For more details, see the batch reference page.
5-5
5 Batch Processing
parfor i = 1:1024
A(i) = sin(i*2*pi/1024);
end
3 Save the file and close the Editor.
4 Run the script in MATLAB with the batch command. Indicate that the script should use a
parallel pool for the loop:
job = batch('mywave','Pool',3)
This command specifies that three workers (in addition to the one running the batch script) are
to evaluate the loop iterations. Therefore, this example uses a total of four local workers,
including the one worker running the batch script. Altogether, there are five MATLAB sessions
involved, as shown in the following diagram.
wait(job)
load(job,'A')
plot(A)
The results look the same as before, however, there are two important differences in execution:
• The work of defining the parfor-loop and accumulating its results are offloaded to another
MATLAB session by batch.
• The loop iterations are distributed from one MATLAB worker to another set of workers
running simultaneously ('Pool' and parfor), so the loop might run faster than having only
one worker execute it.
6 When the job is complete, permanently delete its data and remove its reference from the
workspace:
delete(job)
clear job
5-6
Run Batch Parallel Jobs
Running a script as a batch from the Files panel uses only one worker from the cluster. So even if the
script contains a parfor loop or spmd block, it does not open an additional pool of workers on the
cluster. These code blocks execute on the single worker used for the batch job. If your batch script
requires opening an additional pool of workers, you can run it from the command line, as described in
“Run Batch Job with Parallel Pool” on page 5-5.
When you run a batch job from the Files panel, this also opens the Job Monitor. The Job Monitor is a
tool that lets you track your job in the scheduler queue. For more information about the Job Monitor
and its capabilities, see “Job Monitor” on page 5-48.
See Also
batch
Related Examples
• “Run Batch Job and Access Files from Workers” on page 5-8
5-7
5 Batch Processing
You can offload your computations to run in the background by using batch.
If your code needs access to files, you can use additional options, such as 'AttachedFiles' or
'AdditionalPaths', to make the data accessible. You can continue working in MATLAB® while the
computations take place. If you submit your computations to a remote cluster, you can close MATLAB
and recover the results later.
Prepare Example
Use the supporting function prepareSupportingFiles to copy the required data for this example
to your current working folder.
prepareSupportingFiles;
Your current working folder now contains 4 files: [Link], [Link], [Link], and [Link].
Create a cluster object using parcluster. By default, parcluster uses your default cluster profile.
Check your default cluster profile on the MATLAB Home tab, in the Environment section, in
Parallel > Select a Default Cluster.
c = parcluster();
Place your code inside a function and submit it as a batch job by using batch. For an example of a
custom function, see the supporting function divideData. Specify the expected number of output
arguments and a cell array with inputs to the function.
Note that if you send a script file using batch, MATLAB transfers all the workspace variables to the
cluster, even if your script does not use them. If you have a large workspace, it impacts negatively the
data transfer time. As a best practice, convert your script to a function file to avoid this
communication overhead. You can do this by simply adding a function line at the beginning of your
script. To reduce overhead in this example, divideData is defined in a file outside of this live script.
If your code uses a parallel pool, use the 'Pool' name-value pair argument to create a parallel pool
with the number of workers that you specify. batch uses an additional worker to run the function
itself.
By default, batch changes the initial working folder of the workers to the current folder of the
MATLAB client. It can be useful to control the initial working folder in the workers. For example, you
might want to control it if your cluster uses a different file system, and therefore the paths are
different, such as when you submit from a Windows® client machine to a Linux® cluster.
• To keep the initial working folder of the workers and use their default, set 'CurrentFolder' to
'.'.
• To change the initial working folder, set 'CurrentFolder' to a folder of your choice.
This example uses a parallel pool with three workers and chooses a temporary location for the initial
working folder. Use batch to offload the computations in divideData.
5-8
Run Batch Job and Access Files from Workers
batch runs divideData on a parallel worker, so you can continue working in MATLAB while
computations take place.
If you want to block MATLAB until the job completes, use the wait function on the job object.
wait(job);
To retrieve the results, use fetchOutputs on the job object. As divideData depends on a file that
the workers cannot find, fetchOutputs throws an error. You can access error information by using
getReport on the Error property of Task objects in the job. In this example, the code depends on a
file that the workers cannot find.
getReport([Link](1).Error)
ans =
'Error using divideData (line 4)
Unable to read file '[Link]'. No such file or directory.'
By default, batch automatically analyzes your code and transfers required files to the workers. In
some cases, you must explicitly transfer those files -- for example, when you determine the name of a
file at runtime.
In this example, divideData accesses the supporting file [Link], which batch automatically detects
and transfers. The function also accesses [Link], but it resolves the name of the file at runtime, so
the automatic dependency analysis does not detect it.
type divideData.m
function X = divideData()
A = load("[Link]");
X = zeros(flip(size(A)));
parfor i = 1:3
B = load("B" + i + ".dat");
X = X + A\B;
end
end
If the data is in a location that the workers can access, you can use the name-value pair argument
'AdditionalPaths' to specify the location. 'AdditionalPaths' adds this path to the MATLAB
search path of the workers and makes the data visible to them.
pathToData = pwd;
job(2) = batch(c,@divideData,1,{}, ...
'Pool',3, ...
'CurrentFolder',tempdir, ...
'AdditionalPaths',pathToData);
wait(job(2));
If the data is in a location that the workers cannot access, you can transfer files to the workers by
using the 'AttachedFiles' name-value pair argument. You need to transfer files if the client and
workers do not share the same file system, or if your cluster uses the generic scheduler interface in
5-9
5 Batch Processing
nonshared mode. For more information, see “Configure Using the Generic Scheduler Interface”
(MATLAB Parallel Server).
If you submit the job to a remote cluster, you can close MATLAB after job submission and retrieve the
results later. Before you close MATLAB, make a note of the job ID.
job3ID = job(3).ID
job3ID = 25
When you open MATLAB again, you can find the job by using the findJob function.
job(3) = findJob(c,'ID',job3ID);
wait(job(3));
Alternatively, you can use the Job Monitor to track your job. You can open it from the MATLAB Home
tab, in the Environment section, in Parallel > Monitor Jobs.
To retrieve the results of a batch job, use the fetchOutputs function. fetchOutputs returns a cell
array with the outputs of the function run with batch.
X = fetchOutputs(job(3))
When you have retrieved all the required outputs and do not need the job object anymore, delete it to
clean up its data and avoid consuming resources unnecessarily.
delete(job)
clear job
See Also
parcluster | batch | findJob | fetchOutputs (Job)
5-10
Share Code with Workers
Note For an example that shows how to share code with workers using batch, see “Run Batch Job
and Access Files from Workers” on page 10-18.
You must define each worker session's search path so that it looks for files in the right places. You can
define the path:
• By using the job's AdditionalPaths property. This is the preferred method for setting the path,
because it is specific to the job.
AdditionalPaths identifies folders to be added to the top of the command search path of
worker sessions for this job. If you also specify AttachedFiles, the AttachedFiles are above
AdditionalPaths on the workers' path.
When you specify AdditionalPaths at the time of creating a job, the settings are combined with
those specified in the applicable cluster profile. Setting AdditionalPaths on a job object after it
is created does not combine the new setting with the profile settings, but overwrites existing
settings for that job.
This example sets the MATLAB worker path in a mixed-platform environment to use functions in
both the central repository /central/funcs and the department archive /dept1/funcs, which
each also have a Windows UNC path.
c = parcluster(); % Use default
job1 = createJob(c);
ap = {'/central/funcs','/dept1/funcs', ...
'\\OurDomain\central\funcs','\\OurDomain\dept1\funcs'};
[Link] = ap;
• By putting the path command in any of the appropriate startup files for the worker:
• matlabroot\toolbox\local\startup.m
• matlabroot\toolbox\parallel\user\jobStartup.m
• matlabroot\toolbox\parallel\user\taskStartup.m
Access to these files can be passed to the worker by the job's AttachedFiles or
AdditionalPaths property. Otherwise, the version of each of these files that is used is the one
highest on the worker's path.
5-11
5 Batch Processing
Access to files among shared resources can depend upon permissions based on the user name. You
can set the user name with which the MATLAB Job Scheduler and worker services of MATLAB
Parallel Server software run by setting the MJSUSER value in the mjs_def file before starting the
services. For Microsoft Windows operating systems, there is also MJSPASS for providing the account
password for the specified user. For an explanation of service default settings and the mjs_def file,
see “Modify mjs_def File” (MATLAB Parallel Server) in the MATLAB Parallel Server System
Administrator's Guide.
• InputArguments — This property of each task contains the input data you specified when
creating the task. This data gets passed into the function when the worker performs its evaluation.
• OutputArguments — This property of each task contains the results of the function's evaluation.
• JobData — This property of the job object contains data that gets sent to every worker that
evaluates tasks for that job. This property works efficiently because the data is passed to a worker
only once per job, saving time if that worker is evaluating more than one task for the job. (Note:
Do not confuse this property with the UserData property on any objects in the MATLAB client.
Information in UserData is available only in the client, and is not available to the scheduler or
workers.)
• AttachedFiles — This property of the job object is a cell array in which you manually specify all
the folders and files that get sent to the workers. On the worker, the files are installed and the
entries specified in the property are added to the search path of the worker session.
AttachedFiles contains a list of folders and files that the worker need to access for evaluating a
job's tasks. The value of the property (empty by default) is defined in the cluster profile or in the
client session. You set the value for the property as a cell array of character vectors. Each
character vector is an absolute or relative pathname to a folder or file. (Note: If these files or
folders change while they are being transferred, or if any of the folders are empty, a failure or
error can result. If you specify a pathname that does not exist, an error is generated.)
The first time a worker evaluates a task for a particular job, the scheduler passes to the worker
the files and folders in the AttachedFiles property. On the worker machine, a folder structure is
created that is exactly the same as that accessed on the client machine where the property was
set. Those entries listed in the property value are added to the top of the command search path in
the worker session. (Subfolders of the entries are not added to the path, even though they are
included in the folder structure.) To find out where the files are placed on the worker machine, use
the function getAttachedFilesFolder in code that runs on the worker.
When the worker runs subsequent tasks for the same job, it uses the folder structure already set
up by the job's AttachedFiles property for the first task it ran for that job.
When you specify AttachedFiles at the time of creating a job, the settings are combined with
those specified in the applicable profile. Setting AttachedFiles on a job object after it is created
does not combine the new setting with the profile settings, but overwrites the existing settings for
that job.
5-12
Share Code with Workers
The transfer of AttachedFiles occurs for each worker running a task for that particular job on a
machine, regardless of how many workers run on that machine. Normally, the attached files are
deleted from the worker machine when the job is completed, or when the next job begins.
• AutoAttachFiles — This property of the job object uses a logical value to specify that you want
MATLAB to perform an analysis on the task functions in the job and on manually attached files to
determine which code files are necessary for the workers, and to automatically send those files to
the workers. You can set this property value in a cluster profile using the Profile Manager, or you
can set it programmatically on a job object at the command line.
c = parcluster();
j = createJob(c);
[Link] = true;
The supported code file formats for automatic attachment are MATLAB files (.m extension), P-code
files (.p), and MEX files (.mex). Note that AutoAttachFiles does not include data files for your
job; use the AttachedFiles property to explicitly transfer these files to the workers.
Use listAutoAttachedFiles to get a listing of the code files that are automatically attached to
a job.
If the AutoAttachFiles setting is true for the cluster profile used when starting a parallel pool,
MATLAB performs an analysis on spmd blocks, parfor-loops, and other attached files to
determine what other code files are necessary for execution, then automatically attaches those
files to the parallel pool so that the code is available to the workers.
These additional files can initialize and clean up a worker session as it begins or completes
evaluations of tasks for a job:
• jobStartup.m automatically executes on a worker when the worker runs its first task of a job.
• taskStartup.m automatically executes on a worker each time the worker begins evaluation of a
task.
• poolStartup.m automatically executes on a worker each time the worker is included in a newly
started parallel pool.
• taskFinish.m automatically executes on a worker each time the worker completes evaluation of
a task.
matlabroot/toolbox/parallel/user
You can edit these files to include whatever MATLAB code you want the worker to execute at the
indicated times.
Alternatively, you can create your own versions of these files and pass them to the job as part of the
AttachedFiles property, or include the path names to their locations in the AdditionalPaths
property.
5-13
5 Batch Processing
The worker gives precedence to the versions provided in the AttachedFiles property, then to those
pointed to in the AdditionalPaths property. If any of these files is not included in these properties,
the worker uses the version of the file in the toolbox/parallel/user folder of the worker's
MATLAB installation.
See Also
jobStartup | taskStartup | poolStartup | taskFinish
Related Examples
• “Run Batch Job and Access Files from Workers” on page 5-8
• “Choose How to Manage Data in Parallel Computing” on page 1-37
5-14
Control Random Number Streams on Workers
The random number generation functions rand, randi, and randn behave differently for parallel
calculations compared to your MATLAB client. You can change the behavior of random number
generators on parallel workers or on the client to generate reproducible streams of random numbers.
By default, the MATLAB client and MATLAB workers use different random number generators, even if
the workers are part of a local cluster on the same machine as the client. The table below summarizes
the default settings for the client and workers:
For more information about the available generators and normal transforms, see “Choosing a
Random Number Generator”. Each worker in a cluster draws random numbers from an independent
stream with the properties in the table. By default, the random numbers generated on each worker in
a parfor loop are different from each other and from the random numbers generated on the client.
Note If you have a GPU on your worker, different settings apply to random number streams on the
GPU. For more information, see “Random Number Streams on a GPU” on page 6-72.
For example, you might run a script as a batch job on a worker, and need the same generator or
sequence as the client. Suppose you start with a script file named randScript1.m that contains the
line:
R = rand(1,4);
You can run this script in the client, and then as a batch job on a worker. Notice that the default
generated random number sequences in the results are different.
randScript1; % In client
R
R =
0.8147 0.9058 0.1270 0.9134
[Link]('Processes')
c = parcluster();
5-15
5 Batch Processing
j = batch(c,'randScript1'); % On worker
wait(j);load(j);
R
R =
0.1349 0.6744 0.9301 0.5332
For identical results, you can set the client and worker to use the same generator and seed. Here, the
file randScript2.m contains the following code:
rng(1,'Threefry');
R = rand(1,4);
randScript2; % In client
R
R =
0.1404 0.8197 0.1073 0.4131
j = batch(c,'randScript2'); % On worker
wait(j); load(j);
R
R =
0.1404 0.8197 0.1073 0.4131
To reset the settings of the random number generator to their default values in the client and on the
worker, you can add this code to the end of randScript2.m.
rng('default')
Different Workers
By default, each worker in a cluster working on the same job has an independent random number
stream. If rand, randi, or randn are called in parallel, each worker produces a unique sequence of
random numbers.
Note Because rng('shuffle') seeds the random number generator based on the current time, do
not use this command to set the random number stream on different workers if you want to ensure
independent streams. This is especially true when the command is sent to multiple workers
simultaneously, such as inside a parfor, spmd, or a communicating job. For independent streams on
the workers, use the default behavior; or if that is not sufficient for your needs, consider using a
unique substream on each worker using RandStream.
This example uses two workers in a parallel pool to show they generate unique random number
sequences.
p = parpool(2);
spmd
R = rand(1,4); % Different on each worker
end
R{1},R{2}
5-16
Control Random Number Streams on Workers
ans =
0.1349 0.6744 0.9301 0.5332
ans =
0.6383 0.5195 0.1398 0.6509
delete(p)
If you need all workers to generate the same sequence of numbers, you can set each worker to use
the same generator settings:
p = parpool(2);
spmd
rng(0,'Philox'); % Default seed 0.
R = rand(1,4); % Same on all workers
end
R{1},R{2}
ans =
0.3655 0.6975 0.1789 0.4549
ans =
0.3655 0.6975 0.1789 0.4549
delete(p)
If you need to control the random numbers at each iteration of a parfor-loop, see “Repeat Random
Numbers in parfor-Loops” on page 2-65.
stream = RandStream('Threefry','Seed',0,'NormalTransform','Inversion');
[Link](stream);
R = randn(1,7)
You can run this code on the client and on a worker in a parallel job (using batch or spmd) to
produce the same sequence of random numbers:
R =
-0.3479 0.1057 0.3969 0.6544 -1.8228 0.9587 0.5360
See Also
rng | RandStream
More About
• “Repeat Random Numbers in parfor-Loops” on page 2-65
• “Random Number Streams on a GPU” on page 6-72
• “Creating and Controlling a Random Number Stream”
5-17
5 Batch Processing
This example shows how to monitor the progress of a batch job by using ValueStore.
The batchSvdCode function finds the singular values of random matrices and stores the results in
the ValueStore object with a unique key. Additionally, the function calculates the progress of the
batch job and stores the progress in the ValueStore object.
type batchSvdCode
function batchSvdCode(size)
% Get the ValueStore of the current job.
store = getCurrentValueStore;
for i = 1:numel(size)
% Store results in the ValueStore object.
pause(1) % Use pause to simulate a nontrivial calculation.
key = strcat("Result ",num2str(i));
store(key) = svd(rand(size(i)));
store("progress") = i/numel(size);
end
end
The updateWaitbar callback function runs when the job adds an entry to the ValueStore object.
In this example, you configure the job to add two entries to the ValueStore object in every for-loop
iteration.
type updateWaitbar
function updateWaitbar(w,store,key)
% Update a waitbar using the ValueStore property.
if strcmp(key,"progress")
% Check if the waitbar is a reference to a deleted object.
if isvalid(w)
progress = store(key);
if progress==1
waitbar(progress,w,"Job Completed");
else
% Update the waitbar
waitbar(progress,w);
end
end
else
waitbar(store("progress"),w,("Please wait... " + key + " added"))
end
5-18
Monitor Batch Jobs with ValueStore
Run a batch job on workers using the default cluster profile. Retrieve the ValueStore object on the
client while the job is still running. Show the progress of the job.
size = [8 16 32 20];
c = parcluster;
job = batch(c,@batchSvdCode,0,{size});
store = [Link];
[Link] = @(store,key) updateWaitbar(w,store,key);
wait(job);
Use delete to close the wait bar after the job is completed.
delete(w)
Get the entry value specified by the key "Result 1" from the ValueStore object.
val1 = 8×1
4.3318
1.2988
1.1040
0.8813
0.5711
0.3991
0.2092
0.1048
delete(job)
clear job
See Also
batch | ValueStore
Related Examples
• “Monitor Monte Carlo Batch Jobs with ValueStore” on page 5-22
• “Run Batch Job and Access Files from Workers” on page 5-8
5-19
5 Batch Processing
This example shows how to use batch to offload work to a MATLAB® worker session that runs in the
background.
Run a script as a batch job by using the batch function. By default, batch uses your default cluster
profile. Check your default cluster profile on the MATLAB Home tab, in the Environment section, in
Parallel > Select Parallel Environment. Alternatively, you can specify a cluster profile with the
'Profile' name-value pair argument.
job = batch('myScript');
batch does not block MATLAB and you can continue working while computations take place.
If you want to block MATLAB until the job finishes, use the wait function on the job object.
wait(job);
By default, MATLAB saves the Command Window output from the batch job to the diary of the job. To
retrieve it, use the diary function.
diary(job)
After the job finishes, fetch the results by using the load function.
load(job,'x');
plot(x)
5-20
Run Script as Batch Job
If you want to load all the variables in the batch job, use load(job) instead.
When you have loaded all the required variables, delete the job object to clean up its data and avoid
consuming resources unnecessarily.
delete(job);
clear job
Note that if you send a script file using batch, MATLAB transfers all the workspace variables to the
cluster, even if your script does not use them. The data transfer time for a large workspace can be
substantial. As a best practice, convert your script to a function file to avoid this communication
overhead. For an example that uses a function, see “Run Batch Job and Access Files from Workers” on
page 10-18.
For more advanced options with batch, see “Run Batch Job and Access Files from Workers” on page
10-18.
See Also
batch | wait | load
Related Examples
• “Run Batch Job and Access Files from Workers” on page 5-8
5-21
5 Batch Processing
This example shows how to monitor a Monte Carlo batch job during execution by using ValueStore.
All jobs have an associated ValueStore object that you can use to access data while the job is
running. You can continue to use the command line while the job runs. This example shows how to
use the ValueStore object to access and monitor data from a batch Monte Carlo simulation while
the job is running.
You can estimate the value of π using a variety of Monte Carlo methods. This example shows how to
estimate π with the simple Monte Carlo area method.
To estimate π with the Monte Carlo Area method, you perform these steps:
For more details, see the Simple Monte Carlo Area Method on page 5-26 section of the example.
Run multiple simulations in parallel and store the interim results in the job ValueStore object as
key-value entries. Use the updatePlot on page 5-26 helper function to retrieve and process the
results from the ValueStore object and update the plots to monitor the progress of the simulation.
Specify the radius of the circle and the number of parfor-loops over which the job iterates.
r = 1;
steps = 200;
Create two plots to visualize the interim results of the Monte Carlo simulation. Include settings such
as the title, labels, and limits. Set the aspect ratio of the axes so that they do not change when they
update automatically during the simulation.
axis(ax1,"equal",[-1 1 -1 1])
5-22
Monitor Monte Carlo Batch Jobs with ValueStore
5-23
5 Batch Processing
Create a cluster object from your default cluster parallel environment. To check your default parallel
environment, on the MATLAB® Home tab, in the Environment section, click Parallel and pause on
Select Parallel Environment.
cluster = parcluster;
The GeneratePoints on page 5-25 function, defined at the end of the example, contains the Monte
Carlo simulation definition. Use batch to offload the computations in GeneratePoints with the
input arguments r and steps. Use the Pool name-value argument to create a parallel pool with four
workers. Because the batch function uses another worker to run the function, make sure the number
of pool workers requested is one less than the number of workers available in the cluster.
job = batch(cluster,@generatePoints,1,{r,steps},Pool=4);
Set up the KeyUpdatedFcn callback. Get the ValueStore object of the job and set up a callback
function to execute when the job adds an entry to the ValueStore object.
The UpdatePlot callback function runs when the job adds an entry to the ValueStore object in
each parfor-loop. This function updates the plots with the new data.
5-24
Monitor Monte Carlo Batch Jobs with ValueStore
The job can write information to the ValueStore object before the software sets up the
KeyUpdatedFcn callback. To prevent this behavior by setting up the KeyUpdatedFcn callback
before submitting the job, use the createCommunicatingJob function.
store = [Link];
[Link] = @(store,key) updatePlot(ax1,ax2,store,key);
Use wait to maintain an active connection to the job in a live script. Using wait blocks the command
line while the job is running. Alternatively, call the plain script version of this example from the
MATLAB command line to use the command line during execution. The plots can take a long time to
update.
disp("Waiting for job to finish ...")
wait(job);
disp("Job completed")
Job completed
After the job finishes, you still have access to the job ValueStore object. You can access data from
the ValueStore object with keys. For example, view the data for Step 6.
disp("Fetching example result for step 6:")
Retrieve the results of the job and then delete the job.
pointsData = fetchOutputs(job);
delete(job)
clear job
Supporting Functions
The generatePoints function randomly places points in a square. The function uses rand to
generate two random numbers, x and y, from a uniform distribution in the interval (-r, r). The
function then determines whether the point defined by values of x and y is inside the circle and stores
the values of x and y in the job ValueStore object with a unique key. If the point is inside the circle,
the function assigns a value of 1 and a red color to the entry. If the point is outside the circle, the
function assigns a value of 0 and a blue color to the entry. The ValueStore object gets a new entry
in every iteration of the parfor-loop. Save the results in the sliced variable points, which you can
access as a property of the job.
function points = generatePoints(r,steps)
points = zeros(steps,4);
5-25
5 Batch Processing
Use a plot of the intermediate results to monitor the progress of the Monte Carlo π estimation. The
updatePlot function updates the plot each time the job updates the ValueStore object.
function updatePlot(ax1,ax2,store,key)
% Update results from the job ValueStore object.
result = store(key);
% Update the plots with the new x and y values and the estimate of pi.
hold([ax1 ax2],'on');
plot(ax1,result.x,result.y,'.',Color=result.point_color);
plot(ax2,numel(hits),pi_estimate,".-k");
title(ax2,"Current Estimate of $\pi$",num2str(pi),Interpreter="latex");
hold([ax1 ax2],'off');
drawnow nocallbacks;
end
Given a circle with radius r inscribed within a square with sides of length 2r, the area of the circle is
related to the area of the square by π. This figure illustrates the problem.
5-26
Monitor Monte Carlo Batch Jobs with ValueStore
You can derive π from the ratio of the area of the circle divided by the area of the square:
area of circle
area of square
=
5-27
5 Batch Processing
πr 2 π
2
= 4
2r
To estimate the area of the circle without using π directly, randomly generate a uniform sample of two
dimensional (2-D) points inside the square and count how many are inside the circle. The probability
that a point can be found in the circle is the ratio of the area of the circle divided by the area of the
square.
To determine whether a point is inside the circle, randomly generate two values for the x and y
coordinates of a point and calculate the distance between the point and the origin of the circle. The
distance d from the origin to the generated point is given by this equation:
d= x2 + y2
If d is less than the radius r of the circle, the point is inside the circle. Generate a large sample of
points and count how many are inside the circle. Use this data to obtain a ratio of points inside the
circle to the total number of points generated. This ratio is equivalent to the ratio of the area of the
circle to the area of the square. You can then estimate π using:
points in circle π
total number of points
≈ 4
points in circle
π ≈4×
total number of points
See Also
batch | ValueStore | createCommunicatingJob
Related Examples
• “Monitor Batch Jobs with ValueStore” on page 5-18
• “Run Batch Job and Access Files from Workers” on page 5-8
5-28
Program Independent Jobs
Some of the details of a job and its tasks can depend on the type of scheduler you are using:
5-29
5 Batch Processing
Note Workers running in a local cluster on a Microsoft Windows operating system can display
Simulink graphics and the output from certain functions such as uigetfile and uigetdir. (With
other platforms or schedulers, workers cannot display any graphical output.) This behavior is subject
to removal in a future release.
This section details the steps of a typical programming session with Parallel Computing Toolbox
software using a local cluster:
The objects used by the client session to interact with the cluster are only references to data in the
cluster job storage location, not in the client session. After jobs and tasks are created, you can close
your client session and restart it, and your job still resides in the storage location. You can find
existing jobs using the findJob function or the Jobs property of the cluster object.
You use the parcluster function to create an object in your local MATLAB session representing the
local scheduler.
c = parcluster('local');
Create a Job
You create a job with the createJob function. This statement creates a job in the cluster job storage
location and creates the job object job1 in the client session. If you omit the semicolon at the end of
the command, it displays some information about the job.
job1 = createJob(c)
5-30
Program Independent Jobs on Local Cluster
Job
Properties:
ID: 1
Type: independent
Username: mylogin
State: pending
SubmitDateTime:
StartDateTime:
RunningDuration: 0 days 0h 0m 0s
NumThreads: 1
AutoAttachFiles: true
Auto Attached Files: List files
AttachedFiles: {}
AutoAddClientPath: false
AdditionalPaths: {}
Associated Tasks:
Number Pending: 0
Number Running: 0
Number Finished: 0
Task ID of Errors: []
Task ID of Warnings: []
The State property of the job is pending. This means that the job has not yet been submitted
(queued) for running, so you can now add tasks to it.
The scheduler display now indicates the existence of your job, which is the pending one, as appears in
this partial listing:
c
Local Cluster
Properties:
Profile: local
Modified: false
Host: myhost
NumWorkers: 6
NumThreads: 1
JobStorageLocation: C:\Users\mylogin\AppData\Roaming\MathWorks...
\MATLAB\local_cluster_jobs\R2021b
RequiresOnlineLicensing: false
Associated Jobs:
Number Pending: 1
Number Queued: 0
Number Running: 0
Number Finished: 0
Create Tasks
After you have created your job, you can create tasks for the job using the createTask function.
Tasks define the functions to be evaluated by the workers during the running of the job. Often, the
tasks of a job are all identical. In this example, five tasks each generate a 3-by-3 matrix of random
numbers.
createTask(job1, @rand, 1, {{3,3} {3,3} {3,3} {3,3} {3,3}});
5-31
5 Batch Processing
[Link]
To run your job and have its tasks evaluated, you submit the job to the cluster with the submit
function.
submit(job1)
The local scheduler starts the workers on your machine, and distributes the tasks of job1 to these
workers for evaluation.
The results of each task evaluation are stored in the task object OutputArguments property as a cell
array. After waiting for the job to complete, use the function fetchOutputs to retrieve the results
from all the tasks in the job.
wait(job1)
results = fetchOutputs(job1);
results{1:5}
ans =
ans =
ans =
5-32
Program Independent Jobs on Local Cluster
ans =
ans =
After the job is complete, you can repeat the commands to examine the updated status of the cluster,
job, and task objects:
c
job1
[Link]
The local cluster has no interaction with any other scheduler or MATLAB Job Scheduler, nor with any
other workers that can also be running on your client machine under the mjs service. Multiple
MATLAB sessions on your computer can each start its own local scheduler with its own workers, but
these groups do not interact with each other.
When you end your MATLAB client session, its local scheduler and any workers that happen to be
running also stop immediately.
5-33
5 Batch Processing
This section assumes that you are connecting to a MATLAB Job Scheduler cluster. The basic job
programming sequence is the same for MATLAB Job Scheduler or any third-party scheduler cluster:
Note that the objects that the client session uses to interact with the cluster are only references to
data that is actually contained in the MATLAB Job Scheduler, not in the client session. After jobs and
tasks are created, you can close your client session and restart it, and your job is still stored in the
MATLAB Job Scheduler. You can find existing jobs using the findJob function or the Jobs property
of the MATLAB Job Scheduler cluster object.
A cluster profile identifies the type of cluster to use and its specific properties. In a profile, you define
how many workers a job can access, where the job data is stored, where MATLAB is accessed and
many other cluster properties. The exact properties are determined by the type of cluster.
The step in this section all assume the profile with the name MyProfile identifies the cluster you
want to use, with all necessary property settings. With the proper use of a profile, the rest of the
programming is the same, regardless of cluster type. After you define or import your profile, you can
set it as the default profile in the Profile Manager GUI, or with the command:
[Link]('MyProfile')
Notes In a shared file system, all nodes require access to the folder specified in the cluster object's
JobStorageLocation property.
Because Windows HPC Server requires a shared file system, all nodes require access to the folder
specified in the cluster object's JobStorageLocation property.
5-34
Program Independent Jobs for a Supported Scheduler
In a shared file system, MATLAB clients on many computers can access the same job data on the
network. Properties of a particular job or task should be set from only one client computer at a time.
When you use an LSF® scheduler in a nonshared file system, the scheduler might report that a job is
in the finished state even though the LSF scheduler might not yet have completed transferring the
job's files.
Find a Cluster
You use the parcluster function to identify a cluster and to create an object representing the
cluster in your local MATLAB session.
To find a specific cluster, use the cluster profile to match the properties of the cluster you want to
use. In this example, MyProfile is the name of the profile that defines the specific cluster.
c = parcluster('MyProfile');
Create a Job
You create a job with the createJob function. Although this command executes in the client session,
it actually creates the job on the cluster, c, and creates a job object, job1, in the client session.
job1 = createJob(c)
Job
Properties:
ID: 1
Type: independent
Username: mylogin
State: pending
SubmitDateTime:
StartDateTime:
RunningDuration: 0 days 0h 0m 0s
NumThreads: 1
AutoAttachFiles: true
Auto Attached Files: List files
AttachedFiles: {}
AutoAddClientPath: false
AdditionalPaths: {}
Associated Tasks:
Number Pending: 0
Number Running: 0
Number Finished: 0
Task ID of Errors: []
Task ID of Warnings: []
Note that the job's State property is pending. This means the job has not been queued for running
yet, so you can now add tasks to it.
5-35
5 Batch Processing
MJS Cluster
Properties:
Name: my_mjs
Profile: MyProfile
Modified: false
Host: [Link]
Username: myuser
NumWorkers: 1
NumThreads: 1
NumBusyWorkers: 0
NumIdleWorkers: 1
Associated Jobs:
Number Pending: 1
Number Queued: 0
Number Running: 0
Number Finished: 0
You can transfer files to the worker by using the AttachedFiles property of the job object. For
details, see “Share Code with Workers” on page 5-11.
Create Tasks
After you have created your job, you can create tasks for the job using the createTask function.
Tasks define the functions to be evaluated by the workers during the running of the job. Often, the
tasks of a job are all identical. In this example, each task will generate a 3-by-3 matrix of random
numbers.
[Link]
5-36
Program Independent Jobs for a Supported Scheduler
3 3 pending rand 0 0
4 4 pending rand 0 0
5 5 pending rand 0 0
Alternatively, you can create the five tasks with one call to createTask by providing a cell array of
five cell arrays defining the input arguments to each task.
To run your job and have its tasks evaluated, you submit the job to the job queue with the submit
function.
submit(job1)
The job manager distributes the tasks of job1 to its registered workers for evaluation.
1 Receive AttachedFiles and AdditionalPaths from the job. Place files and modify the path
accordingly.
2 Run the jobStartup function the first time evaluating a task for this job. You can specify this
function in AttachedFiles or AdditionalPaths. When using a MATLAB Job Scheduler, if the
same worker evaluates subsequent tasks for this job, jobStartup does not run between tasks.
3 Run the taskStartup function. You can specify this function in AttachedFiles or
AdditionalPaths. This runs before every task evaluation that the worker performs, so it could
occur multiple times on a worker for each job.
4 If the worker is part of forming a new parallel pool, run the poolStartup function. (This occurs
when executing parpool or when running other types of jobs that form and use a parallel pool,
such as batch.)
5 Receive the task function and arguments for evaluation.
6 Evaluate the task function, placing the result in the task's OutputArguments property. Any
error information goes in the task's Error property.
7 Run the taskFinish function.
The results of each task's evaluation are stored in that task object's OutputArguments property as a
cell array. Use the function fetchOutputs to retrieve the results from all the tasks in the job.
wait(job1)
results = fetchOutputs(job1);
results{1:5}
5-37
5 Batch Processing
When you close the client session of Parallel Computing Toolbox software, all of the objects in the
workspace are cleared. However, the objects in MATLAB Parallel Server software or other cluster
resources remain in place. When the client session ends, only the local reference objects are lost, not
the actual job and task data in the cluster.
Therefore, if you have submitted your job to the cluster job queue for execution, you can quit your
client session of MATLAB, and the job will be executed by the cluster. You can retrieve the job results
later in another client session.
Recover Objects
A client session of Parallel Computing Toolbox software can access any of the objects in MATLAB
Parallel Server software, whether the current client session or another client session created these
objects.
You create cluster objects in the client session by using the parcluster function.
c = parcluster('MyProfile');
When you have access to the cluster by the object c, you can create objects that reference all those
job contained in that cluster. The jobs are accessible in cluster object's Jobs property, which is an
array of job objects:
all_jobs = [Link]
You can index through the array all_jobs to locate a specific job.
5-38
Program Independent Jobs for a Supported Scheduler
Alternatively, you can use the findJob function to search in a cluster for any jobs or a particular job
identified by any of its properties, such as its State.
all_jobs = findJob(c);
finished_jobs = findJob(c,'State','finished')
This command returns an array of job objects that reference all finished jobs on the cluster c.
When restarting a client session, you lose the settings of any callback properties (for example, the
FinishedFcn property) on jobs or tasks. These properties are commonly used to get notifications in
the client session of state changes in their objects. When you create objects in a new client session
that reference existing jobs or tasks, you must reset these callback properties if you intend to use
them.
Jobs in the cluster continue to exist even after they are finished, and after the MATLAB Job Scheduler
is stopped and restarted. The ways to permanently remove jobs from the cluster are explained in the
following sections:
From the command line in the MATLAB client session, you can call the delete function for any job or
task object. If you delete a job, you also remove all tasks contained in that job.
For example, find and delete all finished jobs in your cluster that belong to the user joep.
c = parcluster('MyProfile')
finished_jobs = findJob(c,'State','finished','Username','joep')
delete(finished_jobs)
clear finished_jobs
The delete function permanently removes these jobs from the cluster. The clear function removes
the object references from the local MATLAB workspace.
Start a MATLAB Job Scheduler from a Clean State
When a MATLAB Job Scheduler starts, by default it starts so that it resumes its former session with
all jobs intact. Alternatively, a MATLAB Job Scheduler can start from a clean state with all its former
history deleted. Starting from a clean state permanently removes all job and task data from the
MATLAB Job Scheduler of the specified name on a particular host.
As a network administration feature, the -clean flag of the startjobmanager script is described in
“Start in a Clean State” (MATLAB Parallel Server) in the MATLAB Parallel Server System
Administrator's Guide.
5-39
5 Batch Processing
In principle, you create and run communicating jobs similarly to the way you program independent
jobs:
The differences between independent jobs and communicating jobs are summarized in the following
table.
Some of the details of a communicating job and its tasks might depend on the type of scheduler you
are using. The following sections discuss different schedulers and explain programming
considerations:
5-40
Program Communicating Jobs for a Supported Scheduler
Save the function as the file named colsum.m on the path of the MATLAB client. The software sends
the file to each worker using the job's AttachedFiles property.
While this example has one worker create the magic square and broadcast it to the other workers,
there are alternative methods of getting data to the workers. Each worker could create the matrix for
itself. Alternatively, each worker could read its part of the data from a file on disk, the data could be
passed in as an argument to the task function, or the data could be sent in a file contained in the job's
AttachedFiles property. The solution to choose depends on your network configuration and the
nature of the data.
5-41
5 Batch Processing
You can create and configure the cluster object with this code:
c = parcluster('MyProfile')
where 'MyProfile' is the name of a cluster profile for the type of scheduler you are using. Any
required differences for various cluster options are controlled in the profile. You can have one or
more separate profiles for each type of scheduler. For complete details, see “Discover Clusters and
Use Cluster Profiles” on page 7-2. Create or modify profiles according to the instructions of your
system administrator.
When your cluster object is defined, you create the job object with the createCommunicatingJob
function. The job Type property must be set as 'SPMD' when you create the job.
cjob = createCommunicatingJob(c,'Type','SPMD');
The function file colsum.m (created in “Code the Task Function” on page 5-41) is on the MATLAB
client path, but it has to be made available to the workers. One way to do this is with the job's
AttachedFiles property, which can be set in the profile you used, or by entering this code in the
Command Window:
[Link] = {'colsum.m'}
You can also set other properties on the job, for example, setting the number of workers to use.
Again, profiles might be useful in your particular situation, especially if most of your jobs require
many of the same property settings. To run this example on four workers, you can established this in
the profile, or by the following client code:
[Link] = 4
You create the job's one task with the usual createTask function. In this example, the task returns
only one argument from each worker, and there are no input arguments to the colsum function.
submit(cjob)
Make the MATLAB client wait for the job to finish before collecting the results. The results consist of
one value from each worker. The spmdPlus function in the task shares data between the workers, so
that each worker has the same result.
wait(cjob)
results = fetchOutputs(cjob)
results =
[136]
[136]
[136]
[136]
5-42
Further Notes on Communicating Jobs
Suppose you have a codistributed array D, and you want to use the gather function to assemble the
entire array in the workspace of a single worker.
if spmdIndex == 1
assembled = gather(D);
end
The reason this fails is because the gather function requires communication between all the workers
across which the array is distributed. When the if statement limits execution to a single worker, the
other workers required for execution of the function are not executing the statement. As an
alternative, you can use gather itself to collect the data into the workspace of a single worker:
assembled = gather(D, 1).
In another example, suppose you want to transfer data from every worker to the next worker on the
right (defined as the next higher spmdIndex). First you define for each worker what the workers on
the left and right are.
The reason this code might fail is because, depending on the size of the data being transferred, the
spmdSend function can block execution in a worker until the corresponding receiving worker
executes its spmdReceive function. In this case, all the workers are attempting to send at the same
time, and none are attempting to receive while spmdSend has them blocked. In other words, none of
5-43
5 Batch Processing
the workers get to their spmdReceive statements because they are all blocked at the spmdSend
statement. To avoid this particular problem, you can use the spmdSendReceive function.
5-44
Apply Callbacks to MATLAB Job Scheduler Jobs and Tasks
Client objects representing jobs and tasks in a MATLAB Job Scheduler cluster include the following
properties:
TaskRun
ningFcn
FinishedFc Job or JobFini Specifies the function to execute in the client when a job or task
n task shedFcn completes its execution
TaskFin
ishedFc
n
You can set each of these properties to any valid MATLAB callback value in the Cluster Profile
Manager, see the table and “Add and Modify Cluster Profiles” on page 7-5. The callback follows the
same behavior for Handle Graphics®, passing into the callback function the object (job or task) that
makes the call and an empty argument of event data.
These properties apply only in the client MATLAB session in which they are set. Later sessions that
access the same job or task objects do not inherit the settings from previous sessions. You can apply
the properties to existing jobs and tasks at the command-line, but the cluster profile settings apply
only at the time these objects are first created.
Note The callback properties are available only when using a MATLAB Job Scheduler cluster.
This example shows how to create job and task callbacks at the client session command line.
Create and save a callback function clientTaskCompleted.m on the path of the MATLAB client,
with the following content:
function clientTaskCompleted(task,eventdata)
disp(['Finished task: ' num2str([Link])])
Create a job and set its QueuedFcn, RunningFcn, and FinishedFcn properties, using a function
handle to an anonymous function that sends information to the display.
5-45
5 Batch Processing
c = parcluster('MyMJS');
j = createJob(c,'Name','Job_52a');
[Link] = @(job,eventdata) disp([[Link] ' now ' [Link]]);
[Link] = @(job,eventdata) disp([[Link] ' now ' [Link]]);
[Link] = @(job,eventdata) disp([[Link] ' now ' [Link]]);
createTask(j,@rand,1,{2,4}, ...
'FinishedFcn',@clientTaskCompleted);
Run the job and note the output messages from both the job and task callbacks.
submit(j)
To use the same callbacks for any jobs and tasks on a given cluster, you should set these properties in
the cluster profile. For details on editing profiles in the profile manager, see “Discover Clusters and
Use Cluster Profiles” on page 7-2. These property settings apply to any jobs and tasks created
using a cluster derived from this profile. The sequence is important, and must occur in this order:
1 Set the callback property values for the profile in the profile manager.
2 Use the cluster profile to create a cluster object in MATLAB.
3 Use the cluster object to create jobs and then tasks.
This example shows how to set several job and task callback properties using the profile manager.
Edit your MATLAB Job Scheduler cluster profile in the profile manager so that you can set the
callback properties to the same values in the previous example. The saved profile looks like this:
Create and save a callback function clientTaskCompleted.m on the path of the MATLAB client,
with the following content. (If you created this function for the previous example, you can use that.)
5-46
Apply Callbacks to MATLAB Job Scheduler Jobs and Tasks
function clientTaskCompleted(task,eventdata)
disp(['Finished task: ' num2str([Link])])
Create objects for the cluster, job, and task. Then submit the job. All the callback properties are set
from the profile when the objects are created.
c = parcluster('MyMJS');
j = createJob(c,'Name','Job_52a');
createTask(j,@rand,1,{2,4});
submit(j)
Tips
• You should avoid running code in your callback functions that might cause conflicts. For example,
if every task in a job has a callback that plots its results, there is no guarantee to the order in
which the tasks finish, so the plots might overwrite each other. Likewise, the FinishFcn callback
for a job might be triggered to start before the FinishFcn callbacks for all its tasks are complete.
• Submissions made with batch use applicable job and task callbacks. Parallel pools can trigger job
callbacks defined by their cluster profile.
5-47
5 Batch Processing
Job Monitor
In this section...
“Typical Use Cases” on page 5-48
“Manage Jobs Using the Job Monitor” on page 5-49
“Identify Task Errors Using the Job Monitor” on page 5-49
The Job Monitor displays the jobs in the queue for the scheduler determined by your selection of a
cluster profile. Open the Job Monitor from the MATLAB desktop on the Home tab in the
Environment section, by selecting Parallel > Monitor Jobs.
The job monitor lists all the jobs that exist for the cluster specified in the selected profile. You can
choose any one of your profiles (those available in your current session Cluster Profile Manager), and
whether to display jobs from all users or only your own jobs.
5-48
Job Monitor
• Cancel — Stops a running job and changes its state to 'finished'. If the job is pending or
queued, the state changes to 'finished' without its ever running. This is the same as the
command-line cancel function for the job.
• Delete — Deletes the job data and removes the job from the queue. This is the same as the
command-line delete function for the job. Also closes and deletes an interactive pool job.
• Show Details — This displays detailed information about the job in the Command Window.
• Show Errors — This displays all the tasks that generated an error in that job, with their error
properties.
• Fetch Outputs — This collects all the task output arguments from the job into the client
workspace.
A = [2 4 6 8];
B = inv(A);
If you save this script in a file named invert_me.m, you can try to run the script as a batch job on
the default cluster:
batch('invert_me')
When updated after the job runs, the Job Monitor includes the job created by the batch command,
with an error icon ( ) for this job. Right-click the job in the list, and select Show Errors. For all the
tasks with an error in that job, the task information, including properties related to the error, display
in the MATLAB command window:
ID: 1
State: finished
Function: @[Link]
Parent: Job 8
StartDateTime: 12-Feb-2021 09:29:02
RunningDuration: 0 days 0h 0m 2s
5-49
5 Batch Processing
Overview
Parallel Computing Toolbox and MATLAB Parallel Server software let you solve computationally and
data-intensive problems using MATLAB and Simulink on multicore and multiprocessor computers.
Parallel processing constructs such as parallel for-loops and code blocks, distributed arrays, parallel
numerical algorithms, and message-passing functions let you implement task-parallel and data-
parallel algorithms at a high level in MATLAB without programming for specific hardware and
network architectures.
A job is some large operation that you need to perform in your MATLAB session. A job is broken down
into segments called tasks. You decide how best to divide your job into tasks. You could divide your
job into identical tasks, but tasks do not have to be identical.
The MATLAB session in which the job and its tasks are defined is called the client session. Often, this
is on the machine where you program MATLAB. The client uses Parallel Computing Toolbox software
to perform the definition of jobs and tasks and to run them on a cluster local to your machine.
MATLAB Parallel Server software is the product that performs the execution of your job on a cluster
of machines.
The MATLAB Job Scheduler is the process that coordinates the execution of jobs and the evaluation of
their tasks. The MATLAB Job Scheduler distributes the tasks for evaluation to the server's individual
MATLAB sessions called workers. Use of the MATLAB Job Scheduler to access a cluster is optional;
the distribution of tasks to cluster workers can also be performed by a third-party scheduler, such as
Microsoft Windows HPC Server (including CCS) or Spectrum LSF.
5-50
How Parallel Computing Software Runs a Job
The MATLAB Job Scheduler can be run on any machine on the network. The MATLAB Job Scheduler
runs jobs in the order in which they are submitted, unless any jobs in its queue are promoted,
demoted, canceled, or deleted.
Each worker is given a task from the running job by the MATLAB Job Scheduler, executes the task,
returns the result to the MATLAB Job Scheduler, and then is given another task. When all tasks for a
running job have been assigned to workers, the MATLAB Job Scheduler starts running the next job on
the next available worker.
A MATLAB Parallel Server software setup usually includes many workers that can all execute tasks
simultaneously, speeding up execution of large MATLAB jobs. It is generally not important which
worker executes a specific task. In an independent job, the workers evaluate tasks one at a time as
available, perhaps simultaneously, perhaps not, returning the results to the MATLAB Job Scheduler.
In a communicating job, the workers evaluate tasks simultaneously. The MATLAB Job Scheduler then
returns the results of all the tasks in the job to the client session.
Note For testing your application locally or other purposes, you can configure a single computer as
client, worker, and MATLAB Job Scheduler host. You can also have more than one worker session or
more than one MATLAB Job Scheduler session on a machine.
A large network might include several MATLAB Job Schedulers as well as several client sessions. Any
client session can create, run, and access jobs on any MATLAB Job Scheduler, but a worker session is
registered with and dedicated to only one MATLAB Job Scheduler at a time. The following figure
shows a configuration with multiple MATLAB Job Schedulers.
5-51
5 Batch Processing
Local Cluster
A feature of Parallel Computing Toolbox software is the ability to run a local cluster of workers on the
client machine, so that you can run jobs without requiring a remote cluster or MATLAB Parallel
Server software. In this case, all the processing required for the client, scheduling, and task
evaluation is performed on the same computer. This gives you the opportunity to develop, test, and
debug your parallel applications before running them on your network cluster.
Note To develop and test your code, you can run batch jobs on a local cluster on your client machine
instead of running them on a remote cluster. If you close your MATLAB session, any batch jobs using
the local cluster also stop immediately.
Third-Party Schedulers
As an alternative to using the MATLAB Job Scheduler, you can use a third-party scheduler. This could
be a Microsoft Windows HPC Server (including CCS), Spectrum LSF scheduler, PBS Pro® scheduler,
TORQUE scheduler, or a generic scheduler.
Choosing Between a Third-Party Scheduler and a MATLAB Job Scheduler
You should consider the following when deciding to use a third-party scheduler or the MATLAB Job
Scheduler for distributing your tasks:
If you already have a scheduler, you may be required to use it as a means of controlling access to
the cluster. Your existing scheduler might be just as easy to use as a MATLAB Job Scheduler, so
there might be no need for the extra administration involved.
• Is the handling of parallel computing jobs the only cluster scheduling management you need?
The MATLAB Job Scheduler is designed specifically for MathWorks parallel computing
applications. If other scheduling tasks are not needed, a third-party scheduler might not offer any
advantages.
• Is there a file sharing configuration on your cluster already?
5-52
How Parallel Computing Software Runs a Job
The MATLAB Job Scheduler can handle all file and data sharing necessary for your parallel
computing applications. This might be helpful in configurations where shared access is limited.
• Are you interested in batch mode or managed interactive processing?
When you use a MATLAB Job Scheduler, worker processes usually remain running at all times,
dedicated to their MATLAB Job Scheduler. With a third-party scheduler, workers are run as
applications that are started for the evaluation of tasks, and stopped when their tasks are
complete. If tasks are small or take little time, starting a worker for each one might involve too
much overhead time.
• Are there security concerns?
Your own scheduler might be configured to accommodate your particular security requirements.
• How many nodes are on your cluster?
If you have a large cluster, you probably already have a scheduler. Consult your MathWorks
representative if you have questions about cluster size and the MATLAB Job Scheduler.
• Who administers your cluster?
The person administering your cluster might have a preference for how jobs are scheduled.
• Do you need to monitor your job's progress or access intermediate data?
A job run by the MATLAB Job Scheduler supports events and callbacks, so that particular
functions can run as each job and task progresses from one state to another.
Parallel Computing Toolbox software and MATLAB Parallel Server software are supported on
Windows, UNIX, and Macintosh operating systems. Mixed platforms are supported, so that the
clients, MATLAB Job Scheduler, and workers do not have to be on the same platform. Other
limitations are described at System Requirements.
mjs Service
If you are using the MATLAB Job Scheduler, every machine that hosts a worker or MATLAB Job
Scheduler session must also run the mjs service.
The mjs service controls the worker and MATLAB Job Scheduler sessions and recovers them when
their host machines crash. If a worker or MATLAB Job Scheduler machine crashes, when the mjs
service starts up again (usually configured to start at machine boot time), it automatically restarts the
MATLAB Job Scheduler and worker sessions to resume their sessions from before the system crash.
More information about the mjs service is available in the MATLAB Parallel Server documentation.
A client session communicates with the MATLAB Job Scheduler by calling methods and configuring
properties of a MATLAB Job Scheduler cluster object. Though not often necessary, the client session
can also access information about a worker session through a worker object.
When you create a job in the client session, the job actually exists in the MATLAB Job Scheduler job
storage location. The client session has access to the job through a job object. Likewise, tasks that
5-53
5 Batch Processing
you define for a job in the client session exist in the MATLAB Job Scheduler data location, and you
access them through task objects.
Lifecycle of a Job
When you create and run a job, it progresses through a number of stages. Each stage of a job is
reflected in the value of the job object's State property, which can be pending, queued, running,
or finished. Each of these stages is briefly described in this section.
The figure below illustrates the stages in the lifecycle of a job. In the MATLAB Job Scheduler (or other
scheduler), the jobs are shown categorized by their state. Some of the functions you use for managing
a job are createJob, submit, and fetchOutputs.
Stages of a Job
5-54
How Parallel Computing Software Runs a Job
Note that when a job is finished, its data remains in the MATLAB Job Scheduler's
JobStorageLocation folder, even if you clear all the objects from the client session. The MATLAB
Job Scheduler or scheduler keeps all the jobs it has executed, until you restart the MATLAB Job
Scheduler in a clean state. Therefore, you can retrieve information from a job later or in another
client session, so long as the MATLAB Job Scheduler has not been restarted with the -clean option.
You can permanently remove completed jobs from the MATLAB Job Scheduler or scheduler's storage
location using the Job Monitor GUI or the delete function.
5-55
6
GPU Computing
You can speed up your code by running MATLAB functions on a GPU. If the functions that you want to
use support GPU execution, you can simply use gpuArray to transfer input data to the GPU. To get
started with GPU computing, see “Run MATLAB Functions on a GPU” on page 6-3.
For deep learning, MATLAB provides automatic parallel support for multiple GPUs. See “Deep
Learning with MATLAB on Multiple GPUs” (Deep Learning Toolbox).
You can use the gpuDevice function inspect and select your GPU and use the gpuDeviceTable
functions to inspect multiple GPUs.
If running MATLAB functions on the GPU does not sufficiently speed up your code, or if you need to
use advanced GPU CUDA features, you can write your own CUDA code and run it in MATLAB by
generating an executable MEX file using mexcuda or an executable kernel using
[Link].
6-2
Run MATLAB Functions on a GPU
A = gpuArray([1 0 1; -1 -2 0; 0 1 -1]);
e = eig(A);
Whenever you call any of these functions with at least one gpuArray as a data input argument, the
function executes on the GPU. The function generates a gpuArray as the result, unless returning
numeric data to the local workspace is more appropriate (for example, size). You can mix inputs
using both gpuArray data and arrays stored in host memory in the same function call. gpuArray-
enabled functions include the discrete Fourier transform (fft), matrix multiplication (mtimes), left
matrix division (mldivide), and hundreds of others.
GPU-enabled functions run on the GPU only when the input data is on the GPU. The data type of
parameter arguments such as dimensions or indices do not affect where the function is run. For
example, the sum function in this code runs on the GPU because the data, the first input, is on the
GPU.
A = rand(10);
d = 2;
sum(gpuArray(A),d);
However, the sum function in this code does not run on GPU because the data, the first input, is not
on the GPU.
A = rand(10);
d = 2;
sum(A,gpuArray(d));
Tip Most GPUs perform calculations faster in single precision than in double precision. If your
workflow does not require double precision, consider converting your data to single precision using
the single function or creating single-precision gpuArray data directly. For more information, see
“Perform Calculations in Single Precision” on page 6-45.
If the output of a function running on a GPU could potentially be complex, you must explicitly specify
its input arguments as complex. For more information, see “Work with Complex Numbers on a GPU”
on page 6-39.
6-3
6 GPU Computing
The sparse function can be used to create sparse gpuArray objects. Many MATLAB functions
support sparse gpuArray objects. For more information, see “Work with Sparse Arrays on a GPU” on
page 6-36.
6-4
Run MATLAB Functions on a GPU
For a list of functions with gpuArray support in all MathWorks products, see gpuArray-supported
functions. Alternatively, you can filter by product. On the Help bar, click Functions. In the function
list, browse the left pane to select a product, for example, MATLAB. At the bottom of the left pane,
select GPU Arrays. If you select a product that does not have gpuArray-enabled functions, then the
GPU Arrays filter is not available.
• trainnet
• minibatchpredict
For more information about automatic GPU support in Deep Learning Toolbox, see “Scale Up Deep
Learning in Parallel, on GPUs, and in the Cloud” (Deep Learning Toolbox).
For custom training loops, convert your data to gpuArray and use functions with gpuArray support.
gpuDeviceTable
Alternatively, you can determine how many GPU devices are available, inspect some of their
properties, and select a device to use from the MATLAB desktop. On the Home tab, in the
Environment area, select Parallel > Select GPU Environment.
6-5
6 GPU Computing
This example shows how to use gpuArray-enabled MATLAB functions to operate with gpuArray
objects. You can check the properties of your GPU using the gpuDevice function.
gpuDevice
ans =
CUDADevice with properties:
Create a row vector that repeats values from -15 to 15. To transfer it to the GPU and create a
gpuArray object, use the gpuArray function.
To operate with gpuArray objects, use any gpuArray-enabled MATLAB function. MATLAB
automatically runs calculations on the GPU. For more information, see “Run MATLAB Functions on a
GPU” on page 6-3. For example, use diag, expm, mod, round, abs, and fliplr together.
6-6
Run MATLAB Functions on a GPU
imagesc(gpuF);
colormap(flip(gray));
If you need to transfer the data back from the GPU, use gather. Transferring data back to the CPU
can be costly, and is generally not necessary unless you need to use your result with functions that do
not support gpuArray.
result = gather(gpuF);
whos result
In general, running code on the CPU and the GPU can produce different results due to numerical
precision and algorithmic differences between the GPU and CPU. Answers from the CPU and GPU are
both equally valid floating point approximations to the true analytical result, having been subjected to
different roundoff behavior during computation. In this example, the results are integers and round
eliminates the roundoff errors.
6-7
6 GPU Computing
The following examples pass gpuArray objects to supported MATLAB functions, causing those
functions to run on the GPU.
6-8
Run MATLAB Functions on a GPU
Acknowledgments
MAGMA is a library of linear algebra routines that take advantage of GPU acceleration. Linear
algebra functions implemented for gpuArray objects in Parallel Computing Toolbox leverage
MAGMA to achieve high performance and accuracy.
See Also
gpuArray | gpuDevice | gpuDeviceTable | canUseGPU | validateGPU
Related Examples
• “Identify and Select a GPU Device” on page 6-10
• “Establish Arrays on a GPU” on page 6-15
• “Measure and Improve GPU Performance” on page 6-41
• “Sharpen an Image Using the GPU” on page 6-111
• “Compute the Mandelbrot Set Using GPU-Enabled Functions” on page 6-80
More About
• “GPU Computing Requirements” on page 6-13
• MAGMA
6-9
6 GPU Computing
This example shows how to use gpuDevice to identify and select which device you want to use.
To determine how many GPU devices are available in your computer, use the gpuDeviceCount
function.
gpuDeviceCount("available")
ans = 2
When there are multiple devices, the first is the default. You can examine its properties with the
gpuDeviceTable function to determine if that is the one you want to use.
gpuDeviceTable
ans=2×5 table
Index Name ComputeCapability DeviceAvailable DeviceSelected
_____ __________________ _________________ _______________ ______________
If the first device is the device you want to use, you can proceed. To run computations on the GPU,
use gpuArray enabled functions. For more information, see “Run MATLAB Functions on a GPU” on
page 6-3.
To verify that MATLAB® can use your GPU, use the canUseGPU function. The function returns 1
(true) if there is a GPU available for computation and 0 (false) otherwise.
canUseGPU
ans = logical
1
To diagnose an issue with your GPU setup, for example if canUseGPU returns 0 (false), use the
validateGPU function. Validating your GPU is optional.
validateGPU
6-10
Identify and Select a GPU Device
To use another device, call gpuDevice with the index of the other device.
gpuDevice(2)
ans =
CUDADevice with properties:
Alternatively, you can determine how many GPU devices are available, inspect some of their
properties, and select a device to use from the MATLAB® desktop. On the Home tab, in the
Environment area, select Parallel > Select GPU Environment.
See Also
gpuDevice | gpuDeviceCount | gpuArray | gpuDeviceTable | canUseGPU | validateGPU
6-11
6 GPU Computing
More About
• “Establish Arrays on a GPU” on page 6-15
• “Measure and Improve GPU Performance” on page 6-41
• “Run MATLAB Functions on a GPU” on page 6-3
• “Work with Remote GPUs” on page 6-25
• “GPU Computing Requirements” on page 6-13
6-12
GPU Computing Requirements
Note Requirements:
• MATLAB supports NVIDIA GPU architectures with compute capability 5.0 to 9.x.
• Install the latest graphics driver. Download drivers for your GPU at NVIDIA Driver Downloads.
Use the drivers provided by NVIDIA as these will be the most up-to-date for your GPU. If you are
using a virtual GPU, then contact your system administrator.
For next steps using your GPU, start here: “Run MATLAB Functions on a GPU” on page 6-3.
To diagnose issues with your GPU setup, use the validateGPU function.
Compute Capability
To check your GPU's compute capability, either:
You might be able to use a GPU with an architecture beyond the supported compute capability range.
See “Forward Compatibility for GPU Devices” on page 10-318.
For information about GPU support in earlier releases of MATLAB, see the archived documentation
corresponding to your MATLAB version:
See Also
Related Examples
• “Run MATLAB Functions on a GPU” on page 6-3
• “Identify and Select a GPU Device” on page 6-10
• “Run MATLAB Functions on Multiple GPUs” on page 6-19
• “Deep Learning with MATLAB on Multiple GPUs” (Deep Learning Toolbox)
6-13
6 GPU Computing
External Websites
• Introduction to GPU Computing with MATLAB
6-14
Establish Arrays on a GPU
You can create GPU arrays by transferring existing arrays from host memory to the GPU. Transfer an
array from host memory to the GPU using the gpuArray function.
The gpuArray function supports only numeric input arguments, for example, single, double,
int8, or logical input arguments. The gpuArray function supports complex-valued inputs. For
more information, see “Work with Complex Numbers on a GPU” on page 6-39.
N = 6;
M = magic(N);
G = gpuArray(M);
To transfer arrays from the GPU to host memory, use the gather function. This function returns a
regular MATLAB array that is stored in host memory. Verify that the gather function returns the
correct value by using isequal.
Transferring data to and from the GPU can be costly. Calling gather is generally not necessary
unless you need to use your result with functions that do not support gpuArray.
G = gpuArray(ones(100,"uint32"));
D = gather(G);
OK = isequal(D,ones(100,"uint32"))
Create a 1000-by-1000 random matrix and then transfer it to the GPU. For more information about
generating random numbers on the GPU, see “Random Number Streams on a GPU” on page 6-72.
X = rand(1000);
G = gpuArray(X);
For more information on generating random numbers of the GPU, see “Random Number Streams on a
GPU” on page 6-72.
Create a matrix of double-precision random values and transfer the matrix in single-precision format
to the GPU.
X = rand(1000);
G = gpuArray(single(X));
6-15
6 GPU Computing
construct an array without having to transfer any elements from host memory. For more information,
see gpuArray.
You can also create arrays on the GPU by mirroring the data type of an existing gpuArray using the
like syntax. You can use some functions to construct arrays with the same data type as a prototype
array p by providing like=p as an input argument. Functions that support the like syntax include
zeros, ones, createArray, eye, true, false, rand, randi, randn, cast, and eps.
II = eye(1024,"int32","gpuArray");
size(II)
1024 1024
Create a three-dimensional array of ones with the single data type on the GPU.
G = ones(100,100,50,"single","gpuArray");
size(G)
100 100 50
underlyingType(G)
'single'
Create a 8192-element column vector of zeros with the double data type on the GPU.
Z = zeros(8192,1,"gpuArray");
size(Z)
8192 1
Create a 100-by-100 array of pi with the same data type as a prototype array.
G = gpuArray(single(2));
X = createArray(100,like=G,FillValue=pi);
size(X)
100 100
underlyingType(X)
'single'
X(1:5)
6-16
Establish Arrays on a GPU
Function Description
underlyingType Class of the underlying data in the array
existsOnGPU Indication if array exists on the GPU and is accessible
isreal Indication if array data is real
isUnderlyingType Determine if underlying array data is of specified class, such as
double
isequal Determine if two or more arrays are equal
isnumeric Determine if an array is of a numeric data type
issparse Determine if an array is sparse
length Length of vector or largest array dimension
mustBeUnderlyingType Validate that array has specified underlying type, such as
double
ndims Number of dimensions in the array
size Size of array dimensions
G = rand(100,"gpuArray");
s = size(G)
100 100
Note You can load MAT files containing gpuArray data as in-memory arrays when a GPU is not
available. A gpuArray loaded without a GPU is limited and you cannot use it for computations. To
use a gpuArray loaded without a GPU, retrieve the contents using gather.
For more information about how to save and load variables in the MATLAB workspace, see “Save and
Load Workspace Variables”.
See Also
gpuArray | gather
More About
• “Run MATLAB Functions on a GPU” on page 6-3
• “Identify and Select a GPU Device” on page 6-10
6-17
6 GPU Computing
6-18
Run MATLAB Functions on Multiple GPUs
This example shows how to run MATLAB® code on multiple GPUs in parallel, first on your local
machine, then scaling up to a cluster. As a sample problem, the example uses the logistic map, an
equation that models the growth of a population.
A growing number of features in MATLAB offer automatic parallel support, including multi-GPU
support, without requiring any extra coding. For details, see “Run MATLAB Functions with Automatic
Parallel Support” on page 1-9. For example, the trainnet (Deep Learning Toolbox) function offers
multi-GPU support for training neural networks. For more information, see “Scale Up Deep Learning
in Parallel, on GPUs, and in the Cloud” (Deep Learning Toolbox).
To run computations on a single GPU, use gpuArray objects as inputs to GPU-enabled MATLAB
functions. To learn more about GPU-enabled functions, see “Run MATLAB Functions on a GPU” on
page 6-3.
Create GPU arrays defining the growth rate, r, and the population, x. For more information on
creating gpuArray objects, see “Establish Arrays on a GPU” on page 6-15.
N = 200000;
r = [Link](0,4,N);
x = rand(1,N,"gpuArray");
Use a simple algorithm to iterate the logistic map. Because the algorithm uses GPU-enabled
operators on gpuArray input data, the computations run on the GPU.
numIterations = 1000;
for n=1:numIterations
x = r.*x.*(1-x);
end
When the computations are done, plot the growth rate against the population.
plot(r,x,'.',MarkerSize=1)
xlabel("Growth Rate")
ylabel("Population")
6-19
6 GPU Computing
If you need more performance, GPU arrays supports several options. For a list, see the gpuArray
function page. For example, the algorithm in this example only performs element-wise operations on
GPU arrays, and so you can use the arrayfun function to precompile them for GPU.
You can use parfor-loops to distribute for-loop iterations among parallel workers. If your
computations use GPU-enabled functions, then the computations run on the GPU of the worker. For
example, if you use the Monte Carlo method to randomly simulate the evolution of populations,
simulations are computed with multiple GPUs in parallel using a parfor-loop.
Create a parallel pool with as many workers as GPUs available using parpool. To determine the
number of GPUs available, use the gpuDeviceCount function. By default, MATLAB assigns a
different GPU to each worker for best performance. For more information on selecting GPUs in a
parallel pool, see “Use Multiple GPUs in Parallel Pool” on page 9-67.
numGPUs = gpuDeviceCount("available");
parpool(numGPUs);
Define the number of simulations, and create an array in the GPU to store the population vector for
each simulation.
numSimulations = 100;
X = zeros(numSimulations,N,"gpuArray");
6-20
Run MATLAB Functions on Multiple GPUs
Use a parfor loop to distribute simulations to workers in the pool. The code inside the loop creates a
random gpuArray for the initial population, and iterates the logistic map on it. Because the code
uses GPU-enabled operators on gpuArray input data, the computations automatically run on the
GPU of the worker.
parfor i = 1:numSimulations
X(i,:) = rand(1,N,"gpuArray");
for n=1:numIterations
X(i,:) = r.*X(i,:).*(1-X(i,:));
end
end
When the computations are done, plot the results of all simulations. Each color represents a different
simulation.
figure
plot(r,X,'.',MarkerSize=1)
xlabel("Growth Rate")
ylabel("Population")
With default settings, parpool starts a parallel pool of process workers. Running code in parallel on
process workers often results in data being copied to each worker which can use a significant amount
of GPU memory when working with GPU arrays. In contrast, thread workers can share memory. To
reduce memory usage and lower data transfer costs, use a parallel pool of thread workers by calling
parpool("Threads"). Thread workers support only a subset of functions available for processes
workers. For more information, see “Choose Between Thread-Based and Process-Based
Environments” on page 1-43.
6-21
6 GPU Computing
If you need greater control over your calculations, you can use more advanced parallel functionality.
For example, you can use a [Link] to send data from the workers during
computations. For an example, see “Plot During Parameter Sweep with parfor” on page 2-60.
If you want to generate a reproducible set of random numbers, you can control the random number
generation on the GPU of a worker. For more information, see “Random Number Streams on a GPU”
on page 6-72.
You can use parfeval to run computations asynchronously on parallel pool workers. If your
computations use GPU-enabled functions, then the computations run on the GPU of the worker. As an
example, you run Monte Carlo simulations on multiple GPUs asynchronously.
To hold the results of computations after the workers complete them, use future objects. Preallocate
an array of future objects for the result of each simulation.
f(numSimulations) = [Link];
To run computations with parfeval, you must place them inside a function. Define a function that
contains the code of a single simulation.
function x = myParallelFcn(r)
N = 200000;
x = [Link](1,N);
numIterations = 1000;
for n=1:numIterations
x = r.*x.*(1-x);
end
end
Use a for loop to loop over simulations, and use parfeval to run them asynchronously on a worker
in the parallel pool. myParallelFcn uses GPU-enabled functions on gpuArray input data, so they
run on the GPU of the worker. Because parfeval performs the computations asynchronously, it does
not block MATLAB, and you can continue working while computations happen.
for i=1:numSimulations
f(i) = parfeval(@myParallelFcn,1,r);
end
To collect the results from parfeval when they are ready, you can use fetchOutputs or
fetchNext on the future objects. Also, you can use afterEach or afterAll to invoke functions on
the results automatically when they are ready. For example, to plot the result of each simulation
immediately after it completes, use afterEach on the future objects. Each color represents a
different simulation.
figure
xlabel("Growth Rate")
ylabel("Population")
hold on
afterEach(f,@(x) plot(r,x,'.',MarkerSize=1),0);
wait(f)
hold off
6-22
Run MATLAB Functions on Multiple GPUs
If you have access to a cluster with multiple GPUs, then you can scale up your computations. Use the
parpool function to start a parallel pool on the cluster. When you do so, parallel features, such as
parfor loops or parfeval, run on the cluster workers. If your computations use GPU-enabled
functions on gpuArray input data, then those functions run on the GPU of the cluster worker. Note
that cluster features are supported only in process-based environments. For an example showing how
to run your code on remote GPUs in a cluster, see “Work with Remote GPUs” on page 6-25. To learn
more about running parallel features on a cluster, see “Scale Up from Desktop to Cluster” on page 7-
49.
If you have appropriate hardware connections, then data transfer between multiple GPUs uses fast
peer-to-peer communication, including NVLink, if available.
If you are using a Linux compute cluster with fast interconnects between machines such as
Infiniband, or fast interconnects between GPUs on different machines, such as GPUDirect RDMA, you
might be able to take advantage of fast multi-node support in MATLAB. Enable this support on all the
workers in your pool by setting the environment variable
PARALLEL_SERVER_FAST_MULTINODE_GPU_COMMUNICATION to 1. Set this environment variable in
the Cluster Profile Manager.
6-23
6 GPU Computing
This feature is part of the NVIDIA NCCL library for GPU communication. To configure it, you must set
additional environment variables to define the network interface protocol, especially
NCCL_SOCKET_IFNAME. For more information, see the NCCL documentation and in particular the
section on NCCL Environment Variables.
See Also
gpuArray | gpuDevice | parpool | parfor | parfeval | fetchOutputs | afterEach
Related Examples
• “Run MATLAB Functions on a GPU” on page 6-3
• “Work with Remote GPUs” on page 6-25
• “Scale Up from Desktop to Cluster” on page 7-49
• “Scale Up Deep Learning in Parallel, on GPUs, and in the Cloud” (Deep Learning Toolbox)
More About
• “GPU Computing in MATLAB”
External Websites
• Running Monte Carlo Simulations on Multiple GPUs
6-24
Work with Remote GPUs
This example shows how to run MATLAB® code on multiple remote GPUs in a cluster.
If you have access to a cluster with GPU computing resources, you can use parallel language to
access and use those GPUs for computation. This example shows how to access and use GPU
resources even if your local machine does not have a supported GPU.
Start by prototyping your algorithm on your local machine. This example calculates the standard
map, though the steps of setting up a cluster and running code on remote GPUs can be used to
accelerate any code that runs on a GPU.
The standard map shows the angular position and angular momentum of a rotator after it has
received a number of kicks. The rotator is a stick which can rotate frictionlessly about one of its ends,
and which is periodically kicked on the other tip. The motion of a kicked rotator and is defined by
pn + 1 = pn + K ⋅ sin θn
θ n + 1 = θ n + pn + 1
where θ n and pn determine the angular position and angular momentum of the rotator after the nth
kick and the constant K is the intensity of the kicks on the rotator. θ n and pn are taken modulo 2π.
6-25
6 GPU Computing
Define the number of kicks to simulate over, and the number of θ 0 and p0 values to simulate over.
numKicks = 500;
numThetaValues = 100000;
numPValues = 10;
Run the simulation on your local machine for K=0. This simulates a free rotator whose angular
momentum p remains constant, demonstrating the initial conditions of each simulation. The
simulateRotator function is defined at the end of this example and calculates θ n and pn. If you
have a GPU on your local machine, convert K to a gpuArray. The simulateRotator function uses
the "like" syntax of the zeros function to allocate arrays and perform the simulations on the GPU if
K is a gpuArray. Otherwise, the function performs the simulations on the CPU. For information on
supported GPU devices, see “GPU Computing Requirements” on page 6-13.
K = 0;
if canUseGPU
K = gpuArray(K);
end
[pN,thetaN] = simulateRotator(numKicks,numThetaValues,numPValues,K);
Plot the results of the simulations. The function plotMap is defined at the end of this example.
figure
plotMap(numKicks,pN,thetaN,K)
Run the simulations on your local machine for K=0.6 and plot the results.
6-26
Work with Remote GPUs
K = 0.6;
if canUseGPU
K = gpuArray(K);
end
[pN,thetaN] = simulateRotator(numKicks,numThetaValues,numPValues,K);
figure
plotMap(numKicks,pN,thetaN,K)
If you have a GPU on your local machine, check whether the simulations run faster on the GPU by
timing the execution on the GPU and the CPU using the gputimeit and timeit functions
respectively.
if canUseGPU
gpu = gpuDevice;
disp([Link] + " GPU selected.")
disp("Speedup when running the simulations on a GPU compared to CPU: " + round(tCPU/tGPU) + "
figure
executionEnvironment = ["CPU" "GPU"];
bar(executionEnvironment,[tCPU tGPU])
xlabel("Execution Environment")
6-27
6 GPU Computing
tGPU = 0.0517
tCPU = 2.3159
Setup Cluster
This example uses a MATLAB Parallel Server™ cluster created using Cloud Center. Cloud Center
provides an easy way to create and manage cloud computing resources and access them through
MATLAB. Once you have created a cluster, you can discover it by using the Discover Clusters
button. For more information on creating MATLAB Parallel Server clusters using Cloud Center, see
Create and Discover Clusters.
Create a cluster object. In this example, the Cloud Center cluster is named cloudCenterCluster
and has four machines, each with a single GPU.
c = parcluster("cloudCenterCluster");
6-28
Work with Remote GPUs
Create a parallel pool a number of workers equal to the number of GPUs in the cluster. Alternatively,
to use a batch workflow to offload work to the cluster, for example using batch, you do not need to
create a parallel pool.
gpusInCluster = 4;
pool = parpool(c,gpusInCluster);
You can use the gpuDevice and gpuDeviceTable functions to inspect GPUs on your local machine.
If your local machine does not have a supported GPU, calls to gpuDevice error and calls to
gpuDeviceTable return an empty table. To run these functions on the cluster machines, you can run
them inside an spmd block (or another parallel language feature that runs code on multiple workers,
such as parfor, or parfeval). You can distinguish GPUs with the same name by inspecting their
universally unique identifier (UUID). Verify that the parallel pool has access to the GPUs. You can
optionally also validate each of the GPUs in the cluster by calling validateGPU inside the spmd
block. The validateGPU function runs a series of checks to determine whether your system and GPU
devices are properly configured and ready for use by MATLAB.
spmd
gpu = gpuDevice;
Worker 1:
GPU: A10G
UUID: GPU-e7c907df-338a-f20c-5fd1-e79bdd519955
Worker 2:
GPU: A10G
UUID: GPU-400fdbba-fbff-7be8-9b7d-c61404c48227
Worker 3:
GPU: A10G
UUID: GPU-aafc0b00-89b6-702c-3d0e-6c3aacdfc9d2
Worker 4:
GPU: A10G
UUID: GPU-813c3257-e0dc-93a5-d949-4988fe7dcabf
After you have created a parallel pool, you can use any of the interactive parallel language constructs
provided by MATLAB, for example, parfor, parfeval, and spmd. As each simulation is independent
of all of the others in this example, parfor is a good a choice. For more information on choosing
between parallel computing language features, see “Parallel Language Decision Tables” on page 1-22.
Use a parfor-loop to offload the simulation calculation to the parallel workers and return the
simulation results to the client session and time the parfor-loop.
K = 0:0.1:3;
KTrials = numel(K);
6-29
6 GPU Computing
[pN,thetaN] = simulateRotator(numKicks,numThetaValues,numPValues,gpuK);
pOut(:,:,idx) = pN;
thetaOut(:,:,idx) = thetaN;
end
The output arrays pOut and thetaOut contain gpuArray data. If your local machine has a
supported GPU, you can immediately access and use this data in the client MATLAB session. If your
local machine does not have a supported GPU, call gather before using it in subsequent code.
pOut = gather(pOut);
thetaOut = gather(thetaOut);
Plot Results
Plot the results for each value of K and capture each plot in a frame.
F(KTrials) = struct("cdata",[],"colormap",[]);
fig = figure(Visible="off");
parfor idx=1:KTrials
plotMap(numKicks,pOut(:,:,idx),thetaOut(:,:,idx),K(idx))
F(idx) = getframe(fig);
end
fig = figure(Visible="on");
movie(fig,F)
6-30
Work with Remote GPUs
Supporting Functions
simulateRotator
The simulateRotator function simulates a kicked rotator for numKicks kicks of intensity K, for a
number of initial angular position and angular moment values numThetaValues and numPValues. If
K is a gpuArray, then the function performs the simulations on the GPU. Otherwise, the function
performs the simulations on the CPU.
% Create initial values of p and theta. If K is a gpuArray, create p and theta on the GPU.
zero = zeros(like=K);
p = linspace(zero,(numPValues-1)*2*pi/numPValues,numPValues);
theta = linspace(zero,2*pi,numThetaValues);
[p,theta] = ndgrid(p,theta);
for i=1:numKicks
p = p + K*sin(theta);
theta = theta + p;
end
% Modulo 2pi.
p = mod(p,2*pi);
theta = mod(theta,2*pi);
6-31
6 GPU Computing
end
plotMap
The plotMap function plots θ n and pn, and colors each point according to its initial angular
momentum p0.
function plotMap(numKicks,p,theta,K)
end
See Also
gpuDevice | canUseGPU | gpuDeviceTable | parpool | spmd
Related Examples
• “Run MATLAB Functions on Multiple GPUs” on page 6-19
• “Run MATLAB Functions on a GPU” on page 6-3
• “Run MATLAB Using GPUs in the Cloud” on page 6-33
• “Scale Up Deep Learning in Parallel, on GPUs, and in the Cloud” (Deep Learning Toolbox)
6-32
Run MATLAB Using GPUs in the Cloud
MathWorks provides several ways of accessing MATLAB in public clouds, such as Amazon® Web
Services (AWS®) and Microsoft Azure®, that you can configure according to your needs. You can
access a single machine in the cloud or, if you have MATLAB Parallel Server, you can scale up to a
cluster.
Note When you create your cloud resource, choose a machine with GPUs, such as the P3, P4, P5, or
G5 instances. Instances P3, P4, and P5 have GPUs with high performance for general computation.
G5 instances have GPUs with high single-precision performance for deep learning, image processing,
computer vision, and automated driving simulations.
6-33
6 GPU Computing
Note
• When selecting a virtual machine size, choose a machine with NVIDIA GPUs, such as the NCv3-
series, the NC T4_v3-series, and the ND A100 v4-series virtual machines. These virtual machines
are designed for compute-intensive workloads.
Reference Architectures
MathWorks provides customizable reference architecture templates for AWS and Azure in GitHub®.
Reference architecture templates grant you full control over your cloud resources, including region
and network settings that match your existing cloud infrastructure.
Containers
You can also use containers to create software environments on desktop, server, or cloud
environments. Containers are isolated units of software that contain everything required to run a
specific application and are consistent, portable, and lightweight.
Note By default, a container does not have access to the hardware resources of its host. To grant the
container access to the NVIDIA GPUs of the host system:
• Run the container on a host system with the appropriate NVIDIA GPU drivers installed.
• Make the GPUs of the host visible to the container by using the --gpus flag when you execute the
docker run command. Set this flag to all to grant the container access to all the GPUs of the
host machine.
6-34
Run MATLAB Using GPUs in the Cloud
See Also
Related Examples
• Requirements for Using Cloud Center
• Link Cloud Account to Cloud Center
• What is a Container?
• “Cloud AI Workflow Using the Deep Learning Container” (Deep Learning Toolbox)
• “Work with Remote Data”
6-35
6 GPU Computing
0 1 0 0 0
0 0 0 0 1
S = sparse(X)
(1,2) 1
(2,5) 1
0 0
1 0
0 0
0 0
0 1
(1,5) 1
full(A(5,:))
0 0 0 0 1 0 0 0 0 0
To locate nonzero elements of a sparse GPU array, use the find function. You can then replace the
values you want and construct a new sparse gpuArray.
A = [Link](10);
[row,col] = find(A);
[row,col]
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
6-36
Work with Sparse Arrays on a GPU
See Also
gpuArray | sparse | find
Related Examples
• “Run MATLAB Functions on a GPU” on page 6-3
6-37
6 GPU Computing
6-38
Work with Complex Numbers on a GPU
When creating a gpuArray that has negative elements, use G = gpuArray(complex(x)), then you
can successfully execute sqrt(G). For example,
x = [-1 0 1];
G = gpuArray(complex(x));
rootG = sqrt(G)
If the result is a gpuArray of complex data and all the imaginary parts are zero, these parts are
retained and the data remains complex. This could result in unnecessary calculations being
performed when operating on the data using, for example, sort and isreal.
If using arrayfun, the function input can be specified as complex within the arrayfun call. For
example,
x = [-1 0 1];
G = gpuArray(x);
A = arrayfun(@(p) sqrt(complex(p)), G)
6-39
6 GPU Computing
See Also
gpuArray | complex
Related Examples
• “Run MATLAB Functions on a GPU” on page 6-3
• “Identify and Select a GPU Device” on page 6-10
• “Run MATLAB Functions on Multiple GPUs” on page 6-19
6-40
Measure and Improve GPU Performance
An important measure of the performance of your code is how long it takes to run. The best way to
time code running on a GPU is to use the gputimeit function which runs a function multiple times to
average out variation and compensate for overhead. The gputimeit function also ensures that all
operations on the GPU are complete before recording the time.
For example, measure the time that the lu function takes to compute the LU factorization of a
random matrix A of size N-by-N. To perform this measurement, create a function handle to the lu
function and pass the function handle to gputimeit.
N = 1000;
A = rand(N,"gpuArray");
f = @() lu(A);
numOutputs = 2;
gputimeit(f,numOutputs)
You can also time your code using tic and toc. However, to get accurate timing information for code
running on a GPU, you must wait for operations to complete before calling tic and toc. To do this,
you can use the wait function with a gpuDevice object as its input. For example, measure the time
taken to compute the LU factorization of matrix A using tic, toc, and wait.
D = gpuDevice;
wait(D)
tic
[L,U] = lu(A);
wait(D)
toc
You can view how long each part of your code takes using the MATLAB Profiler. For more information
about profiling your code, see profile and “Profile Your Code to Improve Performance”. The Profiler
is useful for identifying performance bottlenecks in your code but cannot accurately time GPU code
as it does not account for overlapping execution, which is common when you use a GPU.
Use this table to help you decide which timing method to use.
6-41
6 GPU Computing
GPU Benchmarking
Benchmark tests are useful for identifying the strengths and weaknesses of a GPU and for comparing
the performance of different GPUs. Measure the performance of your GPU by using these benchmark
tests:
• Run the “Measure GPU Memory Bandwidth and Processing Power” on page 6-89 example to
obtain detailed information about your GPU, including PCI bus speed, GPU memory read/write,
and peak calculation performance for double-precision matrix calculations.
• Use gpuBench to test memory- and computation-intensive tasks in single and double precision.
gpuBench can be downloaded from the Add-On Explorer or from the MATLAB Central File
Exchange. For more information, see [Link]
34080-gpubench.
6-42
Measure and Improve GPU Performance
If all the functions that your code uses are supported on the GPU, the only necessary modification is
to transfer the input data to the GPU by calling gpuArray. For a list of MATLAB functions that
support gpuArray input, see “Run MATLAB Functions on a GPU” on page 6-3.
A gpuArray object stores data in GPU memory. Because most numeric functions in MATLAB and in
many other toolboxes support gpuArray objects, you can usually run your code on a GPU by making
minimal changes. These functions take gpuArray inputs, perform calculations on the GPU, and
return gpuArray outputs. In general, these functions support the same arguments and data types as
standard MATLAB functions that run on the CPU.
Tip To reduce overhead, limit the number of times you transfer data between the host memory and
the GPU. Create arrays directly on the GPU where possible. For more information see, “Create GPU
6-43
6 GPU Computing
Arrays Directly” on page 6-15. Similarly, only transfer data from the GPU back to the host memory
using gather if the data needs to be displayed, saved, or used in code that does not support
gpuArray objects.
When converting MATLAB code to run on a GPU, it is best to start with MATLAB code that already
performs well. Many of the guidelines for writing code that runs well on a CPU will also improve the
performance of code that runs on a GPU. You can profile your CPU code using the MATLAB Profiler.
The lines of code that take the most time on the CPU will likely be ones that you should improve or
consider moving onto the GPU using gpuArray objects. For more information about profiling your
code, see “Profile Your Code to Improve Performance”.
Because the MATLAB Profiler runs each line of code independently, it does not account for
overlapping execution, which is common when you use a GPU. To time whole algorithms use tic and
toc or gputimeit as described in the “Measure Code Performance on a GPU” on page 6-41 section.
Vectorize Calculations
Vector, matrix, and higher-dimensional operations typically perform much better than scalar
operations on a GPU because GPUs achieve high performance by calculating many results in parallel.
You can achieve better performance by rewriting loops to make use of higher-dimensional operations.
The process of revising loop-based, scalar-oriented code to use MATLAB matrix and vector operations
is called vectorization. For information on vectorization, see “Using Vectorization” and “Improve
Performance Using a GPU and Vectorized Calculations” on page 6-48. This plot from the “Improve
Performance Using a GPU and Vectorized Calculations” on page 6-48 example shows the increase in
performance achieved by vectorizing a function executing on the CPU and on the GPU.
6-44
Measure and Improve GPU Performance
You can improve the performance of code running on your GPU by calculating in single precision
instead of double precision, as GPUs often more have more single-precision floating-point units
(FPUs) than double. In contrast, CPU computations often perform similarly for single-precision and
double-precision data.
You can convert data to single precision using the single function, or you can create single-precision
gpuArray data directly by specifying the underlying type "single" and the data type "gpuArray"
when you create data using a creation function such as rand. For more information on converting
data to single precision and creating single-precision data directly, see “Establish Arrays on a GPU”
on page 6-15.
Typical examples of workflows suitable for single-precision computation on the GPU include image
processing and machine learning. However, other types of calculation, such as linear algebra
problems, typically require double-precision processing. The Deep Learning Toolbox performs many
operations in single precision by default. For more information, see “Deep Learning Precision” (Deep
Learning Toolbox).
The exact performance improvement depends on the GPU card and total number of cores. For an
approximate measure of the relative performance of your GPU in single precision compared to double
precision, query the SingleDoubleRatio property of your device. This property describes the ratio
of single- to double-precision FPUs on the device.
gpu = gpuDevice;
[Link]
6-45
6 GPU Computing
Most desktop GPUs have 24, 32, or even 64 times as many single-precision floating-point units as
double-precision, while some data center GPUs center GPUs (A100 and H100) have only 2 times as
many.
For a comprehensive performance overview of NVIDIA GPU cards, including single- and double-
precision processing power, see [Link]
List_of_Nvidia_graphics_processing_units.
If you have an element-wise function, you can often improve its performance by calling it with
arrayfun. The arrayfun function on the GPU turns an element-wise MATLAB function into a
custom CUDA kernel, which reduces the overhead of performing the operation. You can often use
arrayfun with a subset of your code even if arrayfun does not support your entire code. The
performance of a wide variety of element-wise functions can be improved using arrayfun, including
functions performing many element-wise operations within looping or branching code, and nested
functions where the nested function accesses variables declared in its parent function.
The “Improve Performance of Element-Wise MATLAB Functions on the GPU Using arrayfun” on page
6-52 example shows a basic application of arrayfun. The “Using GPU arrayfun for Monte-Carlo
Simulations” on page 6-99 example shows arrayfun used to improve the performance of a function
executing element-wise operations within a loop. The “Stencil Operations on a GPU” on page 6-112
example shows arrayfun used to call a nested function that accesses variables declared in a parent
function.
If you have a function that performs independent matrix operations on a large number of small
matrices, you can improve its performance by calling it with pagefun. You can use pagefun to
perform matrix operations in parallel on the GPU instead of looping over the matrices. The “Improve
Performance of Small Matrix Problems on the GPU Using pagefun” on page 6-56 example shows
how to improve performance using pagefun when operating on many small matrices.
While MATLAB provides an extensive library of GPU-enabled functions, you can access libraries of
additional functions that do not have analogs in MATLAB. Examples include NVIDIA libraries such as
the NVIDIA Performance Primitives (NPP) and cuRAND libraries. You can compile MEX files that you
write in the CUDA C++ framework using the mexcuda function. You can execute the compiled MEX
files in MATLAB and call functions from NVIDIA libraries. For an example that shows how to write
and run MEX functions that take gpuArray input and return gpuArray output, see “Run MEX
Functions Containing CUDA Code” on page 6-124.
Because many computations require large quantities of memory and most systems use the GPU
constantly for graphics, using the same GPU for computations and graphics is usually impractical.
On Windows systems, a GPU device has two operating models: Windows Display Driver Model
(WDDM) or Tesla Compute Cluster (TCC). To attain the best performance for your code, set the
devices that you use for computing to use the TCC model. To see which model your GPU device is
using, inspect the DriverModel property returned by the gpuDevice function. For more
information about switching models and which GPU devices support the TCC model, consult the
NVIDIA documentation.
6-46
Measure and Improve GPU Performance
To reduce the likelihood of running out of memory on the GPU, do not use one GPU on multiple
instances of MATLAB. To see which GPU devices are available and selected, use the
gpuDeviceTable function.
See Also
gpuDevice | gputimeit | tic | toc | gpuArray | arrayfun | pagefun | mexcuda
More About
• “Identify and Select a GPU Device” on page 6-10
• “Establish Arrays on a GPU” on page 6-15
• “Run MATLAB Functions on a GPU” on page 6-3
6-47
6 GPU Computing
This example shows how to speed up your code by running a function on the GPU instead of the CPU
and by vectorizing the calculations.
MATLAB® is optimized for operations involving matrices and vectors. The process of revising loop-
based, scalar-oriented code to use MATLAB matrix and vector operations is called vectorization.
Vectorized code often runs much faster than the corresponding loop-based code and is generally
shorter and easier to understand. For an introduction to vectorization, see “Using Vectorization”.
This example compares the execution time for a function executing on the CPU and the GPU before
and after vectorizing the function.
1 Transform each column of data from the time domain to the frequency domain.
2 Multiply the frequency-domain data by the transform of a filter vector.
3 Transform the filtered data back to the time domain and store the result in a matrix.
This section performs a fast convolution on a matrix using the fastConvolution supporting
function. The function is defined at the end of this example.
data = complex(randn(4096,100),randn(4096,100));
filter = randn(16,1);
Perform fast convolution on the data using the fastConvolution function on the CPU and measure
the execution time using the timeit function.
CPUtime =
0.0148
gpu = gpuDevice;
disp([Link] + " GPU selected.")
Execute the function on the GPU by changing the input data to be a gpuArray object rather than
normal MATLAB arrays. As the fastConvolution function uses the like syntax of the zeros
function, the output is a gpuArray if the data is a gpuArray. To time function execution on the GPU,
use gputimeit. For functions that use the GPU, use gputimeit instead of timeit as gputimeit
ensures that all operations on the GPU finish before recording the elapsed time. The function takes
longer to execute on the GPU than on the CPU for this particular problem. The reason is that the for-
loop executes a fast Fourier transform (FFT), multiplication, and an inverse FFT (IFFT) operation on
individual columns of length 4096. Performing these operations on each column individually does not
6-48
Improve Performance Using a GPU and Vectorized Calculations
effectively utilize GPU computing power, as GPUs are generally more effective when performing
larger numbers of operations.
gData = gpuArray(data);
gFilter = gpuArray(filter);
GPUtime = gputimeit(@() fastConvolution(gData,gFilter))
GPUtime =
0.0158
Vectorizing code is a straightforward way to improve its performance. You can vectorize the FFT and
IFFT operations simply by passing all of the data as inputs, rather than passing each column
individually within a for-loop. The multiplication operator .* multiplies the filter by every column in
a matrix at once. The vectorized supporting function fastConvolutionVectorized is provided at
the end of this example. To see how the function has been vectorized, compare the supporting
functions fastConvolution and fastConvolutionVectorized.
Perform the same calculations using the vectorized function and compare the timing results to the
execution of the unvectorized function.
CPUtimeVectorized =
0.0062
GPUtimeVectorized =
4.5339e-04
CPUspeedup = CPUtime/CPUtimeVectorized
CPUspeedup =
2.3887
GPUspeedup = GPUtime/GPUtimeVectorized
GPUspeedup =
34.9468
6-49
6 GPU Computing
Vectorizing the code improves performance on the CPU and GPU. However, vectorization improves
performance on the GPU much more than on the CPU. The vectorized function runs roughly 2.4x
faster than the loop-based function on the CPU and roughly 34.9x faster than the loop-based function
on the GPU. The loop-based function runs 7% slower on the GPU than on the CPU, but the vectorized
function runs about 13.6x faster on the GPU than on the CPU.
When you apply the techniques described in this example to your own code, the performance
improvement will strongly depend on your hardware and on the code you run.
Supporting Functions
Perform a fast convolution operation by transforming each column of data from the time domain to
the frequency domain, multiplying it by the transform of a filter vector, transforming back to the time
domain, and storing the result in an output matrix.
function y = fastConvolution(data,filter)
% Zero-pad filter to the column length of data, and transform.
[rows,cols] = size(data);
filter_f = fft(filter,rows);
end
Perform a fast convolution operation, replacing the for-loop with vector operations.
6-50
Improve Performance Using a GPU and Vectorized Calculations
function y = fastConvolutionVectorized(data,filter)
% Zero-pad filter to the length of data, and transform.
[rows,~] = size(data);
filter_f = fft(filter,rows);
See Also
gpuArray | gputimeit | fft | ifft
Related Examples
• “Measure GPU Memory Bandwidth and Processing Power” on page 6-89
• “Measure and Improve GPU Performance” on page 6-41
• “Using Vectorization”
6-51
6 GPU Computing
This example shows how to improve the performance of your code by running MATLAB® functions on
the GPU using arrayfun.
When a MATLAB function contains many element-wise operations, using arrayfun can provide
better performance than executing the MATLAB function directly on the GPU with gpuArray input
data. For a function to be compatible with arrayfun it must be capable of operating on a single
element of the input array to calculate a single element of the output array using scalar operations
and arithmetic.
In this example, you compare the execution times of a function executing on the CPU, on the GPU
without using arrayfun, and on the GPU using arrayfun.
The Lorentz factor determines how, according to the principles of special relativity, the physical
properties of an object change while that object is moving. For an object moving at a velocity v
relative to an observer, the Lorentz factor γ is defined as
1 1
γ= = .
v2 1−β
2
1−
c2
β is the ratio of v to c, where c is the speed of light in a vacuum. The lorentz function, defined at the
end of the example, calculates the Lorentz factor as follows.
Y = 1./sqrt(1-B.*B);
Most MATLAB functions execute on the CPU by default. To execute lorentz on the GPU, provide a
gpuArray object as input. gpuArray objects represent an array stored in GPU memory. Because
many functions support gpuArray inputs, you can often run your code on a GPU with minimal
changes to the code. For more information see, “Run MATLAB Functions on a GPU” on page 6-3.
Because lorentz contains individual element-wise operations, performing each operation one at a
time on the GPU does not yield significant performance improvements. You can improve the
performance by executing all of the operations in the lorentz function at once using arrayfun.
To run the lorentz function on the GPU using arrayfun, define a handle to the function.
lorentzFcn = @lorentz;
In this example, you will compare execution times of the lorentz function operating on arrays
4 8.5
containing10 to 10 elements. Set the number of comparisons to run, and the upper and lower
limits on the size of the arrays to pass to the function.
numComp = 15;
lowerLimit = 4;
upperLimit = 8.5;
6-52
Improve Performance of Element-Wise MATLAB Functions on the GPU Using arrayfun
Specify the size of the arrays to pass to the function as a logarithmically spaced array. This example
can take several minutes to run. To reduce the execution time, reduce the upper limit on the array
size.
arraySize = ceil(logspace(lowerLimit,upperLimit,numComp));
for i = 1:numComp
% CPU execution
tcpu(i) = timeit(@() lorentzFcn(data));
end
Compare Results
To compare the results, plot the execution times against the number of data elements.
6-53
6 GPU Computing
For smaller arrays, the CPU executes the function faster than the GPU. As the size of the input array
increases, the performance of the GPU improves relative to the performance of the CPU. Above a
threshold array size, the GPU executes the function faster than the CPU. The threshold at which GPU
performance exceeds CPU performance depends on the hardware that you use and the function that
you execute.
Calculate the ratio of CPU execution time to GPU execution time only and to GPU execution time
using arrayfun respectively.
gpuObjectSpeedup = tcpu./tgpuObject;
gpuArrayfunSpeedup = tcpu./tgpuArrayfun;
semilogx(arraySize,[gpuObjectSpeedup;gpuArrayfunSpeedup])
xlabel("Input Array Size")
ylabel("Ratio of CPU to GPU Execution Times")
legend(["GPU Execution" "GPU Execution with \fontname{courier}arrayfun"],location="southeast")
6-54
Improve Performance of Element-Wise MATLAB Functions on the GPU Using arrayfun
Executing lorentz using arrayfun is consistently faster than execution on the GPU only. When you
apply the techniques described in this example to your own code, the performance improvement will
strongly depend on your hardware and on the code you run.
Supporting Functions
The lorentz function takes β and calculates the Lorentz factor according to this equation
1 1
γ= = .
v2 1−β
2
1−
c2
function Y = lorentz(B)
Y = 1./sqrt(1-B.*B);
end
See Also
arrayfun | gpuArray | gputimeit
Related Examples
• “Measure and Improve GPU Performance” on page 6-41
• “Using GPU arrayfun for Monte-Carlo Simulations” on page 6-99
• “Illustrating Three Approaches to GPU Computing: The Mandelbrot Set” on page 6-82
6-55
6 GPU Computing
This example shows how to use pagefun to improve the performance of independent operations
applied to multiple matrices arranged in a multidimensional array.
Multidimensional arrays are an extension of 2-D matrices and use additional subscripts for indexing.
A 3-D array, for example uses three subscripts. The first two dimensions represent a matrix and the
third represents pages of elements (sometimes referred to as slices). For more information, see
“Multidimensional Arrays”.
While GPUs can effectively apply small independent operations to large matrices, performance is
suboptimal when these operations are applied in serial, for example when the operations are applied
in a for-loop. In order to avoid serial processing, the arrayfun function applies a scalar operation to
each element of an array in parallel on the GPU. Similarly, the pagefun function applies a function to
each page of a multidimensional GPU array.
The pagefun function supports applying most element-wise functions and a number of matrix
operations that support GPU array input. MATLAB® also provides a number of dedicated page-wise
functions, including pagemtimes, pagemldivide, pagemrdivide, pagetranspose,
pagectranspose, pageinv, pagenorm, and pagesvd. Depending on the task, these functions might
simplify your code or provide better performance than using pagefun.
In this example, a robot is navigating a known map containing a large number of features that the
robot can identify using its sensors. The robot locates itself in the map by measuring the relative
position and orientation of those features and comparing them to the map locations. Assuming the
robot is not completely lost, it can use any difference between the two to correct its position, for
instance by using a Kalman Filter. This example shows an efficient way to compute the feature
positions relative to the robot.
The supporting function randomTransforms is provided at the end of this example and initializes N
transforms with random values, providing a structure as output. It represents positions and
6-56
Improve Performance of Small Matrix Problems on the GPU Using pagefun
orientations using 3-by-1 vectors T and 3-by-3 rotation matrices R. The N translations are packed into
a 3-by-N matrix and the rotations are packed into a 3-by-3-by-N array.
Use the randomTransforms function to set up a map of 1000 features, and a start location for the
robot.
numFeatures = 1000;
Map = randomTransforms(numFeatures,roomDimensions);
Robot = randomTransforms(1,roomDimensions);
The plotRobot function is provided as a supporting file with this example and plots a top-down view
of the room, and a close up view of the robot and nearby features. The robot is represented by a blue
box with wheels and the features are represented by red circles with accompanying lines
representing their orientation. To use this function, open the example as a livescript.
To correctly identify the features in the map, the robot needs to transform the map to put its sensors
at the origin. Then it can find map features by comparing what it sees with what it expects to see.
For a map feature i we can find its position relative to the robot Trel(i) and orientation Rrel(i) by
transforming its global map location:
Rrel(i) = R⊤
botRmap(i)
Trel(i) = R⊤
bot(Tmap(i) − Tbot)
where Tbot and Rbot are the position and orientation of the robot, and Tmap(i) and Rmap(i) represent
the map data. The equivalent MATLAB code looks like this:
Rrel(:,:,i) = Rbot' * Rmap(:,:,i)
Trel(:,i) = Rbot' * (Tmap(:,i) - Tbot)
6-57
6 GPU Computing
The supporting function loopingTransform is provided at the end of this example and loops over
all the transforms in turn, transforming each feature to its location relative to the robot. Note the
like name-value argument for zeros function which makes the function return an array of zeros of
the same data type as a prototype array. For example, if the prototype array is a gpuArray, then
zeros returns a gpuArray. This allows you to use the same code on the GPU in the next section.
Time the calculations using the timeit function. The timeit function times the execution of
loopingTransform multiple times and returns the median of the measurements. Since timeit
requires a function with no arguments, use the @() syntax to create an anonymous function of the
right form.
cpuTime = timeit(@()loopingTransform(Robot,Map,numFeatures))
cpuTime = 0.0042
To run the same code on the GPU, simply pass the input data to the function as a gpuArray. A
gpuArray represents an array stored in GPU memory. Many functions in MATLAB and in other
toolboxes support gpuArray objects, allowing you to run your code on GPUs with minimal changes to
the code. For more information, see “Run MATLAB Functions on a GPU” on page 6-3.
gpu = gpuDevice;
disp([Link] + " GPU selected.")
Create GPU arrays containing the position and orientation of the robot and the features in the map.
gMap.R = gpuArray(Map.R);
gMap.T = gpuArray(Map.T);
gRobot.R = gpuArray(Robot.R);
gRobot.T = gpuArray(Robot.T);
Time the calculations using the gputimeit function. The gputimeit function is the equivalent of
timeit for code that includes GPU computation. It makes sure all GPU operations have finished
before recording the time.
gpuTime = gputimeit(@()loopingTransform(gRobot,gMap,numFeatures))
gpuTime = 0.1905
The GPU version is very slow because, although all calculations were independent, they ran in series.
Using pagefun we can run all the computations in parallel.
The supporting function pagefunTransform is provided at the end of this example and applies the
same transforms as the loopingTransform function using pagefun instead of a for-loop. The first
computation is the calculation of the rotations. This involves a matrix multiply, which translates to the
function mtimes (*). Pass this to pagefun along with the two sets of rotations to be multiplied:
Rel.R = pagefun(@mtimes,Robot.R',Map.R);
6-58
Improve Performance of Small Matrix Problems on the GPU Using pagefun
Robot.R' is a 3-by-3 matrix, and Map.R is a 3-by-3-by-N array. The pagefun function matches each
independent matrix from the map to the same robot rotation, and gives us the required 3-by-3-by-N
output.
The translation calculation also involves a matrix multiply, but the normal rules of matrix
multiplication allow this to come outside the loop without any changes:
gpuPagefunTime = gputimeit(@()pagefunTransform(gRobot,gMap))
gpuPagefunTime = 3.3066e-04
Compare Results
figure
labels = categorical(["CPU Execution","GPU Execution","GPU Execution with \fontname{consolas}page
bar(labels,[cpuTime,gpuTime,gpuPagefunTime])
ylabel("Execution Time (s)")
set(gca,YScale="log")
Calculate how much faster the execution using pagefun is than CPU and simple GPU execution.
6-59
6 GPU Computing
fprintf("Executing the transforms on the GPU using pagefun is %3.2f times faster than on the CPU.
cpuTime/gpuPagefunTime);
Executing the transforms on the GPU using pagefun is 12.65 times faster than on the CPU.
fprintf("Executing the transforms on the GPU using pagefun is %3.2f times faster than using for-l
gpuTime/gpuPagefunTime);
Executing the transforms on the GPU using pagefun is 576.17 times faster than using for-loops on
If the robot is in an unknown part of the map, it can use a global search algorithm to locate itself. The
algorithm tests a number of possible locations by carrying out the above computation and looking for
good correspondence between the features seen by the robot's sensors and what it would expect to
see at that position.
Now there are multiple possible robot positions as well as multiple features. N features and M robots
requires N*M transforms. To distinguish 'robot space' from 'feature space', use the 4th dimension for
rotations and the 3rd for translations. That means that the robot rotations will be 3-by-3-by-1-by-M,
and the translations will be 3-by-1-by-M.
Initialize the search with ten random robot locations. A good search algorithm would use topological
or other clues to seed the search more intelligently.
numRobots = 10;
Robot = randomTransforms(numRobots,roomDimensions);
Robot.R = reshape(Robot.R,3,3,1,[]); % Spread along the 4th dimension
Robot.T = reshape(Robot.T,3,1,[]); % Spread along the 3rd dimension
A supporting function loopingTransform2 is defined at the end of this example and performs a
looping transform using two nested loops, to loop over the robots as well as over the features.
cpuTime = timeit(@()loopingTransform2(Robot,Map,numFeatures,numRobots))
cpuTime = 0.0759
gRobot.R = gpuArray(Robot.R);
gRobot.T = gpuArray(Robot.T);
gpuTime = 2.1059
As before, the looping version runs much slower on the GPU because it is not doing calculations in
parallel.
A supporting function pagefunTransform2 is provided at the end of this example and applies the
same transforms as the loopingTransform2 function using two pagefun calls instead of nested
for-loops. This function needs to incorporate the transpose operator as well as mtimes into a call
to pagefun. The function also applies the squeeze function to the transposed robot orientations to
6-60
Improve Performance of Small Matrix Problems on the GPU Using pagefun
put the spread over robots into the 3rd dimension, to match the translations. Despite this, the
resulting code is considerably more compact.
gpuPagefunTime = gputimeit(@()pagefunTransform2(gRobot,gMap))
gpuPagefunTime = 0.0014
Compare Results
fprintf("Executing the transforms on the GPU using pagefun is %3.2f times faster than on the CPU.
cpuTime/gpuPagefunTime);
Executing the transforms on the GPU using pagefun is 55.85 times faster than on the CPU.
fprintf("Executing the transforms on the GPU using pagefun is %3.2f times faster than using neste
gpuTime/gpuPagefunTime);
6-61
6 GPU Computing
Executing the transforms on the GPU using pagefun is 1549.19 times faster than using nested for-l
Conclusion
The pagefun function supports a number of 2-D operations, as well as most of the scalar operations
supported by arrayfun. Together, these functions allow you to vectorize a range of computations
involving matrix algebra and array manipulation, eliminating the need for loops and making huge
performance gains.
Wherever you are doing small calculations on GPU data in a loop, you should consider converting to a
vectorized implementation in this way. This can also be an opportunity to make use of the GPU to
improve performance where previously it gave no performance gains.
Supporting Functions
for i = 1:N
% Create random translation.
Tform.T(:,i) = rand(3,1) .* roomDimensions';
end
The loopingTransform function transforms every feature to its location relative to the robot by
looping over the transforms in turn.
for i = 1:numFeatures
% Find orientation of map feature relative to the robot.
Rel.R(:,:,i) = Robot.R' * Map.R(:,:,i);
% Find position of map feature relative to the robot.
Rel.T(:,i) = Robot.R' * (Map.T(:,i) - Robot.T);
end
end
6-62
Improve Performance of Small Matrix Problems on the GPU Using pagefun
The pagefunTransform function transforms every feature to its location relative to the robot by
applying the transforms using the pagefun function.
function Rel = pagefunTransform(Robot,Map)
% Find orientation of map feature relative to the robot.
Rel.R = pagefun(@mtimes,Robot.R', Map.R);
% Apply translation.
Rel.T = Robot.R' * (Map.T - Robot.T);
end
The loopingTransform2 function performs a looping transform using two nested loops, to loop over
the robots as well as over the features. The transforms map every feature to its location relative to
every robot.
function Rel = loopingTransform2(Robot,Map,numFeatures,numRobots)
% Preallocate matrices.
Rel.R = zeros(3,3,numFeatures,numRobots,like=Map.R);
Rel.T = zeros(3,numFeatures,numRobots,like=Map.T);
for i = 1:numFeatures
for j = 1:numRobots
% Find orientation of map feature relative to the robot.
Rel.R(:,:,i,j) = Robot.R(:,:,1,j)' * Map.R(:,:,i);
% Find position of map feature relative to the robot.
Rel.T(:,i,j) = ...
Robot.R(:,:,1,j)' * (Map.T(:,i) - Robot.T(:,1,j));
end
end
end
The pagefunTransform2 function performs transforms to map every feature to its location relative
to every robot using two calls to the pagefun function.
function Rel = pagefunTransform2(Robot,Map)
% Find orientation of map feature relative to the robot.
Rt = pagefun(@transpose,Robot.R);
Rel.R = pagefun(@mtimes,Rt,Map.R);
% Find position of map feature relative to the robot.
Rel.T = pagefun(@mtimes,squeeze(Rt), ...
(Map.T - Robot.T));
end
See Also
pagefun | gpuArray | arrayfun | gputimeit
Related Examples
• “Measure and Improve GPU Performance” on page 6-41
• “Improve Performance of Element-Wise MATLAB Functions on the GPU Using arrayfun” on page
6-52
6-63
6 GPU Computing
6-64
Benchmarking A\b on the GPU
This example looks at how we can benchmark the solving of a linear system on the GPU. The
MATLAB® code to solve for x in A*x = b is very simple. Most frequently, we use matrix left division,
also known as mldivide or the backslash operator (\), to calculate x (that is, x = A\b).
Related examples:
It is important to choose the appropriate matrix size for the computations. We can do this by
specifying the amount of system memory in GB available to the CPU and the GPU. The default value is
based only on the amount of memory available on the GPU, and you can specify a value that is
appropriate for your system.
if nargin == 0
g = gpuDevice;
maxMemory = 0.4*[Link]/1024^3;
end
We want to benchmark matrix left division (\), and not the cost of transferring data between the CPU
and GPU, the time it takes to create a matrix, or other parameters. We therefore separate the data
generation from the solving of the linear system, and measure only the time it takes to do the latter.
As with a great number of other parallel algorithms, the performance of solving a linear system in
parallel depends greatly on the matrix size. As seen in other examples, such as “Benchmarking A\b”
on page 8-63, we compare the performance of the algorithm for different matrix sizes.
6-65
6 GPU Computing
end
sizeSingle = 1024:step:maxSizeSingle;
sizeDouble = 1024:step:maxSizeDouble;
We use the number of floating point operations per second as our measure of performance because
that allows us to compare the performance of the algorithm for different matrix sizes.
Given a matrix size, the benchmarking function creates the matrix A and the right-hand side b once,
and then solves A\b a few times to get an accurate measure of the time it takes. We use the floating
point operations count of the HPC Challenge, so that for an n-by-n matrix, we count the floating point
operations as 2/3*n^3 + 3/2*n^2.
The function is passed in a handle to a 'wait' function. On the CPU, this function does nothing. On the
GPU, this function waits for all pending operations to complete. Waiting in this way ensures accurate
timing.
function gflops = benchFcn(A, b, waitFcn)
numReps = 3;
time = inf;
% We solve the linear system a few times and calculate the Gigaflops
% based on the best time.
for itr = 1:numReps
tcurr = timeSolve(A, b, waitFcn);
time = min(tcurr, time);
end
% On the GPU, to ensure accurate timing, we need to wait for the device
% to finish all pending operations.
function waitForGpu(theDevice)
wait(theDevice);
end
Having done all the setup, it is straightforward to execute the benchmarks. However, the
computations can take a long time to complete, so we print some intermediate status information as
6-66
Benchmarking A\b on the GPU
we complete the benchmarking for each matrix size. We also encapsulate the loop over all the matrix
sizes in a function, to benchmark both single- and double-precision computations.
6-67
6 GPU Computing
We can now plot the results, and compare the performance on the CPU and the GPU, both for single
and double precision.
fig = figure;
ax = axes('parent', fig);
plot(ax, [Link], [Link], '-x', ...
[Link], [Link], '-o')
grid on;
legend('GPU', 'CPU', 'Location', 'NorthWest');
title(ax, 'Single-precision performance')
ylabel(ax, 'Gigaflops');
xlabel(ax, 'Matrix size');
drawnow;
6-68
Benchmarking A\b on the GPU
fig = figure;
ax = axes('parent', fig);
plot(ax, [Link], [Link], '-x', ...
[Link], [Link], '-o')
legend('GPU', 'CPU', 'Location', 'NorthWest');
grid on;
title(ax, 'Double-precision performance')
ylabel(ax, 'Gigaflops');
xlabel(ax, 'Matrix size');
drawnow;
6-69
6 GPU Computing
Finally, we look at the speedup of the backslash operator when comparing the GPU to the CPU.
speedupDouble = [Link]./[Link];
speedupSingle = [Link]./[Link];
fig = figure;
ax = axes('parent', fig);
plot(ax, [Link], speedupSingle, '-v', ...
[Link], speedupDouble, '-*')
grid on;
legend('Single-precision', 'Double-precision', 'Location', 'SouthEast');
title(ax, 'Speedup of computations on GPU compared to CPU');
ylabel(ax, 'Speedup');
xlabel(ax, 'Matrix size');
drawnow;
6-70
Benchmarking A\b on the GPU
end
ans =
See Also
gpuArray | gpuDevice | mldivide
Related Examples
• “Measure and Improve GPU Performance” on page 6-41
• “Establish Arrays on a GPU” on page 6-15
• “Benchmarking A\b” on page 8-63
• “GPU Computing Requirements” on page 6-13
6-71
6 GPU Computing
The table below summarizes the default settings for the GPU and CPU on client and worker MATLAB
sessions:
In most cases, it does not matter that the default random number generator on the GPU is not the
same as the default generators on the client or worker CPU. However, if you need to reproduce the
same results on both the GPU and CPU, you can set the generators accordingly.
Rc = rand(1,4)
Rc =
0.8147 0.9058 0.1270 0.9134
Rg = rand(1,4,'gpuArray')
Rg =
0.3640 0.5421 0.6543 0.7436
If you need to generate the same sequence of random numbers on both the GPU and CPU, you can set
the generator settings to match.
There are three random number generator algorithms available on the GPU: 'Threefry',
'Philox', and 'CombRecursive'. All are supported on the CPU. The following table lists the
algorithms for these generators and their properties.
6-72
Random Number Streams on a GPU
You can use rng and gpurng to set the generator algorithm and seed on the CPU and GPU,
respectively. For more information about the GPU random number generators and their performance,
see “Generating Random Numbers on a GPU” on page 6-75.
sc = rng(1,'Threefry');
Rc = rand(1,4)
Rc =
0.1404 0.8197 0.1073 0.4131
sg = gpurng(1,'Threefry');
Rg = rand(1,4,'gpuArray')
Rg =
0.1404 0.8197 0.1073 0.4131
rand and randi now generate the same sequences of random numbers on the client CPU and GPU.
You can also use rng and gpurng to reset the generator algorithm and seed to the default values on
the CPU and GPU respectively.
rsc = rng('default')
rsg = gpurng('default')
The settings are different from those on the client CPU. For more information, see “Control Random
Number Streams on Workers” on page 5-15
If you need to generate different random numbers on each worker, you can change the generator
settings. In this example, each worker creates the same sequence on its GPU and CPU, but different
sequences are generated on each worker.
p = parpool(2);
spmd
rng(spmdIndex,'Threefry');
Rc = rand(1,4)
gpurng(spmdIndex,'Threefry');
Rg = rand(1,4,'gpuArray')
end
delete(p)
On a client CPU, the default 'NormalTransform' setting is 'Ziggurat'. On a worker CPU, the
default setting is 'Inversion'.
6-73
6 GPU Computing
Unless otherwise specified, GPU code uses the 'BoxMuller' transform for the 'Threefry' and
'Philox' generators and the 'Inversion' transform for the 'CombRecursive' generator.
You can set the same generators and transforms on the CPU and the GPU to get the same randn
sequences. The only transform supported on both the CPU and GPU is the 'Inversion' transform.
sc = RandStream('Threefry','NormalTransform','Inversion','Seed',1);
[Link](sc)
sg = [Link]('Threefry','NormalTransform','Inversion','Seed',1);
[Link](sg);
Rc = randn(1,4)
Rc =
-1.0783 0.9144 -1.2412 -0.2196
Rg = randn(1,4,'gpuArray')
Rg =
-1.0783 0.9144 -1.2412 -0.2196
See Also
gpurng | [Link] | RandStream | rng | gpuArray
More About
• “Generating Random Numbers on a GPU” on page 6-75
• “Control Random Number Streams on Workers” on page 5-15
• “Creating and Controlling a Random Number Stream”
• “Establish Arrays on a GPU” on page 6-15
6-74
Generating Random Numbers on a GPU
This example shows how to switch between the different random number generators that are
supported on the GPU.
Random numbers form a key part of many simulation or estimation algorithms. Typically, these
numbers are generated using the functions rand, randi, and randn. Parallel Computing Toolbox™
provides three corresponding functions for generating random numbers directly on a GPU: rand,
randi, and randn. These functions can use one of several different number generation algorithms.
d = gpuDevice;
fprintf("This example is run on a " + [Link] + " GPU.")
[Link]
Each of these generators has been designed with parallel use in mind, providing multiple
independent streams of random numbers. However, they each have some advantages and
disadvantages:
• CombRecursive (also known as MRG32k3a): This generator was introduced in 1999 and has been
widely tested and used.
• Philox (also known as Philox4x32_10): New generator introduced in 2011, specifically designed
for high performance in highly parallel systems such as GPUs.
• Threefry (also known as Threefry4x64_20): New generator introduced in 2011 based on the
existing cryptographic ThreeFish algorithm, which is widely tested and used. This generator was
designed to give good performance in highly parallel systems such as GPUs. This is the default
generator for GPU calculations.
The three generators available on the GPU are also available for use on the CPU in MATLAB®. The
MATLAB generators have the same name and produce identical results given the same initial state.
This is useful when you want to produce the same sets of random numbers on both the GPU and the
CPU. For more information, see “Random Number Streams on a GPU” on page 6-72.
All of these generators pass the standard TestU01 test suite [1].
The function gpurng can store and reset the generator state for the GPU. You can also use gpurng to
switch between the different generators that are provided. Before changing the generator, store the
existing state so that it can be restored at the end of these tests.
6-75
6 GPU Computing
oldState = gpurng;
gpurng(0, "Philox4x32-10");
disp(gpurng)
Type: 'philox'
Seed: 0
State: [7×1 uint32]
Uniformly distributed random numbers are generated on the GPU using either rand, or randi. In
performance terms, these two functions behave very similarly and only rand is measured here.
gputimeit is used to measure the performance to ensure accurate timing results, automatically
calling the function many times and correctly dealing with synchronization and other timing issues.
To compare the performance of the different generators, use rand to generate a large number of
7
random numbers on the GPU using each generator. In the following code, rand generates 10
random numbers and is called 100 times for each generator. Each run is timed using gputimeit.
Generating large samples of random numbers can take several minutes. The results indicate a
performance comparison between the three random number generators available on the GPU.
generators = ["Philox","Threefry","CombRecursive"];
gputimesU = nan(100,3);
for g=1:numel(generators)
% Set the generator
gpurng(0, generators{g});
% Perform calculation 100 times, timing the generator
for rep=1:100
gputimesU(rep,g) = gputimeit(@() rand(10000,1000,"gpuArray"));
end
end
legend(generators)
xlabel("Time to generate 10^7 random numbers (sec)")
ylabel("Frequency")
title("Generating samples in U(0,1) using " + [Link])
hold off
6-76
Generating Random Numbers on a GPU
The newer generators Threefry and Philox have similar performance. Both are faster than
CombRecursive.
Many simulations rely on perturbations sampled from a normal distribution. Similar to the uniform
test, use randn to compare the performance of the three generators when generating normally
distributed random numbers. Generating large samples of random numbers can take several minutes.
generators = ["Philox","Threefry","CombRecursive"];
gputimesN = nan(100,3);
for g=1:numel(generators)
% Set the generator
gpurng(0, generators{g});
% Perform calculation 100 times, timing the generator
for rep=1:100
gputimesN(rep,g) = gputimeit(@() randn(10000,1000,"gpuArray"));
end
end
6-77
6 GPU Computing
Once again, the results indicate that the Threefry and Philox generators perform similarly and are
both notably faster than CombRecursive. The extra work required to produce normally distributed
values reduces the rate at which values are produced by each of the generators.
gpurng(oldState);
Conclusion
In this example, the three GPU random number generators are compared. The exact results vary
depending on your GPU and computing platform. Each generator provides some advantages (+) and
has some caveats (-).
Threefry
• (+) Fast
• (+) Based on well-known and well-tested Threefish algorithm
• (-) Relatively new in real-world usage
Philox
6-78
Generating Random Numbers on a GPU
• (+) Fast
• (-) Relatively new in real-world usage
CombRecursive
References
[1] L'Ecuyer, P., and R. Simard. "TestU01: A C library for empirical testing of random number
generators." ACM Transactions on Mathematical Software. Vol. 33, No. 4, 2007, article 22.
See Also
gpurng | [Link]
More About
• “Random Number Streams on a GPU” on page 6-72
6-79
6 GPU Computing
This example shows how to use GPU-enabled MATLAB® functions to compute a well-known
mathematical construction: the Mandelbrot set. Check your GPU using the gpuDevice function.
Define the parameters. The Mandelbrot algorithm iterates over a grid of real and imaginary parts.
The following code defines the number of iterations, grid size, and grid limits.
maxIterations = 500;
gridSize = 1000;
xlim = [-0.748766713922161, -0.748766707771757];
ylim = [ 0.123640844894862, 0.123640851045266];
You can use the gpuArray function to transfer data to the GPU and create a gpuArray, or you can
create an array directly on the GPU. gpuArray provides GPU versions of many functions that you can
use to create data arrays, such as linspace. For more information, see “Create GPU Arrays
Directly” on page 6-15.
x = [Link](xlim(1),xlim(2),gridSize);
y = [Link](ylim(1),ylim(2),gridSize);
whos x y
Many MATLAB functions support gpuArrays. When you supply a gpuArray argument to any GPU-
enabled function, the function runs automatically on the GPU. For more information, see “Run
MATLAB Functions on a GPU” on page 6-3. Create a complex grid for the algorithm, and create the
array count for the results. To create this array directly on the GPU, use the ones function, and
specify 'gpuArray'.
[xGrid,yGrid] = meshgrid(x,y);
z0 = complex(xGrid,yGrid);
count = ones(size(z0),'gpuArray');
The following code implements the Mandelbrot algorithm using GPU-enabled functions. Because the
code uses gpuArrays, the calculations happen on the GPU.
z = z0;
for n = 0:maxIterations
z = z.*z + z0;
inside = abs(z) <= 2;
count = count + inside;
end
count = log(count);
imagesc(x,y,count)
colormap([jet();flipud(jet());0 0 0]);
axis off
6-80
Compute the Mandelbrot Set Using GPU-Enabled Functions
See Also
gpuArray | complex | linspace
Related Examples
• “Identify and Select a GPU Device” on page 6-10
• “Illustrating Three Approaches to GPU Computing: The Mandelbrot Set” on page 6-82
More About
• “Run MATLAB Functions on a GPU” on page 6-3
• “Work with Complex Numbers on a GPU” on page 6-39
6-81
6 GPU Computing
This example shows how to adapt your MATLAB® code to compute the Mandelbrot Set using a GPU.
Starting with an existing algorithm, this example shows how to adapt your code using Parallel
Computing Toolbox™ to make use of GPU hardware in three ways:
Setup
The values below specify a highly zoomed part of the Mandelbrot Set in the valley between the main
cardioid and the p/q bulb to its left.
A 1000x1000 grid of real parts (X) and imaginary parts (Y) is created between these limits and the
Mandelbrot algorithm is iterated 500 times at each grid location.
maxIterations = 500;
gridSize = 1000;
xlim = [-0.748766713922161, -0.748766707771757];
ylim = [ 0.123640844894862, 0.123640851045266];
Below is an implementation of the Mandelbrot Set using standard MATLAB commands running on the
CPU. This is based on the code provided in Cleve Moler's Experiments with MATLAB e-book. Time the
execution on the CPU using tic and toc.
tic;
x = linspace(xlim(1),xlim(2),gridSize);
y = linspace(ylim(1),ylim(2),gridSize);
[xGrid,yGrid] = meshgrid(x,y);
z0 = xGrid + 1i*yGrid;
6-82
Illustrating Three Approaches to GPU Computing: The Mandelbrot Set
For 500 iterations, calculate the next value of a point on the complex grid z by squaring the previous
value and adding its initial value, z0. Count the number of iterations for which the magnitude of z is
less than or equal to two. This calculation is vectorized such that every location is updated at once.
cpuCount = ones(size(z0));
z = z0;
for n = 0:maxIterations
z = z.*z + z0;
inside = abs(z)<=2;
cpuCount = cpuCount + inside;
end
cpuCount = log(cpuCount);
cpuTime = toc
cpuTime = 4.4007
figure
imagesc(x,y,cpuCount);
c = colormap([jet;flipud(jet);0 0 0]);
axis off
title(sprintf("CPU Execution: %1.3f s",cpuTime));
6-83
6 GPU Computing
Using gpuArray
When MATLAB encounters data on the GPU, calculations with that data are performed on the GPU.
The class gpuArray provides GPU versions of many functions that you can use to create data arrays,
including the linspace, logspace, and meshgrid functions needed here. Similarly, the count
array is initialized directly on the GPU using the function ones.
gpu = gpuDevice;
disp([Link] + " GPU selected.")
Call the naiveGPUMandelbrot function. The supporting function naiveGPUMandelbrot applies the
Mandelbrot algorithm for each point on the grid on the GPU and is provided at the end of this
examples.
[x,y,naiveGPUCount] = naiveGPUMandelbrot(xlim,ylim,gridSize,maxIterations);
Time the execution of the function on the GPU using gputimeit. For functions that use the GPU,
gputimeit is better than tic and toc or timeit because it ensures that all operations on the GPU
finish before recording the elapsed time.
naiveGPUTime = 0.2181
Element-wise Operation
Noting that the algorithm is operating equally on every element of the input, we can place the code in
a function and call it using arrayfun. The function processMandelbrotElement is provided as a
supporting function at the end of this example. For gpuArray inputs, the function used with
arrayfun gets compiled into native GPU code.
An early abort has been introduced into the function processMandelbrotElement because this
function processes only a single element. For most views of the Mandelbrot Set a significant number
of elements stop very early and this can save a lot of processing. The for-loop has also been replaced
by a while-loop because they are usually more efficient. This function makes no mention of the GPU
and uses no GPU-specific features.
Using arrayfun causes MATLAB to make one call to a parallelized GPU operation that performs the
whole calculation, instead of many thousands of calls to separate GPU-optimized operations (at least
6 per iteration). The first time you call arrayfun to run a particular function on the GPU, there is
some overhead time to set up the function for GPU execution. Subsequent calls of arrayfun with the
same function can run faster.
xGrid = gpuArray(xGrid);
yGrid = gpuArray(yGrid);
Using arrayfun, apply the Mandelbrot algorithm for each point on the grid.
6-84
Illustrating Three Approaches to GPU Computing: The Mandelbrot Set
gpuArrayfunTime = 0.0308
A CUDA/C++ implementation of the element processing algorithm is provided with this example,
pctdemo_processMandelbrotElement.cu. The part of the CUDA/C++ code that executes the
Mandelbrot algorithm for a single location is given below.
__device__
unsigned int doIterations( double const realPart0,
double const imagPart0,
unsigned int const maxIters ) {
// Initialize: z = z0
double realPart = realPart0;
double imagPart = imagPart0;
unsigned int count = 0;
// Loop until escape
while ( ( count <= maxIters )
&& ((realPart*realPart + imagPart*imagPart) <= 4.0) ) {
++count;
// Update: z = z*z + z0;
double const oldRealPart = realPart;
realPart = realPart*realPart - imagPart*imagPart + realPart0;
imagPart = 2.0*oldRealPart*imagPart + imagPart0;
}
return count;
}
Compile this file into a parallel thread execution (PTX) file using mexcuda.
Create a [Link] object by passing the CUDA file and the PTX file to the
[Link] function.
cudaFilename = "pctdemo_processMandelbrotElement.cu";
ptxFilename = "pctdemo_processMandelbrotElement.ptx";
kernel = [Link](ptxFilename,cudaFilename);
One GPU thread is required per location in the Mandelbrot Set, with the threads grouped into blocks.
The kernel indicates how big a thread-block is. Calculate the number of thread-blocks required, and
set the GridSize property of the kernel (effectively the number of thread blocks that will be
launched independently by the GPU) accordingly.
6-85
6 GPU Computing
numElements = numel(xGrid);
[Link] = [[Link],1,1];
[Link] = [ceil(numElements/[Link]),1];
count = zeros(size(xGrid),"gpuArray");
gpuCUDAKernelCount = feval(kernel,count,xGrid,yGrid,maxIterations,numElements);
Summary
Plot the results from the different methods and compare the execution times.
method = ["Naive GPU Execution" "GPU Execution Using arrayfun" "CUDAKernel Execution"];
count = cat(3,naiveGPUCount,gpuArrayfunCount,gpuCUDAKernelCount);
time = [naiveGPUTime gpuArrayfunTime gpuCUDAKernelTime];
figure
colormap(c)
tiledlayout("flow")
nexttile
imagesc(x,y,cpuCount);
axis off
title(sprintf("CPU Execution: %1.3f s",cpuTime));
6-86
Illustrating Three Approaches to GPU Computing: The Mandelbrot Set
This example has shown three ways in which a MATLAB algorithm can be adapted to make use of
GPU hardware:
1 Convert the input data to be on the GPU using gpuArray, leaving the algorithm unchanged.
2 Use arrayfun on a gpuArray input to perform the algorithm on each element of the input
independently.
3 Use a [Link] to run some existing CUDA/C++ code using MATLAB data.
The code in this example was timed on a Windows® 10, Intel® Xeon® W-2133 @ 3.60 GHz test
system with an NVIDIA® RTX A5000 GPU.
Supporting Functions
x = [Link](xlim(1),xlim(2),gridSize);
6-87
6 GPU Computing
y = [Link](ylim(1),ylim(2),gridSize);
[xGrid,yGrid] = meshgrid(x,y);
z0 = complex(xGrid,yGrid);
count = ones(size(z0),"gpuArray");
z = z0;
for n = 0:maxIterations
z = z.*z + z0;
inside = abs(z)<=2;
count = count + inside;
end
count = log(count);
end
z0 = complex(x0,y0);
z = z0;
count = 1;
count = log(count);
end
See Also
gpuArray | arrayfun
Related Examples
• “Run MATLAB Functions on a GPU” on page 6-3
• “Measure and Improve GPU Performance” on page 6-41
• “Improve Performance of Element-Wise MATLAB Functions on the GPU Using arrayfun” on page
6-52
• “Run CUDA or PTX Code on GPU” on page 6-117
6-88
Measure GPU Memory Bandwidth and Processing Power
This example shows how to measure some of the key performance characteristics of your GPU
hardware.
GPUs can be used to speed up certain types of computations. However, GPU performance varies
widely between different GPU devices. These three tests quantify the performance of a GPU:
• How quickly can data be sent to the GPU or read back from it?
• How fast can the GPU kernel read and write data?
• How fast can the GPU perform computations in double and single precision?
After assessing these metrics, you can compare the performance of the GPU and the host CPU. This
comparison indicated how much data or computation is required for the GPU to provide an advantage
over the CPU.
gpu = gpuDevice;
disp([Link] + " GPU detected and available.")
The first test estimates how quickly data can be sent to and read from the GPU. Because the GPU is
plugged into the PCI bus, the bandwidth largely depends on how fast the PCI bus is and how many
other devices are using it. However, there are some overheads that are included in the
measurements, particularly the time taken to call the send and read functions and allocate the arrays.
Because these are present in any "real world" use of the GPU, it is reasonable to include these
overheads.
• Create a variable representing the number of bytes required to store a double-precision number.
• Create an vector of sizes, where the maximum size is 1/4 of the available GPU memory. The tests
loop over this vector and create arrays of increasing size. As an array on the GPU in MATLAB®
31
cannot have more than 2 − 1 elements, remove any sizes that will create arrays larger than this.
sizeOfDouble = 8;
maxSize = 0.25*[Link];
maxNumTests = 15;
sizes = logspace(4,log10(maxSize),maxNumTests);
sizes(sizes/sizeOfDouble > intmax) = [];
6-89
6 GPU Computing
• Use the timeit function to time allocating memory and sending data from the GPU to the host
using the gather function.
• Divide the amount of data sent by the measured time to determine the bandwidth.
numTests = numel(sizes);
numElements = floor(sizes/sizeOfDouble);
sendTimes = inf(1,numTests);
gatherTimes = inf(1,numTests);
for idx=1:numTests
disp("Test " + idx + " of " + numTests + ". Timing send and gather for array with " + numElem
Test 1 of 15. Timing send and gather for array with 1250 elements.
Test 2 of 15. Timing send and gather for array with 3240 elements.
Test 3 of 15. Timing send and gather for array with 8398 elements.
Test 4 of 15. Timing send and gather for array with 21768 elements.
Test 5 of 15. Timing send and gather for array with 56425 elements.
Test 6 of 15. Timing send and gather for array with 146258 elements.
Test 7 of 15. Timing send and gather for array with 379107 elements.
Test 8 of 15. Timing send and gather for array with 982663 elements.
Test 9 of 15. Timing send and gather for array with 2547104 elements.
Test 10 of 15. Timing send and gather for array with 6602203 elements.
Test 11 of 15. Timing send and gather for array with 17113191 elements.
Test 12 of 15. Timing send and gather for array with 44358118 elements.
Test 13 of 15. Timing send and gather for array with 114978124 elements.
Test 14 of 15. Timing send and gather for array with 298028173 elements.
Test 15 of 15. Timing send and gather for array with 772501660 elements.
sendBandwidth = (sizes./sendTimes)/1e9;
gatherBandwidth = (sizes./gatherTimes)/1e9;
Determine the peak send and gather speeds. Note that the GPU used in this test supports PCI
Express® version 4.0, which has a theoretical bandwidth of 1.97 GB/s per lane. For the 16-lane slots
used by NVIDIA® compute cards this gives a theoretical bandwidth of 31.52 GB/s.
[maxSendBandwidth,maxSendIdx] = max(sendBandwidth);
[maxGatherBandwidth,maxGatherIdx] = max(gatherBandwidth);
fprintf("Achieved peak send speed of %.2f GB/s",maxSendBandwidth)
6-90
Measure GPU Memory Bandwidth and Processing Power
Plot the data transfer speeds against array size, and circle the peak for each case. With small data set
sizes, overheads dominate. With larger amounts of data the PCI bus is the limiting factor.
figure
semilogx(sizes,sendBandwidth,MarkerIndices=maxSendIdx,Marker="o")
hold on
semilogx(sizes,gatherBandwidth,MarkerIndices=maxGatherIdx,Marker="o")
grid on
title("Data Transfer Bandwidth")
xlabel("Array size (bytes)")
ylabel("Transfer speed (GB/s)")
legend(["Send to GPU" "Gather from GPU"],Location="SouthEast")
hold off
Many operations do very little computation with each element of an array, so these operations are
dominated by the time taken to fetch the data from memory or to write it back. Functions such as
ones, zeros, nan, and true only write their output, whereas functions like transpose and tril
both read and write but do no computation. Even simple operators like plus and minus do so little
computation per element that they are bound only by the memory access speed.
The function plus performs one memory read and one memory write for each floating-point
operation. As such, the function is limited by memory access speed and provides a good indicator of
the speed of a read plus write operation.
Reset your GPU to clear its memory of GPU arrays allocated in the previous section.
reset(gpu)
6-91
6 GPU Computing
sizes = logspace(4.5,log10(maxSize),maxNumTests);
sizes(sizes/sizeOfDouble > intmax) = [];
Measure the speed at which the GPU can read and write to GPU memory. Also measure the speed at
which the host can read and write to host memory. For each array size in sizes:
numTests = numel(sizes);
numElements = floor(sizes/sizeOfDouble);
memoryTimesGPU = inf(1,numTests);
memoryTimesHost = inf(1,numTests);
for idx=1:numTests
disp("Test " + idx + " of " + numTests + ". Timing plus operation on GPU and CPU for arrays w
Test 1 of 15. Timing plus operation on GPU and CPU for arrays with 3952 elements.
Test 2 of 15. Timing plus operation on GPU and CPU for arrays with 9437 elements.
Test 3 of 15. Timing plus operation on GPU and CPU for arrays with 22530 elements.
Test 4 of 15. Timing plus operation on GPU and CPU for arrays with 53788 elements.
Test 5 of 15. Timing plus operation on GPU and CPU for arrays with 128416 elements.
Test 6 of 15. Timing plus operation on GPU and CPU for arrays with 306583 elements.
Test 7 of 15. Timing plus operation on GPU and CPU for arrays with 731942 elements.
Test 8 of 15. Timing plus operation on GPU and CPU for arrays with 1747449 elements.
Test 9 of 15. Timing plus operation on GPU and CPU for arrays with 4171886 elements.
Test 10 of 15. Timing plus operation on GPU and CPU for arrays with 9960023 elements.
Test 11 of 15. Timing plus operation on GPU and CPU for arrays with 23778702 elements.
Test 12 of 15. Timing plus operation on GPU and CPU for arrays with 56769618 elements.
Test 13 of 15. Timing plus operation on GPU and CPU for arrays with 135532606 elements.
Test 14 of 15. Timing plus operation on GPU and CPU for arrays with 323572501 elements.
Test 15 of 15. Timing plus operation on GPU and CPU for arrays with 772501660 elements.
memoryBandwidthGPU = 2*(sizes./memoryTimesGPU)/1e9;
memoryBandwidthHost = 2*(sizes./memoryTimesHost)/1e9;
[maxBWGPU,maxBWIdxGPU] = max(memoryBandwidthGPU);
[maxBWHost,maxBWIdxHost] = max(memoryBandwidthHost);
fprintf("Achieved peak read+write speed on the GPU: %.2f GB/s",maxBWGPU)
6-92
Measure GPU Memory Bandwidth and Processing Power
Plot the read and write speeds against array size, and circle the peak for each case. Comparing this
plot with the data-transfer plot above, it is clear that GPUs can typically read from and write to their
memory much faster than they can get data from the host. So, it is important to minimize the number
of host-GPU or GPU-host memory transfers. Ideally, programs should initially create data on the GPU.
Otherwise, programs should transfer data to the GPU, then do as much as possible with the data
while it is on the GPU before bringing the data back to the host only when complete.
figure
semilogx(sizes,memoryBandwidthGPU,MarkerIndices=maxBWIdxGPU,Marker="o")
hold on
semilogx(sizes,memoryBandwidthHost,MarkerIndices=maxBWIdxHost,Marker="o")
grid on
title("Read+Write Bandwidth")
xlabel("Array size (bytes)")
ylabel("Speed (GB/s)")
legend(["GPU" "Host"],Location="NorthWest")
hold off
Memory speed is less important for operations where there are a high number of floating-point
computations per element read from or written to memory. These operations are said to have high
computational density. In this case, the number and speed of the floating-point units is the limiting
factor.
6-93
6 GPU Computing
Two input matrices are read and one resulting matrix is written, for a total of 3N2 elements read or
written. This gives a computational density of (2N - 1)/3 FLOP/element. Contrast this with the
plus function as used above, which has a computational density of 1/2 FLOP/element.
Reset your GPU to clear its memory of GPU arrays allocated in the previous section and create a
vector of sizes.
reset(gpu)
sizes = logspace(4,log10(maxSize)-1,maxNumTests);
sizes(sizes/sizeOfDouble > intmax) = [];
Double Precision
MATLAB can perform calculations in double precision or single precision. Calculating in single
precision instead of double precision can improve the performance of code running on your GPU, as
most GPU cards are designed for graphics display, which demands a high single-precision
performance. In contrast, CPUs are designed for general purpose computing and so do not provide
this improvement when switching from double to single precision. For more information on
converting data to single precision and performing arithmetic operations on single-precision data, see
“Floating-Point Numbers”. Typical examples of workflows suitable for single-precision computation
on the GPU include image processing and machine learning. However, other types of calculation,
such as linear algebra problems, typically require double-precision processing.
For an approximate measure of the relative performance of your GPU in single precision compared to
double precision, query the SingleDoubleRatio property of your device. This property describes
the ratio of single- to double-precision floating-point units (FPUs) on the device. Most desktop GPUs
have 24, 32, or even 64 times as many single-precision floating-point units as double-precision. Some
GPUs also contain specialized cores that accelerate common deep learning operations. For example,
Ampere architecture and later NVIDIA data center GPUs (A100 and H100) include Tensor Cores that
can accelerate double-precision matrix multiplication. For these data center GPUs, the
SingleDoubleRatio property might not accurately represent the relative performance in single
precision compared to double precision for matrix multiplication.
[Link]
ans =
32
To measure the double-precision processing power, for each array size in sizes:
6-94
Measure GPU Memory Bandwidth and Processing Power
mmTimesHostDouble = inf(1,numTests);
mmTimesGPUDouble = inf(1,numTests);
for idx=1:numTests
disp("Test " + idx + " of " + numTests + ". Timing double-precision matrix-matrix multiplicat
Single Precision
You can convert data to single precision by using the single function, or by specifying single as
the data type in a creation function such as zeros, ones, rand, and eye.
Measure the single-precision processing power. Generate single-precision random data using the
rand function and specifying single as the data type.
NSingle = floor(sqrt(sizes/(sizeOfDouble/2)));
mmTimesHostSingle = inf(1,numTests);
6-95
6 GPU Computing
mmTimesGPUSingle = inf(1,numTests);
for idx=1:numTests
disp("Test " + idx + " of " + numTests + ". Timing single-precision matrix-matrix multiplicat
Plot the processing power against array size for double precision and single precision, and circle the
peak for each case.
figure
loglog(NDouble.^2,mmFlopsGPUDouble,MarkerIndices=maxFlopsGPUDoubleIdx,Marker="o")
hold on
loglog(NSingle.^2,mmFlopsGPUSingle,MarkerIndices=maxFlopsGPUSingleIdx,Marker="o")
loglog(NDouble.^2,mmFlopsHostDouble,MarkerIndices=maxFlopsHostDoubleIdx,Marker="o")
loglog(NSingle.^2,mmFlopsHostSingle,MarkerIndices=maxFlopsHostSingleIdx,Marker="o")
grid on
6-96
Measure GPU Memory Bandwidth and Processing Power
title("Matrix-Matrix Multiply")
xlabel("Matrix size (numel)")
ylabel("processing power (FLOPS)")
legend(["GPU double" "GPU single" "Host double" "Host single"],Location="SouthEast")
hold off
Conclusions
• Transfers from host memory to GPU memory and back are relatively slow.
• The GPU can read and write its memory much faster than the host CPU can read and write its
memory.
• Given large enough data, a GPU can perform calculations faster than the host CPU.
• GPUs perform calculations faster in single precision than double precision, and often much faster.
It is notable that, in each test, large arrays were required for the GPU to outperform the host CPU.
GPUs provide the greatest advantage when working with millions of elements at once.
For more detailed GPU benchmarks, including comparisons between different GPUs, see GPUBench
on the MATLAB Central File Exchange.
See Also
gpuArray | gputimeit | gpuDevice | gpuDeviceTable
6-97
6 GPU Computing
Related Examples
• “Measure and Improve GPU Performance” on page 6-41
• “Establish Arrays on a GPU” on page 6-15
• “GPU Computing Requirements” on page 6-13
6-98
Using GPU arrayfun for Monte-Carlo Simulations
This example shows how to calculate prices for financial options on a GPU using Monte-Carlo
methods.
The example uses three simple types of exotic option, but you can price more complex options in a
similar way. In this example, you compare the time taken to run Monte-Carlo Simulations on the CPU
and using arrayfun on the GPU.
Assume that prices evolve according to a log-normal distribution related to the risk-free interest rate,
the dividend yield (if any), and the volatility in the market. Further, assume that all these quantities
remain fixed over the lifetime of the option. These assumptions lead to this stochastic differential
equation for the price.
dS = S × (r − d)dt + σϵ dt ,
where S is the stock price, r is the risk-free interest rate, d is the annual dividend yield of the stocks,
σ is the volatility of the price, and ϵ represents a Gaussian white-noise process. Assuming that
(S + ΔS)/S is log-normally distributed, this differential equation can be discretized to obtain this
equation.
1 2
St + 1 = St × exp r − d − σ Δt + σϵ Δt .
2
Examine a two-year time window using $100 of stock with these assumptions:
stockPrice = 100;
timeToExpiry = 2;
dividend = 0.01;
riskFreeRate = 0.005;
sampleRate = 1/250;
volatility = 0.20;
To ensure predictable results, set the seed for the CPU and GPU random number generators.
seed = 1234;
rng(seed);
gpurng(seed);
Simulate the path of the stock price over time and plot the results.
price = stockPrice;
time = 0;
h = animatedline(Marker=".");
6-99
6 GPU Computing
grid on
axis tight
xlabel("Time (years)")
ylabel("Stock Price ($)")
The simulateStockPrice function, provided at the end of this example, simulates the stock price
using the discretized differential equation described in the previous section.
Prepare the input data for running 100,000 Monte-Carlo simulations of the stock price.
N = 100000;
startStockPrices = stockPrice*ones(N,1);
6-100
Using GPU arrayfun for Monte-Carlo Simulations
timeToExpiry,sampleRate);
end
timeCPU = toc;
Because each simulation gives an independent estimate of the option price, take the mean as the
result.
To run the simulations on the GPU, prepare the input data on the GPU by creating a gpuArray
object.
gpuStartStockPrices = gpuArray(startStockPrices);
When you call arrayfun with a GPU array and a function handle as inputs, arrayfun applies the
function you specify to each element of the array. This behavior means that looping over each starting
stock price is not necessary. The arrayfun function on the GPU turns an element-wise MATLAB®
function into a custom CUDA® kernel, which reduces the overhead of performing the operation.
Run the simulateStockPrice function using arrayfun and time 100,000 simulations on the GPU
using gputimeit.
histogram(finalStockPricesGPU,100);
xlabel("Stock Price ($)")
ylabel("Frequency")
grid on
6-101
6 GPU Computing
Use a European Asian Option based on the arithmetic mean of the stock price during the lifetime of
the option. The asianCallOption function calculates the mean price by accumulating the price
during the simulation. For a call option, the function exercises the option if the average price is above
the strike price. The payout is the difference between the average price and the strike price. Use the
asianCallOption, provided at the end of this example, to simulate an Asian call option.
strike = 95;
Time 100,000 simulations on the CPU and on the GPU using arrayfun and show the results.
tic
optionPricesCPU = zeros(N,1);
for i=1:N
optionPricesCPU(i) = asianCallOption(startStockPrices(i), ...
riskFreeRate,dividend,volatility,strike, ...
timeToExpiry,sampleRate);
end
timeAsianOptionCPU = toc;
6-102
Using GPU arrayfun for Monte-Carlo Simulations
Use a European-style lookback option whose payout is the difference between the minimum stock
price and the final stock price over the lifetime of the option. The strike price for the option is the
minimum stock price. Because the final stock price is always greater than or equal to the minimum,
the option is always exercised and is not really optional. Use the lookbackCallOption, provided at
the end of this example, for simulating a European-style lookback call option.
Time 100,000 simulations on both the CPU and on the GPU using arrayfun and show the results.
tic
optionPricesCPU = zeros(N,1);
for i=1:N
optionPricesCPU(i) = lookbackCallOption(startStockPrices(i), ...
riskFreeRate,dividend,volatility, ...
timeToExpiry,sampleRate);
end
timeLookbackOptionCPU = toc;
Use an up-and-out barrier option, which becomes invalid if the stock price reaches the barrier level. If
the stock price stays below the barrier level, use the final stock price in a normal European call
option calculation. Use the upAndOutCallOption function, provided at the end of this example, to
simulate an up-and-out barrier call option.
Set the strike price for the option and the barrier price at which it becomes invalid. Use a strike price
of $95 and a barrier price of $150.
6-103
6 GPU Computing
strike = 95;
barrier = 150;
Time 100,000 simulations on the CPU and on the GPU using arrayfun and show the results.
tic
optionPricesCPU = zeros(N,1);
for i=1:N
optionPricesCPU(i) = upAndOutCallOption(startStockPrices(i), ...
riskFreeRate,dividend,volatility,strike, ...
barrier,timeToExpiry,sampleRate);
end
timeBarrierOptionCPU = toc;
Compare Results
Calculate the ratio of CPU execution time to GPU execution time for each simulation.
ratio = 1×4
To visualize the results, plot the ratios of execution times for each simulation.
bar(categorical(["Stock Price" "Asian Call Option" "Lookback Option" "Barrier Option"]), ...
ratio)
ylabel("Ratio of CPU to GPU Execution Time")
6-104
Using GPU arrayfun for Monte-Carlo Simulations
In this example, running the simulations on the GPU with arrayfun is significantly faster than
running the simulations on the CPU.
When you apply the techniques described in this example to your own code, the performance
improvement will strongly depend on your hardware and on the code you run.
Supporting Functions
The simulateStockPrice function takes an initial stock price, a risk-free interest rate, a dividend
rate, a market volatility, a total time window, and a sample rate as input.
function finalStockPrice = simulateStockPrice(price,riskFreeRate,dividend,volatility,T,dT)
t = 0;
while t < T
t = t + dT;
drift = (riskFreeRate - dividend - volatility*volatility/2)*dT;
perturbation = volatility*sqrt(dT)*randn;
price = price.*exp(drift + perturbation);
end
finalStockPrice = price;
end
6-105
6 GPU Computing
The asianCallOption function takes an initial stock price, a risk-free interest rate, a dividend rate,
a market volatility, a strike price, a total time window, and a sample rate as input.
The lookbackCallOption function takes an initial stock price, a risk-free interest rate, a dividend
rate, a market volatility, a total time window, and a sample rate as input.
6-106
Using GPU arrayfun for Monte-Carlo Simulations
The upAndOutCallOption function takes an initial stock price, a risk-free interest rate, a dividend
rate, a market volatility, a strike price, a barrier price, a total time window, and a sample rate as
input.
if price<barrier
% Within barrier, so price as for a European option
optionPrice = exp(-riskFreeRate*T)*max(0,price - strike);
else
% Hit the barrier, so the option is withdrawn
optionPrice = 0;
end
end
See Also
arrayfun | gpuArray | gputimeit
Related Examples
• “Measure and Improve GPU Performance” on page 6-41
• “Improve Performance of Element-Wise MATLAB Functions on the GPU Using arrayfun” on page
6-52
• “Pricing European and American Spread Options” (Financial Instruments Toolbox)
• “Pricing Asian Options” (Financial Instruments Toolbox)
• “Pricing European Call Options Using Different Equity Models” (Financial Instruments Toolbox)
• “Supported Equity Derivative Functions” (Financial Instruments Toolbox)
6-107
6 GPU Computing
This example uses Parallel Computing Toolbox™ to perform a two-dimensional Fast Fourier
Transform (FFT) on a GPU. The two-dimensional Fourier transform is used in optics to calculate far-
field diffraction patterns. These diffraction patterns are observed when a monochromatic light source
passes through a small aperture, such as in Young's double-slit experiment.
Before you simulate the light that has passed through an aperture, define a coordinate system. To get
the correct numerical behavior for calling fft2, arrange x and y so that the zero value is in the
correct place.
N2 = gpuArray(1024);
[gx,gy] = meshgrid(-1:1/N2:(N2-1)/N2);
Simulate the effect of passing a parallel beam of monochromatic light through a small rectangular
aperture. The two-dimensional Fourier transform describes the light field at a large distance from the
aperture. Start by forming aperture as a logical mask based on the coordinate system. The light
source is a double-precision version of the aperture. The far-field light signal is found using fft2.
aperture = (abs(gx)<4/N2).*(abs(gy)<2/N2);
lightsource = double(aperture);
farfieldsignal = fft2(lightsource);
Calculate the far-field light intensity from the magnitude squared of the light field. Use fftshift to
aid visualization.
farfieldintensity = real(farfieldsignal.*conj(farfieldsignal));
imagesc(fftshift(farfieldintensity));
axis("equal");
axis("off");
title("Rectangular Aperture Far-field Diffraction Pattern");
6-108
Use FFT2 on the GPU to Simulate Diffraction Patterns
One of the most famous experiments in optics is Young's double-slit experiment which shows light
interference when an aperture comprises two parallel slits. A series of bright points is visible where
constructive interference takes place. Form the aperture representing two slits. Restrict the aperture
in the y direction to ensure that the resulting pattern is not entirely concentrated along the
horizontal axis.
slits = (abs(gx)<=10/N2).*(abs(gx)>=8/N2);
aperture = slits.*(abs(gy)<20/N2);
lightsource = double(aperture);
farfieldsignal = fft2(lightsource);
farfieldintensity = real(farfieldsignal.*conj(farfieldsignal));
imagesc(fftshift(farfieldintensity));
axis("equal");
axis("off");
title("Double Slit Far-field Diffraction Pattern");
6-109
6 GPU Computing
See Also
gpuArray | fftshift | fft2
Related Examples
• “Illustrating Three Approaches to GPU Computing: The Mandelbrot Set” on page 6-82
• “Improve Performance Using a GPU and Vectorized Calculations” on page 6-48
• “Measure GPU Memory Bandwidth and Processing Power” on page 6-89
6-110
Sharpen an Image Using the GPU
This example shows how to sharpen an image using gpuArray objects and GPU-enabled functions.
Read the image, and send it to the GPU using the gpuArray function.
image = gpuArray(imread("[Link]"));
Convert the image to double arrays, and apply convolutions to obtain the gradient image. Then, using
the gradient image, sharpen the image by a factor of amount.
dimage = im2double(image);
gradient = convn(dimage,ones(3)/9,"same") - convn(dimage,ones(5)/25,"same");
amount = 5;
sharpened = dimage + amount.*gradient;
imshow(imresize([dimage,sharpened],0.7));
title("Original image (left) vs sharpened image (right)");
See Also
gpuArray | convn | imread | imshow
Related Examples
• “Identify and Select a GPU Device” on page 6-10
• “Illustrating Three Approaches to GPU Computing: The Mandelbrot Set” on page 6-82
More About
• “Run MATLAB Functions on a GPU” on page 6-3
6-111
6 GPU Computing
This example uses Conway's "Game of Life" to demonstrate how stencil operations can be performed
using a GPU.
Many array operations can be expressed as a "stencil operation", where each element of the output
array depends on a small region of the input array. Examples include finite differences, convolution,
median filtering, and finite-element methods. This example uses Conway's "Game of Life" to
demonstrate two ways to run a stencil operation on a GPU, starting from the code in Cleve Moler's e-
book Experiments in MATLAB.
The "stencil" in this case is therefore the 3x3 region around each element. Here are some examples of
how a cell is updated:
function paralleldemo_gpu_stencil()
An initial population of cells is created on a 2D grid with roughly 25% of the locations alive.
gridSize = 500;
numGenerations = 100;
initialGrid = (rand(gridSize,gridSize) > .75);
gpu = gpuDevice();
6-112
Stencil Operations on a GPU
The e-book Experiments in MATLAB provides an initial implementation that can be used for
comparison. This version is fully vectorized, updating all cells in the grid in one pass per generation.
function X = updateGrid(X, N)
p = [1 1:N-1];
q = [2:N N];
% Count how many of the eight neighbors are alive.
neighbors = X(:,p) + X(:,q) + X(p,:) + X(q,:) + ...
X(p,p) + X(q,q) + X(p,q) + X(q,p);
% A live cell with two live neighbors, or any cell with
% three live neighbors, is alive at the next step.
X = (X & (neighbors == 2)) | (neighbors == 3);
end
grid = initialGrid;
% Loop through each generation updating the grid and displaying it
for generation = 1:numGenerations
grid = updateGrid(grid, gridSize);
imagesc(grid);
title(num2str(generation));
drawnow;
end
6-113
6 GPU Computing
Now re-run the game and measure how long it takes for each generation.
grid = initialGrid;
timer = tic();
cpuTime = toc(timer);
fprintf('Average time on the CPU: %2.3fms per generation.\n', ...
1000*cpuTime/numGenerations);
To run the Game of Life on the GPU, the initial population is sent to the GPU using gpuArray. The
algorithm remains unchanged. Note that wait is used to ensure that the GPU has finished calculating
before the timer is stopped. This is required only for accurate timing.
grid = gpuArray(initialGrid);
timer = tic();
6-114
Stencil Operations on a GPU
% Print out the average computation time and check the result is unchanged.
fprintf(['Average time on the GPU: %2.3fms per generation ', ...
'(%1.1fx faster).\n'], ...
1000*gpuSimpleTime/numGenerations, cpuTime/gpuSimpleTime);
assert(isequal(grid, expectedResult));
Looking at the calculations in the updateGrid function, it is apparent that the same operations are
applied at each grid location independently. This suggests that arrayfun could be used to do the
evaluation. However, each cell needs to know about its eight neighbors, breaking the element-wise
independence. Each element needs to be able to access the full grid while also working
independently.
The solution is to use a nested function. Nested functions, even those used with arrayfun, can
access variables declared in their parent function. This means that each cell can read the whole grid
from the previous time-step and index into it.
grid = gpuArray(initialGrid);
timer = tic();
% Print out the average computation time and check the result is unchanged.
fprintf(['Average time using GPU arrayfun: %2.3fms per generation ', ...
'(%1.1fx faster).\n'], ...
6-115
6 GPU Computing
1000*gpuArrayfunTime/numGenerations, cpuTime/gpuArrayfunTime);
assert(isequal(grid, expectedResult));
Average time using GPU arrayfun: 0.795ms per generation (14.2x faster).
Note that we also used another new feature of arrayfun here: dimension expansion. We needed to
pass only the row and column vectors, and these were automatically expanded into the full grid. The
effect is as though we called:
[cols,rows] = meshgrid(cols,rows);
as part of the arrayfun call. This saves us both some computation and some data transfer between
CPU memory and GPU memory.
Conclusion
In this example, a simple stencil operation, Conway's "Game of Life", has been implemented on the
GPU using arrayfun and variables declared in the parent function. This technique can be used to
implement a range of stencil operations including finite-element algorithms, convolutions, and filters.
It can also be used to access elements in a look-up table defined in the parent function.
end
See Also
gpuArray | mexcuda | gputimeit
Related Examples
• “Accessing Advanced CUDA Features Using MEX” on page 6-129
• “Illustrating Three Approaches to GPU Computing: The Mandelbrot Set” on page 6-82
More About
• “Run MEX Functions Containing CUDA Code” on page 6-124
6-116
Run CUDA or PTX Code on GPU
1 Compile a parallel thread execution (PTX) file from a CU file using mexcuda. You do not need the
CUDA Toolkit to compile a PTX file using mexcuda.
Use the nvcc compiler in the NVIDIA CUDA Toolkit to compile a PTX file instead of the mexcuda
function.
2 Use the [Link] function to create a CUDAKernel object from the CU file
and the PTX file. The CUDAKernel contains the GPU executable code.
3 Set the properties of the CUDAKernel to control its execution on the GPU.
4 Call feval on the CUDAKernel with the required inputs, to run the kernel on the GPU.
MATLAB code that follows these steps might look something like this:
result = feval(k,g1,g2);
The following sections provide details of these commands and workflow steps.
k = [Link]("[Link]","[Link]");
6-117
6 GPU Computing
When you create a CUDAKernel object without a terminating semicolon, or when you type the object
variable at the command line, MATLAB displays the kernel object properties.
k = [Link]("[Link]","[Link]")
k =
[Link] handle
Package: [Link]
Properties:
ThreadBlockSize: [1 1 1]
MaxThreadsPerBlock: 512
GridSize: [1 1 1]
SharedMemorySize: 0
EntryPoint: '_Z8theEntryPf'
MaxNumLHSArguments: 1
NumRHSArguments: 2
ArgumentTypes: {'in single vector' 'inout single vector'}
The properties of a CUDAKernel object control some of its execution behavior. Use dot notation to
alter the properties that can be changed. For a descriptions of the object properties, see
CUDAKernel. A typical reason for modifying the settable properties is to specify the number of
threads, as described below.
A single PTX file can contain multiple entry points to different kernels. Each of these entry points has
a unique name. The name of each entry point is mangled (as in C++ mangling) but always contains
the original function name from the CU file. For example, if the CU file defines the kernel function as
then the PTX code contains an entry that might be called _Z18simplestKernelEverPff.
When you have multiple entry points, specify the entry name for the particular kernel when calling
[Link] to generate your kernel.
k = [Link]("[Link]","[Link]","myKernel1");
Note The [Link] function searches for your entry name in the PTX file, and
matches on any substring occurrences. Therefore, you should not name any of your entry points as
substrings of any others.
You might not have control over the original entry names, in which case you must be aware of the
unique mangled derived for each. For example, consider the following function template.
6-118
Run CUDA or PTX Code on GPU
v1[idx] += v2[idx];
}
When the template is expanded out for float and double, it results in two entry points, both of which
contain the substring add4.
template __global__ void add4<float>(float *, const float *);
template __global__ void add4<double>(double *, const double *);
Use entry point add4If for the float version, and add4Id for the double version.
k = [Link]("[Link]","double *, const double *","add4Id");
You specify the number of computational threads for your CUDAKernel by setting two of its object
properties:
• GridSize — A vector of three elements, the product of which determines the number of blocks.
• ThreadBlockSize — A vector of three elements, the product of which determines the number of
threads per block. The product cannot exceed the value of the MaxThreadsPerBlock property.
The default value for both of these properties is [1 1 1], but suppose you want to use 500 threads
to run element-wise operations on vectors of 500 elements in parallel. Set the ThreadBlockSize
such that the product of its elements is 500.
k = [Link]("[Link]","[Link]");
[Link] = [500,1,1];
Generally, you set the grid and thread block sizes based on the sizes of your inputs. For information
on thread hierarchy, and multiple-dimension grids and blocks, see the NVIDIA CUDA C Programming
Guide.
Construct CUDAKernel Object with C Prototype Input
If you do not have the CU file corresponding to your PTX file, you can specify the C prototype for your
C kernel instead of the CU file. For example:
k = [Link]("[Link]","float *, const float *, float");
Another use for the C prototype input is when your source code uses an unrecognized renaming of a
supported data type. Suppose your kernel comprises the following code.
typedef float ArgType;
__global__ void add3( ArgType * v1, const ArgType * v2 )
{
int idx = threadIdx.x;
v1[idx] += v2[idx];
}
ArgType itself is not recognized as a supported data type, so the CU file that includes it cannot be
directly used as input when creating the CUDAKernel object in MATLAB. However, the supported
input types to the add3 kernel can be specified as C prototype input to the CUDAKernel constructor.
For example:
6-119
6 GPU Computing
Supported Datatypes
The supported C/C++ standard data types are listed in the following table.
ptrdiff_t, size_t
Also, the following integer types are supported when you include the tmwtypes.h header file in your
program.
Integer Types
int8_T, int16_T, int32_T, int64_T
Argument Restrictions
All inputs can be scalars or pointers, and can be labeled as constant values using const.
• The kernel must return nothing, and operate only on its input arguments (scalars or pointers).
• The kernel is unable to allocate any form of memory, so all outputs must be pre-allocated before
the kernel is executed. Therefore, the sizes of all outputs must be known before you run the
kernel.
• In principle, all pointers passed into the kernel that are not labelled const could contain output
data, since the many threads of the kernel could modify that data.
• All scalar inputs in C (double, float, int, etc.) must be scalars in MATLAB, or scalar (i.e.,
single-element) gpuArray variables.
• All constant pointer inputs in C (const double *, etc.) can be scalars or matrices in MATLAB.
They are cast to the correct type, copied onto the device, and a pointer to the first element is
6-120
Run CUDA or PTX Code on GPU
passed to the kernel. No information about the original size is passed to the kernel. It is as though
the kernel has directly received the result of mxGetData on an mxArray.
• All non-constant pointer inputs in C are transferred to the kernel exactly as non-constant pointers.
However, because a non-constant pointer could be changed by the kernel, this will be considered
as an output from the kernel.
• Inputs from MATLAB workspace scalars and arrays are cast into the requested type and then
passed to the kernel. However, gpuArray inputs are not automatically cast, so their type and
complexity must exactly match those expected.
These rules have some implications. The most notable is that every output from a kernel must
necessarily also be an input to the kernel, since the input allows the user to define the size of the
output (which follows from being unable to allocate memory on the GPU).
Run a CUDAKernel
Use the feval function to evaluate a CUDAKernel on the GPU.
Assume that you have already written some kernels and want to use them in MATLAB to execute on
the GPU. You have a kernel that does a convolution on two vectors; load and run it with two random
input vectors.
k = [Link]("[Link]","[Link]");
result = feval(k,rand(100,1),rand(100,1));
The output is a gpuArray even if the inputs are not. However, it might be more efficient to use
gpuArray objects as input when running a kernel.
k = [Link]("[Link]","[Link]");
i1 = rand(100,1,"single","gpuArray");
i2 = rand(100,1,"single","gpuArray");
result1 = feval(k,i1,i2);
Because the output is a gpuArray, you can now perform other operations using this input or output
data without further transfers between GPU memory and host memory.
When calling [out1, out2] = feval(kernel,in1,in2,in3), the inputs in1, in2, and in3
correspond to each of the input arguments to the function within your CU file. The outputs out1 and
out2 store the values of the first and second non-constant pointer input arguments to the function
after the kernel has been executed.
For example, if the kernel within a CU file has the following signature:
the corresponding kernel object (k) in MATLAB has the following properties:
MaxNumLHSArguments: 1
NumRHSArguments: 2
ArgumentTypes: {'inout single vector' 'in single scalar'}
6-121
6 GPU Computing
Therefore, to use the kernel object from this code with feval, you need to provide feval two input
arguments (in addition to the kernel object), and you can use one output argument.
y = feval(k,x1,x2)
The input values x1 and x2 correspond to pInOut and c in the function prototype. The output
argument y corresponds to the value of pInOut in the function prototype after the kernel has
executed.
The following is a slightly more complicated example that shows a combination of constant and non-
constant pointers:
void moreComplicated( const float * pIn, float * pInOut1, float * pInOut2 )
You can use feval on this code's kernel (k) using three input arguments and two output arguments.
[y1,y2] = feval(k,x1,x2,x3)
The three input arguments x1, x2, and x3, correspond to the three arguments that are passed into
the function. The output arguments y1 and y2, correspond to the values of pInOut1 and pInOut2
after the kernel has executed.
The directive __global__ indicates that this is an entry point to a kernel. The code uses a
pointer to send out the result in a, which is both an input and an output. Save this code in a file
called [Link] in the current directory.
2 Compile the CU code using mexcuda to generate a PTX file called [Link].
k = [Link]("[Link]","[Link]");
6-122
Run CUDA or PTX Code on GPU
4 Run the kernel with two numeric inputs. By default, a kernel runs on one thread.
result = feval(k,2,3)
result =
5
This example extends the previous one to add two vectors together. For simplicity, assume that there
are exactly the same number of threads as elements in the vectors and that there is only one thread
block.
1 The CU code is slightly different from the last example. Both inputs are pointers, and one is
constant because you are not changing it. Each thread will simply add the elements at its thread
index. The thread index must work out which element this thread should add. Getting these
thread- and block-specific values is a very common pattern in CUDA programming.
k = [Link]("[Link]","[Link]","add2");
4 Before you run the kernel, set the number of threads correctly for the vectors you want to add.
N = 128;
[Link] = N;
in1 = ones(N,1,"gpuArray");
in2 = ones(N,1,"gpuArray");
result = feval(k,in1,in2);
For an example that shows how to work with CUDA, and provides CU and PTX files for you to
experiment with, see “Illustrating Three Approaches to GPU Computing: The Mandelbrot Set” on
page 6-82.
See Also
mexcuda | CUDAKernel | feval
Related Examples
• “Run MEX Functions Containing CUDA Code” on page 6-124
• “Accessing Advanced CUDA Features Using MEX” on page 6-129
6-123
6 GPU Computing
In this section...
“Write MEX File Containing CUDA Code” on page 6-124
“Run Resulting MEX Functions” on page 6-124
“Compare to a CUDA Kernel” on page 6-125
“Access Complex Data” on page 6-125
“Compile GPU MEX File” on page 6-126
“Supported Host Compilers” on page 6-126
“Install CUDA Toolkit (Optional)” on page 6-126
You must call the mxInitGPU function at the entry to your MEX file to ensure that the GPU device is
properly initialized and known to MATLAB.
The interface you use to write a MEX file for gpuArray objects is different from the MEX interface
for standard MATLAB arrays.
You can see an example of a MEX file containing CUDA code here:
matlabroot/toolbox/parallel/gpu/extern/src/mex/[Link]
The file also contains these lines, which determine the array size and launch a grid of the proper size:
N = (int)(mxGPUGetNumberOfElements(A));
blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock;
TimesTwo<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, N);
6-124
Run MEX Functions Containing CUDA Code
x = ones(4,4,"gpuArray");
y = mexGPUExample(x)
y =
2 2 2 2
2 2 2 2
2 2 2 2
2 2 2 2
• MEX files can include calls to host-side libraries, including NVIDIA libraries such as the NVIDIA
performance primitives (NPP) or cuFFT libraries. MEX files can also contain calls from the host to
functions in the CUDA runtime library.
• MEX files can analyze the size of the input and allocate memory of a different size, or launch grids
of a different size, from C or C++ code. In contrast, MATLAB code that calls CUDAKernel objects
must preallocate output memory and determine the grid size.
Depending on the needs of your kernel, you can cast the pointer to complex data as the real type or
as the built-in vector type. For example, in MATLAB, suppose you create this matrix:
a = complex(ones(4,"gpuArray"),ones(4,"gpuArray"));
If you pass a gpuArray to a MEX function as the first argument prhs[0], then you can get a pointer
to the complex data by using these calls:
To treat the array as a real, double-precision array of twice the length, use these calls:
You can convert data between complex and real formats on the GPU using these Parallel Computing
Toolbox functions. These operations require a copy to interleave the data.
6-125
6 GPU Computing
• The mxGPUCopyReal and mxGPUCopyImag functions copy the real or the imaginary elements,
respectively, of an mxGPUArray to a single real mxGPUArray.
mexcuda [Link]
If mexcuda cannot locate nvcc, it might be installed in a nondefault location. You can specify the
location of nvcc on your system by storing it in the MW_NVCC_PATH environment variable. You can set
this variable using the setenv command. For example:
setenv("MW_NVCC_PATH","/usr/local/CUDA/bin")
1 Determine which version of CUDA your version of MATLAB uses by consulting the table in
“Install CUDA Toolkit (Optional)” on page 6-126.
2 Consult the NVIDIA CUDA Toolkit Documentation corresponding to the CUDA version
determined in step 1. The documentation lists the supported compilers in the installation guide
section.
Note You do not need the CUDA Toolkit to run MATLAB functions on a GPU or to generate CUDA-
enabled MEX functions.
The CUDA Toolkit contains CUDA libraries and tools for compilation.
Download the appropriate CUDA toolkit version for the version of MATLAB you are using. Check
which version of the toolkit is compatible with your version of MATLAB using this table.
Recommended best practice is to use the latest version of your supported CUDA Toolkit, including
any updates and patches from NVIDIA.
6-126
Run MEX Functions Containing CUDA Code
For more information about the CUDA Toolkit and to download your supported version, see CUDA
Toolkit Archive (NVIDIA).
See Also
mexcuda | CUDAKernel | mex
Related Examples
• “Accessing Advanced CUDA Features Using MEX” on page 6-129
6-127
6 GPU Computing
6-128
Accessing Advanced CUDA Features Using MEX
This example shows how advanced features of the GPU can be accessed using MEX files. It builds on
the example “Stencil Operations on a GPU” on page 6-112. The previous example uses Conway's
"Game of Life" to demonstrate how stencil operations can be performed using MATLAB® code that
runs on a GPU. The present example demonstrates how you can further improve the performance of
stencil operations using an advanced feature of the GPU: shared memory. You do this by writing your
own CUDA® code in a MEX file and calling the MEX file from MATLAB. You can find an introduction
to the use of the GPU in MEX files in “Run MEX Functions Containing CUDA Code” on page 6-124.
As defined in the previous example, in a "stencil operation", each element of the output array
depends on a small region of the input array. Examples include finite differences, convolution, median
filtering, and finite-element methods. If the stencil operation is a key part of your workflow, you can
convert it to a hand-written CUDA kernel. This example uses Conway's "Game of Life" as our stencil
operation and moves the calculation into a MEX file. The "stencil" in this case is therefore the 3x3
region around each element.
Create an initial population of cells on a 2-D grid with approximately 25% of the locations alive.
gridSize = 500;
numGenerations = 200;
initialGrid = (rand(gridSize,gridSize) > .75);
hold off
imagesc(initialGrid);
colormap([1 1 1;0 0.5 0]);
title('Initial Grid');
6-129
6 GPU Computing
To get a performance baseline, start with the initial implementation described in Experiments in
MATLAB. Run this implementation on the GPU by making sure the initial population is on the GPU
using gpuArray. The function updateGrid is provided at the end of this example. updateGrid
counts how many neighbors are alive and decides whether a cell will be alive at the next step.
currentGrid = gpuArray(initialGrid);
% Loop through each generation updating the grid and displaying it
for generation = 1:numGenerations
currentGrid = updateGrid(currentGrid, gridSize);
imagesc(currentGrid);
title(num2str(generation));
drawnow;
end
6-130
Accessing Advanced CUDA Features Using MEX
Re-run the game and measure how long it takes for each generation. In order to time the entire game
using gputimeit, a function that calls each generation, callUpdateGrid, is provided at the end of
this example.
gpuInitialGrid = gpuArray(initialGrid);
When writing a CUDA kernel version of the stencil operation, you have to split the input data into
blocks on which each thread block can operate. Each thread in the block will be reading data that is
also needed by other threads in the block. One way to minimize the number of read operations is to
copy the required input data into shared memory before processing. This copy must include some
neighboring elements to allow correct calculation of the block edges. For the Game of Life, where the
stencil is just a 3x3 square of elements, you need a one element boundary. For example, for a 9x9 grid
processed using 3x3 blocks, the fifth block would operate on the orange highlighted region, where
the yellow elements are the "halo" it must also read.
6-131
6 GPU Computing
The CUDA code that illustrates this approach is shown in the supporting file
pctdemo_life_cuda_shmem.cu. To access this supporting file, open this example as a live script.
The CUDA device function in this file operates as follows:
1 All threads copy the relevant part of the input grid into shared memory, including the halo.
2 The threads synchronize with one another to ensure shared memory is ready.
3 Threads that fit in the output grid perform the Game of Life calculation.
The host code in this file invokes the CUDA device function once for each generation, using the CUDA
runtime API. It uses two different writable buffers for the input and output. At every iteration, the
MEX file swaps the input and output pointers so that no copying is required.
In order to call the function from MATLAB, you need a MEX gateway that unwraps the input arrays
from MATLAB, builds a workspace on the GPU, and returns the output. The MEX gateway function
can be found in the supporting file pctdemo_life_mex_shmem.cpp.
To call your own MEX file, you must first compile it using mexcuda. Compile
pctdemo_life_cuda_shmem.cu and pctdemo_life_mex_shmem.cpp into a MEX function named
pctdemo_life_mex_shmem.
% Calculate the output value using the MEX file with shared memory. The
% initial input value is copied to the GPU inside the MEX file
grid = pctdemo_life_mex_shmem(initialGrid, numGenerations);
gpuMexTime = gputimeit(@()pctdemo_life_mex_shmem(initialGrid, ...
numGenerations));
% Print out the average computation time and check the result is unchanged
6-132
Accessing Advanced CUDA Features Using MEX
assert(isequal(grid, expectedResult));
Conclusion
This example has illustrated a method of reducing the number of read operations by explicitly
copying blocks into shared memory before processing. The performance improvement obtained using
this method will depend on the size of the stencil, the size of the overlap region, and the capabilities
of your GPU. You can use this approach in conjunction with your MATLAB code to optimize your
application.
Using MEX with shared memory: 0.007ms per generation (72.5x faster).
Supporting Functions
This updateGrid function updates the 2-D grid according to how many neighbors are alive.
function X = updateGrid(X, N)
p = [1 1:N-1];
q = [2:N N];
% Count how many of the eight neighbors are alive
neighbors = X(:,p) + X(:,q) + X(p,:) + X(q,:) + ...
X(p,p) + X(q,q) + X(p,q) + X(q,p);
% A live cell with two live neighbors, or any cell with
% three live neighbors, is alive at the next step
X = (X & (neighbors == 2)) | (neighbors == 3);
end
See Also
gpuArray | mexcuda | gputimeit
Related Examples
• “Stencil Operations on a GPU” on page 6-112
• “Illustrating Three Approaches to GPU Computing: The Mandelbrot Set” on page 6-82
6-133
6 GPU Computing
More About
• “Run MEX Functions Containing CUDA Code” on page 6-124
6-134
7
If your computing task is too big or too slow for your local computer, you can offload your calculation
to a cluster onsite or in the cloud to run your MATLAB code with minimal changes. Try Parallel >
Discover Clusters in the MATLAB toolstrip to find out if you already have a cluster available.
If you already have a cluster with a scheduler, you can integrate MATLAB with it using MATLAB
Parallel Server. Alternatively, if you do not have an existing scheduler, then MATLAB Parallel Server
provides MATLAB Job Scheduler.
In this section...
“Create and Manage Cluster Profiles” on page 7-2
“Discover Clusters” on page 7-3
“Create Cloud Cluster” on page 7-5
“Add and Modify Cluster Profiles” on page 7-5
“Import and Export Cluster Profiles” on page 7-9
“Edit Number of Workers and Cluster Settings” on page 7-10
“Use Your Cluster from MATLAB” on page 7-10
Parallel Computing Toolbox comes pre-configured with the cluster profiles Processes and Threads
for running parallel code on your local desktop machine.
Control parallel behavior using the Parallel menu on the MATLAB Home tab.
• Discover other clusters running on your network or on Cloud Center. Click Parallel > Discover
Clusters. For more information, see “Discover Clusters” on page 7-3.
• Create and manage cluster profiles using the Cluster Profile Manager. Click Parallel > Create
and Manage Clusters. For more information, see “Create and Manage Cluster Profiles” on page
7-2.
• batch
• parpool
• parcluster
7-2
Discover Clusters and Use Cluster Profiles
Manage cluster profiles using the Cluster Profile Manager. To open the Cluster Profile Manager, on
the Home tab, in the Environment section, select Parallel > Create and Manage Clusters.
• Discover other clusters running on your network or on Cloud Center. For more information, see
“Discover Clusters” on page 7-3.
• Create a cluster in the cloud, such as Amazon AWS. For more information, see “Create Cloud
Cluster” on page 7-5.
• Add cluster profiles and modify their properties. For more information, see “Add and Modify
Cluster Profiles” on page 7-5.
• Import and export cluster profiles. For more information, see “Import and Export Cluster Profiles”
on page 7-9.
• Specify profile properties. For more information, see “Edit Number of Workers and Cluster
Settings” on page 7-10.
• Validate that a cluster profile is ready for use in MATLAB.
Discover Clusters
You can let MATLAB discover clusters for you. Use either of the following techniques to discover
those clusters which are available for you to use:
• On the Home tab in the Environment section, select Parallel > Discover Clusters
• In the Cluster Profile Manager, select Discover Clusters
This opens the Discover Clusters dialog box, where you can search for MATLAB Parallel Server
clusters:
7-3
7 Clusters and Clouds
If you select On your network, you see a new window. Select this option if your clusters use a
MATLAB Job Scheduler, Microsoft Windows HPC server or other third-party scheduler cluster. As
clusters are discovered, they populate a list for your selection. If you already have a profile for any of
the listed clusters, those profile names are included in the list. If you want to create a new profile for
one of the discovered clusters, select the name of the cluster you want to use, and select Next. The
subsequent dialog box lets you choose if you want to set the created profile as your default. This
option is not supported in MATLAB Online.
If you select On MathWorks Cloud Center, you search for clusters running on Cloud Center. To
access these clusters, you must provide your MathWorks Account login information.
Cluster discovery is supported for MATLAB Job Schedulers, Microsoft Windows HPC server clusters,
other third-party scheduler clusters, and MathWorks Cloud Center clusters. If you need to integrate
your scheduler with MATLAB Parallel Server, or create a cluster profile for a different supported
scheduler, see “Installation” (MATLAB Parallel Server). The following requirements apply to cluster
discovery:
• MATLAB Job Scheduler — MATLAB Job Scheduler clusters support two different means of
discovery:
• Multicast: The discover clusters functionality uses the multicast networking protocol from the
client to search for head nodes where a MATLAB Job Scheduler is running. This requires that
the multicast networking protocol is enabled and working on the network that connects the
MATLAB Job Scheduler head nodes (where the schedulers are running) and the client
machines. This form of discovery might be limited to the client local subnet, and therefore not
always able to discover a MATLAB Job Scheduler elsewhere in your network.
• DNS SRV: An alternative discovery technique is to search for clusters by DNS service records.
The Domain Name System (DNS) is a standard for identifying host names with IP addresses,
either on the Internet or in a private network. Using DNS allows discovery of MATLAB Job
Scheduler clusters by identifying specific hosts rather than broadcasting across your network.
7-4
Discover Clusters and Use Cluster Profiles
A DNS service (SRV) record defines the location of hosts and ports of services, such as those
related to the clusters you want to discover. Your system administrator creates DNS SRV
records in your organization's DNS infrastructure. For a description of the required record,
and validation information, see “DNS SRV Record” (MATLAB Parallel Server).
• HPC Server — The discover clusters functionality uses Active Directory Domain Services to
discover head nodes. HPC Server head nodes are added to the Active Directory during installation
of the HPC Server software.
• Third-party Schedulers – The discover clusters functionality uses a configuration file to discover
third-party scheduler clusters. For more information, see “Configure for Third-Party Scheduler
Cluster Discovery” (MATLAB Parallel Server).
• Cloud Center — The discover clusters functionality requires a working network connection
between the client and the Cloud Center web services running in [Link].
Sign up with your MathWorks Account and complete the required steps. Then, you can create a cloud
cluster and configure parameters, such as the number of machines or the number of workers per
machine. For more information on each of the available parameters, see Create a Cloud Cluster.
When you complete all the steps, MATLAB creates a new cluster profile for you. You can modify its
properties from the Cluster Profile Manager.
To manage your licenses, test cloud connectivity, or manage your cloud clusters in MathWorks Cloud
Center, go to Cluster Profile Manager toolstrip > CLOUD section.
The following example provides instructions on how to add and modify profiles using the Cluster
Profile Manager.
Suppose you want to create a profile to set several properties for jobs to run in a MATLAB Job
Scheduler cluster. The following example illustrates a possible workflow, where you create two
profiles differentiated only by the number of workers they use.
1 In the Cluster Profile Manager, select Add Cluster Profile > MATLAB Job Scheduler. This
specifies that you want a new profile for a MATLAB Job Scheduler cluster.
7-5
7 Clusters and Clouds
In the Description field, enter the text MJS with 4 workers, as shown in the following figure.
Enter the host name for the machine on which the MATLAB Job Scheduler is running, and the
name of the MATLAB Job Scheduler. If you are entering information for an actual MATLAB Job
Scheduler already running on your network, enter the actual names. If you are unsure about the
MATLAB Job Scheduler names and locations on your network, ask your system administrator for
help.
7-6
Discover Clusters and Use Cluster Profiles
Note If the MATLAB Job Scheduler is using a nondefault BASE_PORT setting as defined in the
mjs_def file, the Host property in the cluster profile must be appended with this BASE_PORT
number. For example, MJS-Host:40000.
4 Scroll down to the Workers section, and for the Range of number of workers, enter the two-
element vector [4 4]. This specifies that jobs using this profile require at least four workers and
no more than four workers. Therefore, a job using this profile runs on exactly four workers, even
if it has to wait until four workers are available before starting.
7-7
7 Clusters and Clouds
You might want to edit other properties depending on your particular network and cluster
situation.
5 Select Done to save the profile settings.
To create a similar profile with just a few differences, you can duplicate an existing profile and modify
only the parts you need to change, as follows:
1 In the Cluster Profile Manager, right-click the profile name MyMJSProfile1 in the list and select
Duplicate.
This creates a duplicate profile with a name based on the original profile name appended with
_Copy.
2 Double-click the new profile name and edit its name to be MyMJSprofile2.
3 Select Edit to allow you to change the profile property values.
4 Edit the description field to change its text to MJS with any workers.
5 Scroll down to the Workers section, and for the Range of number of workers, clear the [4 4]
and leave the field blank.
6 Select Done to save the profile settings and to close the properties editor.
You now have two profiles that differ only in the number of workers required for running a job.
When creating a job, you can apply either profile to that job as a way of specifying how many workers
it should run on.
7-8
Discover Clusters and Use Cluster Profiles
You can see examples of profiles for different kinds of supported schedulers in the MATLAB Parallel
Server installation instructions at “Configure Your Cluster” (MATLAB Parallel Server).
1 In the Cluster Profile Manager, select (highlight) the profile you want to export.
2 Select Export > Export. (Alternatively, you can right-click the profile in the listing and select
Export.)
If you want to export all your profiles to a single file, select Export > Export All.
3 In the Export profiles to file dialog box, specify a location and name for the file. The default file
name is the same as the name of the profile it contains, with a .mlsettings extension
appended; you can alter the names if you want to.
Note that you cannot export profiles for Cloud Center personal clusters.
Profiles saved in this way can then be imported by other MATLAB users:
The imported profile appears in your Cluster Profile Manager list. Note that the list contains the
profile name, which is not necessarily the file name. If you already have a profile with the same
name as the one you are importing, the imported profile gets an extension added to its name so
you can distinguish it.
You can also export and import profiles programmatically with the [Link] and
[Link] functions.
You can use an exported profile with MATLAB Compiler and MATLAB Compiler SDK to identify
cluster setup information for running compiled applications on a cluster. For example, the
setmcruserdata function can use the exported profile file name to set the value for the key
ParallelProfile. For more information and examples of deploying parallel applications, see “Pass
Parallel Computing Toolbox Profile at Run Time” (MATLAB Compiler), and “Use Parallel Computing
Toolbox in Deployed Applications” (MATLAB Compiler SDK).
A compiled application has the same default profile and the same list of alternative profiles that the
compiling user had when the application was compiled. This means that in many cases the profile file
is not needed, as might be the case when using the Processes profile for local workers. If an
exported file is used, the first profile in the file becomes the default when imported. If any of the
imported profiles have the same name as any of the existing profiles, they are renamed during import
(though their names in the file remain unchanged).
7-9
7 Clusters and Clouds
• NumWorkers: the number of workers to start a pool. The actual pool size might be limited by
licensing, cluster size, and cluster profile settings. See “Factors That Affect Pool Size” on page 1-
32
• NumThreads: the number of computational threads to use on each worker. You can change
NumThreads, so that your workers can run in multithreaded mode and use all the cores on your
cluster. This allows you to increase the number of computational threads NumThreads on each
worker, without increasing the number of workers NumWorkers. If you have more cores available,
increase NumThreads to take full advantage of the built-in parallelism provided by the
multithreaded nature of many of the underlying MATLAB libraries. For details, see Run MATLAB
on multicore and multiprocessor machines.
Note Do not increase the number of threads across all workers on a machine to exceed the
number of physical cores. In other words, make sure that NumWorkers x NumThreads ≤ number
of physical cores on your machine. Otherwise you might have reduced performance.
To set a cluster profile as the default, use one of the following ways:
• On the Home tab in the Environment section, select Parallel > Select Parallel Environment,
and from there, all your profiles are available. The default profile is indicated. You can select any
profile in the list as the default.
• The Cluster Profile Manager indicates which is the default profile. You can select any profile in the
list, then select Set as Default.
• You can get or set the default profile programmatically by using the
[Link] function. The following sets of commands achieve the
same thing:
[Link]('MyMJSProfile1')
parpool
or
parpool('MyMJSProfile1')
The parcluster function creates a cluster object in your workspace according to the specified
profile. The profile identifies a particular cluster and applies property values. For example,
c = parcluster('MyMJSProfile1')
This command finds the cluster defined by the settings of the profile named MyMJSProfile1 and
sets property values on the cluster object based on settings in the profile. Use a cluster object in
7-10
Discover Clusters and Use Cluster Profiles
functions such as parpool or batch. By applying different profiles, you can alter your cluster
choices without changing your MATLAB application code.
See Also
batch | parpool | parcluster | createJob | setmcruserdata | [Link] |
[Link] | [Link]
Related Examples
• “Run Code on Parallel Pools” on page 1-28
• “Scale Up from Desktop to Cluster” on page 7-49
• “Pass Parallel Computing Toolbox Profile at Run Time” (MATLAB Compiler)
• “Use Parallel Computing Toolbox in Deployed Applications” (MATLAB Compiler SDK)
• “Verify Network Communications for Cluster Discovery” (MATLAB Parallel Server)
More About
• “Installation” (MATLAB Parallel Server)
• “Clusters and Clouds”
External Websites
• [Link]
• [Link]
7-11
7 Clusters and Clouds
Use the Cluster Profile Manager to manage cluster profiles. To set the EnvironmentVariables
property for a cluster profile using the Cluster Profile Manager, use the following steps.
1 Open the Cluster Profile Manager. To open the Cluster Profile Manager, on the Home tab in the
Environment section, select Parallel > Create and Manage Clusters.
2 In the Cluster Profile Manager, select your cluster in the Cluster Profile list. For this example,
select the MyMJSProfile1 cluster.
3 Go to the Workers section. Add the names of environment variables you want to copy from the
client to cluster workers. Use one name per line, with no commas or other delimiters. Any listed
variables that are not set are not copied to the workers.
4 Click Done to save the profile settings.
7-12
Set Environment Variables on Workers
For more information about the Cluster Profile Manager, see “Update MATLAB Job Scheduler Startup
Parameters” (MATLAB Parallel Server).
• When you use createJob or batch to create a job, you can specify the names of environment
variables by using the 'EnvironmentVariables' name-value pair argument. These
environment variables are set on the workers when the job starts. When the job finishes, the
environment variables are returned to their previous values.
• When you use batch to create a parallel pool, you can specify the names of environment variables
by using the 'EnvironmentVariables' name-value pair argument. These environment
variables are set on the workers for the duration of the parallel pool.
See Also
createJob | batch | parpool
More About
• “Create and Manage Cluster Profiles” on page 7-2
• “Update MATLAB Job Scheduler Startup Parameters” (MATLAB Parallel Server)
7-13
7 Clusters and Clouds
Both the original pool and its partitions share the same underlying collection of workers, meaning
using one pool can delay the execution of work on another. Pool partitions inherit some properties
from the original pool and changes to these properties apply to all partitions:
• AttachedFiles
• FileStore
• ValueStore
• IdleTimeout
Pool partitions provide flexibility in managing and optimizing resource use. The information in this
table helps you to decide which pool partitioning strategy to use.
7-14
Partition Parallel Pools to Optimize Resource Use
The following sections describe advanced workflows that demonstrate the full potential of pool
partitioning. While pool partitioning can be useful for specific use cases, you might not need to use
them in typical scenarios.
7-15
7 Clusters and Clouds
7-16
Partition Parallel Pools to Optimize Resource Use
This example shows how to partition a dedicated GPU parallel pool from an existing interactive
parallel pool. For GPU intensive applications like deep learning, creating a GPU only pool dedicates
resources to these applications.
In this example, the gpuCluster profile requests a parallel pool with four GPUs. Start a parallel pool
of 16 workers using the gpuCluster profile.
pool = parpool("gpuCluster",16);
Use the partition function to create a pool partition with one worker for each available GPU for
best performance.
gpuPool = partition(pool,"MaxNumWorkersPerGPU",1);
You can now use the gpuPool pool partition for workflows that require multiple GPUs.
For example, if you have Deep Learning Toolbox, you can use a parfor-loop to train multiple deep
learning networks in parallel on the GPU pool partition. This code snippet shows how to perform a
parallel parameter sweep of mini-batch sizes by training several networks inside a parfor-loop. To
run the parfor-loop on the gpuPool pool partition, specify the gpuPool pool object as the second
argument to the parfor function. To try an example showing how to train multiple networks using
parfor, see “Use parfor to Train Multiple Deep Learning Networks” (Deep Learning Toolbox).
parfor(idx = 1:numMiniBatchSizes,gpuPool)
miniBatchSize = miniBatchSizes(idx);
% trainedNetworks{idx} = trainnet(...,options);
end
This example shows how to partition pools for GPU and CPU tasks and run code on both pools
simultaneously.
In this example, you have a GPU on your local machine. You can partition a pool for the GPU worker
and another pool for the CPU workers.
Use the partition function to create a pool partition with one worker for the available GPU. Also
return a pool partition with the remaining workers that do not have access to a GPU.
[gpuPool,cpuPool] = partition(pool,"MaxNumWorkersPerGPU",1);
7-17
7 Clusters and Clouds
Define a function that models the growth of a population by iterating a logistics map equation.
Submit a parfeval computation to run the populationGrowth function on the gpuPool pool
partition. parfeval does not block MATLAB, which means you can continue executing commands.
f = parfeval(gpuPool,@populationGrowth,2,200000,1000);
While the parfeval computation is running on the GPU in the background, run a parfor-loop on
the remaining workers in the cpuPool pool partition. Specify the cpuPool object as the second
argument to the parfor function.
M = 100;
N = 1e6;
data = rand(M,N);
parfor(idx = 1:M,cpuPool)
out(idx) = sum(data(idx,:))./N;
end
Collect the results from the parfeval computation when it is ready using the fetchOutputs
function. The fetchOutputs function waits until the future finishes.
[x,r] = fetchOutputs(f);
7-18
Partition Parallel Pools to Optimize Resource Use
7-19
7 Clusters and Clouds
When your workflow requires running setup code for every host machine that runs the workers in the
pool, partitioning the pool by host allows you to run the setup code only once for each host. This
example shows how to run a custom setup function for each host in the pool.
Start a parallel pool of 64 workers using the remote cluster profile myCluster.
myClusterPool = parpool("myCluster",64);
Create a pool partition from the myClusterPool with one worker per host.
hostPool = partition(myClusterPool,"MaxNumWorkersPerHost",1);
Use the parfevalOnAll function to run the downloadData helper function asynchronously on all
workers in the hostPool pool. Wait for the future to complete and check for errors from the workers
using the fetchOutputs function. The downloadData function is attached to this example as a
supporting file.
fSetup = parfevalOnAll(hostPool,@downloadData,1);
fetchOutputs(fSetup)
This example shows how to maximize the memory available on an existing interactive parallel pool for
data intensive computations.
The performance of data intensive computations greatly depends on matrix size. When performing
data intensive computations on cluster pools, computations become inefficient if matrices occupy
50% or more of the system memory available to each worker. If a matrix size exceeds this threshold,
you can experience a performance decrease as the operating system begins swapping memory to
disk. When your data parallel computation requires more memory than what is available to the
workers in your pool, consider decreasing the number of workers per host in your pool using the
partition function. Although this results in a pool partition with fewer workers, each worker has
access to more system memory for data intensive computations.
Start a parallel pool of 16 workers using the remote cluster profile myCluster. In this example,
assume every worker has access to 8 GB of system memory. You can use this pool to run general
parallel computations.
poolSize = 16;
pool = parpool("myCluster",poolSize);
7-20
Partition Parallel Pools to Optimize Resource Use
To perform some data intensive work without creating a new pool, you can increase the amount of
memory available to each worker using these steps.
Determine the number of unique hosts in the pool and the number of workers running on each host
and summarize the results in a table. The table indicates the parallel pool has two unique hosts and
eight workers per host.
allWkrs = [Link];
hostnames = {[Link]}';
[hostnames,ia,ic] = unique(hostnames);
numWorkers = accumarray(ic,1);
workersPerHost = table(hostnames,numWorkers)
workersPerHost=2×2 table
hostnames numWorkers
_________________________ __________
"[Link]" 8
"[Link]" 8
Use the information in the table to plan how to partition the pool. For example, to increase the
memory available to each worker to 16 GB, you require a pool with four workers from each host
instead of eight. Use the partition function to create a pool partition with four workers per host.
Display the size of the new highMemPool partition.
highMemPool = partition(pool,"MaxNumWorkersPerHost",4);
highMemPoolSize = [Link]
highMemPoolSize =
8
Calculate the memory available to the workers in the pool partition. Each worker in the
highMemPool partition now has access to 16 GB of memory.
memoryPerWorker = 8; % In GB
totalMemory = memoryPerWorker*poolSize;
newMemoryPerWorker = totalMemory/highMemPoolSize
newMemoryPerWorker =
16
Define the size of the largest array you can run on each worker, which corresponds to 45% of the
memory available to each worker in the pool partition.
You can now run computations with arrays of up to 87926-by-87926 on the workers of the
highMemPool partition.
For example, to run data intensive computations using distributed arrays on the pool partition,
specify the highMemPool pool object to the spmd function.
7-21
7 Clusters and Clouds
spmd(highMemPool)
A = rand(maxMatSize,"codistributed");
b = rand(maxMatSize,1,"codistributed");
x = A\b;
end
This example shows how to partition and setup workers of an existing interactive parallel pool for
multithreaded computations.
Some MATLAB functions by default make use of multithreading on machines with many cores,
increasing computational efficiency. Computations that use these functions perform better when
multiple threads are available than on a single thread. Parallel pool workers use a single
computational thread by default, as they typically associate with a single core. If the MATLAB
functions in your code benefit from implicit multithreading, you can partition a pool with fewer
workers per host and increase the number of computational threads on the workers to leverage the
built-in parallelism. Although this process results in a pool with fewer workers, each worker can
perform multithreaded computations which can increase computation efficiency.
Start a parallel pool of 16 workers using the remote cluster profile myCluster.
poolSize = 16;
pool = parpool("myCluster",poolSize);
If you need this same pool to perform multithreaded computations, you can increase the maximum
number of computational threads on each worker by following these steps.
Determine the number of unique hosts in the pool and the number of workers running on each host,
and summarize the results in a table. Use the information in the table to plan how to partition the
pool.
allWkrs = [Link];
hostnames = {[Link]}';
[uniqueHosts,~,hostIndices] = unique(hostnames);
numWorkers = accumarray(hostIndices,1);
hostWorkers = table(uniqueHosts,numWorkers)
hostWorkers=4×2 table
uniqueHosts numWorkers
____________________________ __________
{'[Link]'} 4
{'[Link]'} 4
{'[Link]'} 4
{'[Link]'} 4
The number of threads across all the workers in the new pool partition must not exceed the maximum
number of workers in the original pool, otherwise you might observe reduced performance.
The table indicates that, for this parallel pool, all hosts have the same number of workers. You can
apply a simple logic by dividing the number of workers on each host by the desired threads per
7-22
Partition Parallel Pools to Optimize Resource Use
worker to find the minimum number of workers per host needed to achieve the required number of
threads per worker.
Determine the minimum number of workers for the partition pool that results in four threads per
worker.
threadsPerWorker = 4;
workersPerHost = ceil(min([Link]/threadsPerWorker))
workersPerHost =
1
multiThreadsPool = partition(pool,"MaxNumWorkersPerHost",workersPerHost);
In cases where workers are unevenly distributed across hosts, you must implement additional logic to
select a specific number of workers from each host using the Workers argument of the partition
function. For an example of a more robust partitioning logic to handle uneven distributions across
hosts, see the unevenHostPartitioning supporting file attached to this example.
To setup the workers for multithreaded computations, increase the maximum number of
computational threads for all workers in the pool partition. Use the parfevalOnAll function to
execute the maxNumCompThreads function with the specified number of threads per worker across
all workers in the pool partition. Retain a copy of the previous maximum number of computational
threads on the workers.
You can now run multithreaded computations on the workers of the multiThreadsPool partition.
For example, to run parfor computations on the pool partition, pass the multiThreadsPool pool
object as the second input argument to parfor.
N = randn(5000);
numIterations = 10;
parfor (idx = 1:numIterations,multiThreadsPool)
out = N*N;
end
When you have completed your multithreaded computations, reset the maximum number of
computational threads for all workers in the pool partition. Use the parfevalOnAll function to
execute the maxNumCompThreads function with the previous maximum number of computational
threads on all workers in the pool partition. Wait for the future to complete and check for errors from
the workers using the fetchOutputs function.
setNumCompThreads = parfevalOnAll(multiThreadsPool,@maxNumCompThreads,0,lastThreads(1));
fetchOutputs(setNumCompThreads)
7-23
7 Clusters and Clouds
computation, partitioning a single worker pool helps you keep track of the specific worker, and also
allows you to use the worker for other parallel work when needed.
7-24
Partition Parallel Pools to Optimize Resource Use
7-25
7 Clusters and Clouds
This example shows how to partition a worker from an existing interactive parallel pool, to keep and
access a large dataset in the memory of the worker. Use this approach to minimize data transfer
between the client and pool workers.
In this example, you create a large voxel image volume on an interactive pool of 10 cluster workers.
Each worker stores 500-by-500-by-500 matrix in memory. If you do not have access to cluster workers
or if your machine does not have enough memory to create and store the 3 GB volume, decrease the
imSize variable before running this example.
Start a parallel pool of 10 workers using the myCluster remote cluster profile.
pool = parpool("myCluster",10);
In a spmd statement, create a simulated voxel image of bubbles using the workers of the parallel
pool. Display a subset of the image.
spmd
V = rand(imSize,"single");
BW = false(size(V));
BW(V < 0.000001) = true;
V = bwdist(BW);
V(V <= 20) = 1;
V(V > 20) = 0;
end
volshow(V{1})
7-26
Partition Parallel Pools to Optimize Resource Use
spmd
V = spmdCat(V,3,1);
end
Now, partition a pool with the worker that stores the voxel image in memory, specifically the worker
whose spmdIndex is 1.
Use the getCurrentWorker function in an spmd statement to identify the workers in the pool. The
getCurrentWorker function returns a Composite with a [Link] object for each
worker in the pool.
spmd
wkrs = getCurrentWorker;
end
Partition a pool using the [Link] object for the worker whose spmdIndex is 1.
dataWkrPool = partition(pool,"Workers",wkrs{1});
To access the voxel image in a parfor-loop or parfeval computation, create a Constant object
with the Composite object of the voxel image, V.
V = [Link](V);
You can now access the data on the worker in a parfor-loop or parfeval computation.
7-27
7 Clusters and Clouds
For example, use parfeval to perform some image processing on the dataWkrPool single worker
pool partition using Image Processing Toolbox™ functions. Define a function to count the number of
bubbles and volume of each bubble in the voxel image. Specify the dataWkrPool pool partition and
the voxel image Constant objects to the parfeval function. Retrieve the results.
f = parfeval(dataWkrPool,@myBubbleFunction,2,V);
[numBubbles,bubbleVolumes] = fetchOutputs(f)
numBubbles =
645
bubbleVolumes = 1×645
This example shows how to partition a worker from an existing parallel pool, and use the worker to
maintain the same database connection to import image data from a database for processing.
When workflows require unique resources, such as database connections or connection to hardware,
assigning these to specific workers ensures that you can easily and repeatedly access the resources
when needed. To use any handle-type resources such as file handles, database and hardware
connections on a parallel pool, it is recommended that you create the handle-type resource for each
worker in the pool using a [Link] object. For database connections, this also
means the database has to bear the overhead of maintaining multiple connections with the different
workers in your pool.
If you are unable to create a database connection for each worker in your pool, you can use this
approach to maintain a database connection on a specific worker that you can repeatedly access.
Start a pool of thread workers on your local machine. Thread-based pools are optimized for less data
transfer, faster scheduling, and reduced memory usage, so they can result in a performance gain in
applications that involve a lot of data transfer between workers.
pool = parpool("Threads");
Use the Workers property of the pool object to obtain the [Link] objects of the workers
in the pool. Partition the pool to isolate the first worker in the allWkrs array.
allWkrs = [Link];
dBWkrPool = partition(pool,"Workers",allWkrs(1));
7-28
Partition Parallel Pools to Optimize Resource Use
Create a Constant object for the database connection using the connectToDatabase helper
function. If you have Database Toolbox™, you can use the database (Database Toolbox) function to
connect to a database. The connectToDatabase helper function is attached to this example as a
supporting file.
cDbase = [Link](@() connectToDatabase("Database"));
Define a function to create and maintain a connection to the database. To run this example, the
getDbaseData function simulates creating a connection to a database and stores the connection in
the Value property of the Constant object. The function also simulates importing data using the
same database connection each time it runs on the worker. If you have Database Toolbox, you can use
the fetch (Database Toolbox) function to import data from a database. The fetchQuery helper
function is attached to this example as a supporting file.
function imgs = getDbaseData(C,query)
conn = [Link];
imgs = fetchQuery(conn,query);
end
Specify queries for the database. Create a Constant object for the image processing filter.
imageNames = ["outdoors" "indoors" "daytime" "nightime"];
sqlqueries = "SELECT * FROM " + imageNames;
cFilter = [Link](randn(16,1));
To import data, schedule the getDbaseData function to run asynchronously with parfeval on the
dBWkrPool pool partition. By specifying the dBWkrPool partition to the parfeval function, the
same worker always runs the getDbaseData function, using the same database connection from the
Constant object to import the data.
fImport = parfeval(dBWkrPool,@getDbaseData,1,cDbase,sqlqueries(1));
In a loop, import the data using parfeval and process the imported data in a parfor-loop. To
minimize the time the workers wait to receive data, stagger the data import and processing
computations.
for j = 1:length(sqlqueries)
% Fetch data asynchronously
data = fetchOutputs(fImport); % Wait for the data to be fetched
% Schedule the next parfeval computation to run in the background.
if j < length(imageNames)
fImport = parfeval(dBWkrPool,@getDbaseData,1,cDbase,sqlqueries(j+1));
end
parfor k=1:size(data,2)
% Zero-pad filter to the length of data, and transform
[rows,~] = size(data);
filterF = fft([Link],rows);
% Transform each column of the input data
imgFft = fft2(data{k});
% Multiply each column by filter and compute inverse transform
out{k} = ifft2(filterF.*imgFft)
end
processedImages.(imageNames(j)) = out;
fprintf("'%s' images processed\n",imageNames(j))
end
7-29
7 Clusters and Clouds
This example shows how to use pool partitions to ensure workers maintain their state across multiple
function calls. You can partition a parallel pool into multiple single-worker pool partitions. This setup
allows you to direct computations to the same worker, enabling the use of persistent variables to
continue computations between function calls.
This example simulates a simple financial trading system where each worker processes market data,
updates its state, and makes trading decisions based on its current state and individual risk factors.
Start by accessing the current parallel pool. If no pool is available, the gcp function creates one using
the default profile. Use the Workers property of the current pool object to obtain the
[Link] objects of the workers in the pool.
pool = gcp;
poolWkrs = [Link];
Partition the pool three times to isolate the first three workers in the poolWkrs array into individual
pool partitions. Store the pool partitions in an array of pool objects.
traderPools(1) = partition(pool,"Workers",poolWkrs(1));
traderPools(2) = partition(pool,"Workers",poolWkrs(2));
traderPools(3) = partition(pool,"Workers",poolWkrs(3));
Define a function for the trading system. The tradingWorker function maintains a persistent state
between function calls, processes new market data, and uses averages to make trading decisions
based on the current state. The decision-making incorporates a worker-specific risk factor to
introduce variability between workers.
7-30
Partition Parallel Pools to Optimize Resource Use
end
decision = [Link];
pause(1) % Simulate processing time
end
Create a user interface table to display the decision data from the workers.
Simulate real-time market data and process it using the partitioned pools. Assign a unique risk factor
that introduces variability in trading decisions to each worker. To ensure that each pool worker uses
the same risk factor every time it runs the tradingWorker function and updates it's state, use the
same pool partition for each risk factor. Retrieve the decisions for each time step and update the
table.
decisions = fetchOutputs(futures);
decisionTable(end+1,:) = {t,decisions(1),decisions(2),decisions(3)};
[Link] = decisionTable;
drawnow limitrate nocallbacks
end
7-31
7 Clusters and Clouds
Clear the persistent state in the worker function. When you clear the function with the persistent
variable from the client, MATLAB® also clears the function on all the workers.
clear tradingWorker
7-32
Partition Parallel Pools to Optimize Resource Use
Pool pa rtition 3
Worker Worker Worker Worker
7-33
7 Clusters and Clouds
If you have multiple workflows with different resource requirements that need to run concurrently,
partitioning the pool into multiple pool partitions allows each workflow to operate independently
without interfering with each other. For an example that uses multiple pool partitions to manage
resources in a data processing pipeline, see “Partition Pools for Efficient Resource Management in
Concurrent Parallel Workflows” on page 7-36.
This example shows to use pool partitions to manage resources efficiently when transitioning
between different workflows without restarting the pool.
In this example, you run a parfor-loop that utilizes all available workers in the pool. After
completing this process, you want to run a memory-intensive task that can only use half of the
available cores to avoid memory issues. Pool partitions allow you to manage this transition seamlessly
without restarting the existing pool.
Start a parallel pool with 10 workers using the default cluster profile. Use a parfor-loop to generate
audio samples of 30 second duration at a sample rate of [Link]. The frequency in the audio signal
changes to a random value every 3 seconds. The generateAudio function is attached to this
example as a supporting file.
pool = parpool(10);
fs = 44100;
frequencyDuration = 3;
audioDuration = 30;
numAudio = 50;
audioSamples = cell(1,numAudio);
parfor idx = 1:numAudio
audioSamples{idx} = generateAudio(audioDuration,frequencyDuration,fs);
end
Next, extract the Short Time Fourier Transform (STFT) of the audio samples in the background. STFT
computations involve performing multiple FFT computations, which can be memory intensive on the
workers. To reduce the number of parfeval computation running at the same time, create a pool
partition with a smaller number of workers to run the parfeval computations.
poolWkrs = [Link];
smallPool = partition(pool,"Workers",poolWkrs(1:2:end));
Submit the extractFeatures parfeval computations to the pool partition by specifying the
smallPool pool object to the parfeval function.
futures(1:numAudio) = [Link];
for a = 1:numAudio
futures(a) = parfeval(smallPool,@extractFeatures,1,audioSamples{a},fs);
end
You can continue to run computations on the client or the workers that are not in the smallPool
partition. For this example, collect the results from the parfeval computations when they are ready
using the fetchOutputs function. The fetchOutputs function waits until the futures finishes.
7-34
Partition Parallel Pools to Optimize Resource Use
sftfData = fetchOutputs(futures);
Local Functions
The extractFeatures function processes the input audio signal audio sampled at frequency fs,
and returns a structure containing the Short-Time Fourier Transform (STFT) features of the original
and reverberated audio. The addReverb and getSTFT helper functions are attached to this example
as a supporting file.
See Also
partition
Related Examples
• “Partition Pools for Efficient Resource Management in Concurrent Parallel Workflows” on page
7-36
More About
• “Run Code on Parallel Pools” on page 1-28
7-35
7 Clusters and Clouds
This example shows how to use pool partitions to effectively manage and optimize resource allocation
in concurrent parallel workflows.
Pool partitions allow you to execute multiple workflows simultaneously without interference, enabling
precise control over resource usage for each workflow. By assigning specific computations such as
parfor, parfeval, and spmd to designated pool partitions, you can ensure that each workflow
operates independently and efficiently.
This method is particularly advantageous for organizing parallel pipeline workflows, where different
stages can have varying resource needs. In such scenarios, pool partitions facilitate smooth data flow
through the pipeline by tailoring resource allocation to match the requirements of each stage.
Additionally, pool partitions are beneficial when running separate workflows concurrently, as they
help manage and limit the resources each workflow consumes.
This example illustrates the use of pool partitions in executing a simulation parallel pipeline with
multiple GPUs alongside a Monte Carlo path planning simulation. You can adapt this approach to
manage the execution of various workflows concurrently to ensure optimal resource distribution and
workflow performance.
Start a parallel pool with 16 workers. For this example, the myCluster profile requests a parallel
pool with 16 workers from a remote cluster, where each host has eight workers and two GPUs.
pool = parpool("myCluster",16);
Create pool partitions tailored to the requirements of different stages in the simulation pipeline using
the partition function.
Use the partition function to create a pool partition with one worker for each available GPU for
best performance. If you do not have a GPU in the pool, the gpuPool partition returns an empty
[Link] object and the GPU computations run on the client.
[gpuPool,cpuPool] = partition(pool,"MaxNumWorkersPerGPU",1);
Using the remaining workers in the cpuPool partition, create two additional partitions. One with
four workers and another with the rest of the workers in the cpuPool partition. You need at least five
workers to run the simulation pipeline and parfor-loop in parallel. If you do not have enough
workers, reduce the number of workers you partition for the cpuLidarPool partition.
cpuWorkers = [Link];
[cpuLidarPool,cpuOtherPool] = partition(cpuPool,"Workers",cpuWorkers(1:4));
This graphic illustrates how the simulation pipeline stages and the Monte Carlo path planning trials
use the pool partitions.
7-36
Partition Pools for Efficient Resource Management in Concurrent Parallel Workflows
In this example, the parallel simulation pipeline models a lidar scanning system using ray tracing.
Lidar sensors, similar to radar and sonar, measure distances by emitting laser pulses that reflect off
objects, allowing them to perceive the structure of their surroundings. By implementing ray tracing
algorithms and performing intersection calculations on multiple GPUs, you can simulate a lidar
scanning system to gather information about nearby structures in a scene and generate a point cloud
map of the environment.
The pipeline calculates intersections between the triangulated scene and laser rays to determine how
much light hits the object surfaces. To speed up these calculations, use the Möller-Trumbore[1]
algorithm, modified to run on the GPU with arrayfun.
To further enhance simulation speed, execute the simulation stages as a parallel pipeline with
multiple parfeval computations. To ensure that the different stages run on the correct workers, run
the parfeval computations on the gpuPool and cpuLidarPool partitions.
7-37
7 Clusters and Clouds
Begin by setting up a scene composed of multiple objects with triangulated surfaces. Specify the
initial light position and movement parameters using the initializeParameters function, which is
defined at the end of this example.
params = initializeParameters;
Next, visualize the scene using the plotScene function, also defined at the end of this example
plotScene(params);
view([-110.88 31.50])
To facilitate data transfer between different workers during the simulation, use a mixture of
PollableDataQueue and DataQueue objects.
Create two PollableDataQueue objects with Destination set to "any" for the simulation
pipeline. The first worker in the pipeline generates input parameters for each scan and sends the
parameters to the stage2InputQueue pollable data queue for processing. One of the GPU workers
then calculates the ray-triangle intersections and sends the results to the stage3SortQueue and
stage4CloudQueue pollable data queue for further processing.
stage2InputQueue = [Link](Destination="any"); % Pollable data queue 1
stage3SortQueue = [Link](Destination="any"); % Pollable data queue 2
stage4CloudQueue = [Link](Destination="any"); % Pollable data queue 3
In this example, you run multiple, short parfeval computations on the gpuPool partition to
calculate the intersections for each scan. In this way, you can interleave other parallel work on the
same gpuPool partition if a worker is free. Create a DataQueue object with the name
stage2TriggerQueue and use the afterEach function to define a function to run each time the
stage2TriggerQueue data queue object receives data.
7-38
Partition Pools for Efficient Resource Management in Concurrent Parallel Workflows
When the input parameters are ready, the worker running stage 1 sends a message to
stage2TriggerQueue. After stage2TriggerQueue receives data, it automatically submits a
parfeval computation to run the findIntersections function on the gpuPool partition. Note
that the input data is already in the stage2InputQueue pollable data queue. The
findIntersections function is defined at the end of the example.
stage2TriggerQueue = [Link];
afterEach(stage2TriggerQueue,@(call) ...
parfeval(gpuPool,@findIntersections,0,stage2InputQueue,stage3SortQueue,stage4CloudQueue));
Prepare and initialize plots to visualize the intermediate scan data from the workers. The
prepareScanningPlot function is defined at the end of this example.
[fig,s,rays] = prepareScanningPlot(params);
To track the progress of the scans on the client, create a DataQueue object with the name
displayQueue. Use the afterEach function to run the displayScanFrames function when
workers send data to the displayQueue data queue object. The displayScanFrames function is
defined at the end of this example.
displayQueue = [Link];
afterEach(displayQueue,@(data) displayScanFrames(data,s,rays));
For stage 1 of the pipeline, use a worker from the cpuLidarPool partition to run the
addParamsToQueue function in the background with parfeval. The addParamsToQueue function
continuously generates input parameters for each scan and sends them to the stage2InputQueue
pollable data queue object. It also sends a message to the stage2TriggerQueue data queue object
to trigger a parfeval computation on the gpuPool partition for stage 2 of the pipeline.
When the worker generates all the scan input parameters, it closes the stage2InputQueue to signal
to the workers in the next stage that there is no more data to send. The addParamsToQueue function
is defined at the end of this example.
fgenerate = parfeval(cpuLidarPool,@addParamsToQueue,0,params,stage2InputQueue,stage2TriggerQueue)
Stage 3
Use a worker from the cpuLidarPool partition to run the sortFrames helper function in the
background with parfeval. The sortFrames function repeatedly polls the stage3SortQueue
pollable data queue for new frame data, establishes a buffer for the frames, and sends them to the
client in the correct sequence using the displayQueue data queue. The sortFrames function stops
execution when a worker from the previous stage closes the stage3SortQueue pollable data queue.
The sortFrames function is attached to this example as a supporting file.
fSort = parfeval(cpuLidarPool,@sortFrames,0,stage3SortQueue,displayQueue);
Stage 4
Run two instances of the collectCloudPointData function using workers from the cpuLidarPool
partition to generate cloud point data. The collectCloudPointData function repeatedly polls the
stage4CloudQueue pollable data queue for new intersection data and stops execution when a
worker from the previous stage closes the stage4CloudQueue pollable data queue. The
collectCloudPointData function is defined at the end of this example.
7-39
7 Clusters and Clouds
fCloud(1) = parfeval(cpuLidarPool,@collectCloudPointData,1,stage4CloudQueue);
fCloud(2) = parfeval(cpuLidarPool,@collectCloudPointData,1,stage4CloudQueue);
Finally, make the figure visible to display the progress of the lidar simulation.
[Link] = "on";
While the lidar simulation pipeline runs, you can use the remaining cpuOtherPool partition to
perform additional computations. For example, you can use a parfor-loop to run multiple trials of a
path planning algorithm using Particle Swarm Optimization (PSO). The goal is to find an optimal path
from a starting position to a target position while avoiding objects in the scene.
Set up the environment parameters, including the starting and target positions, using the same scene
from the simulation pipeline. Define the radius of the objects.
7-40
Partition Pools for Efficient Resource Management in Concurrent Parallel Workflows
Configure the parameters for the PSO algorithm, such as the number of particles, iterations, and
trials. Restrict the problem to two dimensions.
numParticles = 1000;
numIterations = 300;
dim = 2;
numTrials = 100;
Prepare to record the best path and scores for each trial. Use the parfor function to parallelize the
trials for efficiency. To run the parfor-loop on the cpuOtherPool partition, specify the pool object
as the second argument to the parfor function. The planPathPSO helper function is attached to
this example as a supporting file.
parfor(trial = 1:numTrials,cpuOtherPool)
[bestPath(trial,:,:),scores(trial)] = planPathPSO(startPos,targetPos, ...
obstacles,numParticles,dim,numIterations);
end
Identify the trial with the minimum score, which corresponds to the best path found by the PSO
algorithm.
[~,bestInd] = min(scores);
Visualize the environment, obstacles, and the best path on a plot. The plotBestPath function is
defined at the end of the example.
plotBestPath(obstacles,startPos,bestPath(bestInd,:,:),targetPos);
With the lidar simulation pipeline complete, you can retrieve the results from the fCloud parfeval
computations.
7-41
7 Clusters and Clouds
pointCloud = fetchOutputs(fCloud);
Visualize the aggregated lidar sensor points cloud detections using the plotPointCloud function,
which is defined at the end of the example. The points cloud visualizations shows the outline of the
objects in the scene.
plotPointCloud(pointCloud,params);
References
[1] Möller, Tomas, and Ben Trumbore. "Fast, Minimum Storage Ray-Triangle Intersection." Journal of
Graphics Tools 2, no. 1 (January 1997): 21–28. [Link]
The addParamsToQueue function generates input parameters for each scan and manages their
addition to a data queue for processing. For each step, it calculates the origin of the light source as it
moves across the surface of the object, assigns a scan number, and sends this data to the
stage2InputQueue pollable data queue. It also signals a parfeval computation to be scheduled on
the GPU pool by sending a message to the stage2TriggerQueue pollable data queue. The function
includes queue management to prevent the input queue from becoming overloaded by pausing when
the queue length exceeds a specified threshold. After generating parameters foe all the scans, it
closes the stage2InputQueue and submits a final task to the stage2TriggerQueue to close the
stage 2 pollable data [Link] getScanParam helper function is attached to this example as a
supporting file.
function addParamsToQueue(params,stage2InputQueue,stage2TriggerQueue)
fN = 0;
numScans = size([Link],1);
7-42
Partition Pools for Efficient Resource Management in Concurrent Parallel Workflows
for t = 1:[Link]
data = getScanParam(params,t,lidarOrigin);
fN = fN + 1;
function findIntersections(stage2InputQueue,stage3SortQueue,stage4CloudQueue)
[data,OK] = poll(stage2InputQueue,inf);
if OK
rayOriginsGPU = gpuArray([Link]);
rayDirectionsGPU = gpuArray([Link]);
7-43
7 Clusters and Clouds
rayDirectionsGPU(:,1),rayDirectionsGPU(:,2),rayDirectionsGPU(:,3), ...
data.A(:,1)',data.B(:,1)',data.C(:,1)',...
data.A(:,2)',data.B(:,2)',data.C(:,2)', ...
data.A(:,3)',data.B(:,3)',data.C(:,3)');
[Link] = [];
% Send scan number and scan data to next worker to sort for display
output{1} = [Link];
output{2} = data;
send(stage3SortQueue,output);
elseif ~OK
close(stage3SortQueue);
close(stage4CloudQueue);
end
end
7-44
Partition Pools for Efficient Resource Management in Concurrent Parallel Workflows
intersectionPoints = [intersectionPoints;thisIntersectionPoints];
pointCloud = intersectionPoints;
elseif ~OK
pointCloud = intersectionPoints;
return
end
end
end
initializeParameters
The initializeParameters function initializes and returns a structure containing parameters for
the lidar scanning system simulation. It sets the number of rays per revolution, the number of vertical
layers, the field of view of the sensor and the origin positions for the lidar scans. It also defines the
surface profile for the objects in the scene and uses the createTriangulatedSurfaces helper
function to generate the triangulated surface data. The createTriangulatedSurfaces helper
function is attached to this example as a supporting file.
function params = initializeParameters
% Define the object and create the triangulated surface
[Link] = 80;
[Link] = [-20 -20;20 -20;-20 20;20 20;-10 -5;5 5];
[params.A,params.B,params.C,[Link]] = createTriangulatedSurfaces([Link], ...
[Link]);
% LiDAR Parameters
[Link] = 1000; % Number of rays in one complete horizontal revolution
[Link] = 40; % Number of vertical layers
[Link] = 60; % Vertical field of view in degrees
% Simulation Parameters
[Link] = 10; % Degrees per time step
[Link] = 36;
[Link] = single([0,0,1;0,0,2;0,0,3]); % Set lidar origin (position
end
displayScanFrames
7-45
7 Clusters and Clouds
The displayScanFrames function updates a visualization of lidar scan data by modifying the
surface plot and light source based on new data.
function displayScanFrames(data,s,rays)
s(1).UserData = s(1).UserData + [Link];
indices = s(2).UserData;
prepareScanningPlot
The prepareScanningPlot function sets up a figure and axes to visualize the intersections of light
rays with the object. A secondary axes plots the position of the light source as a red marker.
hold on
for idx = 1:length([Link])
rowStart = [Link](idx,1);
rowEnd = [Link](idx,2);
s(idx) = surf(params.A(rowStart:rowEnd,:), ...
params.B(rowStart:rowEnd,:), ...
params.C(rowStart:rowEnd,:), ...
colors(rowStart:rowEnd,:), ...
EdgeColor="none");
end
hold off
view([-110.88 31.50])
7-46
Partition Pools for Efficient Resource Management in Concurrent Parallel Workflows
colormap turbo;
c = colorbar;
[Link] = "Ray Intensity";
view(160,28);
s(1).UserData = zeros(1,size(params.A,1));
s(2).UserData = [Link];
hold on
for idx = 1:3
rays(idx) = plot3([NaN NaN],[NaN NaN],[NaN NaN],"r",LineWidth=3);
end
rays(1).MarkerIndices = 1;
rays(1).Marker = "square";
rays(1).MarkerSize = 8;
rays(1).MarkerFaceColor = "r";
rays(1).DisplayName = "Sensor position";
hold off
axis off
legend(rays(1),Location="southwest")
end
plotScene
The plotScene function displays the scene for the lidar simulation.
function plotScene(params)
figure;
hold on
for idx = 1:length([Link])
rowStart = [Link](idx,1);
rowEnd = [Link](idx,2);
surf(params.A(rowStart:rowEnd,:), ...
params.B(rowStart:rowEnd,:), ...
params.C(rowStart:rowEnd,:));
end
hold off
view(3)
axis square
end
plotPointCloud
The plotPointCloud function displays the accumulated point cloud data from the lidar simulation
pipeline.
function plotPointCloud(pointCloud,params)
figure;
scatter3(pointCloud(:,1),pointCloud(:,2),pointCloud(:,3),1,"filled");
hold on
scatter3([Link](:,1),[Link](:,2),[Link](:,3),"filled");
hold off
xlabel("X");
ylabel("Y");
zlabel("Z");
title("Lidar Point Cloud");
legend("Point cloud","Sensor position",Location="bestoutside");
7-47
7 Clusters and Clouds
axis equal;
grid on;
end
plotBestPath
The plotBestPath function displays the environment, obstacles, and the best path from the PSO
trials.
function plotBestPath(obstacles,startPos,bestPath,targetPos)
figure;
hold on;
scatter(obstacles(:,1),obstacles(:,2),100);
plot(startPos(1),startPos(2),"go","MarkerSize",10);
plot(targetPos(1),targetPos(2),"rx","MarkerSize",10);
plot(bestPath(1,:,1),bestPath(1,:,2),"b--");
legend("Obstacles","Start","Target","Best Path",Location="bestoutside");
title("Robot Path using PSO");
xlabel("X Position");
ylabel("Y Position");
hold off;
end
See Also
partition
Related Examples
• “Partition Parallel Pools to Optimize Resource Use” on page 7-14
7-48
Scale Up from Desktop to Cluster
Develop your parallel MATLAB® code on your local machine and scale up to a cluster.
Clusters provide more computational resources to speed up and distribute your computations. You
can run your code interactively in parallel on your local machine, then on a cluster, without changing
your code. When you are done prototyping your code on your local machine, you can offload your
computations to the cluster using batch jobs. So, you can close MATLAB and retrieve the results later.
Start by prototyping your algorithm on your local machine. The example uses integer factorization as
a sample problem. It is a computationally intensive problem, where the complexity of the
factorization increases with the magnitude of the number. You use a simple algorithm to factorize a
sequence of integer numbers.
Create a vector of prime numbers in 64-bit precision, and multiply pairs of prime numbers randomly
to obtain large composite numbers. Create an array to store the results of each factorization. The
code in each of the following sections in this example can take more than 20 min. To make it faster,
reduce the workload by using fewer prime numbers, such as 2^19. Run with 2^21 to see the
optimum final plots.
primeNumbers = primes(uint64(2^21));
compositeNumbers = primeNumbers.*primeNumbers(randperm(numel(primeNumbers)));
factors = zeros(numel(primeNumbers),2);
Use a loop to factor each composite number, and measure the time that the computation takes.
tic;
for idx = 1:numel(compositeNumbers)
factors(idx,:) = factor(compositeNumbers(idx));
end
toc
Parallel Computing Toolbox™ enables you to scale up your workflow by running on multiple workers
in a parallel pool. The iterations in the previous for loop are independent, and so you can use a
parfor loop to distribute iterations to multiple workers. Simply transform your for loop into a
parfor loop. Then, run the code and measure the overall computation time. The code runs in a
parallel pool with no further changes, and the workers send your computations back to the local
workspace. Because the workload is distributed across several workers, the computation time is
lower.
tic;
parfor idx = 1:numel(compositeNumbers)
factors(idx,:) = factor(compositeNumbers(idx));
end
toc
7-49
7 Clusters and Clouds
When you use parfor and you have Parallel Computing Toolbox, MATLAB automatically starts a
parallel pool of workers. The parallel pool takes some time to start. This example shows a second run
with the pool already started.
The default profile is 'Processes'. You can check that this profile is set as default on the MATLAB
Home tab, in Parallel > Select Parallel Environment. With this profile enabled, MATLAB creates
workers on your machine for the parallel pool. When you use the 'Processes' profile, MATLAB, by
default, starts as many workers as physical cores in your machine, up to the limit set in the
'Processes' profile. You can control parallel behavior using the parallel settings. On the MATLAB
Home tab, select Parallel > Parallel Settings.
To measure the speedup with the number of workers, run the same code several times, limiting the
maximum number of workers. First, define the number of workers for each run, up to the number of
workers in the pool, and create an array to store the result of each test.
numWorkers = [1 2 4 6];
tLocal = zeros(size(numWorkers));
Use a loop to iterate through the maximum number of workers, and run the previous code. To limit
the number of workers, use the second input argument of parfor.
for w = 1:numel(numWorkers)
tic;
parfor (idx = 1:numel(compositeNumbers), numWorkers(w))
factors(idx,:) = factor(compositeNumbers(idx));
end
tLocal(w) = toc;
end
Calculate the speedup by computing the ratio between the computation time of a single worker and
the computation time of each maximum number of workers. To visualize how the computations scale
up with the number of workers, plot the speedup against the number of workers. Observe that the
speedup increases with the number of workers. However, the scaling is not perfect due to overhead
associated with parallelization.
f = figure;
speedup = tLocal(1)./tLocal;
plot(numWorkers, speedup);
title('Speedup with the number of workers');
xlabel('Number of workers');
xticks(numWorkers);
ylabel('Speedup');
7-50
Scale Up from Desktop to Cluster
When you are done with your computation, delete the current parallel pool so you can create a new
one for your cluster. You can obtain the current parallel pool with the gcp function.
delete(gcp);
If your computing task is too big or too slow for your local computer, you can offload your calculation
to a cluster onsite or in the cloud. Before you can run the next sections, you must get access to a
cluster. On the MATLAB Home tab, go to Parallel > Discover Clusters to find out if you already
have access to a cluster with MATLAB Parallel Server™. For more information, see “Discover
Clusters” on page 7-3.
7-51
7 Clusters and Clouds
If you do not have access to a cluster, you must configure access to one before you can run the next
sections. In MATLAB, you can create clusters in a cloud service, such as Amazon® AWS®, directly
from the MATLAB Desktop. On the Home tab, in the Parallel menu, select Create and Manage
Clusters. In the Cluster Profile Manager, click Create Cloud Cluster. To learn more about scaling
up to the cloud, see Getting Started with Cloud Center. To learn more about your options for scaling
to a cluster in your network, see “Installation” (MATLAB Parallel Server).
After you set up a cluster profile, you can modify its properties in Parallel > Create and Manage
Clusters. For more information, see “Discover Clusters and Use Cluster Profiles” on page 7-2. The
following image shows a cluster profile in the Cluster Profile Manager:
7-52
Scale Up from Desktop to Cluster
If you want to run parallel functions in the cluster by default, set your cluster profile as default in
Parallel > Select Parallel Environment:
7-53
7 Clusters and Clouds
You can also use a programmatic approach to specify your cluster. To do so, start a parallel pool in the
cluster by specifying the name of your cluster profile in the parpool command. In the following
code, replace MyCluster with the name of your cluster profile. Also specify the number of workers
with the second input argument.
parpool('MyCluster',64);
As before, measure the speedup with the number of workers by running the same code several times,
and limiting the maximum number of workers. Because the cluster in this example allows for more
workers than the local setup, numWorkers can hold more values. If you run this code, the parfor
loop now runs in the cluster.
numWorkers = [1 2 4 6 16 32 64];
tCluster = zeros(size(numWorkers));
for w = 1:numel(numWorkers)
tic;
parfor (idx = 1:numel(compositeNumbers), numWorkers(w))
factors(idx,:) = factor(compositeNumbers(idx));
end
tCluster(w) = toc;
end
Calculate the speedup, and plot it against the number of workers to visualize how the computations
scale up with the number of workers. Compare the results with those of the local setup. Observe that
the speedup increases with the number of workers. However, the scaling is not perfect due to
overhead associated with parallelization.
figure(f);
hold on
speedup = tCluster(1)./tCluster;
plot(numWorkers, speedup);
title('Speedup with the number of workers');
xlabel('Number of workers');
xticks(numWorkers(2:end));
ylabel('Speedup');
7-54
Scale Up from Desktop to Cluster
When you are done with your computations, delete the current parallel pool.
delete(gcp);
After you are done prototyping and running interactively, you can use batch jobs to offload the
execution of long-running computations in the background with batch processing. The computation
happens in the cluster, and you can close MATLAB and retrieve the results later.
Use the batch function to submit a batch job to your cluster. You can place the contents of your
algorithm in a script, and use the batch function to submit it. For example, the script
myParallelAlgorithm performs a simple benchmark based on the integer factorization problem shown
in this example. The script measures the computation time of several problem complexities with
different number of workers.
Note that if you send a script file using batch, MATLAB transfers all the workspace variables to the
cluster, even if your script does not use them. If you have a large workspace, it impacts negatively the
data transfer time. As a best practice, convert your script to a function file to avoid this
communication overhead. You can do this by simply adding a function line at the beginning of your
script. To learn how to convert myParallelAlgorithm to a function, see myParallelAlgorithmFcn.
7-55
7 Clusters and Clouds
run the function itself. By default, batch changes the current folder of the workers in the cluster to
the current folder of the MATLAB client. It can be useful to control the current folder. For example, if
your cluster uses a different file system, and therefore the paths are different, such as when you
submit from a Windows® client machine to a Linux® cluster. Set the name-value pair
'CurrentFolder' to a folder of your choice, or to '.' to avoid changing the folder of the workers.
totalNumberOfWorkers = 65;
cluster = parcluster('MyCluster');
job = batch(cluster,'myParallelAlgorithmFcn',2,'Pool',totalNumberOfWorkers-1,'CurrentFolder','.')
To monitor the state of your job after it is submitted, open the Job Monitor in Parallel > Monitor
Jobs. When computations start in the cluster, the state of the job changes to running:
You can close MATLAB after the job has been submitted. When you open MATLAB again, the Job
Monitor keeps track of the job for you, and you can interact with it if you right-click it. For example,
to retrieve the job object, select Show Details, and to transfer the outputs of the batch job into the
workspace, select Fetch Outputs.
Alternatively, if you want to block MATLAB until the job completes, use the wait function on the job
object.
7-56
Scale Up from Desktop to Cluster
wait(job);
To transfer the outputs of the function from the cluster, use the fetchOutputs function.
outputs = fetchOutputs(job);
numWorkers = outputs{1};
time = outputs{2};
After retrieving the results, you can use them for calculations on your local machine. Calculate the
speedup, and plot it against the number of workers. Because the code runs factorizations for different
problem complexities, you get a plot for each level. You can see that, for each problem complexity, the
speedup increases with the number of workers, until the overhead for additional workers is greater
than the performance gain from parallelization. As you increase the problem complexity, you achieve
better speedup at large numbers of workers, because overhead associated with parallelization is less
significant.
figure
speedup = time(1,:)./time;
plot(numWorkers,speedup);
legend('Problem complexity 1','Problem complexity 2','Problem complexity 3','Problem complexity 4
title('Speedup vs complexity');
xlabel('Number of workers');
xticks(numWorkers(2:end));
ylabel('Speedup');
See Also
parpool | parfor | batch | fetchOutputs (Job)
7-57
7 Clusters and Clouds
Related Examples
• “Discover Clusters and Use Cluster Profiles” on page 7-2
More About
• “Parallel for-Loops (parfor)”
• “Installation” (MATLAB Parallel Server)
7-58
Scale Up Parallel Code to Large Clusters
7-59
7 Clusters and Clouds
See Also
parpool | parfeval | parfor | batch
Related Examples
• “Scale Up from Desktop to Cluster” on page 7-49
• “Run Script as Batch Job” on page 5-20
7-60
Scale Up Parallel Code to Large Clusters
7-61
7 Clusters and Clouds
This example shows how to access a large data set in the cloud and process it using hundreds of
workers on a large cluster.
In this example, you use datastores and Parallel Computing Toolbox™ to conduct a wind resource
assessment study of over 120,000 sites across the continental United States to find the best site for a
wind farm.
The public data set in this example is part of the Wind Integration National Dataset Toolkit, or WIND
Toolkit [1], [2], [3], [4]. For more information, see Wind Integration National Dataset Toolkit. The
WIND toolkit is stored in a public Amazon S3™ bucket that is authorized for public access, so you do
not need to configure authentication. For best results, run this example from an Amazon® Web
Service (AWS®) cloud cluster.
To access the remote input data, you must specify the geographic region of the bucket using
environmental variables.
setenv("AWS_DEFAULT_REGION","us-west-2");
Create a parallel pool and attach the function files the workers need to the pool. Send the client
environment variable to the workers.
numWorkers = 450;
c = parcluster("HPCProfile");
pool = parpool(c,numWorkers,EnvironmentVariables="AWS_DEFAULT_REGION", ...
AttachedFiles=["windNCReader.m","findWindTurbineSite.m",mfilename("fullpath")]);
To speed up this example, load the pre-prepared windSitesDs datastore. If you need to recreate the
datastore objects, you can use the createWindSitesDatastore helper function attached to this
example.
load("[Link]","windSitesDs")
% windSitesDs = createWindSitesDatastore;
Check whether the workers can access the files in the S3 bucket then reset the datastore.
f = parfeval(@(ds) summary(read(ds)),1,windSitesDs);
testOut = fetchOutputs(f)
reset(windSitesDs);
7-62
Analyze Wind Data with Large Compute Cluster
Create a DataQueue object to send progress summaries from the workers to the client. Use the
afterEach function to define a callback on the client that updates the geographic scatter plot each
time a worker sends the progress of a computation.
d = [Link];
afterEach(d,@(x) updateGeoPlot(s,x));
7-63
7 Clusters and Clouds
Inside the parfor-loop, partition the datastore based on the number of workers in the parallel pool.
Initialize a cell array to store the progress data and specify the number of files to process before the
workers send the progress data to the client. Then, read and analyze data from each file in the
datastore using the findWindTurbine helper function attached to this example.
np = numpartitions(windSitesDs,pool);
parfor a = 1:np
ds = partition(windSitesDs,np,a);
updateSize = 12;
geoTblUpdate = cell(updateSize,5);
store = getCurrentValueStore;
count = 0
updateCount = 0
while hasdata(ds)
count = count+1;
updateCount = updateCount+1;
t = read(ds);
results = findWindTurbineSite(t);
Store the results in the pool's ValueStore object. You can use the ValueStore when the combined
size of all the results is large, or if the client requires the results during the parfor-loop. Otherwise,
if your data is small or not required within the parfor block, the parfor output typically offers
faster performance.
You can specify how often you want to send data back to the client. After processing 12 files, send the
collected site information and preliminary results to the client.
7-64
Analyze Wind Data with Large Compute Cluster
You can now interactively access the results in the pool's ValueStore. Using the ValueStore in this
example is efficient because you keep the data on the cluster storage until you delete the parallel
pool. This eliminates the need to transfer the data to and from the client during post data analysis.
Such transfers can incur data overheads, especially with large amounts of data or on a network with
high latency.
Use another parfor-loop to perform a post-analysis reduction operation to find the site that
generates the maximum power.
clientStore = [Link];
keySet = keys(clientStore);
maxPowerAndKey = cell(1,2);
parfor k = 1:length(keySet)
store = getCurrentValueStore;
key = keySet(k);
results = store(key);
maxPower = [Link];
maxPowerAndKey = compareValue(maxPowerAndKey,{maxPower,key});
end
disp(maxPowerAndKey)
key = maxPowerAndKey{2};
bestSite = clientStore(key);
Site Information
figure;
geoscatter([Link],[Link],"pentagram","filled");
title("Location")
geobasemap streets
7-65
7 Clusters and Clouds
Wind Statistics
figure;
h = polarhistogram("BinEdge",[Link],"BinCounts",[Link]
pax = gca;
[Link] = "top";
[Link] = 'clockwise';
[Link] = 0:45:360;
[Link] = ["N","NE","E","SE","S","SW","W","NW"];
7-66
Analyze Wind Data with Large Compute Cluster
[Link] = num2str(str2double([Link])*100)+"%";
title("Wind Rose")
Display a summary of the annual power, capacity factor and annual energy production for each class
of wind turbine.
disp([Link])
Turbine Class Turbine Rated Power (MW) Averaged Power (kW) Capacity Factor (%) An
_____________ ________________________ ___________________ ___________________ __
1 2 1443.4 72.171
2 2 1537.4 76.871
3 2 1518.2 75.911
After you have finished analyzing the results data, you can delete the parallel pool. Deleting the
parallel pool also deletes the data in the ValueStore so if you want to preserve the data, copy the
data in the ValueStore to another location before deleting the pool.
delete(pool);
7-67
7 Clusters and Clouds
Local Functions
The initializeGeoScatter function initializes a geographic scatter plot you use to display
updates from the workers.
function s = initializeGeoScatter(itbl)
s = geoscatter(itbl,"Latitude","Longitude",ColorVariable="AvgWindSpeed",SizeData=10,MarkerFac
c = colorbar;
[Link] = "Average Wind Speed (m/s)";
[Link] = [0,20];
title("Test Site Locations in the United States");
geolimits([25 50],[-125.4 -65.0]);
end
The compareValue function determines which of the two input cell arrays contains the greater
numerical value at the first position and returns the corresponding cell array.
function v = compareValue(currentMaxPower,candidate)
valueA = currentMaxPower{1};
valueB = candidate{1};
if valueA > valueB
v = currentMaxPower;
else
v = candidate;
end
end
The updateGeoPlot function updates the geographic scatter plot when a worker sends new data to
the client.
function updateGeoPlot(s,x)
[Link] = [[Link];x];
drawnow limitrate nocallbacks;
end
References
[1] Draxl, Caroline, Bri-Mathias Hodge, Andrew Clifton, and Jim McCaa. "Overview and
Meteorological Validation of the Wind Integration National Dataset Toolkit (Technical Report, NREL/
TP-5000-61740)". Golden, CO: National Renewable Energy Laboratory (2015). [Link]
docs/fy15osti/[Link]
[2] Draxl, Caroline, Andrew Clifton, Bri-Mathias Hodge, and Jim McCaa. “The Wind Integration
National Dataset (WIND) Toolkit.” Applied Energy 151 (August 2015): 355–66 [Link]
[Link].2015.03.121
[3] King, J., Andrew Clifton, and Bri-Mathias Hodge. "Validation of Power Output for the WIND Toolkit
(Technical Report, NREL/TP-5D00-61714)". Golden, CO: National Renewable Energy Laboratory
(2014). [Link]
[4] Lieberman-Cribbin, W., Caroline Draxl, and Andrew Clifton. "Guide to Using the WIND Toolkit
Validation Code (Technical Report, NREL/TP-5000-62595)". Golden, CO: National Renewable Energy
Laboratory (2014). [Link]
See Also
“Scale Up Parallel Code to Large Clusters” on page 7-59
7-68
Analyze Wind Data with Large Compute Cluster
Related Examples
• “Process Big Data in the Cloud” on page 4-66
• “Run parfor-Loops Without a Parallel Pool” on page 7-70
• “Scale Up with Parallel Jobs and Tasks” on page 7-75
7-69
7 Clusters and Clouds
This example shows how to run parfor-loops on a large cluster without a parallel pool.
Running parfor computations directly on a cluster allows you to use hundreds of workers to perform
your parfor-loop. When you use this approach, parfor can use all the available workers in the
cluster, and release the workers as soon as the loop completes. This approach is also useful if your
cluster does not support parallel pools. However, when you run parfor computations directly on a
cluster, you do not have access to DataQueue or Constant objects, and the workers restart between
iterations, which can lead to significant overheads.
This example recreates the update of the ARGESIM benchmark CP2 Monte Carlo study [1] by Jammer
et al [2]. For the CP2 Monte Carlo study, you simulate a spring-mass-damper system with different
randomly sampled damping factors in parallel.
Create the cluster object to and display the number of workers available in the cluster. HPCProfile
is a profile for a MATLAB® Job Scheduler cluster.
cluster = parcluster("HPCProfile");
maxNumWorkers = [Link];
fprintf("Number of workers available: %d",maxNumWorkers)
Set the simulation period, time interval, and initial states for the mass-spring system ODE.
period = [0 2]; % Use a period from 0 to 2 seconds
h = 0.001; % time step
t_interval = period(1):h:period(2);
y0 = [0 0.1];
Initialize the random number generator and create an array of damping coefficients sampled from a
uniform distribution with the range [800,1200].
rng(0);
a = 800;
b = 1200;
d = (b-a).*rand(nReps,1)+a;
Execute the ODE solver in a parfor-loop to simulate the system with varying damping coefficients.
To run the parfor computations directly on the cluster, pass the cluster object as the second input
argument to parfor. Use a reduction variable to compute the sum of the motion at each time step.
7-70
Run parfor-Loops Without a Parallel Pool
parfor(n = 1:nReps,cluster)
f = @(t,y) massSpringODE(t,y,d(n));
[tOut,yOut] = ode45(f,t_interval,y0);
y_sum = y_sum + yOut(:,1);
end
Compute the mean response of the system and plot the response against time.
meanY = y_sum./numel(d);
plot(t_interval,meanY)
title("ODE Solution of Mass-Spring System")
xlabel("Time")
ylabel("Motion")
grid on
Compare the computational speedup of running the parfor-loop directly on the cluster to that of
running the parfor-loop on a parallel pool.
7-71
7 Clusters and Clouds
Use the timeExecution helper function attached to this example to measure the execution time of
the parfor-loop workflow on the client, on a parallel pool with 496 workers, and directly on a cluster
with 496 workers available.
[serialTime,hpcPoolTime,hpcClusterTime] = timeExecution("HPCProfile",maxNumWorkers);
elapsedTimes = [serialTime hpcPoolTime hpcClusterTime];
speedUp = elapsedTimes(1)./elapsedTimes;
fprintf("Speedup on cluster = %4.2f\nSpeedup on pool = %4.2f",speedUp(3),speedUp(2))
Create a bar chart comparing the speedup of each execution. The chart shows that running the
parfor-loop directly on the cluster has a similar speedup to that of running the parfor-loop on a
parallel pool.
figure;
x = ["Client","Pool","Cluster"];
bar(x,speedUp);
ylabel("Computational Speedup")
xlabel("parfor Execution Environment")
grid on
7-72
Run parfor-Loops Without a Parallel Pool
The speedup values are similar because the example uses a MATLAB Job Scheduler cluster. When you
run the parfor-loop directly on a MATLAB Job Scheduler cluster, parfor can sometimes resuse
workers without restarting them between iterations, which reduces overheads. If you run the
parfor-loop directly on a third-party scheduler cluster, parfor restarts workers between iterations,
which can result in significant overheads and much lower speedup values.
Helper Functions
This helper function represents the mass-spring system's ODEs that the solver uses.
You can rewrite the differential equation that describes the spring-mass system (eq1) as a system of
first-order ODEs (eq2) that you can solve using the ode45 solver.
ẏ1 = y2
dy2 + ky1 (eq2)
ẏ2 = −
m
7-73
7 Clusters and Clouds
function dy = massSpringODE(t,y0,d)
k = 9000; % spring stiffness (N/m)
m = 450; % mass (kg)
dy = zeros(2,1);
dy(1) = y0(2);
dy(2) = -(d*y0(2)+k*y0(1))/m;
end
References
[1] Breitenecker, Felix, Gerhard Höfinger, Thorsten Pawletta, Sven Pawletta, and Rene Fink.
"ARGESIM Benchmark on Parallel and Distributed Simulation." Simulation News Europe SNE 17, no.
1 (2007): 53-56.
[2] Jammer, David, Peter Junglas, and Sven Pawletta. “Solving ARGESIM Benchmark CP2 ’Parallel
and Distributed Simulation’ with Open MPI/GSL and Matlab PCT - Monte Carlo and PDE Case
Studies.” SNE Simulation Notes Europe 32, no. 4 (December 2022): 211–20. [Link]
sne.32.bncp2.10625.
See Also
“Scale Up Parallel Code to Large Clusters” on page 7-59
Related Examples
• “Analyze Wind Data with Large Compute Cluster” on page 7-62
• “Scale Up with Parallel Jobs and Tasks” on page 7-75
7-74
Scale Up with Parallel Jobs and Tasks
This example shows how to use parallel jobs and tasks to scale up your computations to hundreds of
workers on a large clusters.
You can scale up an existing parfor workflow beyond parallel pool limits by converting the parfor-
loop into multiple tasks for an independent job. This example converts the parfor workflow in the
“Run parfor-Loops Without a Parallel Pool” on page 7-70 example to a job and tasks workflow.
This example recreates an update of the ARGESIM benchmark CP2 Monte Carlo study [1] by Jammer
et al [2]. In the Monte Carlo study, you simulate a spring-mass system with different, randomly
sampled damping factors using jobs and tasks.
Create the cluster object and display the number of workers available in the cluster. HPCProfile is a
profile for a MATLAB® Job Scheduler cluster. Replace the HPCProfile profile with your own cluster
profile.
cluster = parcluster("HPCProfile");
maxNumWorkers = [Link];
fprintf("Number of workers available: %d",maxNumWorkers)
job = createJob(cluster);
period = [0 2];
h = 0.001; % time step
t_interval = period(1):h:period(2);
nReps = 10000000;
Initialize the random number generator and create an array of damping coefficients sampled from a
uniform distribution between 800 and 1200.
rng(0);
a = 800;
b = 1200;
d = (b-a).*rand(nReps,1) + a;
To change the parfor workflow into a jobs and tasks workflow, convert the main body of the parfor-
loop into a function that takes in a vector of damping coefficients and returns the sum of the mass-
spring motion.
7-75
7 Clusters and Clouds
Define the simulation parameters on the worker. To reduce data transfer overheads, specify the time
interval and any other constant parameters directly on the workers instead of transferring them to
the workers as input arguments.
period = [0 2];
h = 0.001;
y0 = [0 0.1];
t_interval = period(1):h:period(2);
To reduce scheduling overheads, partition the iterations into groups for each task instead of
scheduling a task for each iteration. Use a for-loop to iterate through this task's set of damping
coefficients. Use a reduction variable to compute the sum of the motion at each time point.
for n = 1:length(d)
f = @(t,y) massSpringODE(t,y,d(n));
[~,yOut] = ode45(f,t_interval,y0);
y_sum = y_sum + yOut(:,1);
end
You can use a job's ValueStore when the combined size of all the results is large, or if the client
must process interim results while the job is running. Otherwise, if your results data is small, you can
send the results back to client using the task's OutputArgument property.
end
To help reduce overheads when you schedule multiple tasks for a job, partition the iterations into
groups for each task. Try to partition the iterations into groups that are:
• Large enough that the computation time is large compared to the overhead of scheduling the
partition.
• Small enough that there are enough tasks to keep all workers busy.
• Decreasing in size in the last sets of tasks to keep as many workers busy as possible.
The partitionIterations helper function, attached to this example, uses the number of iterations
and desired maximum number of workers to divide the iterations into appropriately sized groups and
returns a cell array where each cell corresponds to one group of iteration indices. The
partitionIterations function allocates larger groups to the initial tasks and progressively
smaller groups to later tasks for a balanced workload distribution.
taskGroups = partitionIterations(nReps,maxNumWorkers);
After you specify the iteration indices for each task, use the cellfun function to extract the damping
coefficients corresponding to each task group into a cell array.
dampingCoeffs = cellfun(@(ind) {d(ind)},taskGroups,UniformOutput=false);
Use a single call to create multiple tasks for the job. Each task executes the taskFcn function with
the corresponding set of input arguments sourced from the dampingCoeffs cell array. Instruct the
workers to return one output argument for each task.
7-76
Scale Up with Parallel Jobs and Tasks
tasks = createTask(job,@taskFcn,1,dampingCoeffs);
submit(job);
If you want to block the MATLAB client until the job completes, use the wait function on the job
object. The wait function is useful when subsequent code depends on the completion of the job.
wait(job);
Access Results
After the job completes, you can retrieve the results from all the tasks using the fetchOutputs
function.
results = fetchOutputs(job);
The fetchOutputs function returns a cell array, where each element is the output of a task. Convert
the cell into a numerical array and compute the sum and the mean of each row.
y_sum = sum(cell2mat(results'),2);
meanY = y_sum./nReps;
plot(t_interval,meanY)
title("ODE Solution of Mass-Spring System")
xlabel("Time")
ylabel("Motion")
grid on
7-77
7 Clusters and Clouds
jobDuration = duration
00:07:32
Compare the computational speedup of converting the parfor workflow into a jobs and tasks
workflow to that of running the parfor-loop on a parallel pool and directly on a cluster.
Use the timeExecution helper function attached to this example to measure the execution time of
the parfor workflow on the client, on a parallel pool with 496 workers, and directly on a cluster with
496 workers available. Convert the job duration into seconds.
[serialTime,hpcPoolTime,hpcClusterTime] = timeExecution("HPCProfile",maxNumWorkers);
jobsAndTaskTime = double(seconds(jobDuration));
elapsedTimes = [serialTime hpcPoolTime hpcClusterTime jobsAndTaskTime];
Calculate the computational speedup and create a bar chart comparing the speedup of each
workflow. The chart shows that using a jobs and tasks workflow has a similar speedup to that of
running the parfor-loop on a parallel pool and larger speedup than running the parfor-loop
directly on the cluster.
7-78
Scale Up with Parallel Jobs and Tasks
speedUp = elapsedTimes(1)./elapsedTimes;
x = ["parfor Client","parfor Pool","parfor Cluster","Jobs and Tasks"];
bar(x,speedUp);
xlabel("Workflow")
ylabel("Computational Speedup")
Helper Functions
This helper function represents the mass-spring system's ODEs the solver uses. You can rewrite the
differential equation that describes the spring-mass system (eq1) as a system of first-order ODEs
(eq2) that you can solve using the ode45 solver.
ẏ1 = y2
dy2 + ky1 (eq2)
ẏ2 = −
m
function dy = massSpringODE(t,y0,d)
k = 9000; % spring stiffness (N/m)
7-79
7 Clusters and Clouds
dy = zeros(2,1);
dy(1) = y0(2);
dy(2) = -(d*y0(2)+k*y0(1))/m;
end
References
[1] Breitenecker, Felix, Gerhard Höfinger, Thorsten Pawletta, Sven Pawletta, and Rene Fink.
"ARGESIM Benchmark on Parallel and Distributed Simulation." Simulation News Europe SNE 17, no.
1 (2007): 53-56.
[2] Jammer, David, Peter Junglas, and Sven Pawletta. “Solving ARGESIM Benchmark CP2 ’Parallel
and Distributed Simulation’ with Open MPI/GSL and Matlab PCT - Monte Carlo and PDE Case
Studies.” SNE Simulation Notes Europe 32, no. 4 (December 2022): 211–20. [Link]
sne.32.bncp2.10625.
See Also
“Scale Up Parallel Code to Large Clusters” on page 7-59
Related Examples
• “Analyze Wind Data with Large Compute Cluster” on page 7-62
• “Run parfor-Loops Without a Parallel Pool” on page 7-70
7-80
8
Performance Profiling
You can improve the performance of your parallel code by using Pool Dashboard or parallel profiling.
Use benchmarks to measure performance.
You can collect pool activity monitoring data interactively with the Pool Dashboard or
programmatically using an ActivityMonitor object and view the data in the Pool Dashboard. For
most use cases, use the Pool Dashboard to interactively collect and view monitoring data. However, if
you need to collect monitoring data to review later or for code that runs on a batch parallel pool, use
the ActivityMonitor object. For details, see “Programmatically Collect Pool Monitoring Data” on
page 8-26.
• MATLAB Toolstrip: On the Home tab, in the Environment section, select Parallel > Open Pool
Dashboard.
• Parallel status indicator: Click the indicator icon and select Open Pool Dashboard.
• MATLAB command prompt: Enter parpoolDashboard.
Section Details
Parallel Constructs Displays information about the types of parallel
constructs the workers execute, the parent
function or script that calls the parallel construct,
and details of the functions the parallel
constructs run, if available.
Timeline Provides a visual representation of the time
workers and the client spend running the parallel
construct and transferring data. For example,
dark blue represents time spent running a
parfor-loop, light blue represents time spent
sending data, and magenta represents time spent
receiving data. When you select a specific parallel
construct, elements in the Timeline graph
unrelated to the selected construct appear in
gray.
8-2
Monitor Pool Workers with Pool Dashboard
Section Details
Worker Summary Condenses the information from the Timeline
graph, providing an overview of each worker's
activity.
Call Stack Expands on the information about the parent
function or script that calls the parallel construct
and the functions the parallel construct runs. The
Call Stack is only visible when you select a
specific parallel construct.
This example shows how to use the Pool Dashboard to compare the performance of parfor-loops.
When you initialize a variable before a parfor-loop and use it inside the loop, you must pass it to
each MATLAB® worker evaluating the loop iterations. The parfor function transfers only the
variables that the loop uses from the client workspace to the workers. However, if the loop variable
indexes all occurrences of the variable, parfor slices the variable and sends each worker only the
part of the variable it needs. Using sliced variables reduces data transfer overheads between the
client and workers.
Compare the performance of a parfor-loop with sliced variables to one without sliced variables by
collecting monitoring data with the Pool Dashboard.
Open the Pool Dashboard. In the Monitoring section of the Pool Dashboard, click Start Monitoring.
When the Pool Dashboard begins collecting monitoring data, return to the Live Editor and click Run
Section.
In this code, parfor breaks the data variable into slices, which are then operated on separately by
different workers.
A = 500;
M = 100;
N = 1e6;
data = randn(M,N);
parfor idx = 1:M
a = max(abs(eig(rand(A))));
b = sum(data(idx, :))./N;
r(idx) = a*b;
end
pause(1)
Now, suppose that you accidentally use a reference to the data variable instead of N inside the
parfor-loop. The problem is that the call to size(data,2) converts the sliced variable data into a
broadcast (non-sliced) variable.
parfor idx = 1:M
a = max(abs(eig(rand(A))));
8-3
8 Performance Profiling
b = sum(data(idx,:))./size(data,2);
r(idx) = a*b;
end
disp("Section complete!")
Section complete!
After the section code is complete, in the Monitoring section , select Stop. The Pool Dashboard
displays the monitoring results.
The Pool Dashboard displays information for both parfor-loops, separated by the one second pause.
In the Parallel Constructs table, select the first parfor computation, which is the parfor-loop
with the sliced data variable. The Timeline graph and the Summary and Worker Summary tables
now display information specific to the selected parfor-loop. Elements in the Timeline graph
unrelated to the selected construct appear in gray. The Call Stack table is now visible below the
Summary table. To expand the Call Stack table, click the right arrow. The Call Stack table displays
the parfor-loop in the Statement column.
The Timeline graph indicates that each worker takes a similar amount of time to execute their
parfor iterations and the workers are not idle for long. Data transfer durations are also brief. In the
Summary table, note the parfor-loop execution duration of 3.291 seconds and the data the client
sends to the workers, totaling 763.02 MB.
8-4
Monitor Pool Workers with Pool Dashboard
In the Parallel Constructs table, select the second parfor construct, which is the parfor-loop with
the accidentally broadcast data variable. The Timeline graph indicates the workers spend the first
one to two seconds receiving data from the client. In the Summary table, the parfor-loop execution
duration is 5.734 seconds and the client sends a total of 763.02 MB of data to the workers. The
execution duration is greater for the parfor-loop with the accidentally broadcast variable due to the
large data being transferred to the workers.
8-5
8 Performance Profiling
As the result is a constant, you can avoid the non-sliced usage of the data variable by computing it
outside the loop. Generally, perform computations that depend solely on broadcast data before the
loop starts, because broadcast data cannot be modified inside the loop. In this case, the computation
is trivial, and results in a scalar, so you benefit from taking the computation out of the loop.
This example shows how to identify details of parfeval computations in monitoring data the Pool
Dashboard displays.
The parfeval function performs asynchronous execution of functions on workers without blocking
the client. Workers execute the function at any time, which makes it challenging to determine when
execution completes. When you collect pool monitoring data for parfeval computations, the Pool
Dashboard displays this data in a way that enables you to identify the details of a specific parfeval
computation among similar computations.
pool = parpool(3);
Collect pool monitoring data for a set of parfeval computations, each running a different function.
8-6
Monitor Pool Workers with Pool Dashboard
Open the Pool Dashboard. In the Monitoring section of the Pool Dashboard, select Start
Monitoring. When the Pool Dashboard begins collecting monitoring data, return to the Live Editor
and select Run Section.
Execute the dollarAuctionModels helper function, attached to this example as a supporting file.
The dollarAuctionModels function runs Monte-Carlo simulations of different dollar auction
models with a specified number of trials asynchronously using the parfeval function.
numTrials = 1000;
auctionFutures = dollarAuctionModels(1000);
pause(1)
Execute a series of asynchronous parfeval computations to price financial options using Monte-
Carlo methods. The helper functions for these models are also attached to this example as supporting
files.
modelFunctions = {@mcAsianCallOption,@mcDownAndOutCallOption,@mcLookbackCallOption,@mcStockPrice,
numModels = length(modelFunctions);
load [Link]
optionFutures(1:numModels) = [Link];
for m = 1:numModels
optionFutures(m) = parfeval(modelFunctions{m},1,params);
end
Use parfevalOnAll to execute a brief pause on all workers to ensure all the parfeval
computations are completed before you stop collecting pool monitoring data.
syncF = parfevalOnAll(@pause,0,0.1);
wait(syncF)
disp("Section complete.")
Section complete.
After the section code is complete, in the Monitoring section of the Pool Dashboard, select Stop. The
Pool Dashboard displays the monitoring results.
Unlike the results from monitoring a parfor-loop, the Parallel Constructs table lists the name of
the function that each parfeval computation evaluates in the Details column. The Function
column lists the parent function or script that schedules the parfeval computation. For example,
the dollarAuctionModels function uses the parfeval function to evaluate the
mcDollarAuction, mcCollabDollarAuction, and mcRiskAverseDollarAuction helper
functions.
8-7
8 Performance Profiling
The Timeline graph represents the time workers spend running parfeval computations in yellow
and parfevalOnAll computations in purple. The same parfevalOnAll computation occurs on all
the workers at different times. You can observe that each worker completes multiple parfeval
computations with no idle time between them. The data transfer bars in blue and magenta help
differentiate the various parfeval bars. The first parfeval bar on worker 2 is longer than the others.
To identify the code responsible for the long-running parfeval computation, select that bar.
The Timeline graph and the Summary and Worker Summary tables now display information
specific to the selected parfeval computation, and the Parallel Constructs table highlights the
row for the selected parfeval bar. The Call Stack table for the selected parfeval computation is
now visible below the Summary table. To expand the Call Stack table, click the right arrow. The
Call Stack table shows the parfeval function call in the Statement column. This information
8-8
Monitor Pool Workers with Pool Dashboard
indicates that the Live Editor script calls the dollarAuctionModels function, which in turn
schedules the long-running parfeval computation. The parfeval computation evaluates the
mcCollabDollarAuction function.
To clear the information for the currently selected parfeval computation and view activity data for
all the workers again, in the Selections section of the Pool Dashboard, click Clear Selections.
This example shows how to analyze pool monitoring data you collect during computations with
distributed arrays.
A distributed array is a single variable, divided over multiple workers in your parallel pool. When you
apply functions to distributed arrays, MATLAB® uses spmd statements to execute these functions
simultaneously on all the workers of the pool. The Pool Dashboard collects monitoring data for each
spmd computation.
In this example, you collect and analyze pool monitoring data while solving a system of linear
equations with distributed arrays on a parallel pool of cluster workers.
Start a parallel pool of cluster workers using the remote cluster profile MyCluster.
pool = parpool("MyCluster",12);
8-9
8 Performance Profiling
Open the Pool Dashboard. In the Monitoring section of the Pool Dashboard, click Start Monitoring.
When the Pool Dashboard begins collecting monitoring data, return to the Live Editor and click Run
Section.
Define the size of a suitably large array for the number of workers in the pool.
nWorkers = [Link];
n = floor(sqrt(4096*4096*nWorkers));
To directly construct distributed arrays on the workers, use the "distributed" argument of the
randi and ones functions. Define the coefficient matrix A and the exact solutions for comparison,
xEx.
A = randi(100,n,n,"distributed");
xEx = ones(n,1,"distributed");
Define the right-hand vector b as the row sum of A. The vector b is also distributed.
b = sum(A,2);
x = A\b;
Calculate the mean error between each element of the obtained result x and the expected values of
xEx.
err = abs(xEx-x);
mErr = mean(err);
disp("Section complete.")
Section complete.
After the section code is complete, in the Monitoring section of the Pool Dashboard, select Stop. The
Pool Dashboard displays the monitoring results.
The Parallel Constructs table and Timeline graph display computations on distributed arrays as
spmd computations. The count of spmd computations in the Parallel Constructs table and Timeline
graph corresponds to the frequency with which MathWorks® utility functions invoke spmd to execute
code on the distributed arrays.
8-10
Monitor Pool Workers with Pool Dashboard
The Parallel Constructs table lists the utility functions that call spmd in the Function column. You
can identify the line of code responsible for any spmd computation in the Call Stack table. For
example, to view the Call Stack table for the spmd computation initiated by the utility function
distributed/sBuild, select the first row in the Parallel Constructs table. The Call Stack table
for the selected spmd computation is now visible below the Summary table. To expand the Call
Stack table, click the right arrow.
The Call Stack table provides detailed information about the code responsible for the spmd
computation in hierarchical order, with the parent function or script and specific code line appearing
in the bottom row. The information in the Call Stack table indicates the utility function
distributed/sBuild creates the distributed array A on the workers.
8-11
8 Performance Profiling
To clear the information for the currently selected spmd computation and view monitoring data for all
spmd computations again, in the Selections section of the Pool Dashboard, click Clear Selections.
The Timeline graph visually represents the duration of the spmd computations on each worker as
orange bars. The data send and receive bars in blue and magenta help differentiate the various spmd
bars. Look for the longest orange bar on any worker, which indicates the longest-running spmd
computation. Select the bar.
8-12
Monitor Pool Workers with Pool Dashboard
The Timeline graph, Summary, and Worker Summary tables now display information specific to
the selected spmd computation, and the Parallel Constructs table highlights the row for the
selected spmd bar. The Call Stack table for the selected spmd computation is also visible. The Call
Stack information indicates that the longest-running spmd statement evaluates the mldivide
function.
8-13
8 Performance Profiling
This example shows how to use the Pool Dashboard to measure and improve the parallel efficiency of
computations on a parallel pool.
The Pool Dashboard parallel efficiency metric helps you identify inefficiencies in your parallel pool
workflow. The Pool Dashboard calculates parallel efficiency using the formula:
where
• Total Busy Time is the cumulative time all workers actively process tasks.
• Duration is the total time from start to end of the monitoring period.
• Number of Workers is the total number of workers in the parallel pool.
In this example, you collect pool monitoring data while executing a workflow to import and
automatically process data using an interactive parallel pool. Use the pool monitoring data,
particularly the parallel efficiency metric, to determine if the workflow uses the pool workers
efficiently.
Open the Pool Dashboard. In the Monitoring section of the Pool Dashboard, click Start Monitoring.
When the Pool Dashboard begins collecting monitoring data, return to the Live Editor and click Run
Section.
disp("Section complete.")
Section complete.
After the section code is complete, in the Monitoring section of the Pool Dashboard, select Stop. The
Pool Dashboard displays the monitoring results.
8-14
Monitor Pool Workers with Pool Dashboard
The Timeline graph indicates that most of the workers remain idle during the parfeval execution.
This idle time stems from the code structure, where the parfor-loop cannot begin until the
parfeval computation is complete.
In the Worker Summary table, the maximum busy time of the workers is 38.272 seconds out of a
total duration of 53.911 seconds. The parallel efficiency for the workflow is 40.81%, indicating that
the workers are not being used effectively.
The pool monitoring data highlights inefficiencies in the parallel processing code. The code uses
asynchronous parfeval computations to import data and then waits for the computations to
complete before proceeding with a parfor-loop to process the data. This approach introduces
unnecessary delays, as the loop waits for the parfeval computation sequentially, which prevents the
software from fully using the parallel workers.
To enhance parallel efficiency, restructure the code to overlap data import and processing tasks,
minimizing worker idle time. Initiate the first data import asynchronously before you start the for-
8-15
8 Performance Profiling
loop. This restructure allows the workers to continue executing other tasks while waiting for the data
import to complete.
Run the restructured code and collect monitoring data with the Pool Dashboard. In the Monitoring
section of the Pool Dashboard, click Start Monitoring. When the Pool Dashboard begins collecting
monitoring data, return to the Live Editor and click Run Section.
future = parfeval(@importDataFromDatabase,1,w);
disp("Section complete.")
Section complete.
After the section code is complete, in the Monitoring section of the Pool Dashboard, select Stop. The
Pool Dashboard displays the monitoring results.
The Timeline graph displays the overlap between data import parfeval and data processing
parfor computations. The parfeval computations now occur asynchronously and the parfor-loop
does not wait for the parfeval computations to complete before executing with the remaining
workers of the pool.
8-16
Monitor Pool Workers with Pool Dashboard
The Worker Summary table still shows similar worker busy times when compared to the inefficient
parallel code, however, the workflow duration is decreased to 35 seconds. This shorter duration
results in an increase in the parallel efficiency for the workflow from 40.81% to 60.48%.
Helper Functions
The importDataFromDatabase function simulates the import of data from a database. The function
generates a magic square matrix of size specified by the input in and simulates a delay by pausing
for 6 seconds.
The processData function calculates the sum of the elements in the input data and simulates a
nontrivial calculation by pausing for 1.2 seconds.
See Also
Functions
parfor | parfeval | distributed | spmd
Tools
Pool Dashboard
8-17
8 Performance Profiling
This example shows how to use pool monitoring data from the Pool Dashboard to optimize a parfor-
loop.
The Pool Dashboard is a tool that provides a visual interface to monitor and optimize parallel tasks.
You can visualize the distribution of workloads across workers to help you optimize your parallel
code.
In this example, you use a parfor-loop to process a collection of images by computing their fast
Fourier transform (FFT). The computational load for each image depends on its file size, which can
vary significantly. Use the Pool Dashboard to understand the workload distribution across the workers
and identify any bottlenecks in the parfor-loop.
Create a parallel pool using the parpool function. By default, parpool uses your default profile.
Check your default profile on the MATLAB Home tab, in Parallel > Select Parallel Environment.
pool = parpool;
Create a collection of image files for analysis using the createFiles helper function, which is
defined at the end of this example.
createFiles;
56 images generated.
Obtain a list of the image filenames and extract the number of images. Preallocate a structure for the
results data.
imageFiles = dir("images/*.jpg");
numImages = numel(imageFiles);
outputSpectra = struct("scanNumber",[],"spectra",[]);
• MATLAB® Toolstrip: On the Home tab in the Environment section, select Parallel > Open Pool
Dashboard.
• Parallel status indicator: Click the indicator icon and select Open Pool Dashboard.
• MATLAB command prompt: Enter parpoolDashboard.
Process the collection of images by computing their FFT. Use a parfor-loop to accelerate image
processing with the fftImage helper function, which is defined at the end of this example.
Collect monitoring data with the Pool Dashboard. In the Monitoring section of the Pool Dashboard,
select Start Monitoring. When the Pool Dashboard begins collecting monitoring data, return to the
Live Editor and click Run Section.
8-18
Optimize parfor-Loops with Pool Dashboard
disp("Section complete.")
Section complete.
After the section code is complete, in the Monitoring section of the Pool Dashboard, select Stop. The
Pool Dashboard displays the monitoring results.
To review the monitoring data, focus on the Timeline graph. The Timeline graph visually represents
the time workers and the client spend running the parfor-loop and transferring data. Dark blue
indicates the time spent running the parfor-loop, while light blue represents sending data and
magenta represents receiving data. You can observe that workers 3, 4 and 5 take significantly longer
to process the images the parfor function assigns to them compared to the other workers. This
observation suggests that the load is not evenly distributed across the workers.
You can use different approaches to optimize the load distribution for the parfor-loop. This section
discusses how to achieve a more balanced workload distribution both when the workload of each
iteration is unknown and when it is known.
8-19
8 Performance Profiling
Randomize Files
If you do not have any information about the workload of each iteration, randomizing the order of
processing can help balance the workload. To process the images in a random order, use the
randperm function to generate a random permutation of indices for the image files.
Collect monitoring data with the Pool Dashboard, in the Monitoring section of the Pool Dashboard,
select Start Monitoring. When the Pool Dashboard begins collecting monitoring data, return to the
Live Editor and click Run Section.
randIndices = randperm(numImages);
randImageFiles = imageFiles(randIndices);
parfor idx = 1:numImages
imgName = randImageFiles(idx).name;
outputSpectra(idx) = fftImage(imgName);
end
disp("Section complete")
Section complete
After the section code is complete, in the Monitoring section of the Pool Dashboard, select Stop. In
the Timeline graph, you can observe that the workers are idle for less time compared to the first
parfor-loop. This observation indicates that the load distribution is more balanced than before.
8-20
Optimize parfor-Loops with Pool Dashboard
• Large enough so that the computation time is substantial compared to the overhead of scheduling
the subrange
• Small enough to ensure there are enough subranges to keep all workers busy
In this example, the computational load for each image depends on its size. To partition iterations
more effectively, you can calculate subranges based on the file sizes. The groupImageFilesBySize
helper function groups the image files by their sizes, using an upper limit of 1.5 times the size of the
largest image file for the cumulative size of the files in each group. The groupImageFilesBySize
function is attached to this example as a supporting file.
[subranges,groupedImageFiles] = groupImageFilesBySize(imageFiles);
To understand how the groupImageFilesBySize function groups the images, view the distribution
of file sizes in the groups in a bar chart.
barSubranges(groupedImageFiles,subranges);
To run a parfor-loop using the calculated subranges, pass a function handle to the
'RangePartitionMethod' name-value argument. This function handle must return a vector of
subrange sizes, and their sum must be equal to the number of iterations.
8-21
8 Performance Profiling
To collect monitoring data with the Pool Dashboard, in the Monitoring section, select Start
Monitoring. When the Pool Dashboard begins collecting monitoring data, return to the Live Editor
and click Run Section.
Section complete
After the section code is complete, in the Monitoring section of the Pool Dashboard, select Stop. In
the Timeline graph, you can observe that almost all of the workers are idle for less time compared to
the first parfor-loop. The parfor-loop also completes in less time.
An alternative to using parfor for parallel processing is the parfeval function. With parfeval,
you can schedule the evaluation of a function on a pool worker for each iteration. This approach
provides more flexibility for scheduling work on the workers and can help prevent workers from
remaining idle, as each worker is assigned one iteration at a time and can perform other tasks if no
new parfeval computations are pending.
8-22
Optimize parfor-Loops with Pool Dashboard
For each image, you schedule a call to the fftImage helper function using parfeval. The software
queues each function call for execution on a worker in the parallel pool. Unlike parfor, which
divides the iterations into subranges, parfeval allows you to manage each task individually.
To collect monitoring data with the Pool Dashboard, in the Monitoring section, select Start
Monitoring. When the Pool Dashboard begins collecting monitoring data, return to the Live Editor
and click Run Section.
futures(1:numImages) = [Link];
for idx = 1:numImages
imgName = imageFiles(idx).name;
futures(idx) = parfeval(@fftImage,1,imgName);
end
As each task completes, you can retrieve the results using the fetchNext function. fetchNext
returns the index of the completed task and its output, allowing you to store the results in the correct
order.
Section complete
After the section code is complete, in the Monitoring section of the Pool Dashboard, select Stop.
The Timeline graph represents the time workers spend running parfeval computations in yellow.
In the Timeline graph, you can observe that each worker completes multiple parfeval
computations. Some workers remain idle for one to two seconds between parfeval computations
while they transfer results data back to the client. However, the workers are idle for less time
compared to the first parfor-loop.
8-23
8 Performance Profiling
Clean Up
The fftImage function computes the FFT of an image and stores the results in a structure.
function output = fftImage(filename)
% Read the image
img = imread(fullfile("images",filename));
% Perform FFT
imgFFT = fft2(double(img));
The createFiles function generates images to process in the example and saves the images to the
images folder.
function createFiles
% Create folder to save images
outputDir = "images";
if exist(outputDir,"dir")
mkdir(outputDir);
end
8-24
Optimize parfor-Loops with Pool Dashboard
The barSubranges function plots the size of the files in each subrange group in a bar chart.
function barSubranges(groupedImageFiles,subranges)
% Initialize variables
lastIdx = 0;
bytes = [[Link]];
cumulativeSums = cumsum(subranges);
See Also
Functions
parfor | parfeval | parforOptions
Tools
Pool Dashboard
8-25
8 Performance Profiling
You can collect pool activity monitoring data programmatically using an ActivityMonitor object or
interactively with the Pool Dashboard. For most workflows, use the Pool Dashboard to interactively
collect and view monitoring data. However, if you need to collect monitoring data to review later or
for code that runs on a batch parallel pool, use an ActivityMonitor object.
This example shows how to use an ActivityMonitor object to collect monitoring data on an
interactive parallel pool.
nWorkers = 3;
pool = parpool(nWorkers);
monitor = [Link];
Run your parallel code. For the purposes of this example, use a simple parfor-loop that iterates over
a series of values.
values = [5 12 13 1 12 5];
parfor (idx = 1:numel(values),3)
u = rand(values(idx)*3e4,1);
out(idx) = max(conv(u,u));
end
After the code completes, stop collecting monitoring data and retrieve the pool monitoring results
collected during the parfor execution.
monitoringResults = stop(monitor);
Visualize the monitoring results in the Pool Dashboard. The parpoolDashboard function opens the
Pool Dashboard and displays the monitoring results in the ActivityMonitorResults object,
monitoringResults.
parpoolDashboard(monitoringResults)
Generally, comparing the execution times of the workers can help you identify the bottlenecks in your
code. The Timeline graph visually represents the time workers and the client spend executing the
8-26
Programmatically Collect Pool Monitoring Data
parfor-loop and transferring data. Dark blue indicates time spent running the parfor-loop, light
blue represents time spent sending data, and magenta represents time spent receiving data.
You can observe that some workers take significantly longer to complete their iterations compared to
other workers, which results in workers remaining idle for most of the parfor execution time. This
observation suggests that the load is not distributed evenly across the workers.
If you know the workload of each iteration in your parfor-loop, then you can use parforOptions to
control the partitioning of iterations into subranges for the workers. For more information, see
parforOptions.
In this example, the greater the value in values, the more computationally intensive the iteration.
Each consecutive pair of values in values balances low and high computational intensity. To
distribute the workload better, create a set of parfor options to divide the parfor iterations into
subranges of size 2.
opts = parforOptions(pool,RangePartitionMethod="fixed",SubrangeSize=2);
monitor = [Link];
Run the same code as before. To use the parfor options, pass them to the second input argument of
parfor.
8-27
8 Performance Profiling
out(idx) = max(conv(u,u));
end
Retrieve the monitoring results and visualize the results in the Pool Dashboard.
monitoringResults = stop(monitor);
parpoolDashboard(monitoringResults)
In the Timeline graph, compare the execution times of the workers. Observe that in the second
parfor-loop, each worker takes a similar amount of time to execute their parfor iterations and
there are no idle workers. The workload is now better distributed.
This example shows how to use an ActivityMonitor object to collect monitoring data on a parallel
pool of a batch job.
Define a function that runs simulations of different dollar auction models using the parfeval
function. The function creates an ActivityMonitor object to collect monitoring data, submits and
waits for the parfeval computations, and retrieves the pool monitoring results.
function monitoringResults = runDollarAuctionModels
% Define simulation parameters
[Link] = 20;
[Link] = 0.05;
[Link] = 0.01;
[Link] = 1000;
[Link] = 0.5;
8-28
Programmatically Collect Pool Monitoring Data
Run the runDollarAuctionModels function as a batch pool job and wait for the batch job to
complete.
job = batch(@runDollarAuctionModels,1,Pool=4,CaptureDiary=false);
wait(job);
out = fetchOutputs(job);
monitoringResults = out{1};
parpoolDashboard(monitoringResults)
In the Pool Dashboard, the Timeline graph represents the time workers spend running the parallel
code and transferring data. Yellow indicates time spent running the parfeval computations, light
blue represents time spent sending data, and magenta represents time spent receiving data.
Observing the Timeline graph, you can see that one parfeval bar is longer than the other bars. To
view information specific to that parfeval computation, click the bar.
8-29
8 Performance Profiling
The Timeline graph and Parallel Constructs, Summary and Worker Summary tables now display
information specific to the selected parfeval computation. You can identify which function the
selected parfeval computation was running in the Parallel Constructs table, under the Details
column.
8-30
Programmatically Collect Pool Monitoring Data
To clear the information for the currently selected parfeval computation and view activity data for
all the workers again, in the Selections section of the Pool Dashboard, select Clear Selections.
See Also
Functions
parfor | parfeval | stop | parforOptions
Objects
ActivityMonitor | ActivityMonitorResults
Tools
Pool Dashboard
8-31
8 Performance Profiling
To save pool monitoring data you collect using the Pool Dashboard as a MAT file:
Alternatively, you can collect pool monitoring data programmatically using an ActivityMonitor
object. You can then use the save or results function to retrieve pool monitoring results as an
ActivityMonitorResults object. To learn more, see “Programmatically Collect Pool Monitoring
Data” on page 8-26.
For example, to save the ActivityMonitorResults object with the name monitoringResults
to a MAT file with the name poolMonitoringResults, in the MATLAB Command Window, run:
save("poolMonitoringResults","monitoringResults");
• Save from the Workspace panel.
• In the Workspace panel, right-click the ActivityMonitorResults object variable and select
Save Selection.
• In the Save Workspace Variables dialog box, provide a name for the file and select Save.
• Open and save in the Pool Dashboard.
• Visualize the monitoring results in the Pool Dashboard. The parpoolDashboard function
opens the Pool Dashboard and displays the monitoring results in the
ActivityMonitorResults object, monitoringResults.
parpoolDashboard(monitoringResults);
• In the File section of the Pool Dashboard, click Save.
• In the Save File to Write dialog box, provide a name for the file.
• Click Save.
8-32
Save and View Pool Monitoring Results
2 In the Select File to Open dialog box, select the saved pool monitoring results MAT file you want
to open.
See Also
Objects
ActivityMonitor | ActivityMonitorResults
Tools
Pool Dashboard
Related Examples
• “Monitor Pool Workers with Pool Dashboard” on page 8-2
• “Programmatically Collect Pool Monitoring Data” on page 8-26
8-33
8 Performance Profiling
The parallel profiler provides an extension of the profile command and the profile viewer
specifically for workers in a parallel pool, to enable you to see how much time each worker spends
evaluating each function and how much time communicating or waiting for communications with the
other workers. For more information about the standard profiler and its views, see “Profile Your Code
to Improve Performance”.
For parallel profiling, you use the mpiprofile command in a similar way to how you use profile.
This example shows how to profile parallel code using the parallel profiler on workers in a parallel
pool.
Run your parallel code. For the purposes of this example, use a simple parfor loop that iterates over
a series of values.
values = [5 12 13 1 12 5];
tic;
parfor idx = 1:numel(values)
u = rand(values(idx)*3e4,1);
out(idx) = max(conv(u,u));
end
toc
After the code completes, view the results from the parallel profiler by calling mpiprofile viewer.
This action also stops profile data collection.
mpiprofile viewer
The report shows execution time information for each function that runs on the workers. You can
explore which functions take the most time in each worker.
Generally, comparing the workers with the minimum and maximum total execution times is useful. To
do so, click Max vs Min Total Time in the report. In this example, observe that conv executes
8-34
Profiling Parallel Code
multiple times and takes significantly longer in one worker than in the other. This observation
suggests that the load might not be distributed evenly across the workers.
• If you do not know the workload of each iteration, then a good practice is to randomize the
iterations, such as in the following sample code.
values = values(randperm(numel(values)));
• If you do know the workload of each iteration in your parfor loop, then you can use
parforOptions to control the partitioning of iterations into subranges for the workers. For more
information, see parforOptions.
In this example, the greater values(idx) is, the more computationally intensive the iteration is.
Each consecutive pair of values in values balances low and high computational intensity. To
distribute the workload better, create a set of parfor options to divide the parfor iterations into
subranges of size 2.
opts = parforOptions(pool,"RangePartitionMethod","fixed","SubrangeSize",2);
Run the same code as before. To use the parfor options, pass them to the second input argument of
parfor.
values = [5 12 13 1 12 5];
tic;
parfor (idx = 1:numel(values),opts)
u = rand(values(idx)*3e4,1);
out(idx) = max(conv(u,u));
end
toc
In the report, select Max vs Min Total Time to compare the workers with the minimum and
maximum total execution times. Observe that this time, the multiple executions of conv take a similar
amount of time in all workers. The workload is now better distributed.
8-35
8 Performance Profiling
The remainder of this section is an example that illustrates some of the features of the parallel profile
viewer. The example profiles parallel execution of matrix multiplication of distributed arrays on a
parallel pool of cluster workers.
parpool
R1 = rand(5e4,'distributed');
R2 = rand(5e4,'distributed');
mpiprofile on
R = R1*R2;
mpiprofile viewer
The last command opens the Profiler window, first showing the Parallel Profile Summary (or function
summary report) for worker 1.
8-36
Profiling Parallel Code
The function summary report displays the data for each function executed on a worker in sortable
columns with the following headers:
Select the name of any function in the list for more details about the execution of that function. The
function detail report for [Link] includes this listing:
8-37
8 Performance Profiling
The code that the report displays comes from the client. If the code has changed on the client since
the communicating job ran on the workers, or if the workers are running a different version of the
functions, the display might not accurately reflect what actually executed.
You can display information for each worker, or use the comparison controls to display information for
several workers simultaneously. Two buttons provide Automatic Comparison Selection, so you can
compare the data from the workers that took the most versus the least amount of time to execute the
code, or data from the workers that spent the most versus the least amount of time in performing
interworker communication. Manual Comparison Selection allows you to compare data from
specific workers or workers that meet certain criteria.
The following listing from the summary report shows the result of using the Automatic Comparison
Selection of Compare (max vs. min TotalTime). The comparison shows data from worker 50
compared to worker 62 because these are the workers that spend the most versus least amount of
time executing the code.
8-38
Profiling Parallel Code
The following figure shows a summary of all the functions executed during the profile collection time.
The Manual Comparison Selection of max Time Aggregate means that data is considered from
all the workers for all functions to determine which worker spent the maximum time on each
function. Next to each function's name is the worker that took the longest time to execute that
function. The other columns list the data from that worker.
8-39
8 Performance Profiling
The next figure shows a summary report for the workers that spend the most versus least time for
each function. A Manual Comparison Selection of max Time Aggregate against min Time >0
Aggregate generated this summary. Both aggregate settings indicate that the profiler should
consider data from all workers for all functions, for both maximum and minimum. This report lists the
data for [Link] from workers 50 and 62, because they spent the
maximum and minimum times on this function. Similarly, other functions are listed.
Select a function name in the summary listing of a comparison to get a detailed comparison. The
detailed comparison for [Link] looks like this, displaying line-by-line
data from both workers:
8-40
Profiling Parallel Code
To see plots of communication data, select Plot All Per Worker Communication in the Show
Figures menu. The top portion of the plot view report plots how much data each worker receives
from each other worker for all functions.
To see only a plot of interworker communication times, select Plot Communication Time Per
Worker in the Show Figures menu.
8-41
8 Performance Profiling
Plots like those in the previous two figures can help you determine the best way to balance work
among your workers, perhaps by altering the partition scheme of your codistributed arrays.
8-42
Profile Parallel Code
This example shows how to profile parallel code using the parallel profiler on workers in a parallel
pool.
Run your parallel code. For the purposes of this example, use a simple parfor loop that iterates over
a series of values.
values = [5 12 13 1 12 5];
tic;
parfor idx = 1:numel(values)
u = rand(values(idx)*3e4,1);
out(idx) = max(conv(u,u));
end
toc
After the code completes, view the results from the parallel profiler by calling mpiprofile viewer.
This action also stops profile data collection.
mpiprofile viewer
The report shows execution time information for each function that runs on the workers. You can
explore which functions take the most time in each worker.
Generally, comparing the workers with the minimum and maximum total execution times is useful. To
do so, click Max vs Min Total Time in the report. In this example, observe that conv executes
multiple times and takes significantly longer in one worker than in the other. This observation
suggests that the load might not be distributed evenly across the workers.
8-43
8 Performance Profiling
• If you do not know the workload of each iteration, then a good practice is to randomize the
iterations, such as in the following sample code.
values = values(randperm(numel(values)));
• If you do know the workload of each iteration in your parfor loop, then you can use
parforOptions to control the partitioning of iterations into subranges for the workers. For more
information, see parforOptions.
In this example, the greater values(idx) is, the more computationally intensive the iteration is.
Each consecutive pair of values in values balances low and high computational intensity. To
distribute the workload better, create a set of parfor options to divide the parfor iterations into
subranges of size 2.
opts = parforOptions(pool,"RangePartitionMethod","fixed","SubrangeSize",2);
mpiprofile on
Run the same code as before. To use the parfor options, pass them to the second input argument of
parfor.
values = [5 12 13 1 12 5];
tic;
parfor (idx = 1:numel(values),opts)
u = rand(values(idx)*3e4,1);
out(idx) = max(conv(u,u));
end
toc
mpiprofile viewer
In the report, select Max vs Min Total Time to compare the workers with the minimum and
maximum total execution times. Observe that this time, the multiple executions of conv take a similar
amount of time in all workers. The workload is now better distributed.
8-44
Profile Parallel Code
See Also
mpiprofile | parpool | parforOptions
8-45
8 Performance Profiling
This example shows how to profile explicit communication to the nearest neighbor worker. It
illustrates the use of spmdSend, spmdReceive, and spmdSendReceive, showing both the slow
(incorrect) and the fast (optimal) way of implementing this algorithm. The problem is explored using
the parallel profiler. For getting started with parallel profiling, see “Profiling Parallel Code” on page
8-34.
The Algorithm
The algorithm we are profiling is a nearest neighbor communication pattern. Each MATLAB worker
needs data only from itself and one neighboring lab. This type of data parallel pattern lends itself well
to many matrix problems, but when done incorrectly, can be needlessly slow. In other words, each lab
depends on data that is already available on an adjacent lab. For example, on a four-lab cluster, lab 1
wants to send some data to lab 2 and needs some data from lab 4 so each lab depends on only one
other lab:
1 depends on -> 4
2 depends on -> 1
3 depends on -> 2
4 depends on -> 3
It is possible to implement any given communication algorithm using spmdSend and spmdReceive.
spmdReceive always blocks your program until the communication is complete, while spmdSend
might not if the data is small. Using spmdSend first, though, doesn't help in most cases.
One way to accomplish this algorithm is to have every worker wait for a receive, and only one worker
start the communication chain by completing a send and then a receive. Alternatively, we can use
spmdSendReceive, and at first glance it may not be apparent that there should be a major
difference in performance.
You can view the code for pctdemo_aux_profbadcomm and pctdemo_aux_profcomm to see the
complete implementations of this algorithm. Look at the first file and notice that it uses spmdSend
and spmdReceive for communication.
It is a common mistake to start thinking in terms of spmdSend and spmdReceive when it is not
necessary. Looking at how this pctdemo_aux_profbadcomm implementation performs will give us a
better idea of what to expect.
8-46
Profiling Explicit Parallel Communication
spmd
spmdBarrier; % to ensure the workers all start at the same time
mpiprofile reset;
mpiprofile on;
pctdemo_aux_profbadcomm;
end
Worker 1:
sending to 2
Worker 2:
receive from 1
Worker 3:
receive from 2
Worker 4:
receive from 3
Worker 5:
receive from 4
Worker 6:
receive from 5
Worker 7:
receive from 6
Worker 8:
receive from 7
Worker 9:
receive from 8
Worker 10:
receive from 9
Worker 11:
receive from 10
Worker 12:
receive from 11
Worker 1:
receive from 12
Worker 2:
sending to 3
Worker 3:
sending to 4
Worker 4:
sending to 5
Worker 5:
sending to 6
Worker 6:
sending to 7
Worker 7:
sending to 8
Worker 8:
sending to 9
Worker 9:
sending to 10
Worker 10:
sending to 11
Worker 11:
sending to 12
Worker 12:
sending to 1
8-47
8 Performance Profiling
mpiprofile viewer
The Parallel Profile Summary report is displayed. On this page, you can see time spent waiting in
communications as an orange bar under the Total Time Plot column. The data below shows that
considerable amount of time was spent waiting. Let's see how the parallel profiler helps to identify
the causes of these waits.
Quickstart Steps
1 View the Parallel Profile Summary table and click the Max vs. Min Total Time button in the
Compare section of the toolstrip. Observe the large orange waiting time indicated for the
pctdemo_aux_profbadcomm>iRecFromPrevLab entry. This is an early indication that there is
something wrong with a corresponding send, either because of network problems or algorithm
problems.
2 To view the worker to worker communication plots, expand the Plots section of the Parallel
Profile Summary and click the Heatmap button in the Plots section of the toolstrip. The first
figure in this view shows all the data received by each worker. In this example each worker is
receiving the same amount of data from the previous worker, so it doesn't seem to be a data
distribution problem. The second figure shows the various communication times including the
time spent waiting for communication. In the third figure, the Comm Waiting Time Per Worker
plot shows a stepwise increase in waiting time. An example Comm Waiting Time Per Worker plot
can be seen below using a 12-node cluster. It is good to go back and check what is happening on
the source worker.
3 Browse what's happening on worker 1. Click the top-level pctdemo_aux_profbadcomm function
to go to the function detail report. Scroll down to the Function listing section and see where
worker 1 spends time and which lines are covered. For comparison with the last worker, select
the last worker using the Go to worker menu in the Compare section of the toolstrip, and
examine the Busy lines table.
To see all the profiled lines of code, scroll down to the last item in the page. An example of this
annotated code listing can be seen below.
8-48
Profiling Explicit Parallel Communication
To clearly see the problem with our usage of spmdSend and spmdReceive, look at the following
Communication Time (Waiting) plot from a 12-node cluster.
In the plot above, you can see the unnecessary waiting using the plot of worker to worker
communication for all functions. The waiting time increases by worker number because
spmdReceive blocks until the corresponding paired spmdSend has completed. Hence, you get
sequential communication even though subsequent workers only need the data that is originating in
the immediate neighbor spmdIndex.
8-49
8 Performance Profiling
You can use spmdSendReceive to send and receive data simultaneously from the worker that you
depend on to get minimal waiting time. You can see this in the corrected version of the
communication pattern implemented in pctdemo_aux_profcomm. Clearly, using spmdSendReceive
is not possible if you need to receive data before you can send it. In such cases, use spmdSend and
spmdReceive to ensure chronological order. However, in cases like this example, when there is no
need to receive data before sending, use spmdSendReceive. Profile this version without resetting
the data collected on the previous version (use mpiprofile resume).
spmd
spmdBarrier;
mpiprofile resume;
pctdemo_aux_profcomm;
end
Worker 1:
sending to 2 receiving from 12
Worker 2:
sending to 3 receiving from 1
Worker 3:
sending to 4 receiving from 2
Worker 4:
sending to 5 receiving from 3
Worker 5:
sending to 6 receiving from 4
Worker 6:
sending to 7 receiving from 5
Worker 7:
sending to 8 receiving from 6
Worker 8:
sending to 9 receiving from 7
Worker 9:
sending to 10 receiving from 8
Worker 10:
sending to 11 receiving from 9
Worker 11:
sending to 12 receiving from 10
Worker 12:
sending to 1 receiving from 11
mpiprofile viewer
This corrected version reduces the waiting time to effectively zero. To see this, view the plots of
worker to worker communication for the pctdemo_aux_profcomm function. Using
spmdSendReceive, the same communication pattern now spends nearly no time waiting, as shown
in the following Communication Time (Waiting) plot.
8-50
Profiling Explicit Parallel Communication
For each 2-D image plot, the coloring scheme is normalized to the task at hand. Therefore, do not use
the coloring scheme in the plot shown above to compare with other plots, since colors are normalized
and are dependent on the maximum value. For this example, using the max value is the best way to
compare the huge difference in waiting times when we use pctdemo_aux_profcomm instead of
pctdemo_aux_profbadcomm.
8-51
8 Performance Profiling
This example shows how to profile the implicit communication that occurs when using an unevenly
distributed array. For getting started with parallel profiling, see “Profiling Parallel Code” on page 8-
34.
This example shows how to use the parallel profiler in the case of an unevenly distributed array. The
easiest way to create a codistributed array is to pass a codistributor as an argument, such as in
rand(N, codistributor). This evenly distributes your matrix of size N between your MATLAB®
workers. To get an unbalanced data distribution, you can get some number of columns of a
codistributed array as a function of spmdIndex.
The data transfer plots in this example are produced using a local cluster with 12 workers.
Everything else is shown running on a local cluster with 4 workers.
The Algorithm
The algorithm we chose for this codistributed array is relatively simple. We generate a large matrix
such that each lab gets an approximately 512-by-512 submatrix, except for the first lab. The first lab
receives only one column of the matrix and the other columns are assigned to the last lab. Thus, on a
four-lab cluster, lab 1 keeps only a 1-by-512 column, labs 2 and 3 have their allotted partitions, and
lab 4 has its allotted partition plus the additional columns (left over from lab 1). The end result is an
unbalanced workload when doing zero communication element-wise operations (such as sin) and
communication delays with data parallel operations (such as codistributed/mtimes). We start
with a data parallel operation first (codistributed/mtimes). We then perform, in a loop, sqrt,
sin, and inner product operations, all of which only operate on individual elements of the matrix.
The MATLAB file code for this example can be found in: pctdemo_aux_profdistarray
In this example, the size of the matrix differs depending on the number of MATLAB workers
(spmdSize). However, it takes approximately the same amount of computation time (not including
communication) to run this example on any cluster, so you can try using a larger cluster without
having to wait a long time.
spmd
spmdBarrier; % synchronize all the labs
mpiprofile reset
mpiprofile on
pctdemo_aux_profdistarray();
end
Worker 1:
This lab has 1024 rows and 1 columns of a codistributed array
Worker 2:
This lab has 1024 rows and 256 columns of a codistributed array
Worker 3:
This lab has 1024 rows and 256 columns of a codistributed array
Worker 4:
This lab has 1024 rows and 511 columns of a codistributed array
Worker 1:
Calling mtimes on codistributed arrays
Calling embarrassingly parallel math functions (i.e. no communication is required)
on a codistributed array.
Done
8-52
Profiling Load Unbalanced Codistributed Arrays
Worker 2:
Calling mtimes on codistributed arrays
Calling embarrassingly parallel math functions (i.e. no communication is required)
on a codistributed array.
Done
Worker 3:
Calling mtimes on codistributed arrays
Calling embarrassingly parallel math functions (i.e. no communication is required)
on a codistributed array.
Done
Worker 4:
Calling mtimes on codistributed arrays
Calling embarrassingly parallel math functions (i.e. no communication is required)
on a codistributed array.
Done
mpiprofile viewer
First, browse the Parallel Profile Summary, making sure it is sorted by the execution time by clicking
the Total Time column. Then follow the link for the function pctdemo_aux_profdistarray to see
the Function Detail Report.
Each MATLAB function entry has its own Busy lines table, which is useful if you want to profile
multiple programs or examples at the same time.
• In the Function Detail Report, observe the communication information for the executed MATLAB
code on a line-by-line basis.
• To compare profiling information, click the Busy Lines button in the View section of the app
toolstrip. In the Compare section of the toolstrip, click the Max vs. Min Total Time button and
choose the numbers of the workers you want to compare in the Go to worker and Compare with
menus. Observe the Busy lines table and check to see which line numbers took the most time.
There are no for-loops in this code and no increasing complexity. However, there still is a large
difference in computation load between the labs. Look at line 35, which contains the code
sqrt( sin( D .* D ) );.
Despite the fact that no communication is required for this element-wise operation, the performance
is not optimal, because some labs do more work than others. In the second row, (D*D*D), the total
8-53
8 Performance Profiling
time taken is the same on both labs. However, the Data Received and Data Sent columns show a large
difference in the amount of data sent and received. The time taken for this mtimes operation is
similar on all labs, because the codistributed array communication implicitly synchronizes
communication between them.
In the last column of the Busy lines table, a bar shows the percentage for the selected field. These
bars can also be used to visually compare Total Time, and Data Sent or Data Received of the main and
comparison labs.
To get more specific information about a codistributed array operation, click the relevant function
name in the Function Detail Report.
To get the inter-lab communication data, click Heatmap in the Plots section of the toolstrip. In the
first figure, you can see that lab 1 transfers the most amount of data, and the last lab (lab 12)
transfers the least amount of data.
Using the heatmaps, you can also see the amount of data communicated between each lab. This is
constant for all labs except for the first and last labs. When there is no explicit communication, this
indicates a distribution problem. In a typical codistributed array mtimes operation, labs that have the
least amount of data (e.g., lab 1) receive all the required data from their neighboring labs (e.g., lab
2).
In the Data Transferred plot, there is a significant decrease in the amount of data transferred to the
last lab and an increase in the amount transferred to the first lab. Observing the Communication
Time plot (not shown) further illustrates that there is something different going on in the first lab.
That is, the first lab is spending the longest amount of time in communication.
8-54
Profiling Load Unbalanced Codistributed Arrays
As you can see, the uneven distribution of a matrix causes unnecessary communication delays when
using data parallel codistributed array operations and uneven work distribution with task parallel (no
communication) operations. In addition, labs (like the first lab in this example) that are receiving
more data start with the least amount of data prior to the codistributed array operation.
8-55
8 Performance Profiling
Often a network is configured to not allow services running as LocalSystem to access UNC or
mapped network shares. In this case, you must run the mjs service under a different user with rights
to log on as a service. See the section “Set MATLAB Job Scheduler Service User” (MATLAB Parallel
Server) in the MATLAB Parallel Server System Administrator's Guide.
If a worker cannot find the task function, it returns the error message
Error using ==> feval
Undefined command/function 'function_name'.
The worker that ran the task did not have access to the function function_name. One solution is to
make sure the location of the function's file, function_name.m, is included in the job's
AdditionalPaths property. Another solution is to transfer the function file to the worker by adding
function_name.m to the AttachedFiles property of the job.
If a worker cannot save or load a file, you might see the error messages
??? Error using ==> save
Unable to write file [Link]: permission denied.
??? Error using ==> load
Unable to read file [Link]: No such file or directory.
A job or task might get stuck in the queued state. To investigate the cause of this problem, look for
the scheduler's logs:
8-56
Troubleshooting and Debugging
• The MATLAB worker failed to start due to licensing errors, the executable is not on the default
path on the worker machine, or is not installed in the location where the scheduler expected it to
be.
• MATLAB could not read/write the job input/output files in the scheduler's job storage location. The
storage location might not be accessible to all the worker nodes, or the user that MATLAB runs as
does not have permission to read/write the job files.
• If using a generic scheduler:
If your job returned no results (i.e., fetchOutputs(job) returns an empty cell array), it is probable
that the job failed and some of its tasks have their Error properties set.
You can use the following code to identify tasks with error messages:
This code displays the nonempty error messages of the tasks found in the job object yourjob.
Debug Logs
If you are using a supported third-party scheduler, you can use the getDebugLog function to read the
debug log from the scheduler for a particular job or task.
For example, find the failed job on your LSF scheduler, and read its debug log:
c = parcluster('my_lsf_profile')
failedjob = findJob(c, 'State', 'failed');
message = getDebugLog(c, failedjob(1))
8-57
8 Performance Profiling
Detailed instructions for other methods of diagnosing connection problems between the client and
MATLAB Job Scheduler can be found in some of the Bug Reports listed on the MathWorks Web site.
The following sections can help you identify the general nature of some connection problems.
If you cannot locate or connect to your MATLAB Job Scheduler with parcluster, the most likely
reasons for this failure are:
If a warning message says that the MATLAB Job Scheduler cannot open a TCP connection to the
client computer, the most likely reasons for this are
• Firewalls do not allow traffic from the MATLAB Job Scheduler to the client.
• The MATLAB Job Scheduler cannot resolve the short hostname of the client computer. Use
pctconfig to change the hostname that the MATLAB Job Scheduler will use for contacting the
client.
if ($?TERM != 0) then
if ("$TERM" != "dumb") then
<your command>
endif
endif
The sftp server starts a shell, usually bash or tcsh, to set your standard read and write permissions
appropriately before transferring files. The server initializes the shell in the standard way, calling files
like .bashrc and .cshrc. The problem occurs if your shell emits text to standard out when it starts.
That text is transferred back to the sftp client running inside MATLAB, and is interpreted as the size
of the sftp server's response message.
To work around this error, locate the shell startup file code that is emitting the text, and either
remove it or bracket it within if statements to see if the sftp server is starting the shell:
if ($?TERM != 0) then
if ("$TERM" != "dumb") then
8-58
Troubleshooting and Debugging
/your command/
endif
endif
You can test this outside of MATLAB with a standard UNIX or Windows sftp command-line client
before trying again in MATLAB. If the problem is not fixed, an error message persists:
Connecting to yourSubmitMachine...
Received message too long 1718579042
Connecting to yourSubmitMachine...
8-59
8 Performance Profiling
This example illustrates the basic steps in creating and running a job that contains a few simple
tasks. Each task evaluates the sum function for an input array.
1 Identify a cluster. Use [Link] to indicate that you are using the
Processes cluster; and use parcluster to create the object c to represent this cluster. For
more information, see “Create a Cluster Object” on page 5-30.
[Link]('Processes');
c = parcluster();
2 Create a job. Create job j on the cluster. (For more information, see “Create a Job” on page 5-
30.)
j = createJob(c)
3 Create three tasks within the job j. Each task evaluates the sum of the array that is passed as an
input argument. For more information, see “Create Tasks” on page 5-31.
submit(j);
5 Wait for the job to complete, then get the results from all the tasks of the job. For more
information, see “Fetch the Job Results” on page 5-32.
wait(j)
results = fetchOutputs(j)
results =
[2]
[4]
[6]
6 Delete the job. When you have the results, you can permanently remove the job from the
scheduler's storage location.
delete(j)
See Also
[Link] | parcluster | createJob
Related Examples
• “Program Independent Jobs on Local Cluster” on page 5-30
• “Program Communicating Jobs” on page 5-40
8-60
Benchmark Cluster Workers
This example shows how to run the MATLAB® benchmark on your cluster workers. The benchmark
measures the execution speed of several MATLAB computations. You can plot these results and
compare the performance of the client and workers.
This example uses pbench, a function that runs a subset of the tests in bench, the MATLAB
benchmark. The tests in this subset are LU, FFT, ODE, and Sparse. For details on these tests, see
bench.
tClient = pbench
tClient = 1×4
Create a parallel pool p using the parpool function. By default, parpool starts a parallel pool with
workers on your default cluster. Select your default cluster on the MATLAB Home tab, in the
Environment area, in Parallel > Select a Default Cluster.
p = parpool();
Run the MATLAB benchmark on the workers using the parfevalOnAll function. parfevalOnAll
offloads the execution of a function to all the workers in the pool, and returns a
[Link] object to hold the results when they are ready. To obtain the results
from the workers, use fetchOutputs on the future object.
f = parfevalOnAll(@pbench,1);
tWorkers = fetchOutputs(f);
Combine the results of the client and workers, and plot them using a bar plot. Compare the relative
performances of the workers and client.
tClientAndWorkers = [tClient;tWorkers];
bar(tClientAndWorkers');
xticklabels({'LU','FFT','ODE','Sparse'});
xlabel("Benchmark type");
ylabel("Benchmark execution time (seconds)");
workerNames = strcat("Worker ",string(1:size(tWorkers,1)));
legend(["Client",workerNames],'Location','bestoutside');
8-61
8 Performance Profiling
By default, the MATLAB client is enabled for multithreading. Multithreading enables MATLAB
numerical functions, such as lu or fft, to run on multiple cores using multiple computational
threads. The workers use a single computational thread by default, because they are typically
associated with a single core. Therefore, the LU test, for example, runs faster on the MATLAB client
than on the workers. Other problems, such as ODEs, cannot benefit from multithreading, so they
perform the same on the MATLAB client and workers. Consider this difference when deciding
whether to distribute computations to MATLAB parallel workers, such as with parfor. For more
details, see “Deciding When to Use parfor” on page 2-2. For more information on multithreading, see
Run MATLAB on multicore and multiprocessor machines.
See Also
bench | parpool | fetchOutputs | parfevalOnAll
Related Examples
• “Benchmark Your Cluster with the HPC Challenge” on page 8-84
• “Scale Up from Desktop to Cluster” on page 7-49
8-62
Benchmarking A\b
Benchmarking A\b
This example shows how to benchmark solving a linear system on a cluster. The MATLAB® code to
solve for x in A*x = b is very simple. Most frequently, one uses matrix left division, also known as
mldivide or the backslash operator (\), to calculate x (that is, x = A\b). Benchmarking the
performance of matrix left division on a cluster, however, is not as straightforward.
One of the most challenging aspects of benchmarking is to avoid falling into the trap of looking for a
single number that represents the overall performance of the system. We will look at the performance
curves that might help you identify the performance bottlenecks on your cluster, and maybe even
help you see how to benchmark your code and be able to draw meaningful conclusions from the
results.
Related examples:
It is very important to choose the appropriate matrix size for the cluster. We can do this by specifying
the amount of system memory in GB available to each worker as an input to this example function.
The default value is very conservative; you should specify a value that is appropriate for your system.
if nargin == 0
memoryPerWorker = 8.00; % In GB
% warning('pctexample:backslashbench:BackslashBenchUsingDefaultMemory', ...
% ['Amount of system memory available to each worker is ', ...
% 'not specified. Using the conservative default value ', ...
% 'of %.2f gigabytes per worker.'], memoryPerWorker);
end
Avoiding Overhead
To get an accurate measure of our capability to solve linear systems, we need to remove any possible
source of overhead. This includes getting the current parallel pool and temporarily disabling the
deadlock detection capabilities.
p = gcp;
if isempty(p)
error('pctexample:backslashbench:poolClosed', ...
['This example requires a parallel pool. ' ...
'Manually start a pool using the parpool command or set ' ...
'your parallel settings to automatically start a pool.']);
end
poolSize = [Link];
pctRunOnAll 'mpiSettings(''DeadlockDetection'', ''off'');'
Starting parallel pool (parpool) using the 'bigMJS' profile ... connected to 12 workers.
8-63
8 Performance Profiling
We want to benchmark matrix left division (\), and not the cost of entering an spmd block, the time it
takes to create a matrix, or other parameters. We therefore separate the data generation from the
solving of the linear system, and measure only the time it takes to do the latter. We generate the input
data using the 2-D block-cyclic codistributor, as that is the most effective distribution scheme for
solving a linear system. Our benchmarking then consists of measuring the time it takes all the
workers to complete solving the linear system A*x = b. Again, we try to remove any possible source
of overhead.
function [A, b] = getData(n)
fprintf('Creating a matrix of size %d-by-%d.\n', n, n);
spmd
% Use the codistributor that usually gives the best performance
% for solving linear systems.
codistr = codistributor2dbc([Link], ...
[Link], ...
'col');
A = [Link](n, n, codistr);
b = [Link](n, 1, codistr);
end
end
Just like with a great number of other parallel algorithms, the performance of solving a linear system
in parallel depends greatly on the matrix size. Our a priori expectations are therefore that the
computations be:
It is therefore important to time the computations for a number of different matrix sizes to gain an
understanding of what "small," "large," and "too large" mean in this context. Based on previous
experiments, we expect:
These are heuristics, and the precise values may change between releases. It is therefore important
that we use matrix sizes that span this entire range and verify the expected performance.
Notice that by changing the problem size according to the number of workers, we employ weak
scaling. Other benchmarking examples, such as “Simple Benchmarking of PARFOR Using Blackjack”
8-64
Benchmarking A\b
on page 8-89 and “Benchmarking Independent Jobs on the Cluster” on page 8-94, also employ
weak scaling. As those examples benchmark task parallel computations, their weak scaling consists
of making the number of iterations proportional to the number of workers. This example, however, is
benchmarking data parallel computations, so we relate the upper size limit of the matrices to the
number of workers.
% Declare the matrix sizes ranging from 1000-by-1000 up to 45% of system
% memory available to each worker.
maxMemUsagePerWorker = 0.45*memoryPerWorker*1024^3; % In bytes.
maxMatSize = round(sqrt(maxMemUsagePerWorker*poolSize/8));
matSize = round(linspace(1000, maxMatSize, 5));
We use the number of floating point operations per second as our measure of performance because
that allows us to compare the performance of the algorithm for different matrix sizes and different
number of workers. If we are successful in testing the performance of matrix left division for a
sufficiently wide range of matrix sizes, we expect the performance graph to look similar to the
following:
8-65
8 Performance Profiling
• What is the best performance we can possibly achieve for a given number of workers?
• For which matrix sizes do 16 workers perform better than 8 workers?
• Is the system memory limiting the peak performance?
Given a matrix size, the benchmarking function creates the matrix A and the right-hand side b once,
and then solves A\b multiple times to get an accurate measure of the time it takes. We use the
floating operations count of the HPC Challenge, so that for an n-by-n matrix, we count the floating
point operations as 2/3*n^3 + 3/2*n^2.
function gflops = benchFcn(n)
numReps = 3;
[A, b] = getData(n);
time = inf;
% We solve the linear system a few times and calculate the Gigaflops
% based on the best time.
for itr = 1:numReps
tcurr = timeSolve(A, b);
if itr == 1
fprintf('Execution times: %f', tcurr);
else
fprintf(', %f', tcurr);
end
time = min(tcurr, time);
end
fprintf('\n');
flop = 2/3*n^3 + 3/2*n^2;
gflops = flop/time/1e9;
end
Having done all the setup, it is straightforward to execute the benchmarks. However, the
computations may take a long time to complete, so we print some intermediate status information as
we complete the benchmarking for each matrix size.
fprintf(['Starting benchmarks with %d different matrix sizes ranging\n' ...
'from %d-by-%d to %d-by-%d.\n'], ...
length(matSize), matSize(1), matSize(1), matSize(end), ...
matSize(end));
gflops = zeros(size(matSize));
for i = 1:length(matSize)
gflops(i) = benchFcn(matSize(i));
fprintf('Gigaflops: %f\n\n', gflops(i));
end
[Link] = matSize;
[Link] = gflops;
8-66
Benchmarking A\b
We can now plot the results, and compare to the expected graph shown above.
fig = figure;
ax = axes('parent', fig);
plot(ax, matSize/1000, gflops);
lines = [Link];
[Link] = '+';
ylabel(ax, 'Gigaflops')
xlabel(ax, 'Matrix size in thousands')
titleStr = sprintf(['Solving A\\b for different matrix sizes on ' ...
'%d workers'], poolSize);
title(ax, titleStr, 'Interpreter', 'none');
8-67
8 Performance Profiling
If the benchmark results are not as good as you might expect, here are some things to consider:
• The underlying implementation is using ScaLAPACK, which has a proven reputation of high
performance. It is therefore very unlikely that the algorithm or the library is causing inefficiencies,
but rather the way in which it is used, as described in the items below.
• If the matrices are too small or too large for your cluster, the resulting performance will be poor.
• If the network communications are slow, performance will be severely impacted.
• If the CPUs and the network communications are both very fast, but the amount of memory is
limited, it is possible you are not able to benchmark with sufficiently large matrices to fully utilize
the available CPUs and network bandwidth.
• For ultimate performance, it is important to use a version of MPI that is tailored for your
networking setup, and have the workers running in such a manner that as much of the
communication happens through shared memory as possible. It is, however, beyond the scope of
this example to explain how to identify and solve those types of problems.
We now look at how to compare different numbers of workers by viewing data obtained by running
this example using different numbers of workers. This data is obtained on a different cluster from the
one above.
Other examples such as “Benchmarking Independent Jobs on the Cluster” on page 8-94 have
explained that when benchmarking parallel algorithms for different numbers of workers, one usually
employs weak scaling. That is, as we increase the number of workers, we increase the problem size
proportionally. In the case of matrix left division, we have to show additional care because the
performance of the division depends greatly on the size of the matrix. The following code creates a
graph of the performance in Gigaflops for all of the matrix sizes that we tested with and all the
different numbers of workers, as that gives us the most detailed picture of the performance
characteristics of matrix left division on this particular cluster.
8-68
Benchmarking A\b
The first thing we notice when looking at the graph above is that 64 workers allow us to solve much
larger linear systems of equations than is possible with only 4 workers. Additionally, we can see that
even if one could work with a matrix of size 60,000-by-60,000 on 4 workers, we would get a
performance of approximately only 10 Gigaflops. Thus, even if the 4 workers had sufficient memory to
solve such a large problem, 64 workers would nevertheless greatly outperform them.
Looking at the slope of the curve for 4 workers, we can see that there is only a modest performance
increase between the three largest matrix sizes. Comparing this with the earlier graph of the
expected performance of A\b for different matrix sizes, we conclude that we are quite close to
achieving peak performance for 4 workers with matrix size of 7772-by-7772.
Looking at the curve for 8 and 16 workers, we can see that the performance drops for the largest
matrix size, indicating that we are near or already have exhausted available system memory.
However, we see that the performance increase between the second and third largest matrix sizes is
very modest, indicating stability of some sort. We therefore conjecture that when working with 8 or
16 workers, we would most likely not see a significant increase in the Gigaflops if we increased the
system memory and tested with larger matrix sizes.
Looking at the curves for 32 and 64 workers, we see that there is a significant performance increase
between the second and third largest matrix sizes. For 64 workers, there is also a significant
performance increase between the two largest matrix sizes. We therefore conjecture that we run out
of system memory for 32 and 64 workers before we have reached peak performance. If that is
correct, then adding more memory to the computers would both allow us to solve larger problems
and perform better at those larger matrix sizes.
8-69
8 Performance Profiling
Speedup
The traditional way of measuring speedup obtained with linear algebra algorithms such as backslash
is to compare the peak performance. We therefore calculate the maximum number of Gigaflops
achieved for each number of workers.
We therefore conclude that we get a speedup of approximately 13.5 when increasing the number of
workers 16 fold, going from 4 workers to 64. As we noted above, the performance graph indicates
that we might be able to increase the performance on 64 workers (and thereby improve the speedup
even further), by increasing the system memory on the cluster computers.
This data was generated using 16 dual-processor, octa-core computers, each with 64 GB of memory,
connected with GigaBit Ethernet. When using 4 workers, they were all on a single computer. We used
2 computers for 8 workers, 4 computers for 16 workers, etc.
Now that we have concluded our benchmarking, we can safely re-enable the deadlock detection in
the current parallel pool.
end
ans =
8-70
Resource Contention in Task Parallel Problems
This example shows why it is difficult to give a concrete answer to the question "How will my parallel
code perform on my multicore machine or on my cluster?"
The answer most commonly given is "It depends on your code as well as your hardware" and this
example will try to explain why this is all one can say without more information.
This example uses parallel code running on workers on the same multicore CPU and highlights the
problem of contention for memory access. To simplify the problem, this example benchmarks your
computer's ability to execute task parallel problems that do not involve disk IO. This allows you to
ignore several factors that might affect parallel code execution, such as:
This figure shows the speedup achieved when performing operations in parallel on a number of
concurrent processes.
8-71
8 Performance Profiling
To understand why it is worthwhile to perform such a simple benchmark, consider the following
example: If one person can fill one bucket of water, carry it some distance, empty it, and take it back
to refill it in one minute, how long will it take two people to go the same round trip with one bucket
each? This simple analogy closely reflects the task parallel benchmarks in this example. At first
glance, it seems absurd that there should be any decrease in efficiency when two people are
simultaneously doing the same thing as compared to one person.
If all things are perfect in our previous example, two people complete one loop with a bucket of water
each in one minute. Each person quickly fills one bucket, carries the bucket over to the destination,
empties it and walks back, and they make sure never to interfere or interrupt one another.
However, imagine that they have to fill the buckets from a single, small water hose. If they arrive at
the hose at the same time, one would have to wait. This is one example of a contention for a shared
resource. Maybe the two people don't need to simultaneously use the hose, and the hose therefore
serves their needs; but if you have 10 people transporting a bucket each, some might always have to
wait.
In the analogy, the water hose corresponds to the computer hardware, in particular memory. If
multiple programs are running simultaneously on one CPU core each, and they all need access to
data that is stored in the computer's memory, some of the programs may have to wait because of
limited memory bandwidth.
8-72
Resource Contention in Task Parallel Problems
Imagine that there is contention at the hose when two people are carrying one bucket each, but then
the task is changed and the people must carry the water quite a bit further away from the hose. When
performing this modified task, the two people spend a larger proportion of their time doing work, i.e.,
walking with the buckets, and a smaller proportion of their time contending over the shared resource,
the hose. They are therefore less likely to need the hose at the same time, so this modified task has a
higher parallel efficiency than the original one.
In the case of the benchmarks in this example, this corresponds on the one hand to running programs
that require lots of access to the computer's memory, but they perform very little work with the data
once fetched. If, on the other hand, the programs perform lots of computations with the data, it
becomes irrelevant how long it took to fetch the data, the computation time will overshadow the time
spent waiting for access to the memory.
The predictability of the memory access of an algorithm also effects how contended the memory
access will be. If the memory is accessed in a regular, predictable manner, there will be less
contention than if the memory is accessed in an irregular manner. This can be seen further below,
where, for example, singular value decomposition calculations result in more contention than matrix
multiplication.
Close any existing parallel pools and start a process-based parallel pool using parpool. With default
settings, parpool starts a pool on the local machine with one worker per physical CPU core, up to
the limit set in the 'Processes' profile.
delete(gcp("nocreate")); % Close any existing parallel pools
p = parpool("Processes");
poolSize = [Link];
A timing function, timingFcn, is provided at the end of this example. The timing function executes a
function five times within an spmd statement, and retains the minimum execution time observed for a
given level of concurrency.
As stated above, this example benchmarks task parallel problems, measuring only the actual runtime.
This means that the example does not benchmark the performance of MATLAB®, Parallel Computing
Toolbox™, or the spmd language construct. Instead, the example benchmarks the ability of the OS
and hardware to simultaneously run multiple copies of a program.
Create an input matrix large enough that it needs to be brought from the computer's memory onto
the CPU each time it is processed. That is, make it large enough to cause resource contention.
sz = 2048;
m = rand(sz*sz,1);
Summation Operations
A function for performing repeated summations on a single array, sumOp, is provided at the end of
this example. Since the summation operations are computationally lightweight, you can expect to see
8-73
8 Performance Profiling
resource contention when running multiple copies of this function simultaneously with a large input
array. Consequently, you should expect it to take longer to evaluate the summation function when
performing multiple such evaluations concurrently than it takes to execute a single such evaluation
on an otherwise idle CPU.
A function for performing repeated Fast Fourier Transforms (FFTs) on a vector, fftOp, is provided at
the end of this example. FFT operations are more computationally intensive than summation
operations, and therefore you should expect not to see the same performance degradations when
concurrently evaluating multiple calls to the FFT function as with calls to the summation function.
A function for performing matrix multiplication, multOp, is provided at the end of this example. The
memory access in matrix multiplication is very regular and so this operation therefore has the
potential to be executed quite efficiently in parallel on a multicore machine.
Measure how long it takes to simultaneously evaluate N summation functions on N workers for values
of N from 1 to the size of the parallel pool.
Measure how long it takes to simultaneously evaluate N FFT functions on N workers for values of N
from 1 to the size of the parallel pool.
Measure how long it takes to simultaneously evaluate N matrix multiplication functions on N workers
for values of N from 1 to the size of the parallel pool.
m = reshape(m,sz,sz);
tmtimes = timingFcn(@() multOp(m),1:poolSize);
clear m
Combine the timing results into a single array and calculate the speedup achieved by running
multiple function invocations concurrently.
Plot the results in a bar chart. This chart shows the speedup with what is known as weak scaling.
Weak scaling is where the number of processes/processors varies, and the problem size on each
process/processor is fixed. This has the effect of increasing the total problem size as you increase the
number of processes/processors. On the other hand, strong scaling is where the problem size is
fixed and the number of processes/processors varies. The effect of this is that as you increase the
number of processes/processors, the work done by each process/processor decreases.
8-74
Resource Contention in Task Parallel Problems
bar(speedup)
legend('Vector Sum', 'Vector FFT', 'Matrix Mult.', ...
'Location', 'NorthWest')
xlabel('Number of Concurrent Processes');
ylabel('Speedup')
title(['Effect of No. Concurrent Processes on ', ...
'Resource Contention and Speedup']);
Looking at the graph above, you can see that problems can scale differently on the same computer.
Considering the fact that other problems and computers may show very different behavior, it should
become clear why it is impossible to give a general answer to the question "How will my (parallel)
application perform on my multi-core machine or on my cluster?" The answer to that question truly
depends on the application and the hardware in question.
Resource contention does not depend only on the function being executed, but also on the size of the
data being processed. To illustrate this, you will measure the execution times of various functions
with various sizes of input data. As before, you are benchmarking the ability of your hardware to
perform these computations concurrently, and not MATLAB or its algorithms. More functions will be
considered than before so that you can investigate the effects of different memory access patterns as
well as the effects of different data sizes.
Define the data sizes and specify the operations that the tests use.
8-75
8 Performance Profiling
Loop through the different data sizes and the functions, and measure the sequential execution time
and the time it takes to execute concurrently on all of the workers in the parallel pool.
end
8-76
Resource Contention in Task Parallel Problems
Plot the speedup of each operation when running concurrently on all workers in the pool for each of
the data sizes, showing the ideal speedup.
figure
ax = axes;
plot(speedup)
set([Link], {'Marker'}, {'+', 'o', '*', 'x', 's', 'd'}')
hold on
xticks(1:length(szs));
xticklabels(szs + "^2")
xlabel('Number of Elements per Process')
ylim([0 poolSize+0.5])
ylabel('Speedup')
hold off
8-77
8 Performance Profiling
When looking at the results, bear in mind how a function interacts with the cache on a CPU. For small
data sizes, you are always working out of the CPU cache for all these functions. In that case, you can
expect to see good speedup. When the input data is too large to fit into the CPU cache, you start
seeing the performance degradation caused by contention for memory access.
Supporting Functions
Timing Function
The timingFcn function takes a function handle and a number of concurrent processes. For a
number of concurrent processes N, the function measures the execution time for the function
represented by the function handle when it is executed N times within an spmd block using N parallel
workers.
time = zeros(1,length(numConcurrent));
numTests = 5;
spmd(n)
tconcurrent = inf;
% Time the function numTests times, and record the minimum time
8-78
Resource Contention in Task Parallel Problems
end
time(ind) = tconcurrent{1};
clear tconcurrent itr tAllDone
if ind == 1
fprintf('Execution times: %f', time(ind));
else
fprintf(', %f', time(ind));
end
end
fprintf('\n');
end
Summation Function
The function sumOp performs 100 summation operations on an input matrix and accumulates the
results. 100 summation operations are performed in order to get accurate timing.
function sumOp(m)
s = 0;
end
FFT Function
The function fftOp performs 10 FFT operations on an input array. 10 FFT operations are performed
in order to get accurate timing.
function fftOp(m)
end
8-79
8 Performance Profiling
function multOp(m)
m*m;
end
See Also
parpool | spmd | spmdBarrier | spmdReduce
Related Examples
• “Choose a Parallel Computing Solution” on page 1-5
• “Profiling Explicit Parallel Communication” on page 8-46
• “Benchmarking A\b” on page 8-63
• “Use parfor to Speed Up Monte-Carlo Code” on page 2-66
More About
• “Run Code on Parallel Pools” on page 1-28
8-80
Programming Tips
Programming Tips
In this section...
“Program Development Guidelines” on page 8-81
“Current Working Directory of a MATLAB Worker” on page 8-82
“Writing to Files from Workers” on page 8-82
“Saving or Sending Objects” on page 8-82
“Using clear function” on page 8-83
“Running Tasks That Call Simulink Software” on page 8-83
“Using pause Function” on page 8-83
“Transmitting Large Amounts of Data” on page 8-83
“Interrupting a Job” on page 8-83
“Speeding Up a Job” on page 8-83
1 Run code normally on your local machine. First verify all your functions so that as you
progress, you are not trying to debug the functions and the distribution at the same time. Run
your functions in a single instance of MATLAB software on your local computer. For programming
suggestions, see “Techniques to Improve Performance”.
2 Decide whether you need an independent or communicating job. If your application
involves large data sets on which you need simultaneous calculations performed, you might
benefit from a communicating job with distributed arrays. If your application involves looped or
repetitive calculations that can be performed independently of each other, an independent job
might be appropriate.
3 Modify your code for division. Decide how you want your code divided. For an independent
job, determine how best to divide it into tasks; for example, each iteration of a for-loop might
define one task. For a communicating job, determine how best to take advantage of parallel
processing; for example, a large array can be distributed across all your workers.
4 Use spmd to develop parallel functionality. Use spmd with a local pool to develop your
functions on several workers in parallel. As you progress and use spmd on the remote cluster,
that might be all you need to complete your work.
5 Run the independent or communicating job with a local scheduler. Create an independent
or communicating job, and run the job using the local scheduler with several local workers. This
verifies that your code is correctly set up for batch execution, and in the case of an independent
job, that its computations are properly divided into tasks.
6 Run the independent job on only one cluster node. Run your independent job with one task
to verify that remote distribution is working between your client and the cluster, and to verify
proper transfer of additional files and paths.
8-81
8 Performance Profiling
7 Run the independent or communicating job on multiple cluster nodes. Scale up your job
to include as many tasks as you need for an independent job, or as many workers as you need for
a communicating job.
Note The client session of MATLAB must be running the Java® Virtual Machine (JVM®) to use
Parallel Computing Toolbox software. Do not start MATLAB with the -nojvm flag.
CHECKPOINTBASE\HOSTNAME_WORKERNAME_mlworker_log\work
where CHECKPOINTBASE is defined in the mjs_def file, HOSTNAME is the name of the node on which
the worker is running, and WORKERNAME is the name of the MATLAB worker session.
For example, if the worker named worker22 is running on host nodeA52, and its CHECKPOINTBASE
value is C:\TEMP\MJS\Checkpoint, the starting current directory for that worker session is
C:\TEMP\mjs\Checkpoint\nodeA52_worker22_mlworker_log\work
• There is more than one worker per machine, and they attempt to write to the same file.
• The workers have a shared file system, and use the same path to identify a file for writing.
In some cases an error can result, but sometimes the overwriting can occur without error. To avoid an
issue, be sure that each worker or parfor iteration has unique access to any files it writes or saves
data to. There is no problem when multiple workers read from the same file.
Similarly, you cannot send a parallel computing object between parallel computing processes by
means of an object's properties. For example, you cannot pass a MATLAB Job Scheduler, job, task, or
worker object to MATLAB workers as part of a job's JobData property.
Also, system objects (e.g., Java classes, .NET classes, shared libraries, etc.) that are loaded, imported,
or added to the Java search path in the MATLAB client, are not available on the workers unless
explicitly loaded, imported, or added on the workers, respectively. Other than in the task function
code, typical ways of loading these objects might be in taskStartup, jobStartup, and in the case
of workers in a parallel pool, in poolStartup and using pctRunOnAll.
8-82
Programming Tips
clear functions
clears all Parallel Computing Toolbox objects from the current MATLAB session. They still remain in
the MATLAB Job Scheduler. For information on recreating these objects in the client session, see
“Recover Objects” on page 5-38.
Interrupting a Job
Because jobs and tasks are run outside the client session, you cannot use Ctrl+C (^C) in the client
session to interrupt them. To control or interrupt the execution of jobs and tasks, use such functions
as cancel, delete, demote, promote, pause, and resume.
Speeding Up a Job
You might find that your code runs slower on multiple workers than it does on one desktop computer.
This can occur when task startup and stop time is significant relative to the task run time. The most
common mistake in this regard is to make the tasks too small, i.e., too fine-grained. Another common
mistake is to send large amounts of input or output data with each task. In both of these cases, the
time it takes to transfer data and initialize a task is far greater than the actual time it takes for the
worker to evaluate the task function.
8-83
8 Performance Profiling
This example shows how to evaluate the performance of a compute cluster with the HPC Challenge
Benchmark. The benchmark consists of several tests that measure different memory access patterns.
For more information, see HPC Challenge Benchmark.
Start a parallel pool of workers in your cluster using the parpool function. By default, parpool
creates a parallel pool using your default cluster profile. Check your default cluster profile on the
Home tab, in Parallel > Select a Default Cluster. In this benchmark, the workers communicate
with each other. To ensure that inter worker communication is optimized, set 'SpmdEnabled' to
true.
pool = parpool(64,'SpmdEnabled',true);
Use the hpccDataSizes function to compute a problem size for each individual benchmark that
fulfills the requirements of the HPC Challenge. This size depends on the number of workers and the
amount of memory available to each worker. For example, allow use of 1 GB per worker.
gbPerWorker = 1;
dataSizes = hpccDataSizes([Link],gbPerWorker);
The HPC Challenge benchmark consists of several pieces, each of which explores the performance of
different aspects of the system. In the following code, each function runs a single benchmark, and
returns a row table that contains performance results. These functions test a variety of operations on
distributed arrays. MATLAB® partitions distributed arrays across multiple parallel workers, so they
can use the combined memory and computational resources of your cluster. For more information on
distributed arrays, see “Distributed Arrays”.
HPL
hpccHPL(m), known as the Linpack Benchmark, measures the execution rate for solving a linear
system of equations. It creates a random distributed real matrix A of size m-by-m and a real random
distributed vector b of length m, and measures the time to solve the system x = A\b in parallel. The
performance is returned in gigaflops (billions of floating-point operations per second).
hplResult = hpccHPL([Link]);
Starting HPCC benchmark: HPL with data size: 27.8255 GB. Running on a pool of 64 workers
Analyzing and transferring files to the workers ...done.
Finished HPCC benchmark: HPL in 196.816 seconds.
DGEMM
hpccDGEMM(m) measures the execution rate of real matrix-matrix multiplication. It creates random
distributed real matrices A, B, and C, of size m-by-m, and measures the time to perform the matrix
multiplication C = beta*C + alpha*A*B in parallel, where alpha and beta are random scalars.
The performance is returned in gigaflops.
8-84
Benchmark Your Cluster with the HPC Challenge
dgemmResult = hpccDGEMM([Link]);
Starting HPCC benchmark: DGEMM with data size: 9.27515 GB. Running on a pool of 64 workers
Analyzing and transferring files to the workers ...done.
Finished HPCC benchmark: DGEMM in 69.3654 seconds.
STREAM
hpccSTREAM(m) assesses the memory bandwidth of the cluster. It creates random distributed
vectors b and c of length m, and a random scalar k, and computes a = b + c*k. This benchmark
does not use interworker communication. The performance is returned in gigabytes per second.
streamResult = hpccSTREAM([Link]);
Starting HPCC benchmark: STREAM with data size: 10.6667 GB. Running on a pool of 64 workers
Analyzing and transferring files to the workers ...done.
Finished HPCC benchmark: STREAM in 0.0796962 seconds.
PTRANS
hpccPTRANS(m) measures the interprocess communication speed of the system. It creates two
random distributed matrices A and B of size m-by-m, and computes A' + B. The result is returned in
gigabytes per second.
ptransResult = hpccPTRANS([Link]);
Starting HPCC benchmark: PTRANS with data size: 9.27515 GB. Running on a pool of 64 workers
Analyzing and transferring files to the workers ...done.
Finished HPCC benchmark: PTRANS in 6.43994 seconds.
RandomAccess
hpccRandomAccess(m) measures the number of memory locations in a distributed vector that can
be randomly updated per second. The result is returned in GUPS, giga updates per second. In this
test, the workers use a random number generator compiled into a MEX function. Attach a version of
this MEX function for each operating system architecture to the parallel pool, so the workers can
access the one that corresponds to their operating system.
addAttachedFiles(pool,{'hpccRandomNumberGeneratorKernel.mexa64','hpccRandomNumberGeneratorKernel.
randomAccessResult = hpccRandomAccess([Link]);
Starting HPCC benchmark: RandomAccess with data size: 16 GB. Running on a pool of 64 workers
Analyzing and transferring files to the workers ...done.
Finished HPCC benchmark: RandomAccess in 208.103 seconds.
FFT
hpccFFT(m) measures the execution rate of a parallel fast Fourier transform (FFT) computation on a
distributed vector of length m. This test measures both the arithmetic capability of the system and the
communication performance. The performance is returned in gigaflops.
fftResult = hpccFFT([Link]);
Starting HPCC benchmark: FFT with data size: 8 GB. Running on a pool of 64 workers
Analyzing and transferring files to the workers ...done.
Finished HPCC benchmark: FFT in 11.772 seconds.
8-85
8 Performance Profiling
Each benchmark results in a single table row with statistics. Concatenate these rows to provide a
summary of the test results.
allResults = [hplResult; dgemmResult; streamResult; ...
ptransResult; randomAccessResult; fftResult];
disp(allResults);
You can use the batch function to offload the computations in the HPC Challenge to your cluster and
continue working in MATLAB.
Before using batch, delete the current parallel pool. A batch job cannot be processed if a parallel
pool is already using all available workers.
delete(gcp);
Send the function hpccBenchmark as a batch job to the cluster by using batch. This function
invokes the tests in the HPC Challenge and returns the results in a table. When you use batch, a
worker takes the role of the MATLAB client and executes the function. In addition, specify these
name-value pair arguments:
• 'Pool': Creates a parallel pool with workers for the job. In this case, specify 32 workers.
hpccBenchmark runs the HPC Challenge on those workers.
• 'AttachedFiles': Transfers files to the workers in the pool. In this case, attach a version of the
hpccRandomNumberGeneratorKernel for each operating system architecture. The workers
access the one that corresponds to their operating system when they execute the
hpccRandomAccess test.
• 'CurrentFolder': Sets the working directory of the workers. If you do not specify this
argument, MATLAB changes the current directory of the workers to the current directory in the
MATLAB client. Set it to '.' if you want to use the current folder of the workers instead. This is
useful when the workers have a different file system.
gbPerWorker = 1;
job = batch(@hpccBenchmark,1,{gbPerWorker}, ...
'Pool',32, ...
'AttachedFiles',{'hpccRandomNumberGeneratorKernel.mexa64','[Link]
'CurrentFolder','.');
After you submit the job, you can continue working in MATLAB. You can check the state of the job by
using the Job Monitor. On the Home tab, in the Environment area, select Parallel > Monitor Jobs.
In this case, wait for the job to finish. To retrieve the results back from the cluster, use the
fetchOutputs function.
8-86
Benchmark Your Cluster with the HPC Challenge
wait(job);
results = fetchOutputs(job);
disp(results{1})
When you use large clusters, you increase the available computational resources. If the time spent on
calculations outweighs the time spent on interworker communication, then your problem can scale up
well. The following figure shows the scaling of the HPL benchmark with the number of workers, on a
cluster with 4 machines and 18 physical cores per machine. Note that in this benchmark, the size of
the data increases with the number of workers.
See Also
parpool | batch
8-87
8 Performance Profiling
Related Examples
• “Scale Up from Desktop to Cluster” on page 7-49
8-88
Simple Benchmarking of PARFOR Using Blackjack
This example benchmarks the parfor construct by repeatedly playing the card game of blackjack,
also known as 21. We use parfor to play the card game multiple times in parallel, varying the
number of MATLAB® workers, but always using the same number of players and hands.
Related examples:
Parallel Version
The basic parallel algorithm uses the parfor construct to execute independent passes through a
loop. It is a part of the MATLAB® language, but behaves essentially like a regular for-loop if you do
not have access to the Parallel Computing Toolbox™ product. Thus, our initial step is to convert a
loop of the form
for i = 1:numPlayers
S(:, i) = playBlackjack();
end
parfor i = 1:numPlayers
S(:, i) = playBlackjack();
end
We modify this slightly by specifying an optional argument to parfor, instructing it to limit to n the
number of workers it uses for the computations. The actual code is as follows:
dbtype pctdemo_aux_parforbench
We will use the parallel pool to allow the body of the parfor loop to run in parallel, so we start by
checking whether the pool is open. We will then run the benchmark using anywhere between 2 and
poolSize workers from this pool.
p = gcp;
if isempty(p)
8-89
8 Performance Profiling
error('pctexample:backslashbench:poolClosed', ...
['This example requires a parallel pool. ' ...
'Manually start a pool using the parpool command or set ' ...
'your parallel settings to automatically start a pool.']);
end
poolSize = [Link];
We time the execution of our benchmark calculations using 2 to poolSize workers. We use weak
scaling, that is, we increase the problem size with the number of workers.
numHands = 2000;
numPlayers = 6;
fprintf('Simulating each player playing %d hands.\n', numHands);
t1 = zeros(1, poolSize);
for n = 2:poolSize
tic;
pctdemo_aux_parforbench(numHands, n*numPlayers, n);
t1(n) = toc;
fprintf('%d workers simulated %d players in %3.2f seconds.\n', ...
n, n*numPlayers, t1(n));
end
8-90
Simple Benchmarking of PARFOR Using Blackjack
tic;
S = zeros(numHands, numPlayers);
for i = 1:numPlayers
S(:, i) = pctdemo_task_blackjack(numHands, 1);
end
t1(1) = toc;
fprintf('Ran in %3.2f seconds using a sequential for-loop.\n', t1(1));
We compare the speedup using parfor with different numbers of workers to the perfectly linear
speedup curve. The speedup achieved by using parfor depends on the problem size as well as the
underlying hardware and networking infrastructure.
speedup = (1:poolSize).*t1(1)./t1;
fig = pctdemo_setup_blackjack(1.0);
[Link] = 'on';
ax = axes('parent', fig);
x = plot(ax, 1:poolSize, 1:poolSize, '--', ...
1:poolSize, speedup, 's', 'MarkerFaceColor', 'b');
t = [Link];
t(t ~= round(t)) = []; % Remove all non-integer x-axis ticks.
[Link] = t;
8-91
8 Performance Profiling
To get reliable benchmark numbers, we need to run the benchmark multiple times. We therefore run
the benchmark multiple times for poolSize workers to allow us to look at the spread of the speedup.
numIter = 100;
t2 = zeros(1, numIter);
for i = 1:numIter
tic;
pctdemo_aux_parforbench(numHands, poolSize*numPlayers, poolSize);
t2(i) = toc;
if mod(i,20) == 0
fprintf('Benchmark has run %d out of %d times.\n',i,numIter);
end
end
8-92
Simple Benchmarking of PARFOR Using Blackjack
We take a close look at the speedup of our simple parallel program when using the maximum number
of workers. The histogram of the speedup allows us to distinguish between outliers and the average
speedup.
speedup = t1(1)./t2*poolSize;
clf(fig);
ax = axes('parent', fig);
hist(speedup, 5);
a = axis(ax);
a(4) = 5*ceil(a(4)/5); % Round y-axis to nearest multiple of 5.
axis(ax, a)
xlabel(ax, 'Speedup');
ylabel(ax, 'Frequency');
title(ax, sprintf('Speedup of parfor with %d workers', poolSize));
m = median(speedup);
fprintf(['Median speedup is %3.2f, which corresponds to '...
'efficiency of %3.2f.\n'], m, m/poolSize);
8-93
8 Performance Profiling
In this example, we show how to benchmark an application using independent jobs on the cluster, and
we analyze the results in some detail. In particular, we:
• Show how to benchmark a mixture of sequential code and task parallel code.
• Explain strong and weak scaling.
• Discuss some of the potential bottlenecks, both on the client and on the cluster.
Note: If you run this example on a large cluster, it might take an hour to run.
Related examples:
function paralleldemo_distribjob_bench
Before we interact with the cluster, we verify that the MATLAB® client is configured according to our
needs. Calling parcluster will give us a cluster using the default profile or will throw an error if the
default is not usable.
myCluster = parcluster;
Timing
We time all operations separately to allow us to inspect them in detail. We will need all those detailed
timings to understand where the time is spent, and to isolate the potential bottlenecks. For the
purposes of the example, the actual function we benchmark is not very important; in this case we
simulate hands of the card game blackjack or 21.
We write all of the operations to be as efficient as possible. For example, we use vectorized task
creation. We use tic and toc for measuring the elapsed time of all the operations instead of using
the job and task properties CreateDateTime, StartDateTime, FinishDateTime, etc., because
tic and toc give us sub-second granularity. Note that we have also instrumented the task function
so that it returns the time spent executing our benchmark computations.
function [times, description] = timeJob(myCluster, numTasks, numHands)
% The code that creates the job and its tasks executes sequentially in
% the MATLAB client starts here.
% We first measure how long it takes to create a job.
timingStart = tic;
start = tic;
job = createJob(myCluster);
[Link] = toc(start);
[Link] = 'Job creation time';
% Create all the tasks in one call to createTask, and measure how long
% that takes.
start = tic;
8-94
Benchmarking Independent Jobs on the Cluster
% Once the job has been submitted, we hope all its tasks execute in
% parallel. We measure how long it takes for all the tasks to start
% and to run to completion.
start = tic;
wait(job);
[Link] = toc(start);
[Link] = 'Job wait time';
% Get the execution time of the tasks. Our task function returns this
% as its second output argument.
[Link] = max([results{:,2}]);
[Link] = 'Task execution time';
% Measure how long it takes to delete the job and all its tasks.
start = tic;
delete(job);
[Link] = toc(start);
[Link] = 'Job deletion time';
% Measure the total time elapsed from creating the job up to this
% point.
[Link] = toc(timingStart);
[Link] = 'Total time';
[Link] = numTasks;
[Link] = 'Number of tasks';
end
8-95
8 Performance Profiling
• Job creation time: The time it takes to create a job. For a MATLAB Job Scheduler cluster, this
involves a remote call, and the MATLAB Job Scheduler allocates space in its data base. For other
cluster types, job creation involves writing a few files to disk.
• Task creation time: The time it takes to create and save the task information. The MATLAB Job
Scheduler saves this in its data base, whereas other cluster types save it in files on the file system.
• Job submission time: The time it takes to submit the job. For a MATLAB Job Scheduler cluster,
we tell it to start executing the job it has in its data base. We ask other cluster types to execute all
the tasks we have created.
• Job wait time: The time we wait after the job submission until job completion. This includes all
the activities that take place between job submission and when the job has completed, such as:
cluster may need to start all the workers and to send the workers the task information; the
workers read the task information, and execute the task function. In the case of a MATLAB Job
Scheduler cluster, the workers then send the task results to the MATLAB Job Scheduler, which
writes them to its data base, whereas for the other cluster types, the workers write the task
results to disk.
• Task execution time: The time spent simulating blackjack. We instrument the task function to
accurately measure this time. This time is also included in the job wait time.
• Results retrieval time: The time it takes to bring the job results into the MATLAB client. For the
MATLAB Job Scheduler, we obtain them from its data base. For other cluster types, we read them
from the file system.
• Job deletion time: The time it takes to delete all the job and task information. The MATLAB Job
Scheduler deletes it from its data base. For the other cluster types, we delete the files from the file
system.
• Total time: The time it takes to perform all of the above.
We know that most clusters are designed for batch execution of medium or long running jobs, so we
deliberately try to have our benchmark calculations fall within that range. Yet, we do not want this
example to take hours to run, so we choose the problem size so that each task takes approximately 1
minute on our hardware, and we then repeat the timing measurements a few times for increased
accuracy. As a rule of thumb, if your calculations in a task take much less than a minute, you should
consider whether parfor meets your low-latency needs better than jobs and tasks.
numHands = 1.2e6;
numReps = 5;
We explore speedup by running on a different number of workers, starting with 1, 2, 4, 8, 16, etc.,
and ending with as many workers as we can possibly use. In this example, we assume that we have
dedicated access to the cluster for the benchmarking, and that the cluster's NumWorkers property
has been set correctly. Assuming that to be the case, each task will execute right away on a dedicated
worker, so we can equate the number of tasks we submit with the number of workers that execute
them.
numWorkers = [Link] ;
if isinf(numWorkers) || (numWorkers == 0)
error('pctexample:distribjobbench:InvalidNumWorkers', ...
['Cannot deduce the number of workers from the cluster. ' ...
'Set the NumWorkers on your default profile to be ' ...
'a value other than 0 or inf.']);
end
8-96
Benchmarking Independent Jobs on the Cluster
We vary the number of tasks in a job, and have each task perform a fixed amount of work. This is
called weak scaling, and is what we really care the most about, because we usually scale up to the
cluster to solve larger problems. It should be compared with the strong scaling benchmarks shown
later in this example. Speedup based on weak scaling is also known as scaled speedup.
Sequential Execution
We measure the sequential execution time of the computations. Note that this time should be
compared to the execution time on the cluster only if they have the same hardware and software
configuration.
seqTime = inf;
for itr = 1:numReps
start = tic;
pctdemo_task_blackjack(numHands, 1);
seqTime = min(seqTime, toc(start));
end
fprintf('Sequential execution time: %f seconds\n', seqTime);
We first look at the overall speedup achieved by running on different numbers of workers. The
speedup is based on the total time used for the computations, so it includes both the sequential and
the parallel portions of our code.
8-97
8 Performance Profiling
This speedup curve represents the capabilities of multiple items with unknown weights associated
with each of them: The cluster hardware, the cluster software, the client hardware, the client
software, and the connection between the client and the cluster. Therefore, the speedup curve does
not represent any one of these, but all taken together.
If the speedup curve meets your desired performance targets, you know that all the aforementioned
factors work well together in this particular benchmark. However, if the speedup curve fails to meet
your targets, you do not know which of the many factors listed above is the most to blame. It could
even be that the approach taken in the parallelization of the application is to blame rather than either
the other software or hardware.
All too often, novices believe that this single graph gives the complete picture of the performance of
their cluster hardware or software. This is indeed not the case, and one always needs to be aware
that this graph does not allow us to draw any conclusions about potential performance bottlenecks.
titleStr = sprintf(['Speedup based on total execution time\n' ...
'Note: This graph does not identify performance ' ...
'bottlenecks']);
pctdemo_plot_distribjob('speedup', [[Link]], [[Link]], ...
weak(1).totalTime, titleStr);
We dig a little bit deeper and look at the times spent in the various steps of our code. We
benchmarked weak scaling, that is, the more tasks we create, the more work we perform. Therefore,
the size of the task output data increases as we increase the number of tasks. With that in mind, we
expect the following to take longer the more tasks we create:
8-98
Benchmarking Independent Jobs on the Cluster
• Task creation
• Retrieval of job output arguments
• Job destruction time
We have no reason to believe that the following increases with the number of tasks:
After all, the job is created before we define any of its tasks, so there is no reason why it should vary
with the number of tasks. We might expect to see only some random fluctuations in the job creation
time.
Normalized Times
We already concluded that task creation time is expected to increase as we increase the number of
tasks, as does the time to retrieve job output arguments and to delete the job. However, this increase
is due to the fact that we are performing more work as we increase the number of workers/tasks. It is
therefore meaningful to measure the efficiency of these three activities by looking at the time it takes
to perform these operations, and normalize it by the number of tasks. This way, we can look to see if
any of the following times stay constant, increase, or decrease as we vary the number of tasks:
8-99
8 Performance Profiling
The normalized times in this graph represent the capabilities of the MATLAB client and the portion of
the cluster hardware or software that it might interact with. It is generally considered good if these
curves stay flat, and excellent if they are decreasing.
These graphs sometimes show that the time spent retrieving the results per task goes down as the
number of tasks increases. That is undeniably good: We become more efficient the more work we
perform. This might happen if there is a fixed amount of overhead for the operation and if it takes a
fixed amount of time per task in the job.
We cannot expect a speedup curve based on total execution time to look particularly good if it
includes a significant amount of time spent on sequential activities such as the above, where the time
spent increases with the number of tasks. In that case, the sequential activities will dominate once
there are sufficiently many tasks.
It is possible that the time spent in each of following steps varies with the number of tasks, but we
hope it does not:
8-100
Benchmarking Independent Jobs on the Cluster
In both cases, we look at the elapsed time, also referred to as wall clock time. We look at neither the
total CPU time on the cluster nor the normalized time.
There are situations where each of the times shown above could increase with the number of tasks.
For example:
• With some third-party cluster types, the job submission involves one system call for each task in
the job, or the job submission involves copying files across the network. In those cases, the job
submission time may increase linearly with the number of tasks.
• The graph of the task execution time is the most likely to expose hardware limitations and
resource contention. For example, the task execution time could increase if we are executing
multiple workers on the same computer, due to contention for limited memory bandwidth. Another
example of resource contention is if the task function were to read or write large data files using a
single, shared file system. The task function in this example, however, does not access the file
system at all. These types of hardware limitations are covered in great detail in the example
“Resource Contention in Task Parallel Problems” on page 8-71.
8-101
8 Performance Profiling
Now that we have dissected the times spent in the various stages of our code, we want to create a
speedup curve that more accurately reflects the capabilities of our cluster hardware and software. We
do this by calculating a speedup curve based on the job wait time.
When calculating this speedup curve based on the job wait time, we first compare it to the time it
takes to execute a job with a single task on the cluster.
Job wait time might include the time to start all the MATLAB workers. It is therefore possible that this
time is bounded by the IO capabilities of a shared file system. The job wait time also includes the
average task execution time, so any deficiencies seen there also apply here. If we do not have
dedicated access to the cluster, we could expect the speedup curve based on job wait time to suffer
significantly.
Next, we compare the job wait time to the sequential execution time, assuming that the hardware of
the client computer is comparable to the compute nodes. If the client is not comparable to the cluster
nodes, this comparison is absolutely meaningless. If your cluster has a substantial time lag when
assigning tasks to workers, e.g., by assigning tasks to workers only once per minute, this graph will
be heavily affected because the sequential execution time does not suffer this lag. Note that this
graph will have the same shape as the previous graph, they will only differ by a constant,
multiplicative factor.
8-102
Benchmarking Independent Jobs on the Cluster
As we have mentioned before, the job wait time consists of the task execution time plus scheduling,
wait time in the cluster's queue, MATLAB startup time, etc. On an idle cluster, the difference between
the job wait time and task execution time should remain constant, at least for small number of tasks.
As the number of tasks grows into the tens, hundreds, or thousands, we are bound to eventually run
into some limitations. For example, once we have sufficiently many tasks/workers, the cluster cannot
tell all the workers simultaneously to start executing their task, or if the MATLAB workers all use the
same file system, they might end up saturating the file server.
titleStr = 'Difference between job wait time and task execution time';
pctdemo_plot_distribjob('barTime', [[Link]], ...
[[Link]] - [[Link]], titleStr);
8-103
8 Performance Profiling
We now measure the execution time of a fixed-size problem, while varying the number of workers we
use to solve the problem. This is called strong scaling, and it is well known that if an application has
any sequential parts, there is an upper limit to the speedup that can be achieved with strong scaling.
This is formalized in Amdahl's law, which has been widely discussed and debated over the years.
You can easily run into the limits of speedup with strong scaling when submitting jobs to the cluster.
If the task execution has a fixed overhead (which it ordinarily does), even if it is as little as one
second, the execution time of our application will never go below one second. In our case, we start
with an application that executes in approximately 60 seconds on one MATLAB worker. If we divide
the computations among 60 workers, it might take as little as one second for each worker to compute
its portion of the overall problem. However, the hypothetical task execution overhead of one second
has become a major contributor to the overall execution time.
Unless your application runs for a long time, jobs and tasks are usually not the way to achieve good
results with strong scaling. If the overhead of task execution is close to the execution time of your
application, you should investigate whether parfor meets your requirements. Even in the case of
parfor, there is a fixed amount of overhead, albeit much smaller than with regular jobs and tasks,
and that overhead limits to the speedup that can be achieved with strong scaling. Your problem size
relative to your cluster size may or may not be so large that you experience those limitations.
As a general rule of thumb, it is only possible to achieve strong scaling of small problems on large
numbers of processors with specialized hardware and a great deal of programming effort.
8-104
Benchmarking Independent Jobs on the Cluster
As we have already discussed, speedup curves that depict the sum of the time spent executing
sequential code in the MATLAB client and time executing parallel code on the cluster can be very
misleading. The following graph shows this information in the worst-case scenario of strong scaling.
We deliberately chose the original problem to be so small relative to our cluster size that the speedup
curve would look bad. Neither the cluster hardware nor software was designed with this kind of a use
in mind.
8-105
8 Performance Profiling
The strong scaling results did not look good because we deliberately used jobs and tasks to execute
calculations of short duration. We now look at how parfor applies to that same problem. Note that
we do not include the time it takes to open the pool in our time measurements.
pool = parpool(numWorkers);
parforTime = inf;
strongNumHands = ceil(numHands/numWorkers);
for itr = 1:numReps
start = tic;
r = cell(1, numWorkers);
parfor i = 1:numWorkers
r{i} = pctdemo_task_blackjack(strongNumHands, 1); %#ok<PFOUS>
end
parforTime = min(parforTime, toc(start));
end
delete(pool);
Starting parallel pool (parpool) using the 'bigMJS' profile ... connected to 256 workers.
Analyzing and transferring files to the workers ...done.
The original, sequential calculations took approximately one minute, so each worker needs to perform
only a few seconds of computations on a large cluster. We therefore expect strong scaling
performance to be much better with parfor than with jobs and tasks.
8-106
Benchmarking Independent Jobs on the Cluster
Summary
We have seen the difference between weak and strong scaling, and discussed why we prefer to look
at weak scaling: It measures our ability to solve larger problems on the cluster (more simulations,
more iterations, more data, etc.). The large number of graphs and the amount of detail in this
example should also be a testament to the fact that benchmarks cannot be boiled down to a single
number or a single graph. We need to look at the whole picture to understand whether the
application performance can be attributed to the application, the cluster hardware or software, or a
combination of both.
We have also seen that for short calculations, parfor can be a great alternative to jobs and tasks. For
more benchmarking results using parfor, see the example “Simple Benchmarking of PARFOR Using
Blackjack” on page 8-89.
end
8-107
8 Performance Profiling
Sequential Blackjack
This example plays the card game of blackjack, also known as 21. We simulate a number of players
that are independently playing thousands of hands at a time, and display payoff statistics. Simulating
the playing of blackjack is representative of Monte Carlo analysis of financial instruments. The
simulation can be done completely in parallel, except for the data collection at the end.
For details about the computations, view the code for pctdemo_setup_blackjack.
Related examples:
We start by getting the example difficulty level. If you want to use a different example difficulty level,
use paralleldemoconfig and then run this example again.
difficulty = pctdemo_helper_getDefaults();
We get the number of players and the number of hands each player plays from
pctdemo_setup_blackjack. The difficulty parameter controls the number of players that we
simulate. You can view the code for pctdemo_setup_blackjack for full details.
We use pctdemo_task_blackjack to simulate a single player who plays numHands hands, and we
call that function numPlayers times to simulate all the players. Because the separate invocations of
the function are independent one of another, we can easily use the Parallel Computing Toolbox to
perform these simulations. You can view the code for pctdemo_task_blackjack for full details.
startTime = clock;
S = zeros(numHands, numPlayers); % Preallocate for the results.
for i = 1:numPlayers
S(:, i) = pctdemo_task_blackjack(numHands, 1);
end
The time used for the sequential simulations should be compared against the time it takes to perform
the same set of calculations using the Parallel Computing Toolbox in the “Distributed Blackjack” on
page 8-110 example. The elapsed time varies with the underlying hardware.
We display the expected fraction of the bet that is won or lost in each hand, along with the confidence
interval. We also show the evolution of the winnings and losses of each of the players we simulate.
You can view the code for pctdemo_plot_blackjack for full details.
8-108
Sequential Blackjack
pctdemo_plot_blackjack(fig, S);
8-109
8 Performance Profiling
Distributed Blackjack
This example uses the Parallel Computing Toolbox™ to play the card game of blackjack, also known
as 21. We simulate a number of players that are independently playing thousands of hands at a time,
and display payoff statistics. Simulating the playing of blackjack is representative of Monte Carlo
analysis of financial instruments. The simulation can be done completely in parallel, except for the
data collection at the end.
For details about the computations, view the code for pctdemo_setup_blackjack.
Related examples:
Because the blackjack players are independent one of another, we can simulate them in parallel. We
do this by dividing the problem up into a number of smaller tasks.
The example uses the default profile when identifying the cluster to use. “Discover Clusters and Use
Cluster Profiles” on page 7-2 explains how to create new profiles and how to change the default
profile. If you want to use a different example difficulty level or number of tasks, use
paralleldemoconfig and then run this example again.
We get the number of players and the number of hands each player plays from
pctdemo_setup_blackjack. The difficulty parameter controls the number of players that we
simulate. You can view the code for pctdemo_setup_blackjack for full details.
We divide the simulation of the numPlayers players among the numTasks tasks. Thus, task i
simulates splitPlayers{i} players.
We create a job and one task in the job for each split. Notice that the task function is the same
function that was used in the sequential example. You can view the code for pctdemo_task_blackjack
for full details.
startTime = clock;
job = createJob(myCluster);
for i = 1:numTasks
8-110
Distributed Blackjack
submit(job);
wait(job);
Let us verify that we received all the results that we expected. fetchOutputs will throw an error if
the tasks did not complete successfully, in which case we need to delete the job before throwing the
error.
try
jobResults = fetchOutputs(job);
catch err
delete(job);
rethrow(err);
end
S = cell2mat(jobResults');
We have now finished all the verifications, so we can delete the job.
delete(job);
The time used for the distributed simulations should be compared against the time it takes to perform
the same set of calculations in the “Sequential Blackjack” on page 8-108 example. The elapsed time
varies with the underlying hardware and network infrastructure.
We display the expected fraction of the bet that is won or lost in each hand, along with the confidence
interval. We also show the evolution of the winnings and losses of each of the players we simulate.
You can view the code for pctdemo_plot_blackjack for full details.
pctdemo_plot_blackjack(fig, S);
8-111
8 Performance Profiling
8-112
Parfeval Blackjack
Parfeval Blackjack
This example uses Parallel Computing Toolbox™ to play the card game of blackjack, also known as
21. We simulate a number of players that are independently playing thousands of hands at a time, and
display payoff statistics. This example runs the simulations asynchronously on a parallel pool of
workers, using parfeval. In this way, we can update a display of the results as they become
available.
Related examples:
You can find the code shown in this example in the function:
function paralleldemo_blackjack_parfeval
Because the blackjack players are independent of one another, we can simulate them in parallel. We
do this by dividing the problem up into a number of function evaluations. We run a maximum of
numPlayers simulations, where each player plays numHands hands of blackjack. We plot the results
as soon as they become available, and we terminate the simulation if the elapsed time exceeds
maxSimulationTime seconds, or if the user cancels execution.
numPlayers = 100;
numHands = 5000;
maxSimulationTime = 20;
We call the parfeval function to request evaluation of the simulation on the parallel pool workers.
The parallel pool will be created automatically if necessary. The parfeval function returns a
[Link] object, which we use to access results when they become available. You can view
the code for pctdemo_task_blackjack for full details.
The parallel pool workers immediately start running pctdemo_task_blackjack, and we can collect
and display results as soon as they are available by using the fetchNext method. We use
resultsSoFar to accumulate results. We update the array completed to indicate which elements of
futures have completed, and increment the counter numCompleted. We supply the optional
argument timeout to the fetchNext method so that it returns quickly if no new results are
available.
8-113
8 Performance Profiling
We collect and display results by calling fetchNext in a loop until we have seen numPlayers
results. When fetchNext returns new results, we assign the results into resultsSoFar, update the
completed array and the numCompleted counter, and update the plot. We abort the loop early if the
user presses the cancel button on the waitbar, or the maxSimulationTime expires.
startTime = clock();
while numCompleted < numPlayers
8-114
Parfeval Blackjack
end
% Now the simulation is complete, we can cancel the futures and delete
% the waitbar.
cancel(futures);
delete(hWaitBar);
end
8-115
9
Objects
9 Objects
[Link]
Parallel pool activity monitor
Description
Use ActivityMonitor to monitor and collect data on worker activity in a parallel pool.
You can retrieve the monitoring results using the results function and view the monitoring data in
the Pool Dashboard.
Creation
Syntax
monitor = [Link]
monitor = [Link](pool)
monitor = [Link]( ___ ,Start=start)
Description
To save monitoring results, use the results function. To stop collecting and save monitoring results,
use the stop function.
Input Arguments
9-2
[Link]
You can use an interactive or batch parallel pool. ActivityMonitor is not supported on parallel
pools of thread workers.
Example: parpool("Processes");
Example: batch(...,Pool=4);
Collect pool monitoring data immediately after creation, specified as a logical or numeric true (1) or
false (0).
Output Arguments
Object Functions
results Retrieve results from parallel pool activity monitor
stop Stop monitoring parallel pool activity
start Start collecting parallel pool activity monitoring data
Examples
Create an ActivityMonitor object to start collecting pool monitoring data. With default settings,
[Link] automatically starts an interactive parallel pool using the
default profile if one does not exist.
monitor = [Link];
Stop the activity monitor and retrieve the results collected during the parfor execution.
monitorResults = stop(monitor);
9-3
9 Objects
pool = parpool("MyCluster");
Create an ActivityMonitor object to collect monitoring data for the pool but do not start collecting
data immediately.
monitor = [Link](pool,Start=false);
Collect activity monitoring data on a batch pool job using an ActivityMonitor object.
Write a function that creates an ActivityMonitor object to collect monitoring data, executes
parallel tasks, and collects pool monitoring results.
monitor = [Link];
f(1:100) = [Link];
for idx = 1:100
f(idx) = parfeval(@(n) real(eig(randn(n))),1,5e2);
end
maxFuture = afterEach(f,@max,1);
wait(maxFuture);
monitorResults = stop(monitor);
end
Run the myParallelCode function as a batch pool job using the myCluster profile and wait for the
batch job to complete.
j = batch(@myParallelCode,1,Pool=4,Profile="myCluster");
wait(j);
out = fetchOutputs(j);
monitoringResults = out{1};
Limitations
• ActivityMonitor is not supported on parallel pools of thread workers.
9-4
[Link]
Alternative Functionality
Tool
You can use the Pool Dashboard to collect and view pool monitoring data on an interactive parallel
pool.
Version History
Introduced in R2025a
See Also
Functions
results | stop | start
Objects
ActivityMonitorResults
Tools
Pool Dashboard
9-5
9 Objects
ActivityMonitorResults
Results from monitoring pool activity
Description
An ActivityMonitorResults object contains the results from collecting pool activity monitoring
data using a ActivityMonitor object. The ActivityMonitor object monitors and collects data on
worker activity in a parallel pool.
You can retrieve the monitoring results using the results function and view the monitoring results
data in the Pool Dashboard.
Creation
You can create an ActivityMonitorResults object in one of these ways:
• Use either the results or stop function on an ActivityMonitor object to retrieve pool
monitoring results.
• Save pool monitoring data collected using the Pool Dashboard.
Properties
StartTime — Pool monitoring start time
datetime scalar
9-6
ActivityMonitorResults
Examples
Create an ActivityMonitor object to start collecting pool monitoring data. With default settings,
[Link] automatically starts an interactive parallel pool using the
default profile if one does not exist.
monitor = [Link];
Create some large data on the client, then build a Constant object, C, transferring the data to the
pool.
data = rand(1000);
C = [Link](data);
Run multiple parfor-loops accessing the data. For efficiency, preallocate the results array.
x = eye(5);
for ii = 1:5
parfor jj = 1:20
x(ii,jj) = [Link](ii,jj);
end
end
Stop the activity monitor and retrieve the ActivityMonitorResults object that contains the
monitoring results collected during the execution of the parfor-loops.
monitoringResults = stop(monitor);
parpoolDashboard(monitoringResults)
9-7
9 Objects
Version History
Introduced in R2025a
See Also
Functions
results | stop | start
Objects
ActivityMonitor
Tools
Pool Dashboard
9-8
ClusterPool
ClusterPool
Parallel pool of workers on a cluster of machines
Description
Use parpool to create a parallel pool of workers on a cluster of machines. After you create the pool,
parallel pool features, such as parfor or parfeval, run on the workers. With the ClusterPool
object, you can interact with the parallel pool.
Creation
• Create a parallel pool on a cluster of machines by using the parpool function.
pool = parpool("myCluster")
Properties
AttachedFiles — Files and folders copied to workers
cell array of character vectors
Files and folders copied to workers, specified as a cell array of character vectors. To attach files and
folders to the pool, use addAttachedFiles.
Indication whether user-added entries on client path are added to worker paths, specified as a logical
value.
Data Types: logical
9-9
9 Objects
Flag that indicates whether the parallel pool is running, specified as a logical value.
Data Types: logical
Environment variables copied to the workers, specified as a cell array of character vectors.
Queue of FevalFutures to run on the parallel pool, returned as an FevalQueue object. You can use
this property to check the pending and running future variables of the parallel pool. To create future
variables, use parfeval and parfevalOnAll. For more information on future variables, see
Future.
Data Types: FevalQueue
Store of files accessible to both client and workers, specified as a FileStore object.
Time in minutes after which the pool shuts down if idle, specified as an integer greater than zero. A
pool is idle if it is not running code on the workers. By default 'IdleTimeout' is the same as the
value in your parallel settings. For more information on parallel settings, see “Specify Your Parallel
Settings” on page 1-35.
Flag that indicates whether the parallel pool is busy, specified as true or false. The pool is busy if
there is outstanding work for the pool to complete.
9-10
ClusterPool
Store of data accessible to both client and workers, specified as a ValueStore object.
Information about workers comprising the parallel pool, returned as an array of [Link]
objects.
Object Functions
addAttachedFiles Attach files or folders to parallel pool
Composite Create and access nondistributed variables on multiple workers from client
delete Shut down parallel pool
listAutoAttachedFiles List of files automatically attached to job, task, or parallel pool
parfeval Run function on parallel pool worker
parfevalOnAll Run function asynchronously on all workers in parallel pool
parforOptions Options set for parfor
partition Partition parallel pool
ticBytes Start counting bytes transferred within parallel pool
tocBytes Read how many bytes have been transferred since calling ticBytes
updateAttachedFiles Update attached files or folders on parallel pool
spmd Execute code in parallel on workers of parallel pool
Version History
Introduced in R2020a
Starting in R2024a, ClusterPool objects support pools with up to 2000 workers. Before R2024a,
ClusterPool supports pools with up to 1000 workers.
See Also
parpool
Topics
“Run Code on Parallel Pools” on page 1-28
“Choose Between Thread-Based and Process-Based Environments” on page 1-43
9-11
9 Objects
codistributed
Access elements of arrays distributed among workers in parallel pool
Description
Arrays partitioned among the workers in a parallel pool are accessible from the workers as
codistributed array objects. Codistributed array objects on workers that you create inside spmd
statements or from within task functions of communicating jobs are accessed as distributed arrays on
the client.
Creation
Use either the codistributed function, or the [Link] function to create a
codistributed object.
Syntax
C = codistributed(X)
C = codistributed(X,workerIndex)
C = codistributed(X,codist)
C = codistributed(X,workerIndex,codist)
C = codistributed(C1,codist)
Description
C = codistributed(X) distributes a replicated array X using the default distribution scheme and
returns a codistributed array C. X must be a replicated array, that is, it must have the same value on
all workers. The size of array C is the same as the size of X.
9-12
codistributed
Input Arguments
X — Array to distribute
array
codist — Codistributor
codistributor1d object | codistributor2dbc object
Index of the worker where the local array is stored, specified as a positive integer scalar.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Output Arguments
C — Codistributed array
codistributed array
Object Functions
gather Transfer distributed array, Composite object, or gpuArray object to local
workspace
getCodistributor Codistributor object for existing codistributed array
getLocalPart Local portion of codistributed array
globalIndices Global indices for local part of codistributed array
Inf Create codistributed array of all Inf values
iscodistributed True for codistributed array
redistribute Redistribute codistributed array with another distribution scheme
The object functions for codistributed arrays are too numerous to list here. Most resemble and
behave the same as built-in MATLAB functions. For a complete list of object functions, see “Run
MATLAB Functions with Distributed Arrays” on page 4-5.
Among the object functions there are several for examining the characteristics of the array itself.
Most behave like the MATLAB functions of the same name.
iscodistributed True for codistributed array
isreal Determine whether array uses complex storage
isUnderlyingType Determine whether input has specified underlying data type
length Length of largest array dimension
ndims Number of array dimensions
9-13
9 Objects
Examples
parpool('Processes',4)
spmd
N = 1000;
X = magic(N);
C1 = codistributed(X);
end
Array X is replicated on every worker, and array C1 is partitioned among the workers.
Create a 1000-by-1000 codistributed array C2, distributed by rows (over the first dimension) with the
codistributor1d distribution scheme.
spmd
N = 1000;
X = magic(N);
C2 = codistributed(X,codistributor1d(1));
end
Tips
The gather function performs the inverse of codistributed. Use the gather function to retrieve
codistributed arrays into the client work space.
Alternative Functionality
You can also create a codistributed array explicitly from spmd code or a communicating job task with
any of these MATLAB functions.
• [Link]
• [Link]
• [Link]
• [Link]
• [Link]
• [Link]
• eye
• false
• Inf
9-14
codistributed
• NaN
• ones
• rand
• randi
• randn
• sparse
• true
• zeros
Version History
Introduced in R2008b
See Also
distributed | gather | getLocalPart | spmd | parpool | codistributor1d |
codistributor2dbc | subsref | subsasgn | globalIndices | redistribute
Topics
“Create and Use Distributed Arrays” on page 4-2
“Working with Codistributed Arrays” on page 4-38
“Run MATLAB Functions with Distributed Arrays” on page 4-5
“Nondistributed Versus Distributed Arrays” on page 4-36
“What Is a Datastore?”
9-15
9 Objects
codistributor1d
1-D distribution scheme for codistributed array
Description
Use a codistributor1d object to define the one-dimensional distribution scheme for a
codistributed array. The one-dimensional codistributor distributes arrays along a single specified
dimension, the distribution dimension, in a noncyclic, partitioned manner.
Creation
Syntax
codist = codistributor1d
codist = codistributor1d(Dimension)
codist = codistributor1d(Dimension,Partition)
codist = codistributor1d(Dimension,Partition,gsize)
Description
codist = codistributor1d returns a codistributor1d object using the default dimension and
partition. The default dimension is the last nonsingleton dimension of the codistributed array. The
default partition distributes the array along the default dimension as evenly as possible.
The resulting codistributor of any of the above syntaxes is incomplete because its global size is not
specified. Use a codistributor constructed this way as an argument to other functions as a template
codistributor when creating codistributed arrays.
You can use the resulting codistributor object to build a codistributed array from its local parts with
[Link]. To use a default dimension, specify [Link]
for the Dimension property; the function derives the distribution dimension from gsize and selects
the last nonsingleton dimension as the default dimension. Similarly, to use a default partition, specify
[Link] for the Partition property; the function derives the default
partition from the global size and distribution dimension.
9-16
codistributor1d
The local part on worker workerIndex of a codistributed array using such a codistributor is of size
gsize in all dimensions except dimension, where the size is part(workerIndex). The local part
has the same class and attributes as the overall codistributed array. The overall global array can be
reconstructed by concatenating the various local parts along dimension dimension.
Input Arguments
Properties
Dimension — Distribution dimension
scalar integer
Distribution dimension, specified as a scalar integer. The distribution dimension specifies the
dimension over which you distribute the codistributed array.
Partitioning vector, specified as an integer row vector. The partitioning vector specifies the
distribution of the codistributed array to the workers.
Object Functions
[Link] Create codistributed cell array
[Link] Distributed colon operation
[Link] Allocate space for sparse codistributed matrix
[Link] Create codistributed sparse identity matrix
[Link] Create codistributed sparse array of uniformly distributed pseudo-random
values
[Link] Create codistributed sparse array of normally distributed pseudo-random
values
eye Create codistributed identity matrix
false Create codistributed array of logical 0 (false)
globalIndices Global indices for local part of codistributed array
Inf Create codistributed array of all Inf values
isComplete True if codistributor object is complete
NaN Create codistributed array of all NaN values
ones Create codistributed array of all ones
rand Create codistributed array of uniformly distributed random numbers
randn Create codistributed array of normally distributed random numbers
sparse Create codistributed sparse matrix
true Create codistributed array of logical 1 (true)
zeros Create codistributed array of all zeros
Examples
9-17
9 Objects
N = 1000;
spmd
codistr = codistributor1d(1); % 1st dimension (rows)
C = ones(N,codistr);
end
Use a fully specified codistributor1d object to create a N-by-N codistributed matrix from its local
parts. Then visualize which elements are stored on worker 2.
Start with full sized array on each worker then set myLocalSize to default part of whole array.
N = 1000;
spmd
codistr = codistributor1d( ...
[Link], ...
[Link], ...
[N N]);
myLocalSize = [N N]; %
myLocalSize([Link]) = [Link](spmdIndex);
myLocalPart = spmdIndex*ones(myLocalSize);
D = [Link](myLocalPart,codistr);
end
spy(D==2);
Version History
Introduced in R2009b
See Also
codistributed | codistributor2dbc | redistribute
9-18
codistributor2dbc
codistributor2dbc
2-D block-cyclic distribution scheme for codistributed array
Description
A codistributor2dbc object defines the two-dimensional block-cyclic distribution scheme for a
codistributed array object. The 2-D block-cyclic codistributor can distribute only two-dimensional
matrices. It distributes matrices along two subscripts over a rectangular computational grid of
workers in a blocked, cyclic manner. For a complete description of 2-D block-cyclic distribution,
default parameters, and the relationship between block size and worker grid, see “2-Dimensional
Distribution” on page 4-46. The parallel matrix computation software library ScaLAPACK uses the 2-D
block-cyclic codistributor.
Creation
Syntax
codist = codistributor2dbc
codist = codistributor2dbc(WorkerGrid)
codist = codistributor2dbc(WorkerGrid,BlockSize)
codist = codistributor2dbc(WorkerGrid,BlockSize,Orientation)
codist = codistributor2dbc(WorkerGrid,BlockSize,Orientation,gsize)
Description
The resulting codistributor of any of the above syntaxes is incomplete because its global size is not
specified. Use a codistributor constructed this way as an argument to other functions as a template
codistributor when creating codistributed arrays.
The resulting codistributor object is complete. Use a codistributor constructed this way to build a
codistributed array from its local parts with the [Link] function. To use the default
values for each argument, specify WorkerGrid as [Link],
9-19
9 Objects
Input Arguments
Properties
WorkerGrid — Worker grid of codistributor2dbc object
[Link] (default) | 1-by-2 numeric vector
Worker grid of the codistributor2dbc object, specified as a two-element vector defining the rows
and columns of the worker grid. The number of rows multiplied by the number of columns must equal
the number of workers for the codistributed array.
Block size of the codistributor2dbc object, specified as a positive integer. This property is the
ScaLAPACK block size associated with the codistributor2dbc object.
Object Functions
[Link] Create codistributed cell array
[Link] Distributed colon operation
[Link] Allocate space for sparse codistributed matrix
[Link] Create codistributed sparse identity matrix
[Link] Create codistributed sparse array of uniformly distributed
pseudo-random values
[Link] Create codistributed sparse array of normally distributed
pseudo-random values
[Link] Default computational grid for 2-D block-cyclic distributed
arrays
eye Create codistributed identity matrix
false Create codistributed array of logical 0 (false)
globalIndices Global indices for local part of codistributed array
Inf Create codistributed array of all Inf values
isComplete True if codistributor object is complete
NaN Create codistributed array of all NaN values
9-20
codistributor2dbc
Examples
N = 1000;
spmd
codistr = codistributor2dbc;
D = ones(N,codistr);
end
Use a fully specified codistributor2dbc object to create a N-by-N codistributed matrix from its
local parts.
N = 1000;
Use the default values for the worker grid and block size, and specify the orientation and the grid size
of the worker grid.
spmd
codistr = codistributor2dbc(...
[Link], ...
[Link], ...
'row',[N,N]);
end
Use the globalIndices method on the codistributor object to get the global indices for the local
part of the codistributed array before creating the array itself. Use length to get the length of the
largest global index and set it as the size of the local part of the codistributed array. Create the
codistributed array with the [Link] function.
spmd
myLocalSize = [length(globalIndices(codistr,1)), ...
length(globalIndices(codistr,2))];
myLocalPart = spmdIndex*ones(myLocalSize);
D = [Link](myLocalPart,codistr);
end
Then use the spy function to visualize which elements are stored on worker 2.
spy(D==2)
9-21
9 Objects
The sparsity pattern shows the distribution of the elements of array D stored on worker 2.
Version History
Introduced in R2009b
See Also
codistributed | codistributor1d | getLocalPart | redistribute |
[Link]
9-22
Composite
Composite
Create and access nondistributed variables on multiple workers from client
Description
Composite objects contain references to variables stored on parallel workers running an spmd
statement. A Composite object resembles a cell array with one element for each worker and can
contain different values for each worker. You can retrieve values using cell-array indexing and define
values for the entries using indexing or an spmd block. The actual data on the workers remains
available for subsequent spmd execution, while the Composite exists on the client and the parallel
pool remains open.
Creation
spmd statements automatically create composite variables on the client when the body of an spmd
statement returns values. Therefore, you rarely need to create Composite objects directly.
You can also create Composite objects explicitly with the Composite function.
Syntax
c = Composite
c = Composite(nworkers)
c = Composite(pool, ___ )
Description
c = Composite creates a Composite object on the client using workers from the current parallel
pool.
The actual number of workers that the object references depends on the size of the pool and any
existing Composite objects. If a parallel pool is not open, the Composite function starts a parallel
pool of workers using the default profile.
To create a Composite object manually, you must do so outside any spmd statements. Initially, each
entry of the manually created Composite object contains no data. Define values for the entries by
using indexing or an spmd block.
c = Composite(pool, ___ ) creates a Composite object using workers from the parallel pool
specified by the [Link] object pool. Use this syntax when you want to create Composite
objects on a pool other than the pool the gcp function returns.
9-23
9 Objects
Input Arguments
Number of workers creating the Composite object, specified as a positive integer, Inf, or a two-
element vector containing positive integers or Inf values. If nworkers is a scalar, it specifies the
exact number of workers to use. If nworkers is a two-element vector, its first and second elements
specify the minimum and maximum number of workers to use, respectively.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Output Arguments
c — Composite array
Composite object
Composite array on the client using workers from the parallel pool, returned as a Composite object.
Object Functions
exist Check whether Composite is defined on workers
gather Transfer distributed array, Composite object, or gpuArray object to local workspace
subsasgn Subscripted assignment for Composite
subsref Subscripted reference for Composite
Other object functions of a Composite object behave similarly to these MATLAB array functions:
disp Display value of variable
end Terminate block of code or indicate last array index
isempty Determine whether array is empty
length Length of largest array dimension
ndims Number of array dimensions
numel Number of array elements
size Array size
Examples
This example shows how to create a Composite object with no defined elements, and then assign
values using a for-loop on the client.
9-24
Composite
Start a parallel pool with four workers and create a Composite object with an element for each
worker.
p = parpool("Processes",4);
c = Composite
c =
Worker 1: No data
Worker 2: No data
Worker 3: No data
Worker 4: No data
Use a for-loop on the client to define values for the elements of the Composite object. The value
that you assign to each element is stored on the workers. Display the Composite object.
for w = 1:length(c)
c{w} = rand;
end
c{:}
ans = 0.8147
ans = 0.9058
ans = 0.1270
ans = 0.9134
This example shows how to specify the number of workers and consequently the number of elements
in a Composite object.
Create a Composite object with only four workers from the current parallel pool and assign values to
the Composite elements in an spmd block. Display the Composite object.
c = Composite(4);
spmd
c = spmdIndex;
end
c{:}
ans = 1
9-25
9 Objects
ans = 2
ans = 3
ans = 4
This example shows how to use an spmd block and a distributed array to create Composite objects
on the client.
Start a parallel pool with four workers and distribute an array of four integers to the workers. Each
worker gets one integer.
p = parpool("Processes",4);
d = distributed([3 1 4 2]);
Use the parts of the distributed array on each worker to set the values of the Composite object c.
spmd
c = getLocalPart(d);
end
c{:}
ans = 3
ans = 1
ans = 4
ans = 2
whos c
myClusterPool = parpool(myMJSCluster,15);
Partition the myClusterPool to prepare for running an spmd statement. Use the partition
function to create a new pool, spmdPool, where each host is limited to a maximum of one worker.
This setup helps distribute tasks evenly across hosts.
9-26
Composite
[spmdPool,otherPool] = partition(myClusterPool,"MaxNumWorkersPerHost",1);
j = Composite(spmdPool);
Use a for-loop on the client to define values for the elements of the Composite object.
m = 1000000;
for w = 1:length(j)
j{w} = rand(m,2);
end
spmd
for p = drange(1:spmdSize)
z = j(:,1) + 1i*j(:,2);
c = sum(abs(z) < 1);
end
k = spmdPlus(c);
p = 4*k/(m*spmdSize);
end
approxPi = p{1}
approxPi =
3.1418
Tips
• The Composite function creates a Composite object on the workers of the existing parallel pool.
If no pool exists, the Composite function starts a new parallel pool unless automatically starting
pools is disabled in your parallel settings. If no parallel pool exists and Composite cannot start
one, the result is a 1-by-1 Composite object in the client workspace.
Version History
Introduced in R2008a
You can now specify a parallel pool to use to create Composite objects. Use this syntax to create
Composite on a pool other than the pool the gcp function returns.
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
9-27
9 Objects
See Also
parpool | [Link] | spmd
Topics
“Access Worker Variables with Composites” on page 4-17
9-28
[Link]
[Link]
Kernel executable on GPU
Description
A CUDAKernel object represents a CUDA kernel that can execute on a GPU. You create the kernel
from CU and PTX files. For an example of how to create and use a CUDAKernel object, see “Run
CUDA or PTX Code on GPU” on page 6-117.
Creation
Syntax
kern = [Link](ptxFile,cuFile)
kern = [Link](ptxFile,cuFile,func)
kern = [Link](ptxFile,cProto)
kern = [Link](ptxFile,cProto,func)
Description
Use feval with kern as an input to execute the CUDA kernel on the GPU. For information on
executing your kernel object, see “Run a CUDAKernel” on page 6-121.
Input Arguments
9-29
9 Objects
You can provide the name of a PTX file, or pass its contents as a string.
Example: "[Link]"
Data Types: char | string
The function examines the CUDA source file to find the function prototype for the CUDA kernel that is
defined in the PTX code. The CUDA source file must contain a kernel definition starting with
'__global__'.
Example: "[Link]"
Data Types: char | string
Function entry point, specified as a character vector. func must unambiguously define the
appropriate entry point in the PTX file.
Note The [Link] function searches for the specified entry point in the PTX
file, and matches on any substring occurrences. Therefore, you should not name any of your entry
points as substrings of any others.
Example: "add1"
Data Types: char | string
cProto — C prototype
string scalar | character vector
C prototype for the kernel call, specified as a character vector. Specify multiple input arguments
separated by commas.
Example: "float *,float,int"
Data Types: char | string
Properties
ThreadBlockSize — Size of block of threads on kernel
positive integer vector
Size of a block of threads on the kernel, specified as a vector of positive integers of length 1, 2, or 3
(since thread blocks can be up to 3-dimensional). The product of the elements of ThreadBlockSize
must not exceed the MaxThreadsPerBlock for this kernel, and no element of ThreadBlockSize
can exceed the corresponding element of the GPUDevice property MaxThreadBlockSize.
Example: [8 8 8]
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
9-30
[Link]
Maximum number of threads permissible in a single block for this CUDA kernel. The product of the
elements of ThreadBlockSize must not exceed this value.
Example: 1024
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Size of grid of thread blocks, specified as an integer vector of length 3. This is effectively the number
of thread blocks launched independently by the GPU. None of the elements of this vector can exceed
the corresponding element in the vector of the MaxGridSize property of the GPUDevice object.
Example: [977 1 1]
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
The amount of dynamic shared memory (in bytes) that each thread block can use. Each thread block
has an available shared memory region. This memory is shared with registers on the multiprocessors.
SharedMemorySize must not exceed the MaxShmemPerBlock property of the GPUDevice object.
As with all memory, this needs to be allocated before the kernel is launched. It is common for the size
of this shared memory region to be tied to the size of the thread block. Setting this value on the
kernel ensures that each thread in a block can access this available shared memory region.
Example: 16000
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
The entry point name in the PTX code called by the kernel.
Example: "_Z13returnPointerPKfPy"
Data Types: char | string
The maximum number of left hand side arguments that the kernel supports. It cannot be greater than
the number of right hand side arguments, and if any inputs are constant or scalar it will be less.
Example: 1
9-31
9 Objects
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 |
logical
The required number of right hand side arguments needed to call this kernel. All inputs need to
define either the scalar value of an input, the elements for a vector input/output, or the size of an
output argument.
Example: 5
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Cell array of character vectors of length NumRHSArguments. Each of the character vectors indicates
what the expected MATLAB data type for that input is by specifying a numeric type such as uint8,
single, or double followed by the word scalar or vector to indicate if we are passing by
reference or value. In addition, if that argument is only an input to the kernel, it is prefixed by in;
and if it is an input/output, it is prefixed by inout. This allows you to decide how to efficiently call the
kernel with both MATLAB arrays and gpuArray objects, and to see which of the kernel inputs are
being treated as outputs.
Example: {'inout double vector'} {'in double vector'} {'in double vector'} {'in
uint32 scalar'} {'in uint32 scalar'}
Data Types: cell
Object Functions
feval Evaluate kernel on GPU
setConstantMemory Set some constant memory on GPU
existsOnGPU Determine if gpuArray or CUDAKernel is available on GPU
Examples
This example shows how to create a CUDAKernel object using a PTX file and a CU file, or using a
PTX file and the function prototype.
9-32
[Link]
Compile the CU file into a PTX file using mexcuda with the -ptx option.
Create a CUDA kernel using the PTX file and the CU file.
kern = [Link]("[Link]","[Link]");
Create a CUDA kernel using the PTX file and the function prototype of the addToVector function.
Both of the preceding statements return a kernel object that you can use to call the addToVector
CUDA kernel.
This example shows how to create a CUDAKernel object from a PTX file with more than one entry
point.
Suppose your CU file, [Link], contains a function add1 for adding two doubles together and a
function add2 for adding two vectors together.
Compile the CU file into a PTX file using mexcuda with the -ptx option.
The PTX file contains two entry points corresponding to the add1 and add2 functions. When your
PTX code contains multiple entry points, you must specify an entry when creating your kernel.
Create a kernel for adding two doubles together and specify the entry point add1.
k = [Link]("[Link]","[Link]","add1");
Version History
Introduced in R2010b
9-33
9 Objects
See Also
feval | mexcuda | gpuArray | GPUDevice
Topics
“Run CUDA or PTX Code on GPU” on page 6-117
9-34
distributed
distributed
Create and access elements of distributed arrays from client
Description
A distributed array on the client represents an array that is partitioned out among the workers in a
parallel pool. You operate on the entire array as a single entity; however, workers operate only on
their part of the array and automatically transfer data between themselves when necessary. A
distributed array resembles a normal MATLAB array in the way you index and manipulate its
elements, but none of its elements exist on the client. Codistributed arrays that you create inside
spmd statements are accessible as distributed arrays from the client.
Creation
Use the distributed function or use the "distributed" option of array creation functions such as
ones or zeros. For a list of array creation functions that create distributed arrays directly on
workers, see “Alternative Functionality” on page 9-41.
Syntax
D = distributed(ds)
D = distributed(X)
D = distributed(C,dim)
D = distributed(tX)
Description
To retrieve the distributed array elements from the pool back to an array in the MATLAB workspace,
use the gather function.
Use this syntax to create a distributed array from local data only if the MATLAB client can store all of
X in memory. To create large distributed arrays, use the previous syntax to create a distributed array
from a datastore, or the "distributed"option of array creation functions such as ones, zeros, or
any other creation functions listed in “Alternative Functionality” on page 9-41.
If the input argument is already a distributed array, the result is the same as the input.
D = distributed(C,dim) creates a distributed array from the Composite object C, with the
entries of C concatenated and distributed along the dimension dim. If you omit dim, then the first
dimension is the distribution dimension.
All entries of the Composite object must have the same class. Dimensions other than the distribution
dimension must be the same.
9-35
9 Objects
D = distributed(tX) converts the tall array tX into a distributed array distributed along the first
dimension. tX must be defined in a parallel environment that can run distributed arrays.
Input Arguments
ds — Datastore
TabularTextDatastore object | ImageDatastore object | SpreadsheetDatastore object |
KeyValueDatastore object | FileDatastore object | TallDatastore object | ...
Object Type
TabularTextDatastore object Text files
ImageDatastore object Image files
SpreadsheetDatastore object Spreadsheet files
KeyValueDatastore object MAT files as well as sequence files you
produce using mapreduce
FileDatastore object Custom format files
TallDatastore object MAT-files and sequence files produced by
the write function of the tall data type
ParquetDatastore object Parquet files
DatabaseDatastore object Database
X — Array to distribute
array
Distribution dimension, specified as a scalar integer. The distribution dimension specifies the
dimension over which you distribute the Composite object.
Tall array to convert to a distributed array, specified as a tall array. The tall array must be defined in a
parallel environment that supports distributed arrays.
Output Arguments
D — Distributed array
distributed array
Distributed array stored in parts on the workers of the open parallel pool, returned as a distributed
array.
9-36
distributed
Object Functions
gather Transfer distributed array, Composite object, or gpuArray object to local workspace
write Write distributed data to an output location
Several MATLAB toolboxes include functions with distributed array support. For a list of functions in
all MathWorks products that support distributed arrays, see All Functions List (Distributed Arrays).
Several object functions enable you to examine the characteristics of a distributed array. Most behave
like the MATLAB functions of the same name.
isdistributed True for distributed array
isreal Determine whether array uses complex storage
isUnderlyingType Determine whether input has specified underlying data type
length Length of largest array dimension
ndims Number of array dimensions
size Array size
underlyingType Type of underlying data determining array behavior
Examples
This example shows how to create and load distributed arrays using datastore.
First, create a datastore using an example data set. This data set is too small to show equal
partitioning of the data over the workers. To simulate a large data set, artificially increase the size of
the datastore using repmat.
files = repmat("[Link]",10,1);
ds = tabularTextDatastore(files);
Create a distributed table by reading the datastore in parallel. Partition the datastore with one
partition per worker. Each worker then reads all data from the corresponding partition. The files must
be in a shared location accessible from the workers.
dt = distributed(ds);
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
summary(dt)
Variables:
min 1
max 2505
NaNs 23,510
9-37
9 Objects
min -1036
max 1438
NaNs 23,510
Create a large distributed array directly on the workers by using a build function.
Nlarge = 1000;
D2 = rand(Nlarge,"distributed");
Retrieve elements of a distributed array back to the local workspace. You can use whos to determine
the location of the data in the workspace by examining the Class variable.
D3 = gather(D2);
whos
Start a parallel pool of workers and create a Composite object by using spmd.
p = parpool("Processes",4);
spmd
C = rand(3,spmdIndex-1);
end
C
C =
9-38
distributed
To create a distributed array from the Composite object, use the distributed function. For this
example, distribute the entries along the second dimension.
d = distributed(C,2)
d =
spmd
d
end
Worker 1:
This worker does not store any elements of d.
Worker 2:
This worker stores d(:,1).
LocalPart: [3x1 double]
Codistributor: [1x1 codistributor1d]
Worker 3:
This worker stores d(:,2:3).
LocalPart: [3x2 double]
Codistributor: [1x1 codistributor1d]
Worker 4:
This worker stores d(:,4:6).
LocalPart: [3x3 double]
Codistributor: [1x1 codistributor1d]
When you are finished with the computations, delete the parallel pool.
delete(p);
This example shows how to convert a tall array into a distributed array.
Create a tall table using an example data set. If you have Parallel Computing Toolbox™ installed,
when you use the tall function, MATLAB automatically starts a parallel pool of workers unless you
turn off the default parallel pool preference. The default cluster uses local process workers on your
machine.
9-39
9 Objects
size = 2000000;
tt = tall(table((1:size)',randn(size,1),randn(size,1),randn(size,1), ...
'VariableNames',["Exp","Rep1","Rep2","Rep3"]))
tt =
Convert the tall table into a distributed table. MATLAB partitions the data in the tall table along the
first dimension and distributes it to the workers.
dt = distributed(tt);
Variables:
Min 1
Max 2e+06
Min -5.1402
Max 4.8763
Min -4.7961
Max 4.9875
Min -4.8369
Max 5.1454
9-40
distributed
Finally, examine how much data is stored on each worker. The data is partitioned evenly over the
workers.
spmd
dt
end
Worker 1:
Worker 2:
Worker 3:
Worker 4:
Tips
• A distributed array is created on the workers of the existing parallel pool. If no pool exists,
distributed starts a new parallel pool unless the automatic starting of pools is disabled in your
parallel settings. If there is no parallel pool and distributed cannot start one, MATLAB returns
the result as a nondistributed array in the client workspace.
Alternative Functionality
This table lists the available MATLAB functions that create distributed arrays directly on the
workers. For more information, see the Extended Capabilities section of the function reference page.
eye [Link]
false [Link]
Inf [Link]
NaN [Link]
9-41
9 Objects
ones [Link]
true [Link]
zeros [Link]
rand [Link]
randi
randn
Version History
Introduced in R2008a
Use the distributed function to convert a tall array to a distributed array and access MATLAB
functions that have distributed array support.
In previous releases, when you used a tall array with the distributed function, MATLAB threw an
error.
See Also
codistributed | tall | gather | parpool | spmd | datastore | tall | spmd
Topics
“Create and Use Distributed Arrays” on page 4-2
“Run MATLAB Functions with Distributed Arrays” on page 4-5
“Nondistributed Versus Distributed Arrays” on page 4-36
“What Is a Datastore?”
9-42
FileStore
FileStore
File storage shared by MATLAB clients and workers
Description
FileStore is an object that stores files owned by a specific job. Each entry of the object consists of a
file and its corresponding key. When the owning job is deleted, the FileStore object is deleted as
well. Use FileStore to store files from MATLAB workers that can be retrieved by MATLAB clients
during the execution of a job (even while the job is still running).
• Any MATLAB process client or worker can write an entry to the FileStore at any time. Any
MATLAB process client or worker can then read this entry from the FileStore at any time.
However, the ordering of operations executed by different processes is not guaranteed.
• FileStore can be used to return files when a cluster has no shared file system, or to run code
that is not concerned about the location of any shared file system.
• FileStore is not held in system memory, so it can be used to store large results.
Creation
The FileStore object is automatically created when you create:
• A job on a cluster, which is a [Link] object. To create a job, use the batch, createJob,
or createCommunicatingJob function.
• A parallel pool of process workers on the local machine, which is a ProcessPool object. To
create a process pool, use the parpool function.
• A parallel pool of thread workers on the local machine, which is a ThreadPool object. To create a
thread pool, use the parpool function.
• A parallel pool of workers on a cluster of machines, which is a ClusterPool object. To create a
cluster pool, use the parpool function.
You can access the FileStore object on a worker by using the getCurrentFileStore function.
You can then retrieve the FileStore object on a client by using the FileStore property that is
associated with the job or the parallel pool. For example, see “Run Batch Job and Retrieve Files from
Workers” on page 9-44.
Properties
KeyUpdatedFcn — Callback executed when entry is added or replaced
function handle
Callback executed when an entry is added or replaced, specified as a function handle. The function
handle must accept two input arguments that represent the FileStore object and its key when an
entry is added or replaced.
9-43
9 Objects
Callback executed when an entry is removed, specified as a function handle. The function handle
must accept two input arguments that represent the FileStore object and its key when an entry is
removed.
Object Functions
isKey Determine if ValueStore or FileStore object contains keys
keys Return all keys of ValueStore or FileStore object
copyFileToStore Copy files from local file system to FileStore object
copyFileFromStore Copy files from FileStore object to local file system
remove Remove entries from ValueStore or FileStore object
Examples
Run a simulation on workers and retrieve the file storage of the job on a client. The file storage is a
FileStore object with key-file entries.
The following simulation finds the average and standard deviation of random matrices and stores the
results in the FileStore object.
type workerStatsCode
function workerStatsCode(models)
% Get the FileStore of the current job
store = getCurrentFileStore;
for i = 1:numel(models)
% Compute the average and standard deviation of random matrices
A = rand(models(i));
M = mean(A);
S = std(A);
% Save simulation results in temporary files
sourceTempFile = strcat(tempname("C:\myTempFolder"),".mat");
save(sourceTempFile,"M","S");
% Copy files to FileStore object as key-file pairs
key = strcat("result_",num2str(i));
copyFileToStore(store,sourceTempFile,key);
end
end
The following callback function is executed when a file is copied to the FileStore object.
type fileNewEntry
function fileNewEntry(store,key)
destination = strcat(key,".mat");
fprintf("Result %s added. Copying to local file system: %s\n",key,destination);
copyFileFromStore(store,key,destination);
end
9-44
FileStore
models = [4,8,32,20];
c = parcluster;
job = batch(c,@workerStatsCode,0,{models});
Retrieve the FileStore object on the client while the job is still running. Show the progress of the
job.
store = [Link];
[Link] = @fileNewEntry;
wait(job);
Display all the information on the variables stored in the file "result_3.mat".
Run a simulation on a parallel pool of process workers and retrieve the file storage on a client.
The following simulation finds the average and standard deviation of random matrices and stores the
results in the FileStore object.
type workerStatsCode
function workerStatsCode(models)
% Get the FileStore of the current job
store = getCurrentFileStore;
for i = 1:numel(models)
% Compute the average and standard deviation of random matrices
A = rand(models(i));
M = mean(A);
S = std(A);
% Save simulation results in temporary files
sourceTempFile = strcat(tempname("C:\myTempFolder"),".mat");
save(sourceTempFile,"M","S");
% Copy files to FileStore object as key-file pairs
key = strcat("result_",num2str(i));
copyFileToStore(store,sourceTempFile,key);
end
end
The following callback function is executed when a file is copied to the FileStore object.
type fileNewEntry
9-45
9 Objects
function fileNewEntry(store,key)
destination = strcat(key,".mat");
fprintf("Result %s added. Copying to local file system: %s\n",key,destination);
copyFileFromStore(store,key,destination);
end
pool = parpool('Processes');
Get the FileStore for this pool and assign the callback function to be executed when an entry is
added.
store = [Link];
[Link] = @fileNewEntry;
models = [4,8,32,20];
future = parfeval(@workerStatsCode,0,models);
wait(future);
Run Independent Tasks and Retrieve Data and Files from All Tasks
Run a job of independent tasks. Then, retrieve the data and file storage of the job on a client.
The following simulation finds the permutations and combinations of a vector, and stores the results
in the ValueStore and FileStore objects.
type taskFunction
function taskFunction(dataset,keyname)
% Get the ValueStore and FileStore of the current job
valueStore = getCurrentValueStore;
fileStore = getCurrentFileStore;
% Run the simulation to find permutation and combination
[result,logFile] = runSimulation(dataset);
% Store results in ValueStore to release system memory
9-46
FileStore
valueStore(keyname) = result;
% Copy file to FileStore to retrieve the file from non-shared file system
copyFileToStore(fileStore,logFile,keyname);
end
Create independent tasks for the job. Each task runs the simulation with the given input.
set_1 = {[12,34,54],2};
set_2 = {[45,33],1};
set_3 = {[12,12,12,13,14],3};
tasks = createTask(job,@taskFunction,0,{{set_1,"sim_1"},{set_2,"sim_2"},{set_3,"sim_3"}});
Show the result of the third task that is stored in the ValueStore object.
result_3 = valueStore("sim_3")
Copy files from the file storage as specified by the corresponding keys "sim_1" and "sim_2" to the
local files "analysis_1.mat" and "analysis_2.mat".
copyFileFromStore(fileStore,["sim_1" "sim_2"],["analysis_1.mat" "analysis_2.mat"]);
Display all the information on the variables stored in the local files.
whos -file 'analysis_1.mat'
9-47
9 Objects
Limitations
• When using [Link] clusters with 'HasSharedFileSystem' set to
false, the visibility of modifications made to FileStore while a job is running depends on your
specific implementation. Without additional synchronization between the MATLAB client and
worker JobStorageLocation, changes might only be visible once the job has completed.
Version History
Introduced in R2022a
See Also
getCurrentFileStore | [Link] | ProcessPool | ClusterPool | ValueStore
9-48
gpuArray
gpuArray
Array stored on GPU
Description
A gpuArray object represents an array stored in GPU memory. A large number of functions in
MATLAB and in other toolboxes support gpuArray objects, allowing you to run your code on GPUs
with minimal changes to the code. To work with gpuArray objects, use any gpuArray-enabled
MATLAB function such as fft, mtimes or mldivide. To find a full list of gpuArray-enabled
functions in MATLAB and in other toolboxes, see GPU-supported functions. For more information, see
“Run MATLAB Functions on a GPU” on page 6-3.
If you want to retrieve the array from the GPU, for example when using a function that does not
support gpuArray objects, use the gather function.
Note You can load MAT files containing gpuArray data as in-memory arrays when a GPU is not
available. A gpuArray object loaded without a GPU is limited and you cannot use it for computations.
To use a gpuArray object loaded without a GPU, retrieve the contents using gather.
Creation
Use gpuArray to convert an array in the MATLAB workspace into a gpuArray object. Some
MATLAB functions also allow you to create gpuArray objects directly. For more information, see
“Establish Arrays on a GPU” on page 6-15.
Syntax
G = gpuArray(X)
Description
G = gpuArray(X) copies the array X to the GPU and returns a gpuArray object.
Input Arguments
X — Array
numeric array | logical array
Array to transfer to the GPU, specified as a numeric or logical array. The GPU device must have
sufficient free memory to store the data. If X is already a gpuArray object, gpuArray outputs X
unchanged.
9-49
9 Objects
Object Functions
arrayfun Apply function to each element of array on GPU
gather Transfer distributed array, Composite object, or gpuArray object to local workspace
pagefun Apply function to each page of distributed or GPU array
There are several methods for examining the characteristics of a gpuArray object. Most behave like
the MATLAB functions of the same name.
Several MATLAB toolboxes include functions with gpuArray support. To view lists of all functions in
these toolboxes that support gpuArray objects, use the links in the following table. Functions in the
lists with information indicators have limitations or usage notes specific to running the function on a
GPU. You can check the usage notes and limitations in the Extended Capabilities section of the
function reference page. For information about updates to individual gpuArray-enabled functions,
see the release notes.
9-50
gpuArray
For a list of functions with gpuArray support in all MathWorks products, see gpuArray-supported
functions. Alternatively, you can filter by product. On the Help bar, click Functions. In the function
list, browse the left pane to select a product, for example, MATLAB. At the bottom of the left pane,
select GPU Arrays. If you select a product that does not have gpuArray-enabled functions, then the
GPU Arrays filter is not available.
Examples
To transfer data from the CPU to the GPU, use the gpuArray function.
Create an array X.
X = [1,2,3];
ans = logical
1
9-51
9 Objects
XSq = 1×3
1 4 9
ans = logical
0
You can create data directly on the GPU directly by using some MATLAB functions and specifying the
option "gpuArray".
G =
ans = logical
1
This example shows how to use gpuArray-enabled MATLAB functions to operate with gpuArray
objects. You can check the properties of your GPU using the gpuDevice function.
gpuDevice
ans =
CUDADevice with properties:
9-52
gpuArray
DeviceAvailable: true
DeviceSelected: true
Create a row vector that repeats values from -15 to 15. To transfer it to the GPU and create a
gpuArray object, use the gpuArray function.
X = [-15:15 0 -15:15 0 -15:15];
gpuX = gpuArray(X);
whos gpuX
To operate with gpuArray objects, use any gpuArray-enabled MATLAB function. MATLAB
automatically runs calculations on the GPU. For more information, see “Run MATLAB Functions on a
GPU” on page 6-3. For example, use diag, expm, mod, round, abs, and fliplr together.
gpuE = expm(diag(gpuX,-1)) * expm(diag(gpuX,1));
gpuM = mod(round(abs(gpuE)),2);
gpuF = gpuM + fliplr(gpuM);
9-53
9 Objects
If you need to transfer the data back from the GPU, use gather. Transferring data back to the CPU
can be costly, and is generally not necessary unless you need to use your result with functions that do
not support gpuArray.
result = gather(gpuF);
whos result
In general, running code on the CPU and the GPU can produce different results due to numerical
precision and algorithmic differences between the GPU and CPU. Answers from the CPU and GPU are
both equally valid floating point approximations to the true analytical result, having been subjected to
different roundoff behavior during computation. In this example, the results are integers and round
eliminates the roundoff errors.
This example shows how to use MATLAB functions and operators with gpuArray objects to compute
the integral of a function by using the Monte Carlo integration method.
Define the number of points to sample. Sample points in the domain of the function, the interval
[-1,1] in both x and y coordinates, by creating random points with the rand function. To create a
random array directly on the GPU, use the rand function and specify "gpuArray". For more
information, see “Establish Arrays on a GPU” on page 6-15.
n = 1e6;
x = 2*rand(n,1,"gpuArray")-1;
y = 2*rand(n,1,"gpuArray")-1;
Define the function to integrate, and use the Monte Carlo integration formula on it. This function
approximates the value of π by sampling points within the unit circle. Because the code uses
gpuArray-enabled functions and operators on gpuArray objects, the computations automatically
run on the GPU. You can perform binary operations such as element-wise multiplication using the
same syntax that you use for MATLAB arrays. For more information about gpuArray-enabled
functions, see “Run MATLAB Functions on a GPU” on page 6-3.
f = x.^2 + y.^2 <= 1;
result = 4*nnz(f)/n
result = 3.1433
Limitations
• None of the following can exceed intmax("int32"):
9-54
gpuArray
parallel pool has access to a unique GPU, you can instead manually split or initially generate your
data as multiple gpuArray objects on different workers. For examples showing how to use
gpuArray data in a parallel pool, see “Run MATLAB Functions on Multiple GPUs” on page 6-19.
• Sparse gpuArray limitations:
For more information, see “Work with Sparse Arrays on a GPU” on page 6-36.
Tips
• If you need better performance, or if a function is not available on the GPU, gpuArray supports
the following options:
• To precompile and run purely element-wise code on gpuArray objects, use the arrayfun
function.
• To run C++ code containing CUDA device code or library calls, use a MEX function. For more
information, see “Run MEX Functions Containing CUDA Code” on page 6-124.
• To run existing GPU kernels written in CUDA C++, use the MATLAB CUDAKernel interface.
For more information, see “Run CUDA or PTX Code on GPU” on page 6-117.
• To generate CUDA code from MATLAB code, use GPU Coder™. For more information, see “Get
Started with GPU Coder” (GPU Coder).
• Most GPUs perform calculations faster in single precision than in double precision. If your
workflow does not require double precision, consider converting your data to single precision
using the single function or creating single-precision gpuArray data directly. For more
information, see “Perform Calculations in Single Precision” on page 6-45.
• To control the random number stream on the GPU, use the gpurng function.
Alternatives
You can also create a gpuArray object using some MATLAB functions by specifying a gpuArray
output. The following table lists the MATLAB functions that enable you to create gpuArray objects
directly. For more information, see the Extended Capabilities section of the function reference page.
eye(___,"gpuArray") createArray(___,"gpuArray")
false(___,"gpuArray") [Link]
Inf(___,"gpuArray") [Link]
NaN(___,"gpuArray") [Link]
ones(___,"gpuArray") [Link]
rand(___,"gpuArray") [Link]
randi(___,"gpuArray") [Link]
randn(___,"gpuArray") [Link]
true(___,"gpuArray") [Link]
9-55
9 Objects
zeros(___,"gpuArray")
Version History
Introduced in R2010b
You can now create and use single-precision sparse GPU arrays. Sparse matrices provide efficient
storage of data that has a large percentage of zeros and reduce computation time by eliminating
operations on zero elements. Using single-precision sparse GPU arrays allows you to reduce memory
usage further and accelerate calculations by taking advantage of your GPU's single-precision floating-
point units (FPUs).
For more information, see “Work with Sparse Arrays on a GPU” on page 6-36.
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
isgpuarray | canUseGPU | arrayfun | gpuDevice | existsOnGPU | gather | reset | pagefun |
gputimeit
Topics
“Establish Arrays on a GPU” on page 6-15
“Run MATLAB Functions on a GPU” on page 6-3
“Identify and Select a GPU Device” on page 6-10
“Work with Sparse Arrays on a GPU” on page 6-36
“Work with Complex Numbers on a GPU” on page 6-39
9-56
gpuDevice
gpuDevice
Query or select a GPU device
Description
A GPUDevice object represents a graphic processing unit (GPU) in your computer. You can use the
GPU to run MATLAB code that supports gpuArray variables or execute CUDA kernels using
CUDAKernel objects.
You can use a GPUDevice object to inspect the properties of your GPU device, reset the GPU device,
or wait for your GPU to finish executing a computation. To obtain a GPUDevice object, use the
gpuDevice function. You can also select or deselect your GPU device using the gpuDevice function.
If you have access to multiple GPUs, use the gpuDevice function to choose a specific GPU device on
which to execute your code.
You do not need to use a GPUDevice object to run functions on a GPU. For more information on how
to use GPU-enabled functions, see “Run MATLAB Functions on a GPU” on page 6-3.
Creation
Syntax
gpuDevice
D = gpuDevice
D = gpuDevice(ind)
gpuDevice([])
Description
gpuDevice displays the properties of the currently selected GPU device. If there is no currently
selected device, gpuDevice selects the default device without clearing it. Use this syntax when you
want to inspect the properties of your GPU device.
D = gpuDevice returns a GPUDevice object representing the currently selected device. If there is
no currently selected device, gpuDevice selects the default device and returns a GPUDevice object
representing that device without clearing it.
D = gpuDevice(ind) selects the GPU device specified by index ind. If the specified GPU device is
not supported, an error occurs. This syntax resets the specified device and clears its memory, even if
the device is already currently selected (equivalent to the reset function). All workspace variables
representing gpuArray or CUDAKernel variables are now invalid and must be cleared from the
workspace or redefined.
gpuDevice([]), with an empty argument (as opposed to no argument), deselects the GPU device
and clears its memory of gpuArray and CUDAKernel variables. This syntax leaves no GPU device
selected as the current device.
9-57
9 Objects
Input Arguments
Properties
Identity
Name of the GPU device, specified as a character array. The name assigned to the device is derived
from the GPU device model.
Data Types: char
Index of the GPU device, specified as an integer in the range 1 to gpuDeviceCount. Use this index
to select a particular GPU device.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
The UUID typically starts with 'GPU-' and includes a 36-character hexadecimal sequence. You can
use the UUID to distinguish otherwise identical GPUs.
Data Types: char
State
Flag for currently selected device, specified by the logical values 0 (false) or 1 (true).
Data Types: logical
9-58
gpuDevice
Flag for available device, specified by the logical values 0 (false) or 1 (true). This property
indicates whether the device is available for use in the current MATLAB session. Unsupported
devices with a DeviceSupported property of 0 (false) are always unavailable. A device can also be
unavailable if its ComputeMode property is set to 'Exclusive thread', 'Exclusive process',
or 'Prohibited'.
Data Types: logical
Flag for supported device, specified by the logical values 0 (false) or 1 (true). Not all devices are
supported; for example, devices with insufficient ComputeCapability.
Data Types: logical
Date and time the device was last accessed by the current MATLAB session, specified as a scalar
datetime array. If the device has not been accessed in this session, then LastAccessed is Not-a-
Time (NaT).
Querying properties of the currently selected device does not update LastAccessed.
Data Types: datetime
Memory
9-59
9 Objects
Total memory (in bytes) available for data, specified as a scalar value. This property is available only
for the currently selected device. This value can differ from the value reported by the NVIDIA System
Management Interface due to memory caching.
Data Types: double
Caching policy of the GPU device, specified as 'balanced', 'minimum', or 'maximum'. The
caching policy determines how much GPU memory can be cached to accelerate computation,
specified as one of the following values.
• 'minimum' – The amount of memory that can be cached on the GPU device is minimal.
• 'balanced' – The amount of memory that can be cached on the GPU device is balanced. This
policy provides a balance between GPU memory usage and computational performance.
• 'maximum' – The amount of memory that can be cached on the GPU device is limited only by the
total memory of the device.
The default value is 'balanced' for devices in 'Default' or 'Prohibited' compute mode and
'maximum' for devices in 'Exclusive process' compute mode. For more information on the
compute mode property, see ComputeMode.
Note
• Resetting the device using reset, clearing the device using gpuDevice([]), or selecting
another device using gpuDevice resets the caching policy to the default policy.
• Saving and loading a MAT file containing a GPUDevice object does not preserve the caching
policy.
• You cannot set the caching policy of a device that is not selected. For example, after storing a first
GPUDevice object in an array and selecting another device, you cannot set the caching policy of
the first GPUDevice object.
Driver
Graphics driver version currently in use by the GPU device, specified as a character array.
Download the latest graphics driver for your GPU at NVIDIA Driver Downloads.
Data Types: char
9-60
gpuDevice
For more information about changing models and which GPU devices support 'TCC', see the NVIDIA
documentation.
Data Types: char
For more information changing the compute mode of your GPU device, consult the NVIDIA
documentation.
Data Types: char
Capabilities
9-61
9 Objects
Computational capability of the GPU device, specified as a character array. To use the selected GPU
device in MATLAB, ComputeCapability must meet the required specification in “GPU Computing
Requirements” on page 6-13.
Data Types: char
Ratio of single- to double-precision floating point units (FPUs) on the device, specified as a scalar
value.
The ratio indicates the single-precision processing power relative to the double-precision processing
power of the device. Devices that are suitable for double-precision computations, such as solving
linear systems, generally have a lower ratio. Devices that are suitable for single-precision
computations, such as training deep neural networks and rendering graphics, generally have a larger
ratio.
Data Types: double
Kernel Programming
Maximum supported number of threads per block during CUDAKernel execution, specified as a
scalar value.
Example: 1024
Data Types: double
9-62
gpuDevice
Maximum supported amount of shared memory that a thread block can use during CUDAKernel
execution, specified as a scalar value.
Data Types: double
Maximum size in each dimension for thread block, specified as a vector. Each dimension of a thread
block must not exceed these dimensions. Also, the product of the thread block size must not exceed
MaxThreadsPerBlock.
Example: [1024 1024 64]
Data Types: double
CUDA toolkit version used by the current release of MATLAB, specified as a scalar value.
Data Types: double
Object Functions
reset Reset GPU device and clear its memory
wait (GPUDevice) Wait for GPU calculation to complete
9-63
9 Objects
For a complete list of functions, use the methods function on the GPUDevice object:
methods('[Link]')
You can get help on any of the object functions with the following command:
help [Link]
where functionname is the name of the function. For example, to get help on isAvailable, type:
help [Link]
Examples
This example shows how to use gpuDevice to identify and select which device you want to use.
To determine how many GPU devices are available in your computer, use the gpuDeviceCount
function.
gpuDeviceCount("available")
ans = 2
When there are multiple devices, the first is the default. You can examine its properties with the
gpuDeviceTable function to determine if that is the one you want to use.
gpuDeviceTable
ans=2×5 table
Index Name ComputeCapability DeviceAvailable DeviceSelected
_____ __________________ _________________ _______________ ______________
If the first device is the device you want to use, you can proceed. To run computations on the GPU,
use gpuArray enabled functions. For more information, see “Run MATLAB Functions on a GPU” on
page 6-3.
To verify that MATLAB® can use your GPU, use the canUseGPU function. The function returns 1
(true) if there is a GPU available for computation and 0 (false) otherwise.
canUseGPU
ans = logical
1
9-64
gpuDevice
To diagnose an issue with your GPU setup, for example if canUseGPU returns 0 (false), use the
validateGPU function. Validating your GPU is optional.
validateGPU
To use another device, call gpuDevice with the index of the other device.
gpuDevice(2)
ans =
CUDADevice with properties:
Alternatively, you can determine how many GPU devices are available, inspect some of their
properties, and select a device to use from the MATLAB® desktop. On the Home tab, in the
Environment area, select Parallel > Select GPU Environment.
9-65
9 Objects
Create an object representing the default GPU device and query its compute capability.
D = gpuDevice;
[Link]
ans =
'8.6'
Compare the compute capabilities and availability of the GPU devices in your system using
gpuDeviceTable.
gpuDeviceTable
ans=2×5 table
Index Name ComputeCapability DeviceAvailable DeviceSelected
_____ __________________ _________________ _______________ ______________
9-66
gpuDevice
D = gpuDevice
D =
CUDADevice with properties:
[Link]
ans =
'balanced'
Change the caching policy to allow the GPU to cache the maximum amount of memory for
accelerating computation.
[Link] = "maximum";
[Link]
ans =
'maximum'
Reset the caching policy to the default policy by setting the property to [].
[Link] = [];
Calling reset(D) or selecting another device with gpuDevice also resets the caching policy to its
default value.
If you have access to several GPUs, you can perform your calculations on multiple GPUs in parallel
using a parallel pool.
To determine the number of GPUs that are available for use in MATLAB, use the gpuDeviceCount
function.
availableGPUs = gpuDeviceCount("available")
9-67
9 Objects
availableGPUs = 3
Start a parallel pool with as many workers as available GPUs. For best performance, MATLAB assigns
a different GPU to each worker by default.
parpool("Processes",availableGPUs);
To identify which GPU each worker is using, call gpuDevice inside an spmd block. The spmd block
runs gpuDevice on every worker.
spmd
gpuDevice
end
Use parallel language features, such as parfor or parfeval, to distribute your computations to
workers in the parallel pool. If you use gpuArray enabled functions in your computations, these
functions run on the GPU of the worker. For more information, see “Run MATLAB Functions on a
GPU” on page 6-3. For an example, see “Run MATLAB Functions on Multiple GPUs” on page 6-19.
When you are done with your computations, shut down the parallel pool. You can use the gcp
function to obtain the current parallel pool.
delete(gcp("nocreate"));
If you want to use a different choice of GPUs, then you can use gpuDevice to select a particular GPU
on each worker, using the GPU device index. You can obtain the index of each GPU device in your
system using the gpuDeviceCount function.
Suppose you have three GPUs available in your system, but you want to use only two for a
computation. Obtain the indices of the devices.
[availableGPUs,gpuIndx] = gpuDeviceCount("available")
availableGPUs = 3
gpuIndx = 1×3
1 2 3
Start your parallel pool. Use an spmd block and gpuDevice to associate each worker with one of the
GPUs you want to use, using the device index. The spmdIndex function identifies the index of each
worker.
parpool("Processes",numel(useGPUs));
spmd
gpuDevice(useGPUs(spmdIndex));
end
9-68
gpuDevice
As a best practice, and for best performance, assign a different GPU to each worker.
When you are done with your computations, shut down the parallel pool.
delete(gcp("nocreate"));
Version History
Introduced in R2010b
Use the gpuDevice function to inspect these new properties of your GPU device:
• LastAccessed — the date and time the device was last accessed by the current MATLAB session.
• SingleDoubleRatio — the ratio of single- to double-precision floating point units (FPUs) on the
device.
Creating or querying a GPUDevice object now displays only the Name, Index, ComputeCapability,
DriverModel, TotalMemory, AvailableMemory, DeviceAvailable, and DeviceSelected
properties. To view all of the properties of a device, create or query a GPUDevice object without
suppressing output and click the Show all properties link.
D = gpuDevice
D =
Inspect the universally unique identifier (UUID) of your GPU using the UUID property of a
GPUDevice object. You can use the UUID to distinguish otherwise identical GPUs.
For example, you can inspect the UUID of two GPUs using the gpuDeviceTable function.
gpuDeviceTable(["Index","Name","UUID"])
9-69
9 Objects
Alternatively, you can select a GPU using the gpuDevice function and query its UUID.
D = gpuDevice;
[Link]
'GPU-957b509e-28ca-ae88-59c8-b7435d0f98f4'
• GraphicsDriverVersion property added to show the graphics driver version currently in use.
• DriverModel property added to show the operating model of the graphics driver on Windows.
• CachePolicy property added to allow changes to GPU memory caching policy.
• The DriverVersion property is no longer displayed by default but you can still query the
property using dot notation. There are no plans to remove the DriverVersion property.
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
gpuArray | gpuDeviceTable | gpuDeviceCount | canUseGPU | validateGPU | arrayfun | reset
| wait (GPUDevice) | GPUDeviceManager
Topics
“Identify and Select a GPU Device” on page 6-10
“Run MATLAB Functions on a GPU” on page 6-3
“Run MATLAB Functions on Multiple GPUs” on page 6-19
“GPU Computing Requirements” on page 6-13
External Websites
Deep Learning with GPUs and MATLAB
9-70
GPUDeviceManager
GPUDeviceManager
Namespace: [Link]
Description
[Link] broadcasts events that indicate when a GPU device is selected,
deselected, or reset. Use [Link] to set up notifications that inform you
when your GPU device is selected, deselected, or reset without having to call gpuDevice or monitor
data stored on the GPU. You can also use [Link] to automatically
change your GPU settings when a GPU is selected.
Creation
Description
Note You can only use one instance of [Link] available in a given
MATLAB session.
Properties
SelectedDevice — Selected GPU device
GPUDevice object
The selected GPU device, specified as a GPUDevice object. If no GPU device is selected, then the
property is an empty GPUDevice array.
Attributes:
GetAccess public
9-71
9 Objects
Methods
Public Methods
Input Arguments:
• gdm - [Link]
object.
• index - Index of desired GPU device,
specified as an integer in the range [1,
gpuDeviceCount].
Return Value:
Input Arguments:
• gdm - [Link]
object.
Output Arguments:
9-72
GPUDeviceManager
Events
Event Name Trigger Event Data Event Attributes
DeviceSelected Triggered after a GPU [Link] NotifyAccess:
device is selected. viceEventData private
Properties: ListenAccess:
public
• DeviceIndex -
Index of the selected
GPU device.
DeviceDeselecting Triggered just before a [Link] NotifyAccess:
GPU device is viceEventData private
deselected.
Properties: ListenAccess:
public
• DeviceIndex -
Index of the GPU
device being
deselected.
Note When you reset a GPU device, the software triggers DeviceDeselecting and then
DeviceSelected.
For more information about using events, see the examples on this page and “Overview Events and
Listeners”.
Examples
gdm =
GPUDeviceManager with properties:
Select a GPU device and use the GPU device manager to inspect the selected GPU device.
gpu = gpuDevice;
[Link]
ans =
CUDADevice with properties:
9-73
9 Objects
DriverModel: 'TCC'
TotalMemory: 25544294400 (25.54 GB)
AvailableMemory: 25120866304 (25.12 GB)
DeviceAvailable: true
DeviceSelected: true
gdm = [Link];
Create callback functions that the software calls when a GPU device is selected or about to be
deselected. These functions display the device index of the GPU and whether it has been selected or
deselected. Even if they are not used, callback functions must define at least two input arguments:
the event source and the event data. For more information, see “Overview Events and Listeners”.
Create event listeners, bound to the DeviceSelected and DeviceDeselecting events of the GPU
device manager gdm, that call the callback functions.
selectedListener = listener(gdm,"DeviceSelected",selectedMessage);
deselectedListener = listener(gdm,"DeviceDeselecting",deselectedMessage);
To check that the callback functions and listeners are configured correctly, select and deselect your
GPU.
gpuDevice;
gpuDevice([]);
delete(selectedListener)
delete(deselectedListener)
gdm = [Link];
Create a function handle to the setCachePolicy function. The setCachePolicy function, defined
at the end of this example, changes the caching policy of the selected GPU to 'maximum'.
9-74
GPUDeviceManager
Create an event listener, bound to the DeviceSelected event of the GPU device manager gdm, that
calls the callback function selectedFcn. The software sets the caching policy to 'maximum' when a
new GPU device is selected. The cachePolicy property of a gpuDevice object determines how
much GPU memory can be cached to accelerate computation.
selectedListener = listener(gdm,"DeviceSelected",selectedFcn);
To check that the callback function and listener are configured correctly, deselect any already
selected GPUs, then select your GPU and inspect its CachePolicy property.
gpuDevice([]);
gpu = gpuDevice;
[Link]
ans =
'maximum'
The setCachePolicy function receives a GPU device manager object source and changes the
caching policy of the currently selected GPU device.
function setCachePolicy(gdm)
end
Version History
Introduced in R2016a
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
9-75
9 Objects
See Also
gpuDevice | listener | gpuDeviceTable | gpuDeviceCount
Topics
“Run MATLAB Functions on a GPU” on page 6-3
“GPU Computing Requirements” on page 6-13
“Run MATLAB Functions on Multiple GPUs” on page 6-19
9-76
mxGPUArray
mxGPUArray
Type for MATLAB gpuArray
Description
mxGPUArray is an opaque C language type that allows a MEX function access to the elements in a
MATLAB gpuArray. Using the mxGPU API, you can perform calculations on a MATLAB gpuArray, and
return gpuArray results to MATLAB.
All MEX functions receive inputs and pass outputs as mxArrays. A gpuArray in MATLAB is a special
kind of mxArray that represents an array stored on the GPU. In your MEX function, you use
mxGPUArray objects to access an array stored on the GPU: these objects correspond to MATLAB
gpuArrays.
The mxGPU API contains functions that manipulate mxGPUArray objects. These functions allow you
to extract mxGPUArrays from input mxArrays, to wrap output mxGPUArrays as mxArrays for return
to MATLAB, to determine the characteristics of the arrays, and to get pointers to the underlying
elements. You can perform calculations by passing the pointers to CUDA functions that you write or
that are available in external libraries.
The header file that contains this type is mxGPUArray.h. You include it with the line:
#include "gpu/mxGPUArray.h"
See Also
gpuArray, mxArray
Version History
Introduced in R2013a
9-77
9 Objects
[Link]
Access cluster properties and behaviors
Constructors
parcluster
Container Hierarchy
Parent None
Children [Link], [Link]
Description
A [Link] object provides access to a cluster, which controls the job queue, and
distributes tasks to workers for execution.
Types
The two categories of clusters are the MATLAB Job Scheduler and common job scheduler (CJS). The
MATLAB Job Scheduler is available in the MATLAB Parallel Server. The CJS clusters encompass all
other types, including the local, generic, and third-party schedulers.
Use MJSComputeCloud objects to interact with MATLAB Parallel Server for Amazon EC2® clusters.
9-78
[Link]
Methods
Common to All Cluster Types
MJSComputeCloud
Local
Properties
Common to All Cluster Types
9-79
9 Objects
Property Description
ClusterMatlabRoot Specifies path to MATLAB for workers to use
Host Host name of the cluster head node
JobStorageLocation Location where cluster stores job and task
information
Jobs List of jobs contained in this cluster
LicenseNumber License number to use when running jobs with
this cluster
Modified True if any properties in this cluster have been
modified
NumThreads Number of computational threads for workers
NumWorkers Number of workers available for this cluster
OperatingSystem Operating system of nodes used by cluster
PreferredPoolNumWorkers Preferred number of workers in a parallel pool
Profile Profile used to build this cluster
RequiresOnlineLicensing true if the cluster is using online licensing
Type Type of this cluster
UserData Information associated with cluster object within
client session
• If you use the generic scheduler interface in remote mode to interact with a third-party scheduler,
and the client and workers use different operating systems, specify a structure. The structure
must have the fields 'windows' and 'unix'. The fields are the Windows and UNIX path
corresponding to the folder where the cluster stores job and task information. The following
structure specifies the same folder using a Windows UNC path ('\\organization\some
\path') and a UNIX path ('/organization/some/path'):
struct('windows', '\\organization\some\path', 'unix', '/organization/some/path')
• Otherwise, use a character vector or string to specify the folder where the cluster stores job and
task information.
MJS cluster objects have the following properties in addition to the common properties:
Property Description
AllHostAddresses IP addresses of the cluster host
BusyWorkers Workers currently running tasks
IdleWorkers Workers currently available for running tasks
HasSecureCommunication True if cluster is using secure communication
9-80
[Link]
Property Description
MaxNumWorkers Maximum number of workers this cluster can
have.
MJSComputeCloud
MJSComputeCloud cluster objects have the following properties in addition to the common
properties:
Property Description
BusyWorkers Workers currently running tasks
Certificate Cluster SSL certificate
HasSecureCommunication true if cluster is using secure communication
Identifier Unique cluster identifier
IdleWorkers Workers currently available for running tasks
MatlabVersion Version of MATLAB running on the workers
9-81
9 Objects
Property Description
MaxNumWorkers Maximum number of workers this cluster can
have.
Local
Local cluster objects have no editable properties beyond the properties common to all clusters.
HPC Server
HPCServer cluster objects have the following properties in addition to the common properties:
Property Description
ClusterVersion Version of Microsoft Windows HPC Server
running on the cluster
HasSharedFilesystem Specify whether client and cluster nodes share
job storage location
JobDescriptionFile Name of XML job description file to use when
creating jobs
JobTemplate Name of job template to use for jobs submitted to
HPC Server
9-82
[Link]
Property Description
Name Name of this cluster
UseSOAJobSubmission Allow service-oriented architecture (SOA)
submission on HPC Server
PBSPro and Torque cluster objects have the following properties in addition to the common
properties:
Property Description
AdditionalProperties Additional properties for plugin scripts
HasSharedFilesystem Specify whether client and cluster nodes share
job storage location
PluginScriptsLocation Folder containing scheduler plugin scripts
ProcsPerNode Number of processors per node, specified as a
finite positive integer scalar.
9-83
9 Objects
Property Description
SubmitArguments Specify additional arguments to use when
submitting jobs. You can use this property to set
the AdditionalSubmitArgs additional
property.
LSF and Slurm cluster objects have the following properties in addition to the common properties:
Property Description
AdditionalProperties Additional properties for plugin scripts
HasSharedFilesystem Specify whether client and cluster nodes share
job storage location
PluginScriptsLocation Folder containing scheduler plugin scripts
SubmitArguments Specify additional arguments to use when
submitting jobs. You can use this property to set
the AdditionalSubmitArgs additional
property.
Generic
Generic cluster objects are supported on clients running Windows, macOS, or Linux.
If you create a Generic cluster object from an R2017a or later profile, you have the following
properties in addition to the common properties:
Property Description
AdditionalProperties Additional properties for plugin scripts
HasSharedFilesystem Specify whether client and cluster nodes share
job storage location
PluginScriptsLocation Folder containing scheduler plugin scripts
If you create a Generic cluster object from an R2016b or earlier profile, you have the following
properties in addition to the common properties:
Property Description
CancelJobFcn Function to run when canceling job
CancelTaskFcn Function to run when canceling task
CommunicatingSubmitFcn Function to run when submitting communicating
job
DeleteJobFcn Function to run when deleting job
DeleteTaskFcn Function to run when deleting task
GetJobStateFcn Function to run when querying job state
HasSharedFilesystem Specify whether client and cluster nodes share
job storage location
9-84
[Link]
Property Description
IndependentSubmitFcn Function to run when submitting independent job
Help
For further help on cluster objects, including links to help for specific cluster types and object
properties, at the command line, type:
help [Link]
See Also
[Link], [Link], [Link], [Link],
[Link]
Version History
Introduced in R2012a
The ResourceTemplate property of the LSF, Slurm, PBSPro and TORQUE cluster objects has been
removed. To control resource allocation, modify the independentSubmitFcn.m and
communicatingSubmitFcn.m functions located in the PluginScriptsLocation instead.
9-85
9 Objects
[Link]
Hadoop cluster for mapreducer, mapreduce and tall arrays
Constructors
[Link]
Description
A [Link] object provides access to a cluster for configuring mapreducer, mapreduce,
and tall arrays.
Properties
A [Link] object has the following properties.
Property Description
AdditionalPaths Folders to add to MATLAB search path of
workers, specified as a character vector, string or
string array, or cell array of character vectors
AttachedFiles Files and folders that are sent to workers during
a mapreduce call, specified as a character vector,
string or string array, or cell array of character
vectors
AutoAttachFiles Specifies whether automatically attach files
ClusterMatlabRoot Specifies path to MATLAB for workers to use
HadoopConfigurationFile Application configuration file to be given to
Hadoop
HadoopInstallFolder Installation location of Hadoop on the local
machine
HadoopProperties Map of name-value property pairs to be given to
Hadoop
LicenseNumber License number to use with online licensing
RequiresOnlineLicensing Specify whether cluster uses online licensing
SparkInstallFolder Installation location of Spark on the local
machine
SparkProperties Map of name-value property pairs to be given to
Spark
When you offload computations to workers, any files that the client needs for computations must also
be available on workers. By default, the client attempts to detect and attach these files. To turn off
automatic detection, set the AutoAttachFiles property to false. If the software cannot find all the
files, or if sending files from client to worker is slow, use one of these options.
9-86
[Link]
• If the files are in a folder that is not accessible on the workers, set the AttachedFiles property.
The cluster copies each file you specify from the client to the workers.
• If the files are in a folder that is accessible on the workers, you can set the AdditionalPaths
property instead. Use the AdditionalPaths property to add paths to the MATLAB search path
for each worker and avoid copying files unnecessarily from the client to the workers.
HadoopProperties allows you to override configuration properties for Hadoop. See the list of
properties in the Hadoop documentation.
SparkProperties allows you to override configuration properties for Spark. See the list of
properties in the Spark documentation.
Help
For further help, type:
help [Link]
The amount of data gathered to the client is limited by the Spark properties:
• [Link]
• [Link]
The amount of data to gather from a single Spark task must fit in these properties. A single Spark
task processes one block of data from HDFS, which is 128 MB of data by default. If you gather a tall
array containing most of the original data, you must ensure these properties are set to fit.
If these properties are set too small, you see an error like the following.
Error using tall/gather (line 50)
Out of memory; unable to gather a partition of size 300m from Spark.
Adjust the values of the Spark properties [Link] and
[Link] to fit this partition.
The error message also specifies the property settings you need.
Adjust the properties either in the default settings of the cluster or directly in MATLAB. To adjust the
properties in MATLAB, add name-value pairs to the SparkProperties property of the cluster. For
example:
cluster = [Link];
[Link]('[Link]') = '2048m';
[Link]('[Link]') = '2048m';
mapreducer(cluster);
9-87
9 Objects
The amount of working memory for a MATLAB Worker is limited by the Spark property:
• [Link]
By default, this is set to 2.5 GB. You typically need to increase this if you use arrayfun, cellfun, or
custom datastores to generate large amounts of data in one go. It is advisable to increase this if you
come across lost or crashed Spark Executor processes.
You can adjust these properties either in the default settings of the cluster or directly in MATLAB. To
adjust the properties in MATLAB, add name-value pairs to the SparkProperties property of the
cluster. For example:
cluster = [Link];
[Link]('[Link]') = '4096m';
mapreducer(cluster);
Version History
Introduced in R2014b
See Also
[Link] | [Link]
Topics
“Use Tall Arrays on a Spark Cluster” on page 4-99
“Run mapreduce on a Hadoop Cluster” on page 4-106
9-88
[Link]
[Link]
Spark cluster for mapreducer, mapreduce and tall arrays
Description
A [Link] object represents and provides access to a Spark cluster. Use the
[Link] object as input to the mapreduce and mapreducer functions, for
specifying the Spark cluster as the parallel execution environment for tall arrays and mapreduce.
Creation
Use the parcluster function to create a [Link] cluster object from a Spark
cluster profile. Alternatively, use the [Link] function (described here) to create
a Spark cluster object.
Syntax
sparkCluster = [Link]
sparkCluster = [Link](Name,Value)
Description
Properties
AdditionalPaths — Folders to add to MATLAB search path
character vector | string | string array | cell array of character vectors
Folders to add to MATLAB search path of workers, specified as a character vector, string or string
array, or cell array of character vectors.
When you offload computations to workers, any files that the client needs for computations must also
be available on workers. By default, the client attempts to detect and attach these files. To turn off
automatic detection, set the AutoAttachFiles property to false. If the software cannot find all the
files, or if sending files from client to worker is slow, use one of these options.
• If the files are in a folder that is not accessible on the workers, set the AttachedFiles property.
The cluster copies each file you specify from the client to the workers.
9-89
9 Objects
• If the files are in a folder that is accessible on the workers, you can set the AdditionalPaths
property instead. Use the AdditionalPaths property to add paths to the MATLAB search path
for each worker and avoid copying files unnecessarily from the client to the workers.
Files and folders sent to workers during a mapreduce call, specified as a character vector, string or
string array, or cell array of character vectors
Jobs contained within the cluster, returned as a [Link] object or an array of [Link]
objects. When the cluster contains more than one job, MATLAB sorts the jobs in the array by their ID
property. This sorting is consistent with the order in which you create the jobs, regardless of the
values of the State property of each job.
Logical true if any properties in this cluster have been modified compared to the cluster profile,
returned as a logical true (1) if you have modified the cluster properties and logical false (0)
otherwise.
Data Types: logical
9-90
[Link]
Operating system of the cluster worker machines, specified as one of these values:
• "windows"
• "unix"
• "mixed"
Name of the profile used to create cluster object, specified as a character vector.
Data Types: char
Path to the Spark installation on client machine, specified as the comma-separated pair consisting of
SparkInstallFolder and a character vector or string array. If this property is not set, the default
is the value specified by the environment variable SPARK_PREFIX, or if that is not set, then
SPARK_HOME.
Data Types: char
SparkProperties allows you to override configuration properties for Spark. See the list of
properties in the Spark documentation.
Data associated with the cluster object in the current session, specified as any MATLAB data type.
Object Functions
mapreduce Programming technique for analyzing data sets that do not fit in memory
9-91
9 Objects
mapreducer Define parallel execution environment for mapreduce and tall arrays
saveAsProfile Save cluster properties to specified profile
saveProfile Save modified cluster properties to its current profile
Examples
To learn how to create a profile for your Spark cluster, see “Client Configuration” (MATLAB Parallel
Server).
sparkCluster = parcluster("SparkProfile")
mr = mapreducer(sparkCluster)
cluster =
Spark Cluster
Properties:
Type: Spark
Profile: SparkProfile
Modified: false
NumThreads: 1
RequiresOnlineLicensing: false
ClusterMatlabRoot: /network/installs/MATLAB/R2024a/matlab
SparkInstallFolder: /network/installs/spark/3.0.2-3.2
SparkProperties: [1x1 [Link]]
Create the cluster object by specifying the Spark installation on your machine, and set the Spark
cluster as the mapreduce parallel execution environment.
sparkCluster = [Link](SparkInstallFolder="/host/spark-install");
mr = mapreducer(sparkCluster)
Limitations
• Spark cluster profiles do not support being set as the default profile.
• Spark clusters do not support parallel pools and batch jobs.
The amount of data gathered to the client is limited by the Spark properties:
9-92
[Link]
• [Link]
• [Link]
The default value of the [Link] property of a Spark job submitted from MATLAB
is 2560 MB.
The amount of data to gather from a single Spark task must fit in these properties. A single Spark
task processes one block of data from HDFS, which is 128 MB of data by default. If you gather a tall
array containing most of the original data, you must ensure these properties are set to fit.
If these properties are set too small, you see an error like the following.
The error message also specifies the property settings you need.
Adjust the properties either in the default settings of the cluster or directly in MATLAB. To adjust the
properties in MATLAB, you can add these Spark properties to the SparkProperties table of the
Spark cluster profile.
cluster = parcluster("SparkProfile");
[Link]('[Link]') = '2048m';
[Link]('[Link]') = '2048m';
mapreducer(cluster);
Version History
Introduced in R2022b
You can now create and validate cluster profiles for Spark based clusters integrated with MATLAB
Parallel Server.
See Also
mapreduce | mapreducer
Topics
“Use Tall Arrays on a Spark Cluster” on page 4-99
9-93
9 Objects
[Link]
Random number stream on a GPU
Description
Use [Link] to control the global GPU random number stream and create
multiple independent streams on the GPU. When you generate random numbers on a GPU, the
numbers are drawn from the GPU random number stream. This stream is different from the random
stream of the client MATLAB session on the CPU.
To create random numbers on the GPU, use the random number generator functions rand, randi,
and randn. If you use a GPU random number stream, then the results are returned as a gpuArray.
By default, these functions draw numbers from the global GPU random number stream. To use a
different stream, follow the syntaxes described in “Object Functions” on page 9-97.
Creation
Use the following syntaxes to create a single [Link] object. If you want to
create multiple independent streams simultaneously, use the [Link]
function.
Syntax
s = [Link](gentype)
s = [Link](gentype,Name=Value)
Description
Input Arguments
Random number generator algorithm, specified as one of the following three random number
generator algorithms supported on the GPU.
9-94
[Link]
For more information on the differences between generating random numbers on the GPU and CPU,
see “Random Number Streams on a GPU” on page 6-72.
Random number seed, specified as a nonnegative integer or as "shuffle". The seed specifies the
starting point for the algorithm to generate random numbers. Specify Seed as an integer when you
want reproducible results. Specifying Seed as "shuffle" seeds the generator based on the current
time.
The normal transformation algorithm to use when generating normally distributed random numbers
generated using the randn function, specified as "BoxMuller" or "Inversion".
The "BoxMuller" option supports the "Threefry" and "Philox" generator types only.
Stream index of the current stream, specified as a positive integer. The stream index identifies
individual streams when you create multiple streams at once using the function
[Link].
9-95
9 Objects
Current state of the random number stream, specified as a vector. The internal state determines the
sequence of random numbers produced by the random number stream. The size of this state vector
depends on the generator chosen.
Saving and restoring the internal state of the generator with the State property allows you to
reproduce a sequence of random numbers. When you specify the state, use a value previously read
from a [Link] object. Alternatively, you can use reset to return a stream to a
predictable state without having previously read from the State property.
Properties
Type — Random number generator algorithm
'Threefry4x64_20' | 'Philox4x32_10' | 'MRG32K3A'
This property is read-only after object creation. To set this property, use the gentype argument when
you create the stream.
To set this property, use the Seed argument when you create the stream or use the reset function.
Random number seed, specified as a nonnegative integer. The seed specifies the starting point for the
algorithm to generate random numbers. Specify Seed as an integer when you want reproducible
results.
The normal transformation algorithm to use when generating normally distributed random numbers
generated using the randn function, specified as 'BoxMuller' or 'Inversion'.
The 'BoxMuller' option supports the "Threefry" and "Philox" generator types only.
Data Types: char
Number of streams in the group in which the current stream was created, represented as a positive
integer. Create multiple streams at once using the function [Link].
9-96
[Link]
Stream index of the current stream, specified as a positive integer. The stream index identifies
individual streams when you create multiple streams at once using the function
[Link].
Current state of the random number stream, specified as a vector. The internal state determines the
sequence of random numbers produced by the random number stream s. The size of this state vector
depends on the generator chosen.
Saving and restoring the internal state of the generator with the State property allows you to
reproduce a sequence of random numbers. When you specify the state, use a value previously read
from a [Link] object. Alternatively, you can use reset to return a stream to a
predictable state without having previously read from the State property.
Antithetic values, represented as 0 (false). This property indicates whether S generates antithetic
pseudorandom values, that is, the usual values subtracted from 1 for uniform values.
This property is always 0. The stream does not generate antithetic values.
Data Types: logical
Full precision generation, represented as 1 (true). This property indicates whether the random
number stream generates values using full precision. Two random numbers are consumed to ensure
all bits of a double are set.
Object Functions
[Link] Create independent random number streams on a GPU
[Link] List random number generator algorithms on the GPU
[Link] Get current global GPU random number stream
[Link] Set GPU global random number stream
reset (RandStream) Reset random number stream
By default, when you create random numbers on the GPU using random number generation
functions, such as rand, the random numbers are drawn from the global random number stream on
the GPU. To specify a different stream, create a [Link] object and pass it as
9-97
9 Objects
the first input argument. For instance, create a 4-by-1 vector of random numbers using the Philox
4x32 generator algorithm.
s = [Link]("Philox");
r = rand(s,4,1);
These functions accept a [Link] object and generate random numbers on the
GPU:
p = randperm(s,n)
p = randperm(s,n,k)
Examples
You can change the global random number stream on the GPU. First, define the random number
stream that you want to set as the new global stream.
newStr = [Link]("Philox")
newStr =
[Link](newStr);
newStr
newStr =
9-98
[Link]
Seed: 0
NormalTransform: BoxMuller
On a GPU, the functions rand, randi, and randn now draw random numbers from the new global
stream using the "Philox" generator algorithm.
If you have applications that require generating the same random numbers on the GPU and the CPU,
you can set the streams to match. Create matching streams on both the GPU and CPU, and set them
as the global stream in each case.
stCPU = RandStream("Threefry",Seed=0,NormalTransform="Inversion");
stGPU = [Link]("Threefry",Seed=0,NormalTransform="Inversion");
Only the Inversion normal transformation algorithm is available on both the GPU and CPU.
Set these streams to be the global streams on the CPU and GPU, respectively.
[Link](stCPU);
[Link](stGPU);
Calling rand and randn now produces the same sets of numbers on both the GPU and the client
MATLAB session.
rC = rand(1,8)
rG = rand(1,8,"gpuArray")
rC =
0.1726 0.9207 0.8108 0.7169 0.8697 0.7920 0.4159 0.6503
rG =
0.1726 0.9207 0.8108 0.7169 0.8697 0.7920 0.4159 0.6503
rnC = randn(1,8)
rnG = randn(1,8,"gpuArray")
rnC =
-0.9438 1.4095 0.8807 0.5736 1.1250 0.8133 -0.2124 0.3862
rnG =
-0.9438 1.4095 0.8807 0.5736 1.1250 0.8133 -0.2124 0.3862
Version History
Introduced in R2011b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
9-99
9 Objects
See Also
RandStream | gpurng
Topics
“Random Number Streams on a GPU” on page 6-72
“Generating Random Numbers on a GPU” on page 6-75
“Establish Arrays on a GPU” on page 6-15
9-100
[Link]
[Link]
Access job properties and behaviors
Constructors
createCommunicatingJob, createJob, findJob, recreate
Container Hierarchy
Parent [Link]
Children [Link]
Description
A [Link] object provides access to a job, which you create, define, and submit for execution.
Types
The following table describes the available types of job objects. The job type is determined by the
type of cluster, and whether the tasks must communicate with each other during execution.
Methods
Common to All Job Types
9-101
9 Objects
CJS Jobs
CJS job objects have the following methods in addition to the common methods:
getTaskSchedulerIDs Scheduler IDs of tasks in job
Properties
Common to All Job Types
Property Description
AdditionalPaths Folders to add to MATLAB search path of
workers, specified as a character vector, string or
string array, or cell array of character vectors
AttachedFiles Files and folders that are sent to workers,
specified as a character vector, string or string
array, or cell array of character vectors
AutoAddClientPath Specifies whether user-added-entries on the
client's path are automatically added to each
worker's path
AutoAttachFiles Specifies if dependent code files are
automatically sent to workers
CreateDateTime Date and time when the job is created
EnvironmentVariables Names of environment variables that are sent to
the workers
FileStore File storage of the job that is accessible even
while the job is still running, specified as a
FileStore object
FinishDateTime Date and time when the job finishes running
ID Job's numeric identifier
JobData Information made available to all workers for
job's tasks
Name Name of job
Parent Cluster object containing this job
RunningDuration Current duration of the job, specified as a
duration object
StartDateTime Date and time when the job starts running
State State of job: 'pending', 'queued', 'running',
'finished', or 'failed'
StorageBytes Number of bytes that the data for this job
occupies in the job storage location
9-102
[Link]
Property Description
SubmitDateTime Date and time when the job is submitted to the
queue
Tag Label associated with job
Tasks Array of task objects contained in job
Type Job type: 'independent', 'pool', or 'spmd'
UserData Information associated with job object
Username Name of user who owns job
ValueStore Data storage of the job that is accessible even
while the job is still running, specified as a
ValueStore object
When you offload computations to workers, any files that the client needs for computations must also
be available on workers. By default, the client attempts to detect and attach these files. To turn off
automatic detection, set the AutoAttachFiles property to false. If the software cannot find all the
files, or if sending files from client to worker is slow, use one of these options.
• If the files are in a folder that is not accessible on the workers, set the AttachedFiles property.
The cluster copies each file you specify from the client to the workers.
• If the files are in a folder that is accessible on the workers, you can set the AdditionalPaths
property instead. Use the AdditionalPaths property to add paths to the MATLAB search path
for each worker and avoid copying files unnecessarily from the client to the workers.
MATLAB Job Scheduler independent job objects and MATLAB Job Scheduler communicating job
objects have the following properties in addition to the common properties:
Property Description
AuthorizedUsers Users authorized to access job
FinishedFcn Callback function executed on client when this
job finishes
NumWorkersRange Minimum and maximum limits for number of
workers to run job
QueuedFcn Callback function executed on client when this
job is submitted to queue
RestartWorker True if workers are restarted before evaluating
first task for this job
RunningFcn Callback function executed on client when this
job starts running
Timeout Time limit, in seconds, to complete job
CJS Jobs
CJS independent job objects do not have any properties beyond the properties common to all job
types.
CJS communicating job objects have the following properties in addition to the common properties:
9-103
9 Objects
Property Description
NumWorkersRange Minimum and maximum limits for number of
workers to run job
Communicating Jobs
MATLAB Job Scheduler communicating job objects and CJS communicating job objects have this
property in addition to the common properties:
Property Description
SpmdEnabled Indication if pool type job can run spmd code
Help
To get further help on a particular type of [Link] object, including a list of links to help for
its properties, type help [Link].<job-type>. For example:
help [Link]
See Also
[Link], [Link], [Link]
Version History
Introduced in R2012a
9-104
[Link]
[Link]
Parallel pool of workers
Description
Use parpool to create a parallel pool. After you create the pool, parallel pool features, such as
parfor or parfeval, run on the workers. With the [Link] object, you can interact with
the parallel pool.
• ProcessPool
• ThreadPool
• ClusterPool
Creation
There are several ways to a [Link] object.
Version History
Introduced in R2013b
See Also
[Link] | Future
Topics
“Run Code on Parallel Pools” on page 1-28
9-105
9 Objects
[Link]
Build and use constant from data or function handle
Description
Use a Constant object to avoid unnecessarily copying data multiple times from your current
MATLAB session to workers in a parallel pool. You can build a Constant object once on a client and
transfer the constant to the workers once. Access the Constant in multiple parfor-loops, spmd
blocks, or parfeval calls. The value you access in a Constant object is constant. You can share
your parallel code that uses Constant objects with MATLAB users who do not have Parallel
Computing Toolbox. For more information, see [Link].
Creation
Use [Link] to create a Constant object from an array, a function handle, or a
composite object. Use the Value property to access the underlying data.
Syntax
C = [Link](X)
C = [Link](FH)
C = [Link](FH,cleanupFH)
C = [Link](COMP)
Description
Each worker can access the array X within a parallel language construct (parfor, spmd, parfeval)
using the Value property to read the data.
Use this syntax to create and use any handle-type resources on a parallel pool, such as file handles
and database connections. If you want to evaluate a function on each worker to set up workers before
computations, use parfevalOnAll instead.
9-106
[Link]
Use this syntax when you want to construct data only on the workers, such as when the data is too
large to conveniently fit in the client, or when you load the data from a file that only the workers can
access. Access the values using the Value property.
Input Arguments
X — Input data
MATLAB variable
Input data, specified as any MATLAB variable that can be saved and loaded.
MATLAB evaluates the build function to get the Value property of the Constant object. The function
must take no input arguments and must return one output argument.
• When you read the Value property for the first time in your MATLAB session or on a parallel pool
worker, MATLAB stores the result from running fcn() in that environment as the Value property.
• The function is run only once in your MATLAB session or on a parallel pool worker. When you read
the Value property after the first time, you read the stored result.
• If you read the Value property on a different parallel pool worker, MATLAB returns the result
from running fcn() on that worker.
Function handle for the cleanup function, specified as a function handle. The function must take one
input argument, the Value property of the Constant object.
MATLAB runs the cleanup function when C is cleared. The Constant object C is cleared when you:
Example: @fclose
The COMP object must have a defined value on every worker otherwise you will receive an error.
Example: spmd COMP = rand(3); end; C
Properties
Value — Underlying data or handle-type resource
MATLAB variable
9-107
9 Objects
Independent copy of underlying data or handle-type resource, specified as any MATLAB variable that
can be saved and loaded or a handle variable.
Use the Value property of a Constant to access underlying data or handle variable.
Examples
Create a numeric Constant from an array on the client, and use it in multiple parfor-loops on the
same pool.
Create some large data on the client, then build a Constant object, C transferring the data to the
pool only once.
data = rand(1000);
C = [Link](data);
Run multiple parfor-loops accessing the data. For efficiency, preallocate the results array.
x = eye(5);
for ii = 1:5
parfor jj = 1:5
x(ii,jj) = [Link](ii,jj);
end
end
x
x = 5×5
Use [Link] and tempname to create a temporary file on each worker. When you
pass the fclose function as the cleanup function handle, the file is automatically closed when C is
cleared.
C = [Link](@() fopen(tempname(pwd),'wt'),@fclose);
spmd
disp(fopen([Link]));
end
9-108
[Link]
Worker 1:
C:\myTemporaryFiles\tpb2d60042_d684_4705_b084_63496d07b936
Worker 2:
C:\myTemporaryFiles\tpc6bef84f_bebe_44fc_acb2_ddd2fcba5026
Worker 3:
C:\myTemporaryFiles\tpf6775778_b06a_46ba_b502_27e2c253c66f
Worker 4:
C:\myTemporaryFiles\tp4dc6e57a_6b65_437a_8eb7_82877403eee3
Worker 5:
C:\myTemporaryFiles\tpd0e279ac_a141_49f0_a0b6_90c4cad137a4
Worker 6:
C:\myTemporaryFiles\tpf02acaad_60a5_441a_b1a1_46e4c66f33a1
clear C;
Build Constant object from Composite objects on pool workers inside an spmd block.
Create a Composite object by using spmdBroadcast to send some large data to all workers in an
spmd block.
spmd
if spmdIndex == 1
x = spmdBroadcast(1,rand(5000));
else
x = spmdBroadcast(1);
end
end
Build a Constant object with the Composite object and use it in a parfor-loop.
xc = [Link](x);
parfor idx = 1:10
s(idx) = sum([Link](:,idx));
end
s
s = 1×10
103 ×
2.5110 2.5256 2.5060 2.4909 2.5078 2.5187 2.4791 2.4842 2.4926 2.4
9-109
9 Objects
Tips
You must use the [Link] function in the MATLAB client session.
You can use a Constant object with an already running parallel pool or subsequent parallel pools.
Version History
Introduced in R2015b
When you call the [Link] function without input arguments, it initializes a
Constant object in an invalid state. Before R2023b, calling the [Link] function
without input arguments errors.
You can use [Link] with no arguments to assign invalid Constant objects to
array elements. When you create or grow an array of Constant objects without assigning values to
each element, any new elements of the array contain invalid Constant elements.
MATLAB will no longer automatically transfer Constant objects from your current MATLAB session
to workers in a parallel pool. MATLAB will send the Constant object to workers only if the object is
required to execute your code.
In previous releases, MATLAB automatically sent the Constant object to the workers in the parallel
when the pool was started.
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
parfor | spmd | parpool | parcluster | parfeval | tempname | fclose | spmdBroadcast
9-110
[Link]
[Link]
Send and listen for data between client and workers
Description
A DataQueue object enables asynchronous and automatic processing of data or messages sent
between workers and client in a parallel pool while a computation is carried out. For example, you
can send intermediate values to the client and automatically calculate the progress of the
computation.
To send data from a parallel pool worker back to the client, first create a DataQueue object at the
client. Pass this DataQueue into a parfor-loop or other parallel language construct, such as spmd.
From the workers, call send to send data back to the client. At the client, specify a function to
automatically process the data received by using afterEach.
• You can call send from the worker or client that created the DataQueue if required. DataQueue
sends the data only to the client or worker that created the DataQueue.
• You can create the queue on the workers and send it back to the client to enable communication in
the reverse direction.
You cannot send a queue from one worker to another. To transfer data between workers, use
spmd, spmdSend, or spmdReceive instead.
• Unlike all other handle objects, DataQueue and PollableDataQueue instances do remain
connected when they are sent to workers.
Creation
Syntax
q = [Link]
Description
q = [Link] creates an object that you can use to send or listen for messages
(or data) between the client and workers. Create the DataQueue on the worker or client where you
want to receive the data.
Properties
QueueLength — Number of items currently held on the queue
zero or positive integer
The number of items of data waiting to be removed from the queue, specified as a zero or positive
integer. The value is 0 or a positive integer on the worker or client that created the DataQueue
9-111
9 Objects
instance. If the client creates the DataQueue instance, the value is 0 on all workers. If a worker
creates the DataQueue, the value is 0 on the client and all other workers.
Object Functions
afterEach Define a function to call when new data is received on a data queue
send Send data between clients and workers using a data queue
Examples
q = [Link];
afterEach(q, @disp);
Start a parfor-loop, and send a message. The pending message is passed to the afterEach
function, in this example @disp.
parfor i = 1:3
send(q, i);
end;
For more details on listening for data using a DataQueue, see afterEach.
When you send a message to a DataQueue object, the message waits in the queue until it is
processed by a listener. Each message adds 1 to the queue length. In this example, you use the
QueueLength property to find the length of a DataQueue object.
When a client or worker creates a DataQueue object, any messages that are sent to the queue are
held in the memory of that client or worker. If the client creates a DataQueue object, the
QueueLength property on all workers is 0. In this example, you create a DataQueue object on the
client, and send data from a worker.
parpool(1);
q = [Link]
9-112
[Link]
q =
DataQueue with properties:
QueueLength: 0
A newly created DataQueue has an empty queue. You can use parfor to find [Link] on
the worker. Find the queue length on the client, and the queue length on the worker.
On the client: 0
parfor i = 1
fprintf('On the worker: %i\n', [Link])
end
On the worker: 0
As the queue is empty, the QueueLength is 0 for both the client and the worker. Next, send a
message to the queue from the worker. Then, use the QueueLength property to find the length of the
queue.
On the client: 1
parfor i = 1
fprintf('On the worker: %i\n', [Link])
end
On the worker: 0
The QueueLength property is 1 on the client, and 0 on the worker. Create a listener to process the
queue by immediately displaying the data.
el = afterEach(q, @disp);
On the client: 0
9-113
9 Objects
In this example, you use a DataQueue to update a wait bar with the progress of a parfor-loop.
When you create a parfor-loop, you offload each iteration to workers in a parallel pool. Information
is only returned from the workers when the parfor-loop completes. You can use a DataQueue to
update a wait bar at the end of each iteration.
When you update a wait bar with the progress of your parfor-loop, the client must record
information about how many iterations remain.
Tip If you are creating new parallel code and want to monitor the progress of your code, consider
using a parfeval workflow. For more information, see “Update User Interface Asynchronously Using
afterEach and afterAll” on page 10-336.
The helper function parforWaitbar, defined at the end of this example, updates a wait bar. The
function uses persistent to store information about the number of remaining iterations.
Create a DataQueue, D. Then use afterEach to run parforWaitbar after messages are sent to the
DataQueue.
Set the number of iterations for your parfor-loop, N. Use the wait bar w and the number of iterations
N to initialize the function parforWaitbar.
At the end of each iteration of the parfor-loop, the client runs parforWaitbar and incrementally
updates the wait bar.
N = 100;
parforWaitbar(w,N)
The function parforWaitbar uses persistent variables to store the number of completed iterations
on the client. No information is required from the workers.
Run a parfor-loop with N iterations. For this example, use pause and rand to simulate some work.
After each iteration, use send to send a message to the DataQueue. When a message is sent to the
DataQueue, the wait bar updates. Because no information is required from the workers, send an
empty message to avoid unnecessary data transfer.
After the parfor-loop completes, use delete to close the wait bar.
parfor i = 1:N
pause(rand)
send(D,[]);
end
9-114
[Link]
delete(w);
Define the helper function parforWaitbar. When you run parforWaitbar with two input
arguments, the function initializes three persistent variables (count, h, and N). When you run
parforWaitbar with one input argument, the wait bar updates.
function parforWaitbar(waitbarHandle,iterations)
persistent count h N
if nargin == 2
% Initialize
count = 0;
h = waitbarHandle;
N = iterations;
else
% Update the waitbar
This example shows how to perform a parallel parameter sweep with parfeval and send results
back during computations with a DataQueue object.
parfeval does not block MATLAB, so you can continue working while computations take place.
The example performs a parameter sweep on the Lorenz system of ordinary differential equations, on
the parameters σ and ρ, and shows the chaotic nature of this system.
d
x=σ y−z
dt
d
y =x ρ−z −y
dt
d
z = xy − βx
dt
9-115
9 Objects
parpool("Threads");
Define the range of parameters that you want to explore in the parameter sweep.
gridSize = 40;
sigma = linspace(5,45,gridSize);
rho = linspace(50,100,gridSize);
beta = 8/3;
[rho,sigma] = meshgrid(rho,sigma);
After you define the parameters, you can perform the parallel parameter sweep.
To visualize the interim results of the parameter sweep, create a surface plot. Note that initializing
the Z component of the surface with NaN creates an empty plot.
figure;
surface = surf(rho,sigma,NaN(size(sigma)));
xlabel('\rho','Interpreter','Tex')
ylabel('\sigma','Interpreter','Tex')
9-116
[Link]
To send interim data from the workers, create a DataQueue object. Set up a function that updates
the surface plot each time a worker sends data by using the afterEach function. The updatePlot
function is a supporting function defined at the end of the example.
Q = [Link];
afterEach(Q,@(data) updatePlot(surface,data));
parfeval works more efficiently when you distribute the workload. To distribute the workload,
group the parameters to explore into partitions. For this example, split into uniform partitions of size
step by using the colon operator (:). The resulting array partitions contains the boundaries of the
partitions. Note that you must add the end point of the last partition.
step = 100;
partitions = [1:step:numel(sigma),numel(sigma)+1]
partitions = 1×17
9-117
9 Objects
• Large enough that the computation time is large compared to the overhead of scheduling the
partition.
• Small enough that there are enough partitions to keep all workers busy.
To represent function executions on parallel workers and hold their results, use future objects.
f(1:numel(partitions)-1) = [Link];
for ii = 1:numel(partitions)-1
f(ii) = parfeval(@parameterSweep,1,partitions(ii),partitions(ii+1),sigma,rho,beta,Q);
end
parfeval does not block MATLAB, so you can continue working while computations take place. The
workers compute in parallel and send intermediate results through the DataQueue as soon as they
become available.
If you want to block MATLAB until parfeval completes, use the wait function on the future objects.
Using the wait function is useful when subsequent code depends on the completion of parfeval.
wait(f);
After parfeval finishes the computations, wait finishes and you can execute more code. For
example, plot a selection of the Lorenz system solutions. Use the fetchOutputs function to retrieve
the results stored in the future objects.
results = fetchOutputs(f);
idxs = randperm(numel(results),4);
figure
for n = 1:numel(idxs)
nexttile
a = results{idxs(n)};
plot3(a(:,1),a(:,2),a(:,3))
grid on
xlabel("x")
ylabel("y")
zlabel("z")
title("Lorenz System Solution", ...
"\rho = "+ num2str(rho(idxs(n)),'%5.2f') + " \sigma = "+ num2str(sigma(idxs(n)),'%5.2f'),
end
9-118
[Link]
If your parameter sweep needs more computational resources and you have access to a cluster, you
can scale up your parfeval computations. For more information, see “Scale Up from Desktop to
Cluster” on page 7-49.
Define a helper function that solves the Lorenz system on a partition of the parameters to explore.
Send intermediate results to the MATLAB client by using the send function on the DataQueue
object.
function results = parameterSweep(first,last,sigma,rho,beta,Q)
results = cell(last-first,1);
for ii = first:last-1
lorenzSystem = @(t,a) [sigma(ii)*(a(2) - a(1)); a(1)*(rho(ii) - a(3)) - a(2); a(1)*a(2) -
[t,a] = ode45(lorenzSystem,[0 100],[1 1 1]);
send(Q,[ii,a(end,3)]);
results{ii-first+1} = a;
end
end
Define another helper function that updates the surface plot when new data arrives.
9-119
9 Objects
function updatePlot(surface,data)
[Link](data(1)) = data(2);
drawnow('limitrate');
end
Tips
• You can only automatically process data or messages sent using a DataQueue object. To manually
retrieve data after it has been received on the client or a worker, use a
[Link] object to send the data instead.
Version History
Introduced in R2017a
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
gcp | afterEach | poll | parfor | send | spmd | [Link] |
spmdSend | spmdReceive
Topics
Class Attributes
Property Attributes
“Plot During Parameter Sweep with parfor” on page 2-60
9-120
[Link]
[Link]
Send and poll data between client and workers
Description
A PollableDataQueue object enables synchronous sending and polling for data or messages
between the client and workers in a parallel pool during a computation. For example, from a worker,
you can send intermediate values to the client or another worker and use the values in another
computation. You can also:
Unlike all other handle objects, PollableDataQueue and DataQueue objects remain connected
when you transfer them.
Creation
Syntax
q = [Link]
q = [Link](Destination=destination)
Description
If you want the client or any worker to be able to poll the PollableDataQueue object to receive
data, set Destination="any".
Input Arguments
9-121
9 Objects
• "creator" — Allows only the client or worker that creates the queue to poll the queue and
receive data. Any data sent to the queue is immediately sent to the client or worker that creates
the queue.
• "any" — Allows the client or any worker in the parallel pool to poll the queue to receive data. The
data waits in the queue and is sent to whichever client or worker polls the queue, making that
client or worker the destination for the specific data.
Properties
IsClosed — Queue closure state
false (default) | or true
This property is read-only after you close the queue using the close object function.
• false — The queue is not closed and you can send data to the queue.
• true — The queue is closed and you cannot send data to the queue. Any attempt to send data to
the queue results in an error. You can continue to poll the queue for data. You cannot reopen a
closed queue.
The number of items of data currently held in the queue that a worker or the client can potentially
poll to receive, represented as zero or a positive integer.
The destination behavior of the queue, set using the Destination name-value argument, determines
the QueueLength property value:
• If you create a PollableDataQueue object without setting the Destination argument, or if you
set Destination to "creator", the QueueLength is 0 or a positive integer on the worker or
client that creates the PollableDataQueue object.
• If the client creates the PollableDataQueue object, the value is 0 on all workers.
• If a worker creates the PollableDataQueue, the value is 0 on the client and all other
workers.
• If you set Destination to "any", the value is 0 or a positive integer on the client and all
workers.
The QueueLength property value is 0 or a positive integer on the worker or client that creates the
PollableDataQueue object. If the client creates the PollableDataQueue object, the value is 0 on
all workers. If a worker creates the PollableDataQueue, the value is 0 on the client and all other
workers.
Object Functions
close Close pollable data queue
poll Retrieve data sent to pollable data queue
9-122
[Link]
send Send data between clients and workers using a data queue
Examples
p = [Link];
Run a parfor-loop, and send a message, such as data with the value 1.
parfor idx = 1
send(p,idx);
end
poll(p)
For more details on polling for data using a PollableDataQueue object, see poll.
Use a PollableDataQueue object with Destination set to "any" to send messages from the
client to multiple workers in a parallel pool.
numWorkers = 4;
pool = parpool("Threads",numWorkers);
Create two PollableDataQueue objects, a queue named workerPdq (you create by setting
Destination to "any") to send messages to workers, and a queue named clientPdq to receive
messages back from the workers.
workerPdq = [Link](Destination="any");
clientPdq = [Link];
Use parfevalOnAll to execute the analyzeMessage helper function on all workers. Pass the
workerPdq and clientPdq queues as arguments to the function.
parfevalOnAll(@analyzeMessage,0,workerPdq,clientPdq);
9-123
9 Objects
Poll the clientPdq queue to receive messages from the workers. Use inf to wait indefinitely for
each message.
ans =
"Worker 1 received message!"
ans =
"Worker 2 received message!"
ans =
"Worker 3 received message!"
ans =
"Worker 4 received message!"
Define the helper function analyzeMessage that each worker executes. The function polls the
inQueue queue for a message and extracts the worker number. The function then sends a
confirmation message back to the outQueue queue.
function analyzeMessage(inQueue,outQueue)
message = poll(inQueue,2);
workerNum = sscanf(message,"Hello, Worker %u");
send(outQueue,compose("Worker %d received message!",workerNum));
pause(2)
end
When you send a message to a PollableDataQueue object, the message waits in the queue. Each
message adds 1 to the queue length. When you use poll, one message is collected from the queue.
In this example, you use the QueueLength property to find the length of a PollableDataQueue
object and observe how the Destination argument affects it.
parpool(1);
queue = [Link]
queue =
PollableDataQueue with properties:
QueueLength: 0
9-124
[Link]
IsClosed: false
Initially, the queue is empty. Check the queue length on the client and the worker. The QueueLength
property value is 0 for both the client and the worker.
fprintf("Queue length on the client: %i\n",[Link])
parfor idx = 1
fprintf("Queue length on the worker: %i\n",[Link])
end
Next, send a message to the queue from the worker. Then, use the QueueLength property to find the
length of the queue. With Destination set to "creator", the QueueLength property value is 1 on
the client (which created the queue) and 0 on the worker.
parfor idx = 1
send(queue,"A message");
end
fprintf("Queue length on the client: %i\n",[Link])
parfor idx = 1
fprintf("Queue length on the worker: %i\n",[Link])
end
msg =
"A message"
Check the length of the queue again. The QueueLength property value is now 0 because you have
removed a message.
fprintf("Queue length on the client: %i\n",[Link])
Create a PollableDataQueue object with Destination set to "any". This command creates a
PollableDataQueue object that the client or any worker in the pool can poll to receive data.
queueAny = [Link](Destination="any")
queueAny =
PollableDataQueue with properties:
QueueLength: 0
IsClosed: false
9-125
9 Objects
parfor idx = 1
send(queueAny,"Another message");
end
Check the queue length. With Destination set to "any", both the client and the worker show a
QueueLength property value of 1, demonstrating that the client or worker can poll the queue to
receive data.
parfor idx = 1
fprintf("Queue length on the worker: %i\n",[Link]);
end
Finally, retrieve the message from the queue and check the queue length. The QueueLength
property value is 0 because the queue processing is complete.
msg = poll(queueAny)
msg =
"Another message"
parfor idx = 1
fprintf("Queue length on the worker: %i\n",[Link]);
end
Tips
• You can only manually retrieve data or messages sent using a PollableDataQueue object. To
automatically process data after it is received on the client, use a [Link]
object to send the data instead.
• To send data from a parallel pool worker back to the client, first create a PollableDataQueue
object at the client. Pass this PollableDataQueue object in a parfor-loop or other parallel
language construct, such as parfeval. From the workers, call send to send data back to the
client. At the client, use poll to retrieve the result of a message or data sent from a worker.
• To send data from the client to the workers, create the queue on the workers and send it back to
the client. For an example of this workflow, see “Receive Communication on Workers” on page 3-
23.
• You cannot send data from one worker to another. To transfer data between workers, use spmd,
spmdSend, or spmdReceive instead.
Version History
Introduced in R2017a
9-126
[Link]
Use the close object function to close a PollableDataQueue object. When you close a
PollableDataQueue, you change the isClosed property to true and you can no longer send data
using the PollableDataQueue object.
You can specify the destination behavior of a PollableDataQueue object using the Destination
name-value argument. For example, to create a PollableDataQueue object that can send messages
or data to any worker or client in the pool, set the Destination name-value argument to "any".
You can create a PollableDataQueue object on a worker and transfer it to another worker via the
client to transfer data or messages between workers.
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
Functions
poll | send | close | parfeval | parfevalOnAll | parfor
Objects
[Link]
Topics
“Receive Communication on Workers” on page 3-23
“Send Messages to Workers Using Pollable Data Queues” on page 3-36
“Perform Image Acquisition and Parallel Image Processing” on page 3-19
9-127
9 Objects
[Link]
Access task properties and behaviors
Constructors
createTask, findTask
Container Hierarchy
Parent [Link]
Children none
Description
A [Link] object provides access to a task, which executes on a worker as part of a job.
Types
The following table describes the available types of task objects, determined by the type of cluster.
Methods
All task type objects have the same methods, described in the following table.
Properties
Common to All Task Types
Property Description
CaptureDiary Specify whether to return diary output
CreateDateTime Date and time when the task is created
Diary Text produced by execution of task object's
function
9-128
[Link]
Property Description
Error Task error information
ErrorIdentifier Task error identifier
ErrorMessage Message from task error
FinishDateTime Date and time when the task is finished
Function Function called when evaluating task
ID Task's numeric identifier
InputArguments Input arguments to task function
Name Name of this task
NumOutputArguments Number of arguments returned by task function
OutputArguments Output arguments from running task function on
worker
Parent Job object containing this task
RunningDuration Current duration of the task, specified as a
duration object.
StartDateTime Date and time when the task is started
State Current state of task
UserData Information associated with this task object
Warnings Warning information issued during execution of
the task, captured in a struct array with the fields
message, identifier, and stack
Worker Object representing worker that ran this task
MATLAB Job Scheduler task objects have the following properties in addition to the common
properties:
Property Description
FailureInfo Information returned from failed task
FinishedFcn Callback executed in client when task finishes
MaximumRetries Maximum number of times to rerun failed task
NumFailures Number of times tasked failed
RunningFcn Callback executed in client when task starts
running
Timeout Time limit, in seconds, to complete task
CJS Tasks
CJS task objects have the following properties in addition to the common properties:
9-129
9 Objects
Property Description
SchedulerID If you have submitted the task to a third-party
scheduler, this is the ID that the scheduler gives to
the task on submission. For example, this
corresponds to the JOBID on a SLURM scheduler.
Help
To get further help on either type of [Link] object, including a list of links to help for its
properties, type:
help [Link]
help [Link]
See Also
[Link], [Link], [Link]
Version History
Introduced in R2012a
9-130
[Link]
[Link]
Access parallel worker information
Constructors
• getCurrentWorker in the workspace of the MATLAB worker.
• In the client workspace, a [Link] object is available from:
Container Hierarchy
Parent • [Link]
• [Link]
Children none
Description
A [Link] object provides access to the MATLAB worker session that executes a task as
part of a job. The job can be an interactive parallel pool job or a batch job.
Types
Worker Type Description
[Link] MATLAB worker on MATLAB Job Scheduler
cluster
[Link] MATLAB worker on CJS cluster
[Link] MATLAB thread worker
Methods
There are no methods for a [Link] object other than generic methods for any objects in
the workspace, such as delete, etc.
Properties
MATLAB Job Scheduler Worker
The following table describes the properties of a MATLAB Job Scheduler worker.
Property Description
AllHostAddresses IP addresses of worker host
9-131
9 Objects
Property Description
ComputerType Type of computer on which the worker ran; the
value of the MATLAB function computer
executed on the worker
Name Name of worker, set when worker session started
Parent MATLAB Job Scheduler cluster to which this
worker belongs
CJS Worker
Property Description
ComputerType Type of computer on which the worker ran; the
value of the MATLAB function computer
executed on the worker
Host Host name where the worker executed the task
ProcessId Process identifier for the worker
Thread Worker
Property Description
ComputerType Type of computer on which the worker ran; the
value of the MATLAB function computer
executed on the worker
Host Host name where the worker executed the task
Help
To get further help on the types of [Link] objects, including a list of links to help for its
properties, type:
help [Link]
help [Link]
help [Link]
See Also
[Link], [Link], [Link]
Version History
Introduced in R2012a
9-132
ProcessPool
ProcessPool
Parallel pool of process workers on the local machine
Description
Use parpool to create a parallel pool of process workers on your local machine. After you create the
pool, parallel pool features, such as parfor or parfeval, run on the workers. With the
ProcessPool object, you can interact with the parallel pool.
Creation
There are several ways to a ProcessPool object.
• Create a parallel pool of process workers on the local machine by using the parpool function.
pool = parpool("Processes")
• Create a pool partition from an existing parallel pool using the partition function.
Properties
AttachedFiles — Files and folders copied to workers
cell array of character vectors
Files and folders copied to workers, specified as a cell array of character vectors. To attach files and
folders to the pool, use addAttachedFiles.
Indication whether user-added entries on client path are added to worker paths, specified as a logical
value.
Data Types: logical
9-133
9 Objects
Flag that indicates whether the parallel pool is running, specified as a logical value.
Data Types: logical
Environment variables copied to the workers, specified as a cell array of character vectors.
Queue of FevalFutures to run on the parallel pool, specified as an FevalQueue object. You can use
this property to check the pending and running future variables of the parallel pool. To create future
variables, use parfeval and parfevalOnAll. For more information on future variables, see
Future.
Data Types: FevalQueue
Store of files accessible to both client and workers, specified as a FileStore object.
Time in minutes after which the pool shuts down if idle, specified as an integer greater than zero. A
pool is idle if it is not running code on the workers. By default 'IdleTimeout' is the same as the
value in your parallel settings. For more information on parallel settings, see “Specify Your Parallel
Settings” on page 1-35.
Flag that indicates whether the parallel pool is busy, specified as true or false. The pool is busy if
there is outstanding work for the pool to complete.
9-134
ProcessPool
Store of data accessible to both client and workers, specified as a ValueStore object.
Information about workers comprising the parallel pool, returned as an array of [Link]
objects.
Object Functions
addAttachedFiles Attach files or folders to parallel pool
Composite Create and access nondistributed variables on multiple workers from client
delete Shut down parallel pool
listAutoAttachedFiles List of files automatically attached to job, task, or parallel pool
parfeval Run function on parallel pool worker
parfevalOnAll Run function asynchronously on all workers in parallel pool
partition Partition parallel pool
parforOptions Options set for parfor
ticBytes Start counting bytes transferred within parallel pool
tocBytes Read how many bytes have been transferred since calling ticBytes
updateAttachedFiles Update attached files or folders on parallel pool
spmd Execute code in parallel on workers of parallel pool
Version History
Introduced in R2020a
Starting in R2022b, the local profile has been renamed to Processes. There are no plans to
remove local. To start a parallel pool of process workers on the local machine, use Processes
instead.
See Also
parpool
Topics
“Run Code on Parallel Pools” on page 1-28
“Choose Between Thread-Based and Process-Based Environments” on page 1-43
9-135
9 Objects
RemoteClusterAccess
Connect to schedulers when client utilities are not available locally
Constructor
r = [Link](username)
r = [Link](username,P1,V1,...,Pn,Vn)
Description
r = [Link](username) creates a RemoteClusterAccess
object with the Username set to username.
By default, you are prompted for a password when you connect to the cluster.
Tip If you have set up a cluster profile for a remote cluster, use parcluster. For more information,
see “Discover Clusters and Use Cluster Profiles” on page 7-2.
You only need to use RemoteClusterAccess directly if you need to modify plugin scripts for third-
party schedulers that do not have a built-in cluster type. You use plugin scripts when you connect to a
cluster using the Generic scheduler interface. For more information, see “Configure Using the
Generic Scheduler Interface” (MATLAB Parallel Server).
Use RemoteClusterAccess when you need to modify settings for remote cluster connection,
submission, or data transfer.
• 'AuthenticationMode' — Authentication mode you use when you connect to the cluster,
specified as a string scalar, character vector, string array or cell array.
• 'Agent' – the client interfaces with an SSH agent running on the client machine.
• 'IdentityFile' – the client uses an identity file to authenticate when you connect to the
cluster. If you specify a file using the IdentityFilename option, you use that file. Otherwise,
MATLAB prompts you to specify the full path to an identity file when you connect.
• 'Multifactor' – the client prompts you for input one or more times. For example, if two-
factor authentication (2FA) is enabled on the client, the client requests your password and a
response for the second authentication factor.
9-136
RemoteClusterAccess
• 'Password' – the client prompts you for your SSH password. Your user name is specified by
the Username property.
For more information and detailed examples, see “Submit from a Remote Host” (MATLAB Parallel
Server) and “Submit Without a Shared File System” (MATLAB Parallel Server).
Methods
Method Name Description
connect connect(r,clusterHost) establishes a connection to the specified
host using the user credential options supplied in the constructor. File
mirroring is not supported. clusterHost must run Linux.
connect(r,clusterHost,remoteDataLocation) establishes a
connection to the specified host using the user credential options
supplied in the constructor. remoteDataLocation identifies a folder
on the clusterHost that is used for file mirroring. The user
credentials supplied in the constructor must have write access to this
folder.
disconnect disconnect(r) disconnects the existing remote connection. The
connect method must have already been called.
doLastMirrorForJob doLastMirrorForJob(r,job) performs a final copy of changed files
from the remote remoteDataLocation to the local
JobStorageLocation for the supplied job. Any running mirrors for
the job also stop and the job files are removed from the remote
remoteDataLocation. The startMirrorForJob or
resumeMirrorForJob method must have already been called.
getRemoteJobLocation getRemoteJobLocation(r,jobID,remoteOS) returns the full path
to the remote job location for the supplied jobID. Valid values for
remoteOS are 'pc' and 'unix'.
isJobUsingConnection isJobUsingConnection(r,jobID) returns true if the job is
currently being mirrored.
reconnect reconnect(r) recreates the existing SSH connections to the remote
host.
9-137
9 Objects
getConnectedAccessWithMirror(...,P1,V1,...Pn,Vn) passes
the additional parameters to the RemoteClusterAccess constructor.
Properties
A RemoteClusterAccess object has the following read-only properties. Their values are set when
you construct the object or call its connect method.
9-138
RemoteClusterAccess
If this property is set to true, you are prompted for a password when
you connect. If an identity file is not supplied, this property is not
used.
9-139
9 Objects
To set this property, use any of the following syntaxes to connect to the
cluster:
• connect(r,clusterHost,remoteDataLocation)
• r =
getConnectedAccessWithMirror(host,remoteDataLocatio
n,username)
• r =
getConnectedAccessWithMirror(___,P1,V1,...Pn,Vn)
Port Port number you use to connect to the cluster, returned as an integer
scalar between 1 and 65535.
9-140
RemoteClusterAccess
Examples
Mirror files from the remote data location. Assume the object job represents a job on your generic
scheduler.
remoteConnection = [Link]('testname');
connect(remoteConnection,'headnode1','/tmp/filemirror');
startMirrorForJob(remoteConnection,job);
submit(job)
% Wait for the job to finish
wait(job);
% Ensure that all the local files are up to date, and remove the
% remote files
doLastMirrorForJob(remoteConnection,job);
For more information and examples, see “Submit from a Remote Host” (MATLAB Parallel Server) and
“Submit Without a Shared File System” (MATLAB Parallel Server).
Version History
Introduced in R2011a
See Also
Topics
“Plugin Scripts for Generic Schedulers” (MATLAB Parallel Server)
9-141
9 Objects
ThreadPool
Parallel pool of thread workers on the local machine
Description
Use parpool to create a parallel pool of thread workers on your local machine. After you create the
pool, parallel pool features, such as parfor or parfeval, run on the workers. With the ThreadPool
object, you can interact with the parallel pool.
Creation
• Create a parallel pool of thread workers on the local machine by using the parpool function.
pool = parpool('Threads')
• Create a pool partition from an existing parallel pool using the partition function.
Properties
Busy — Flag that indicates whether the thread pool is busy
true | false
Flag that indicates whether the thread pool is busy, returned as true or false. The pool is busy if
there is outstanding work for the pool to complete.
Queue of FevalFuture objects to run on the thread pool, returned as a FevalQueue object. You can
use this property to check the pending and running future variables of the parallel pool. To create
future variables, use parfeval and parfevalOnAll. For more information on future variables, see
Future.
Data Types: FevalQueue
Store of files accessible to both client and workers, returned as a FileStore object.
9-142
ThreadPool
Number of thread workers comprising the parallel pool, returned as an integer. You can specify the
number of thread workers during pool creation with parpool.
Store of data accessible to both client and workers, returned as a ValueStore object.
Information about workers comprising the parallel pool, returned as an array of [Link]
objects.
Object Functions
Composite Create and access nondistributed variables on multiple workers from client
delete Shut down parallel pool
parfeval Run function on parallel pool worker
parfevalOnAll Run function asynchronously on all workers in parallel pool
partition Partition parallel pool
parforOptions Options set for parfor
spmd Execute code in parallel on workers of parallel pool
Limitations
• Pools created using parpool('Threads') and backgroundPool are both thread-based pools
which utilize the same resources. It is possible that activity on one pool may block activity on the
other and vice versa. Additionally, persistent data and random number generation stream state are
shared in between these pools. For more information on controlling random number streams, see
“Control Random Number Streams on Workers” on page 5-15.
• Not all functionality is supported in a thread-based environment. For details on specific
limitations, see “Check Thread Supported Functions”.
Version History
Introduced in R2020a
See Also
parpool
Topics
“Run Code on Parallel Pools” on page 1-28
“Choose Between Thread-Based and Process-Based Environments” on page 1-43
“Run MATLAB Functions in Thread-Based Environment”
9-143
9 Objects
ValueStore
Data storage shared by MATLAB clients and workers
Description
ValueStore is an object that stores data owned by a specific job. Each entry of the object consists of
a value and its corresponding key. When the owning job is deleted, the ValueStore object is deleted
as well. Use ValueStore to store data from MATLAB workers that can be retrieved by MATLAB
clients during the execution of a job (even while the job is still running).
• Any MATLAB process client or worker can write an entry to the ValueStore at any time. Any
MATLAB process client or worker can then read this entry from the ValueStore at any time.
However, the ordering of operations executed by different processes is not guaranteed.
• ValueStore is not held in system memory, so it can be used to store large results.
Creation
The ValueStore object is automatically created when you create:
• A job on a cluster, which is a [Link] object. To create a job, use the batch, createJob,
or createCommunicatingJob function.
• A parallel pool of process workers on the local machine, which is a ProcessPool object. To
create a process pool, use the parpool function.
• A parallel pool of thread workers on the local machine, which is a ThreadPool object. To create a
thread pool, use the parpool function.
• A parallel pool of workers on a cluster of machines, which is a ClusterPool object. To create a
cluster pool, use the parpool function.
You can access the ValueStore object on a worker by using the getCurrentValueStore function.
You can then retrieve the ValueStore object on a client by using the ValueStore property that is
associated with the job or the parallel pool. For example, see “Run Batch Job and Retrieve Data from
Workers” on page 9-145.
Properties
KeyUpdatedFcn — Callback executed when entry is added or replaced
function handle
Callback executed when an entry is added or replaced, specified as a function handle. The function
handle must accept two input arguments that represent the ValueStore object and its key when an
entry is added or replaced.
9-144
ValueStore
Callback executed when an entry is removed, specified as a function handle. The function handle
must accept two input arguments that represent the ValueStore object and its key when an entry is
removed.
Object Functions
isKey Determine if ValueStore or FileStore object contains keys
keys Return all keys of ValueStore or FileStore object
put Add key-value pairs to ValueStore object
get Get values from ValueStore object
remove Remove entries from ValueStore or FileStore object
Examples
Run a simulation on workers and retrieve the data storage of the job on a client. The data storage is a
ValueStore object with key-value entries.
The following simulation finds the singular values of random matrices and stores the results in the
ValueStore object.
type workerSvdCode
function workerSvdCode(models)
% Get the ValueStore of the current job
store = getCurrentValueStore;
for i = 1:numel(models)
% Store simulation results in the ValueStore object
pause(1)
key = strcat("result_",num2str(i));
store(key) = svd(rand(models(i)));
store("progress") = i/numel(models);
end
end
The following callback function is executed when an entry is added to the ValueStore object.
type handleNewEntry
function handleNewEntry(store,key)
if strcmp(key,"progress")
fprintf("Progress update: %.2f %%\n",store(key)*100);
else
fprintf("Result %s added\n",key);
end
end
models = [8,16,32,20];
c = parcluster;
job = batch(c,@workerSvdCode,0,{models});
9-145
9 Objects
Retrieve the ValueStore object on the client while the job is still running. Show the progress of the
job.
store = [Link];
[Link] = @handleNewEntry;
wait(job);
Get the entry value as specified by the key "result_1" from the object.
val1 = store("result_1")
val1 =
4.3318
1.2988
1.1040
0.8813
0.5711
0.3991
0.2092
0.1048
Run simulation on a parallel pool of process workers and retrieve the data storage on a client.
The following simulation finds the inverse of random matrices and stores the results in the
ValueStore object.
type workerInvCode
function workerInvCode(models)
% Get the ValueStore of the current job
store = getCurrentValueStore;
for i = 1:numel(models)
% Store simulation results in the ValueStore object
pause(1);
key = strcat("result_",num2str(i));
store(key) = inv(rand(models(i)));
end
end
The following callback function is executed when an entry is added to the ValueStore object.
type handleUpdatedEntry
9-146
ValueStore
function handleUpdatedEntry(store,key)
fprintf("Result %s added\n",key);
end
pool = parpool('Processes');
Get the ValueStore for this pool and assign the callback function to be executed when an entry is
added.
store = [Link];
[Link] = @handleUpdatedEntry;
models = [4,8,32,20];
future = parfeval(@workerInvCode,0,models);
wait(future);
Run Independent Tasks and Retrieve Data and Files from All Tasks
Run a job of independent tasks. Then, retrieve the data and file storage of the job on a client.
The following simulation finds the permutations and combinations of a vector, and stores the results
in the ValueStore and FileStore objects.
type taskFunction
function taskFunction(dataset,keyname)
% Get the ValueStore and FileStore of the current job
valueStore = getCurrentValueStore;
fileStore = getCurrentFileStore;
% Run the simulation to find permutation and combination
[result,logFile] = runSimulation(dataset);
% Store results in ValueStore to release system memory
valueStore(keyname) = result;
% Copy file to FileStore to retrieve the file from non-shared file system
copyFileToStore(fileStore,logFile,keyname);
end
9-147
9 Objects
save(logFile,"permutations","combinations")
end
c = parcluster;
job = createJob(c);
Create independent tasks for the job. Each task runs the simulation with the given input.
set_1 = {[12,34,54],2};
set_2 = {[45,33],1};
set_3 = {[12,12,12,13,14],3};
tasks = createTask(job,@taskFunction,0,{{set_1,"sim_1"},{set_2,"sim_2"},{set_3,"sim_3"}});
submit(job);
wait(job);
valueStore = [Link];
fileStore = [Link];
Show the result of the third task that is stored in the ValueStore object.
result_3 = valueStore("sim_3")
Copy files from the file storage as specified by the corresponding keys "sim_1" and "sim_2" to the
local files "analysis_1.mat" and "analysis_2.mat".
Display all the information on the variables stored in the local files.
9-148
ValueStore
Limitations
• When using [Link] clusters with 'HasSharedFileSystem' set to
false, the visibility of modifications made to ValueStore while a job is running depends on your
specific implementation. Without additional synchronization between the MATLAB client and
worker JobStorageLocation, changes might only be visible once the job has completed.
Version History
Introduced in R2022a
See Also
getCurrentValueStore | [Link] | ProcessPool | ThreadPool | ClusterPool |
FileStore | createCommunicatingJob
Topics
“Monitor Batch Jobs with ValueStore” on page 5-18
“Monitor Monte Carlo Batch Jobs with ValueStore” on page 5-22
9-149
10
Functions
10 Functions
addAttachedFiles
Attach files or folders to parallel pool
Syntax
addAttachedFiles(pool,filenames)
Description
addAttachedFiles(pool,filenames) attaches files or folders to a parallel pool. The files or
folders are immediately transferred to each worker in the parallel pool.
If you specify files that are already attached to the pool, the files are not updated. To update attached
files, use updateAttachedFiles.
Examples
You can use addAttachedFiles and gcp to add files to the current parallel pool.
Use addAttachedFiles to attach two files "myFun1.m" and "myFun2.m" to the current parallel
pool. To get the current parallel pool, use gcp.
addAttachedFiles(gcp,["myFun1.m" "myFun2.m"])
Input Arguments
pool — Parallel pool
[Link]
Files or folders to attach, specified as a string scalar, string array, character vector, or cell array of
character vectors. Each character vector can specify either an absolute or relative path to a file or
folder.
If you specify a relative path, the path is relative to the current working directory on the client.
Example: ["myFun1.m" "myFun2.m"]
Data Types: string | char | cell
10-2
addAttachedFiles
Version History
Introduced in R2013b
See Also
gcp | getAttachedFilesFolder | listAutoAttachedFiles | parpool |
updateAttachedFiles
Topics
“Add and Modify Cluster Profiles” on page 7-5
10-3
10 Functions
afterEach
Define a function to call when new data is received on a data queue
Syntax
listener = afterEach(queue,funtocall)
Description
listener = afterEach(queue,funtocall) specifies a function funtocall to execute each
time the queue receives new data. You can specify multiple different functions to call, because each
call to afterEach creates a new listener on the queue. If you want to specify another function, call
afterEach again. To remove the registration of the function with the queue, delete the returned
listener object.
You must call afterEach in the same process where you created the data queue, otherwise an error
occurs. After calling afterEach, any current data in the queue is immediately passed to the specified
function.
Examples
If you call afterEach and there are items on the queue waiting to be dispatched, these items are
immediately dispatched to the afterEach function. Call afterEach before sending data to the
queue, to ensure that on send, the function handle specified by afterEach is called.
If you then send messages to the queue, each message is passed to the function handle specified by
afterEach immediately.
parfor i = 1
send(q, 2);
end
send(q, 3)
You can also first send various messages to the queue. When you call afterEach, the pending
messages are passed to the afterEach function, in this example to the function handle @disp.
q = [Link];
parfor i = 1
send(q, 2);
10-4
afterEach
end
send(q, 3)
afterEach(q, @disp);
D = [Link];
listener = [Link](@disp);
[Link](1)
delete(listener)
[Link](1)
No data is returned because you have removed the callback by deleting the listener.
Input Arguments
queue — Data queue
[Link]
Callback function added to the list of functions to call when new data is received from queue,
specified as a function handle.
function foo(data)
end
When you call send(queue,someData), the data queue serializes someData and sends it back to
the client. On the client, the data queue de-serializes someData and passes it as the input to
foo(data).
Example: listener = afterEach(queue,funtocall)
10-5
10 Functions
Output Arguments
listener — listener
[Link]
Version History
Introduced in R2017a
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
[Link] | poll | parfor | send | [Link] |
[Link]
10-6
arrayfun
arrayfun
Apply function to each element of array on GPU
Syntax
B = arrayfun(func,A)
B = arrayfun(func,A1,...,An)
[B1,...,Bm] = arrayfun(func, ___ )
Description
Note This function behaves similarly to the MATLAB function arrayfun, except that the evaluation
of the function happens on the GPU, not on the CPU. Any required data not already on the GPU is
moved to GPU memory. The MATLAB function passed in for evaluation is compiled and then executed
on the GPU. All output arguments are returned as gpuArray objects.
[B1,...,Bm] = arrayfun(func, ___ ) returns multiple output arrays B1,...,Bm when the
function func returns m output values. func can return output arguments having different data
types, but the data type of each output must be the same each time func is called.
Examples
Define a function, cal. The function cal applies a gain and an offset correction to an array of
measurement data. The function performs only element-wise operations when applying the gain
factor and offset to each element of the rawdata array.
function c = cal(rawdata,gain,offset)
c = (rawdata.*gain) + offset;
end
meas = 1×4
10-7
10 Functions
1 2 3 4
gn =
offs =
Run the calibration function on the GPU. The function runs on the GPU because the input arguments
gn and offs are already GPU arrays, and are therefore stored in GPU memory. Before the function
runs, it converts the input array meas to a gpuArray object.
corrected = arrayfun(@cal,meas,gn,offs)
corrected =
Performing a small number of element-wise operations on a GPU is unlikely to speed up your code.
For an example showing how arrayfun execution speed scales with input array size, see “Improve
Performance of Element-Wise MATLAB Functions on the GPU Using arrayfun” on page 6-52.
Define a function that applies element-wise operations to multiple inputs and returns multiple
outputs.
Create gpuArray input data, and evaluate the function on the GPU.
s1 = rand(400,"gpuArray");
s2 = rand(400,"gpuArray");
s3 = rand(400,"gpuArray");
[o1,o2] = arrayfun(@myFun,s1,s2,s3);
whos
10-8
arrayfun
function Y = myRandFun(X)
R = rand;
Y = R.*X;
end
Run the function on the GPU. As G is a 4-by-4 gpuArray object, arrayfun applies the myRandfun
function 16 times, generating 16 different random scalar values, H.
G = ones(4,"gpuArray")*2;
H = arrayfun(@myRandFun,G)
H =
Input Arguments
func — Function to apply
function handle
Function to apply to the elements of the input arrays, specified as a function handle.
func can contain the following built-in MATLAB functions and operators.
10-9
10 Functions
Functions that create arrays (such as Inf, NaN, ones, rand, randi, randn, and zeros) do not
support size specifications as input arguments. Instead, the size of the generated array is determined
by the size of the input variables to your functions. Enough array elements are generated to satisfy
the needs of your input or output variables. You can specify the data type using both class and like
syntaxes. The following examples show supported syntaxes for array-creation functions:
a = rand;
b = ones;
c = zeros(like=x);
d = Inf("single");
e = randi([0 9],"uint32");
When you use rand, randi, and randn to generate random numbers within func, each element is
generated from a different substream. For more information about generating random numbers on
the GPU, see “Random Number Streams on a GPU” on page 6-72.
When you use switch, case, otherwise within func, case expressions support only numeric and
logical values.
A — Input array
scalars | vectors | matrices | multidimensional arrays
10-10
arrayfun
Input array, specified as scalars, vectors, matrices, or multidimensional arrays. At least one input
array argument must be a gpuArray for arrayfun to run on the GPU. Each array that is stored in
CPU memory is converted to a gpuArray before the function is evaluated. If you plan to make
several calls to arrayfun with the same array, it is more efficient to convert that array to a
gpuArray.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 |
logical
Output Arguments
B — Output array
gpuArray
Limitations
• The sizes of A1,...,An must match or be compatible. The size of output array B depends on the
sizes of A1,...,An. For more information, see “Compatible Array Sizes for Basic Operations”.
• Because the operations supported by arrayfun are strictly element-wise, and each computation
of each element is performed independently of the others, certain restrictions are imposed:
10-11
10 Functions
Tips
• The first time you call arrayfun to run a particular function on the GPU, there is some overhead
time to set up the function for GPU execution. Subsequent calls of arrayfun with the same
function can run faster.
Version History
Introduced in R2010b
R2025a: Support for like syntax of intmin, intmax, realmin, and realmax
You can now use the intmin, intmax, realmin, and realmax functions and specify a prototype
array using the like syntax in functions you apply using arrayfun.
For example, this function uses intmin and intmax to determine whether elements of integer
gpuArray x are saturated.
You can now call arrayfun inside P-code files or use arrayfun to evaluate functions obfuscated as a
P-code file in standalone applications compiled using MATLAB Compiler.
For more information about packaging a MATLAB function into a standalone application, see “Create
Standalone Application from MATLAB” (MATLAB Compiler).
You can now call arrayfun in a class method to evaluate functions defined in the class definition file
(a file with a .m extension that contains the classdef keyword).
For example, this class contains a method, output, that uses arrayfun to evaluate a local function,
localFun.
classdef TestClass
methods
function output = func(obj,x)
output = arrayfun(@localFun,x);
end
end
end
10-12
arrayfun
For more information about defining classes in MATLAB, see “Creating a Simple Class”.
You can now use P-code files with arrayfun. You can:
For more information about P-code files, see “Create a Content-Obscured File with P-Code”.
R2024a: Support for cell array case expressions in switch, case, otherwise
Use a cell array as the case expression to compare the switch expression against multiple values
within the function you apply using arrayfun. For example, you can use case {x1,y1} to execute
the corresponding code if the switch expression matches at least one of x1 and y1.
You can now use switch conditional statements in functions you apply using arrayfun. This
functionality has these limitations:
Passing arrays from a parent workspace to a nested function and indexing into the array within the
nested function now errors
For example, in the following code, the variable parentWorkspaceVar is created in the parent
workspace of the foo function. If foo is used in an arrayfun call with gpuArray input, and if the
foo function passes parentWorkspaceVar as input to a nested function within foo, the code errors.
10-13
10 Functions
Errors Workaround
function y = exampleFunction function y = exampleFunction
parentWorkspaceVar = 1:9; parentWorkspaceVar = 1:9;
x = ones(2,"gpuArray"); x = ones(2,"gpuArray");
y = arrayfun(@foo,x); y = arrayfun(@foo,x);
In the following code, the variable workspaceVar is created in the workspace of the bar function. If
bar is used in an arrayfun call with gpuArray input, and if a nested function foo writes into
workspaceVar, the code errors.
As a workaround, instead of writing to the variable (workspaceVar) within the nested function
(foo), add another output to the nested function and use the output to write to the variable.
Errors Workaround
function x = exampleFunction function x = exampleFunction
z = ones(2,"gpuArray"); z = ones(2,"gpuArray");
x = arrayfun(@bar,z); x = arrayfun(@bar,z);
function x = foo(z) function [x,y] = foo(z) % Add another output y to the nested functi
workspaceVar = 10; % ERRORS y = 10;
x = z; x = z;
end end
y = workspaceVar; y = workspaceVar;
end end
end end
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
The arrayfun function fully supports GPU arrays. To run the function on a GPU, specify the input
data as a gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-3.
See Also
gather | gpuArray | pagefun
10-14
arrayfun
Topics
“Improve Performance of Element-Wise MATLAB Functions on the GPU Using arrayfun” on page 6-52
“Using GPU arrayfun for Monte-Carlo Simulations” on page 6-99
10-15
10 Functions
batch
Run MATLAB script or function on worker
Syntax
j = batch(script)
j = batch(expression)
j = batch(myCluster,script)
j = batch(myCluster,expression)
j = batch(fcn,N,{x1,...,xn})
j = batch(myCluster,fcn,N,{x1,...,xn})
j = batch( ___ ,Name,Value)
Description
j = batch(script) runs the script file script on a worker in the cluster specified by the default
cluster profile. (Note: Do not include the .m file extension with the script name.) The function returns
j, a handle to the job object that runs the script. The script file script is copied to the worker.
By default, workspace variables are copied from the client to workers when you run
batch(script). Job and task objects are not copied to workers.
By default, workspace variables are copied from the client to workers when you run
batch(expression). Job and task objects are not copied to workers.
j = batch(fcn,N,{x1,...,xn}) runs the function fcn on a worker in the cluster specified by the
default cluster profile. The function returns j, a handle to the job object that runs the function. The
function is evaluated with the given arguments, x1,...,xn, and returns N output arguments. The
function file for fcn is copied to the worker. (Note: Do not include the .m file extension with the
function name argument.)
j = batch( ___ ,Name,Value) specifies options that modify the behavior of a job using one or
more name-value arguments. These options support batch for functions and scripts, unless otherwise
indicated. Use this syntax in addition to any of the input argument combinations in previous syntaxes.
Examples
10-16
batch
This example shows how to use batch to offload work to a MATLAB® worker session that runs in the
background.
Run a script as a batch job by using the batch function. By default, batch uses your default cluster
profile. Check your default cluster profile on the MATLAB Home tab, in the Environment section, in
Parallel > Select Parallel Environment. Alternatively, you can specify a cluster profile with the
'Profile' name-value pair argument.
job = batch('myScript');
batch does not block MATLAB and you can continue working while computations take place.
If you want to block MATLAB until the job finishes, use the wait function on the job object.
wait(job);
By default, MATLAB saves the Command Window output from the batch job to the diary of the job. To
retrieve it, use the diary function.
diary(job)
After the job finishes, fetch the results by using the load function.
load(job,'x');
plot(x)
10-17
10 Functions
If you want to load all the variables in the batch job, use load(job) instead.
When you have loaded all the required variables, delete the job object to clean up its data and avoid
consuming resources unnecessarily.
delete(job);
clear job
Note that if you send a script file using batch, MATLAB transfers all the workspace variables to the
cluster, even if your script does not use them. The data transfer time for a large workspace can be
substantial. As a best practice, convert your script to a function file to avoid this communication
overhead. For an example that uses a function, see “Run Batch Job and Access Files from Workers” on
page 10-18.
For more advanced options with batch, see “Run Batch Job and Access Files from Workers” on page
10-18.
You can offload your computations to run in the background by using batch.
If your code needs access to files, you can use additional options, such as 'AttachedFiles' or
'AdditionalPaths', to make the data accessible. You can continue working in MATLAB® while the
10-18
batch
computations take place. If you submit your computations to a remote cluster, you can close MATLAB
and recover the results later.
Prepare Example
Use the supporting function prepareSupportingFiles to copy the required data for this example
to your current working folder.
prepareSupportingFiles;
Your current working folder now contains 4 files: [Link], [Link], [Link], and [Link].
Create a cluster object using parcluster. By default, parcluster uses your default cluster profile.
Check your default cluster profile on the MATLAB Home tab, in the Environment section, in
Parallel > Select a Default Cluster.
c = parcluster();
Place your code inside a function and submit it as a batch job by using batch. For an example of a
custom function, see the supporting function divideData. Specify the expected number of output
arguments and a cell array with inputs to the function.
Note that if you send a script file using batch, MATLAB transfers all the workspace variables to the
cluster, even if your script does not use them. If you have a large workspace, it impacts negatively the
data transfer time. As a best practice, convert your script to a function file to avoid this
communication overhead. You can do this by simply adding a function line at the beginning of your
script. To reduce overhead in this example, divideData is defined in a file outside of this live script.
If your code uses a parallel pool, use the 'Pool' name-value pair argument to create a parallel pool
with the number of workers that you specify. batch uses an additional worker to run the function
itself.
By default, batch changes the initial working folder of the workers to the current folder of the
MATLAB client. It can be useful to control the initial working folder in the workers. For example, you
might want to control it if your cluster uses a different file system, and therefore the paths are
different, such as when you submit from a Windows® client machine to a Linux® cluster.
• To keep the initial working folder of the workers and use their default, set 'CurrentFolder' to
'.'.
• To change the initial working folder, set 'CurrentFolder' to a folder of your choice.
This example uses a parallel pool with three workers and chooses a temporary location for the initial
working folder. Use batch to offload the computations in divideData.
batch runs divideData on a parallel worker, so you can continue working in MATLAB while
computations take place.
If you want to block MATLAB until the job completes, use the wait function on the job object.
wait(job);
10-19
10 Functions
To retrieve the results, use fetchOutputs on the job object. As divideData depends on a file that
the workers cannot find, fetchOutputs throws an error. You can access error information by using
getReport on the Error property of Task objects in the job. In this example, the code depends on a
file that the workers cannot find.
getReport([Link](1).Error)
ans =
'Error using divideData (line 4)
Unable to read file '[Link]'. No such file or directory.'
By default, batch automatically analyzes your code and transfers required files to the workers. In
some cases, you must explicitly transfer those files -- for example, when you determine the name of a
file at runtime.
In this example, divideData accesses the supporting file [Link], which batch automatically detects
and transfers. The function also accesses [Link], but it resolves the name of the file at runtime, so
the automatic dependency analysis does not detect it.
type divideData.m
function X = divideData()
A = load("[Link]");
X = zeros(flip(size(A)));
parfor i = 1:3
B = load("B" + i + ".dat");
X = X + A\B;
end
end
If the data is in a location that the workers can access, you can use the name-value pair argument
'AdditionalPaths' to specify the location. 'AdditionalPaths' adds this path to the MATLAB
search path of the workers and makes the data visible to them.
pathToData = pwd;
job(2) = batch(c,@divideData,1,{}, ...
'Pool',3, ...
'CurrentFolder',tempdir, ...
'AdditionalPaths',pathToData);
wait(job(2));
If the data is in a location that the workers cannot access, you can transfer files to the workers by
using the 'AttachedFiles' name-value pair argument. You need to transfer files if the client and
workers do not share the same file system, or if your cluster uses the generic scheduler interface in
nonshared mode. For more information, see “Configure Using the Generic Scheduler Interface”
(MATLAB Parallel Server).
10-20
batch
If you submit the job to a remote cluster, you can close MATLAB after job submission and retrieve the
results later. Before you close MATLAB, make a note of the job ID.
job3ID = job(3).ID
job3ID = 25
When you open MATLAB again, you can find the job by using the findJob function.
job(3) = findJob(c,'ID',job3ID);
wait(job(3));
Alternatively, you can use the Job Monitor to track your job. You can open it from the MATLAB Home
tab, in the Environment section, in Parallel > Monitor Jobs.
To retrieve the results of a batch job, use the fetchOutputs function. fetchOutputs returns a cell
array with the outputs of the function run with batch.
X = fetchOutputs(job(3))
When you have retrieved all the required outputs and do not need the job object anymore, delete it to
clean up its data and avoid consuming resources unnecessarily.
delete(job)
clear job
Input Arguments
script — MATLAB script
character vector | string scalar
By default, workspace variables are copied from the client to workers when you specify this
argument. Job and task objects are not copied to workers.
Example: batch('aScript');
Data Types: char | string
By default, workspace variables are copied from the client to workers when you specify this
argument. Job and task objects are not copied to workers.
Example: batch('y = magic(3)');
10-21
10 Functions
myCluster — Cluster
[Link] object
N — Number of outputs
nonnegative integer
Number of outputs expected from the evaluated function fcn, specified as a nonnegative integer.
Example: batch(@myFunction,1,{x,y});
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Name-Value Arguments
Specify optional pairs of arguments as Name1=Value1,...,NameN=ValueN, where Name is the
argument name and Value is the corresponding value. Name-value arguments must appear after
other arguments, but the order of the pairs does not matter.
Before R2021a, use commas to separate each name and value, and enclose Name in quotes.
Example: j = batch(@myFunction,1,{x,y},'Pool',3);
Variables to copy to workers, specified as the comma-separated pair consisting of 'Workspace' and
a structure scalar.
The default value is a structure scalar with fields corresponding to variables in the client workspace.
Specify variables as fields in the structure scalar.
10-22
batch
Workspace variables are only copied from the client to workers if you specify script or
expression. Job and task objects are not copied to workers.
Example: [Link] = 5; j = batch('aScript','Workspace',workspace);
Data Types: struct
Cluster profile used to identify the cluster, specified as the comma-separated pair consisting of
'Profile' and a character vector or string. If this option is omitted, the default profile is used to
identify the cluster and is applied to the job and task properties.
Example: j = batch('aScript','Profile','Processes');
Data Types: char | string
Paths to add to the MATLAB search path of the workers before the script or function executes,
specified as the comma-separated pair consisting of 'AdditionalPaths' and a character vector,
string array, or cell array of character vectors.
The default search path might not be the same on the workers as it is on the client; the path
difference could be the result of different current working folders (cwd), platforms, or network file
system access. Specifying the 'AdditionalPaths' name-value argument helps ensure that workers
look for files, such as code files, data files, or model files, in the correct locations.
You can use 'AdditionalPaths' to access files in a shared file system. Note that path
representations can vary depending on the target machines. 'AdditionalPaths' must be the paths
as seen by the machines in the cluster. For example, if Z:\data on your local Windows machine is /
network/data to your Linux cluster, then add the latter to 'AdditionalPaths'. If you use a
datastore, use 'AlternateFileSystemRoots' instead to deal with other representations. For more
information, see “Set Up Datastore for Processing on Different Machines or Clusters”.
Note that AdditionalPaths only helps to find files when you refer to them using a relative path or
file name, and not an absolute path.
Example: j = batch(@myFunction,1,{x,y},'AdditionalPaths','/network/data/');
Data Types: char | string | cell
Files or folders to transfer to the workers, specified as the comma-separated pair consisting of
'AttachedFiles' and a character vector, string array, or cell array of character vectors.
Example: j = batch(@myFunction,1,{x,y},'AttachedFiles','[Link]');
Data Types: char | string | cell
Flag to add user-added entries on the client path to worker paths, specified as the comma-separated
pair consisting of 'AutoAddClientPath' and a logical value.
10-23
10 Functions
Example: j = batch(@myFunction,1,{x,y},'AutoAddClientPath',false);
Data Types: logical
Flag to enable dependency analysis and automatically attach code files to the job, specified as the
comma-separated pair consisting of 'AutoAttachFiles' and a logical value. If you set the value to
true, the batch script or function is analyzed and the code files that it depends on are automatically
transferred to the workers.
Example: j = batch(@myFunction,1,{x,y},'AutoAttachFiles',true);
Data Types: logical
Folder in which the script or function executes, specified as the comma-separated pair consisting of
'CurrentFolder' and a character vector or string. There is no guarantee that this folder exists on
the worker. The default value for this property is the current directory of MATLAB when the batch
command is executed. If the argument is '.', there is no change in folder before batch execution.
Example: j = batch(@myFunction,1,{x,y},'CurrentFolder','.');
Data Types: char | string
Flag to collect the diary from the function call, specified as the comma-separated pair consisting of
'CaptureDiary' and a logical value. For information on the collected data, see diary.
Example: j = batch('aScript','CaptureDiary',false);
Data Types: logical
Environment variables to copy from the client session to the workers, specified as the comma-
separated pair consisting of 'EnvironmentVariables' and a character vector, string array, or cell
array of character vectors. The names specified here are appended to the EnvironmentVariables
property specified in the applicable parallel profile to form the complete list of environment variables.
Listed variables that are not set are not copied to the workers. These environment variables are set
on the workers for the duration of the batch job.
Example: j = batch('aScript','EnvironmentVariables',"MY_ENV_VAR");
Data Types: char | string | cell
Number of workers to make into a parallel pool, specified as the comma-separated pair consisting of
'Pool' and either:
10-24
batch
• A nonnegative integer.
• A 2-element vector of nonnegative integers, which is interpreted as a range. The size of the
resulting parallel pool is as large as possible in the range requested.
In addition, note that batch uses another worker to run the batch job itself.
The script or function uses this pool to execution statements such as parfor and spmd that are
inside the batch code. Because the pool requires N workers in addition to the worker running the
batch, the cluster must have at least N+1 workers available. You do not need a parallel pool already
running to execute batch, and the new pool that batch creates is not related to a pool you might
already have open. For more information, see “Run Batch Job with Parallel Pool” on page 5-5.
If you use the default value, 0, the script or function runs on only a single worker and not on a
parallel pool.
Flag to specify if spmd support is enabled on the parallel pool of a batch job, specified as a logical
value. You can disable support only on a local or MATLAB Job Scheduler cluster.
Output Arguments
j — Job
[Link] object
Tips
• To view the status or track the progress of a batch job, use the Job Monitor, as described in “Job
Monitor” on page 5-48. You can also use the Job Monitor to retrieve a job object for a batch job
that was created in a different session, or for a batch job that was created without returning a job
object from the batch call.
• Delete any batch jobs you no longer need to avoid consuming cluster storage resources
unnecessarily.
• To develop and test your code, you can run batch job on a local cluster on your client machine. If
you close your MATLAB session, any batch jobs using the local cluster also stop immediately.
10-25
10 Functions
• When you offload work to a remote cluster, you can close the MATLAB client session while the job
is processing and retrieve information from a batch job later or in a new client session.
Version History
Introduced in R2008a
Starting in R2024a, batch supports pools with up to 2000 workers. Before R2024a, batch supports
pools with up to 1000 workers.
R2024a: Disable spmd communication between workers for batch job pools
When you use the 'Pool' name-value argument to create a parallel pool, the software creates a pool
with spmd communication enabled by default. To use pools without spmd communication enabled,
use the 'SpmdEnabled' name-value argument to disable spmd support.
R2021a: batch now evaluates cell array input arguments {C1,...,Cn} as C1,...,Cn
Behavior changed in R2021a
Starting in R2021a, a function fcn offloaded with batch evaluates cell array input arguments
{C1,...,Cn} as fcn(C1,...,Cn). In previous releases {C1,...,Cn} threw an error and
{{C1,...,Cn}} was evaluated as fcn(C1,...,Cn).
Starting in R2021a, use the following code to offload fcn({a,b},{c,d}) on the cluster myCluster
with one output.
batch(myCluster,@fcn,1,{{a,b},{c,d}});
batch(myCluster,@fcn,1,{{{a,b},{c,d}}});
See Also
delete | diary | findJob | load | wait | fetchOutputs (Job)
Topics
“Set Environment Variables on Workers” on page 7-12
10-26
bsxfun
bsxfun
Binary singleton expansion function for gpuArray
Syntax
C = bsxfun(FUN,A,B)
Description
Note
Examples
Use bsxfun with a matrix to subtract the mean of each column from all elements in that column.
Then normalize by the standard deviation of each column.
A = rand(4,'gpuArray');
B = bsxfun(@minus,A,mean(A));
C = bsxfun(@rdivide,B,std(B))
You can use bsxfun to evaluate a function for different combinations of inputs.
A = rand(4,'gpuArray');
B = bsxfun(@minus,A,mean(A));
C = bsxfun(@rdivide,B,std(B))
C =
10-27
10 Functions
Create a function handle that represents the function f(a,b) = 1 - ae-b. Use bsxfun to apply the
function to vectors a and b. bsxfun uses singleton expansion to expand the vectors into matrices and
evaluates the function with all permutations of the input variables.
a = gpuArray(1:7);
b = gpuArray(pi*[0 1/4 1/2 3/4 1 5/4 6/4 7/4 2]).';
fun = @(a,b) 1 - a.*exp(-b);
c = bsxfun(fun,a,b)
c =
Input Arguments
FUN — Binary function to apply
function handle
Function to apply to the elements of the input arrays, specified as a function handle. FUN must be a
handle to a supported element-wise function, or an element-wise function written in the MATLAB
language that uses supported functions and syntax. Fun must return scalar values. For each output
argument, FUN must return values of the same class each time it is called.
FUN must be a handle to a function that is written in the MATLAB language. You cannot specify FUN
as a handle to a MEX-function.
func can contain the following built-in MATLAB functions and operators.
10-28
bsxfun
Functions that create arrays (such as Inf, NaN, ones, rand, randi, randn, and zeros) do not
support size specifications as input arguments. Instead, the size of the generated array is determined
by the size of the input variables to your functions. Enough array elements are generated to satisfy
the needs of your input or output variables. You can specify the data type using both class and like
syntaxes. The following examples show supported syntaxes for array-creation functions:
a = rand;
b = ones;
c = zeros(like=x);
d = Inf("single");
e = randi([0 9],"uint32");
When you use rand, randi, and randn to generate random numbers within func, each element is
generated from a different substream. For more information about generating random numbers on
the GPU, see “Random Number Streams on a GPU” on page 6-72.
When you use switch, case, otherwise within func, case expressions support only numeric and
logical values.
10-29
10 Functions
Input arrays, specified as scalars, vectors, matrices, or multidimensional arrays. Inputs A and B must
have compatible sizes. For more information, see “Compatible Array Sizes for Basic Operations”.
Whenever a dimension of A or B is singleton (equal to one), bsxfun virtually replicates the array
along that dimension to match the other array. In the case where a dimension of A or B is singleton,
and the corresponding dimension in the other array is zero, bsxfun virtually diminishes the singleton
dimension to zero.
At least one of the inputs must be a gpuArray. Each array that is stored on CPU memory is converted
to a gpuArray before the function is evaluated. If you plan to make several calls to bsxfun with the
same array, it is more efficient to convert that array to a gpuArray.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 |
logical
Complex Number Support: Yes
Output Arguments
C — Output array
scalar | vector | matrix | multidimensional array
Output array, returned as a scalar, vector, matrix, or multidimensional array, depending on the sizes
of A and B. C is returned as a gpuArray.
Tips
• The first time you call bsxfun to run a particular function on the GPU, there is some overhead
time to set up the function for GPU execution. Subsequent calls of bsxfun with the same function
can run faster.
• Nonsingleton dimensions of input arrays must match each other. In other words, the
corresponding dimensions of arguments A, B, etc., must be equal to each other, or equal to one.
Whenever a dimension of an input array is singleton (equal to 1), bsxfun uses singleton
expansion. The array is replicated along the singleton dimension to match the largest of the other
arrays in that dimension. When a dimension of an input array is singleton and the corresponding
dimension in another argument array is zero, bsxfun virtually diminishes the singleton dimension
to 0.
Each dimension of the output array C is the same size as the largest of the input arrays in that
dimension for nonzero size, or zero otherwise. The following code shows how dimensions of size 1
are scaled up or down to match the size of the corresponding dimension in other arguments.
R1 = rand(2,5,4,'gpuArray');
R2 = rand(2,1,4,3,'gpuArray');
R = bsxfun(@plus,R1,R2);
size(R)
2 5 4 3
R1 = rand(2,2,0,4,'gpuArray');
R2 = rand(2,1,1,4,'gpuArray');
R = bsxfun(@plus,R1,R2);
size(R)
2 2 0 4
10-30
bsxfun
• Because the operations supported by bsxfun are strictly element-wise, and each computation of
each element is performed independently of the others, certain restrictions are imposed:
Version History
Introduced in R2012a
See Also
arrayfun | gather | gpuArray | pagefun
10-31
10 Functions
cancel
Cancel job or task
Syntax
cancel(t)
cancel(j)
Description
cancel(t) stops the task object, t, that is currently in the pending or running state. The task's
State property is set to 'finished', and no output arguments are returned. An error message
stating that the task was canceled is placed in the task object's ErrorMessage property, and the
worker session running the task is restarted.
cancel(j) stops the job object, j, that is pending, queued, or running. The job's State property is
set to 'finished', and a cancel is executed on all tasks in the job that are not in the 'finished'
state. A job object that has been canceled cannot be started again.
If the job is running from a MATLAB Job Scheduler, any worker sessions that are evaluating tasks
belonging to the job object are restarted.
If the specified job or task is already in the 'finished' state, no action is taken.
Examples
Cancel Tasks
Cancel a task. Note afterward the task's State and Error properties.
c = parcluster();
job1 = createJob(c);
t = createTask(job1, @rand, 1, {3,3});
cancel(t)
t
Task with properties:
ID: 1
State: finished
Function: @rand
Parent: Job 1
StartDateTime:
RunningDuration: 0 days 0h 0m 0s
Input Arguments
t — Task
[Link] object
10-32
cancel
j — Job
[Link] object
Version History
Introduced before R2006a
See Also
cancelAll | delete | submit
10-33
10 Functions
cancelAll
Cancel all jobs or tasks
Syntax
cancelAll([Link])
Description
cancelAll([Link]) stops all queued or running elements of the specified pool.
Examples
pool = parpool;
f = parfeval(pool,@pause,0,Inf);
[Link]
ans =
FevalQueue with properties:
cancelAll([Link])
[Link]
ans =
FevalQueue with properties:
10-34
cancelAll
Input Arguments
[Link] — Queue of FevalFuture objects to run on the background pool
FevalFuture scalar | FevalFuture array
Queue of FevalFuture objects to run on the background pool, specified as an FevalFuture scalar
and FevalFuture array.
Version History
Introduced in R2022a
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
parfeval | cancel | delete
10-35
10 Functions
changePassword
Prompt MATLAB Job Scheduler password change
Syntax
changePassword(mjs)
changePassword(mjs,username)
Description
changePassword(mjs) prompts you to change your password as the current user on the MATLAB
Job Scheduler cluster represented by cluster object mjs. In the dialog box that opens, you must enter
your current password and the new password.
changePassword(mjs,username) prompts you as the MATLAB Job Scheduler cluster admin user
to change the password for another specified user. In the dialog box that opens, you must enter the
cluster admin user password and the new password for the user. Use this syntax to enable the cluster
administrator to reset a password for a user who is not available or has forgotten their password.
Note The cluster administrator creates the admin account when they start the MATLAB Job
Scheduler with a security level of 1, 2, or 3.
Examples
Change your password for the MATLAB Job Scheduler cluster corresponding to a cluster profile
called MyMjsProfile.
mjs = parcluster("MyMjsProfile");
changePassword(mjs)
Change your password for the MATLAB Job Scheduler cluster on which the parallel pool is running.
p = gcp;
mjs = [Link];
changePassword(mjs)
Change the password for a user named john. The cluster administrator can perform this operation
from any MATLAB client that can access the MATLAB Job Scheduler.
10-36
changePassword
As the cluster administrator with the username admin, access the MATLAB Job Scheduler cluster by
creating a [Link] object. This call generates prompts for the administrator to
provide their username and password.
mjs = [Link](Profile="MyMjsProfile",Username="admin");
After the administrator logs into the MATLAB Job Scheduler cluster, they can change the password
for john. This call generates prompts for the administrator's password and then for a new password
for john.
changePassword(mjs,"john");
At this point, the administrator can change the MATLAB Job Scheduler session user back to john.
[Link] = "john"; % Prompted again for password.
Input Arguments
mjs — Cluster object representing MATLAB Job Scheduler cluster
[Link] object
Cluster object representing the MATLAB Job Scheduler cluster on which the password is changing,
specified as a [Link] object. You can create a [Link] cluster
object using the parcluster function or the [Link] function.
Username of the user whose password is changing, specified as a character vector or string scalar.
Data Types: char | string
Version History
Introduced in R2010b
10-37
10 Functions
See Also
logout | parcluster | startjobmanager
Topics
“Set MATLAB Job Scheduler Cluster Security” (MATLAB Parallel Server)
10-38
classUnderlying
classUnderlying
(Not recommended) Class of elements within gpuArray or distributed array
Syntax
C = classUnderlying(D)
Description
C = classUnderlying(D) returns the name of the class of the elements contained within the
gpuArray or distributed array D. Similar to the MATLAB class function, this returns a character
vector indicating the class of the data.
Examples
Examine the class of the elements of a gpuArray.
N = 1000;
G8 = ones(1,N,'uint8','gpuArray');
G1 = NaN(1,N,'single','gpuArray');
c8 = classUnderlying(G8)
c1 = classUnderlying(G1)
c8 =
uint8
c1 =
single
N = 1000;
D8 = ones(1,N,'uint8','distributed');
D1 = NaN(1,N,'single','distributed');
c8 = classUnderlying(D8)
c1 = classUnderlying(D1)
c8 =
uint8
c1 =
single
10-39
10 Functions
Version History
Introduced in R2013b
See Also
codistributed | distributed | gpuArray | underlyingType | isUnderlyingType |
mustBeUnderlyingType
10-40
clear
clear
Remove objects from MATLAB client workspace
Syntax
clear obj
Description
clear obj removes the object obj from the MATLAB client workspace.
Note To remove variables from the workspace of pool or cluster workers, use parfevalOnAll to
run the clear function on the workers to preserve workspace transparency. If you try to use clear
directly in a parfor-loop or spmd block, you encounter an error. For more information, see “Ensure
Transparency in parfor-Loops or spmd Statements” on page 2-51.
Examples
Create two job objects on the MATLAB Job Scheduler cluster myMJSCluster.
c = parcluster(myMJSCluster);
delete([Link]) % Delete any existing jobs
job1 = createJob(c);
job2 = createJob(c);
Copy job1 to a new variable named job1copy, then clear job1 and job2 from the MATLAB
workspace.
job1copy = job1;
clear job1 job2;
Restore the cleared job objects to the workspace using the cluster object [Link] property as j1 and
j2.
j1 = [Link](1);
j2 = [Link](2);
Verify that the first job in the MATLAB Job Scheduler is identical to job1copy, while the second job
is not.
isequal (job1copy,j1)
ans =
1
isequal (job1copy,j2)
10-41
10 Functions
ans =
0
Input Arguments
obj — Object to clear from MATLAB workspace
object | array of objects
Object to clear from the MATLAB workspace, specified as an object or an array of objects.
Tips
If the object obj references an object in the cluster, this function clears it from the workspace, but it
remains in the cluster. You can restore obj to the workspace with the parcluster, findJob, or
findTask function, or with the Jobs or Tasks property.
Version History
Introduced before R2006a
See Also
createJob | createTask | findJob | findTask | parcluster
10-42
close
close
Namespace: [Link]
Syntax
close(pollablequeue)
Description
close(pollablequeue) closes the PollableDataQueue object specified by pollablequeue. You
can no longer send data to the queue using the send function.
Examples
Define a function, sendMessages, that sends messages to a queue. It sends five messages,
simulating work by pausing for one second between sending each message.
function sendMessages(queue)
for i = 1:5
send(queue,sprintf("Message %d from worker",i));
pause(1);
end
end
Create a pollable data queue, and use parfeval to execute the sendMessages function on a worker.
Pause briefly to allow the worker to send some messages.
queue = [Link];
f = parfeval(@sendMessages,0,queue);
pause(2);
To stop the worker from sending any more data to the queue, call close on the queue.
close(queue);
Wait for the future object f to complete. Use the Error property of future object f to verify that an
error occurred due to an attempt to send messages to the closed queue.
wait(f);
[Link]
ans =
'Failed to send data because the DataQueue has been closed.'
10-43
10 Functions
This example shows how to use the close function to signal to multiple queue receivers that no more
data will be sent, avoiding the need for multiple "stop" messages.
Define a function dataGenFcn that simulates data acquisition by generating random data and
sending the result to the next worker through a PollableDataQueue object. After generating data
for a predefined number of iterations, the function closes the workerQueue to signal to the
processing workers that it will no longer send data.
function dataGenFcn(workerQueue,numIter)
for idx = 1:numIter
data = randn(5e2);
send(workerQueue,data);
pause(0.1)
end
close(workerQueue);
end
Define the function dataProcessFcn to continuously poll the queue for data, process each received
value, and store the results. The loop continues until the processing workers drain the closed queue.
When the closed queue is empty, polling returns an empty array and sets OK to false, breaking the
while-loop.
function allResults = dataProcessFcn(workerQueue)
allResults = [];
while true
[data,OK] = poll(workerQueue,Inf);
if ~OK
break
end
result = max(real(eig(data)));
allResults = [allResults;result];
pause(0.2)
end
end
Define the number of iterations and use parfeval to execute the worker functions asynchronously.
The first worker generates the data, and the other workers in the pool receive and process the data.
numIter = 100;
dataGenFuture = parfeval(@dataGenFcn,0,queue,numIter);
for f = 1:3
dataProcessFutures(f) = parfeval(@dataProcessFcn,1,queue);
end
10-44
close
Wait for the data processing workers to complete their tasks, and then retrieve all the results from
the processing workers using fetchOutputs. Display a histogram of the results.
wait(dataProcessFutures);
allResults = fetchOutputs(dataProcessFutures);
histogram(allResults)
Input Arguments
pollablequeue — Pollable data queue
PollableDataQueue object
After you close a PollableDataQueue object, you can no longer send data to the queue. Any
attempt to send data to the queue results in an error. You can continue to poll the queue for data. You
cannot reopen a closed queue.
Example: p = [Link];
Version History
Introduced in R2025a
10-45
10 Functions
See Also
Functions
poll | send
Objects
[Link]
Topics
“Perform Data Acquisition and Processing on Pool Workers” on page 3-47
“Control Hardware and Acquire Data in Parallel” on page 3-39
10-46
[Link]
[Link]
Create codistributed array from distributed data
Syntax
D = [Link](L,codist)
D = [Link](L,codist,'noCommunication')
Description
D = [Link](L,codist) forms a codistributed array with getLocalPart(D) =
L. The codistributed array D is created as if you had combined all copies of the local array L. The
distribution scheme is specified by codist. Global error checking ensures that the local parts
conform with the specified distribution scheme. For information on constructing codistributor objects,
see the reference pages for codistributor1d and codistributor2dbc.
codist must be complete, which you can check by calling [Link](). The
requirements on the size and structure of the local part L depend on the class of codist. For the 1-D
and 2-D block-cyclic codistributors, L must have the same class and sparsity on all workers.
Furthermore, the local part L must represent the region described by the globalIndices method
on codist.
Examples
Create a codistributed array of size 1001-by-1001 such that column ii contains the value ii.
spmd
N = 1001;
globalSize = [N,N];
% Distribute the matrix over the second dimension (columns),
% and let the codistributor derive the partition from the
% global size.
codistr = codistributor1d(2, ...
[Link],globalSize)
10-47
10 Functions
Version History
Introduced in R2009b
See Also
codistributor1d | codistributor2dbc | gather | globalIndices | getLocalPart |
redistribute | subsasgn | subsref
10-48
[Link]
[Link]
Create codistributed cell array
Syntax
C = [Link](n)
C = [Link](m,n,p,...)
C = [Link]([m,n,p,...])
C = cell(n,codist)
C = cell(m,n,p,...,codist)
C = cell([m,n,p,...],codist)
Description
C = [Link](n) creates an n-by-n codistributed array of underlying class cell,
distributing along columns.
Optional arguments to [Link] must be specified after the required arguments, and in
the following order:
• codist — A codistributor object specifying the distribution scheme of the resulting array. If
omitted, the array is distributed using the default distribution scheme. For information on
constructing codistributor objects, see the reference pages for codistributor1d and
codistributor2dbc.
• 'noCommunication' — Specifies that no communication is to be performed when constructing
the array, skipping some error checking steps.
spmd
C = cell(8,codistributor1d());
end
Examples
With four workers,
spmd(4)
C = [Link](1000);
end
10-49
10 Functions
creates a 1000-by-1000 distributed cell array C, distributed by its second dimension (columns). Each
worker contains a 1000-by-250 local piece of C.
spmd(4)
codist = codistributor1d(2, 1:spmdSize);
C = cell(10, 10, codist);
end
creates a 10-by-10 codistributed cell array C, distributed by its columns. Each worker contains a 10-
by-spmdIndex local piece of C.
Version History
Introduced in R2009b
See Also
cell | [Link]
10-50
[Link]
[Link]
Distributed colon operation
Syntax
[Link](a,d,b)
[Link](a,b)
[Link]( ___ ,codist)
[Link]( ___ ,'noCommunication')
[Link]( ___ ,codist,'noCommunication')
Description
[Link](a,d,b) partitions the vector a:d:b into spmdSize contiguous subvectors
of equal, or nearly equal length, and creates a codistributed array whose local portion on each worker
is the spmdIndex-th subvector.
[Link](a,b) uses d = 1.
Optional arguments to [Link] must be specified after the required arguments, and
in the following order:
[Link]( ___ ,codist) uses the codistributor object codist to specify the
distribution scheme of the resulting vector. If omitted, the result is distributed using the default
distribution scheme. For information on constructing codistributor objects, see the reference pages
for codistributor1d and codistributor2dbc.
Examples
Partition the vector 1:10 into four subvectors among four workers.
parpool('Processes',4);
spmd(4)
C = [Link](1,10)
end
Worker 1:
This worker stores C(1:3).
LocalPart: [1 2 3]
Codistributor: [1x1 codistributor1d]
Worker 2:
This worker stores C(4:6).
LocalPart: [4 5 6]
Codistributor: [1x1 codistributor1d]
Worker 3:
This worker stores C(7:8).
LocalPart: [7 8]
10-51
10 Functions
Version History
Introduced in R2009b
See Also
codistributor1d | codistributor2dbc | colon | for
10-52
[Link]
[Link]
Allocate space for sparse codistributed matrix
Syntax
SD = [Link](M,N,nzmax)
SD = spalloc(M,N,nzmax,codist)
SD = [Link]( ___ ,typename)
Description
SD = [Link](M,N,nzmax) creates an M-by-N all-zero sparse codistributed
matrix with room to hold nzmax nonzeros.
• codist — A codistributor object specifying the distribution scheme of the resulting array. If
omitted, the array is distributed using the default distribution scheme. The allocated space for
nonzero elements is consistent with the distribution of the matrix among the workers according to
the Partition of the codistributor.
• 'noCommunication' — Specifies that no communication is to be performed when constructing
the array, skipping some error checking steps. You can also use this argument with SD =
spalloc(M,N,nzmax,codistr).
SD = [Link]( ___ ,typename) also specifies the data type (class) of any of the
previous syntaxes. The typename input can be either "single", "double", or "logical".
Examples
Allocate space for a 1000-by-1000 sparse codistributed matrix with room for up to 2000 nonzero
elements. Use the default codistributor. Define several elements of the matrix.
Use spalloc to initialize a 10-by-10 all-zero sparse codistributed single-precision matrix with room
for up to 20 nonzero elements. Define several elements in the matrix.
spmd
SD = [Link](10,10,20,"single");
10-53
10 Functions
SD(1:3,1:3) = magic(3);
end
Version History
Introduced in R2009b
You can specify the output data type by specifying the typename argument as "double",
"single", or "logical".
See Also
spalloc | sparse | [Link]
10-54
[Link]
[Link]
Create codistributed sparse identity matrix
Syntax
CS = [Link](n)
CS = [Link](m,n)
CS = [Link]([m,n])
CS = speye(n,codist)
CS = speye(m,n,codist)
CS = speye([m,n],codist)
CS = [Link]( ___ ,typename)
Description
CS = [Link](n) creates an n-by-n sparse codistributed array of underlying class
double.
Optional arguments to [Link] must be specified after the required arguments, and
in the following order:
• codist — A codistributor object specifying the distribution scheme of the resulting array. If
omitted, the array is distributed using the default distribution scheme. For information on
constructing codistributor objects, see the reference pages for codistributor1d and
codistributor2dbc.
• 'noCommunication' — Specifies that no interworker communication is to be performed when
constructing the array, skipping some error checking steps.
spmd
CS = [Link](8,codistributor1d);
end
CS = [Link]( ___ ,typename) also specifies the data type (class) for any of the
previous syntaxes. The typename input can be either "single" or "double".
To create a sparse codistributed array of underlying class logical, first create an array of underlying
class double and then cast it using the logical function:
CLS = logical(speye(m,n,codistributor1d))
10-55
10 Functions
Examples
With four workers, create a 1000-by-1000 sparse codistributed double array CS, distributed by its
second dimension (columns). Each worker contains a 1000-by-250 local piece of CS.
spmd(4)
CS = speye(1000,codistributor)
end
Create a 10-by-10 sparse codistributed double array CS, distributed by its columns. Each worker
contains a 10-by-spmdIndex local piece of CS.
spmd(4)
codist = codistributor1d(2,1:spmdSize);
CS = speye(10,10,codist);
end
spmd(6)
SD = [Link](500,500,"single");
end
Version History
Introduced in R2009b
You can specify the output data type by specifying the typename argument as "double" or
"single".
See Also
speye | [Link] | sparse
10-56
[Link]
[Link]
Create codistributed sparse array of uniformly distributed pseudo-random values
Syntax
CS = [Link](m,n,density)
CS = sprand(n,codist)
DS = [Link]( ___ ,typename)
Description
CS = [Link](m,n,density) creates an m-by-n sparse codistributed array with
approximately density*m*n uniformly distributed nonzero double entries.
• codist — A codistributor object specifying the distribution scheme of the resulting array. If
omitted, the array is distributed using the default distribution scheme. For information on
constructing codistributor objects, see the reference pages for codistributor1d and
codistributor2dbc.
• 'noCommunication' — Specifies that no interworker communication is to be performed when
constructing the array, skipping some error checking steps.
DS = [Link]( ___ ,typename) also specifies the data type (class) for any of the
previous syntaxes. The typename input can be either "single" or "double".
Examples
With four workers, create a 1000-by-1000 sparse codistributed double array CS with approximately
1000 nonzeros. CS is distributed by its second dimension (columns).
spmd(4)
CS = [Link](1000,1000,0.001);
end
10-57
10 Functions
Create a random 500-by-1000 sparse codistributed single-precision array with density 0.1.
spmd(5)
CS = [Link](500,1000,0.1,"single");
end
Tips
When you use sprand on the workers in the parallel pool, or in an independent or communicating
job, each worker sets its random generator seed to a value that depends only on the spmdIndex or
task ID. Therefore, the array on each worker is unique for that job. However, if you repeat the job,
you get the same random data.
Version History
Introduced in R2009b
You can specify the output data type by specifying the typename argument as "double" or
"single".
See Also
sprand | rand | [Link]
10-58
[Link]
[Link]
Create codistributed sparse array of normally distributed pseudo-random values
Syntax
CS = [Link](m,n,density)
CS = sprandn(n,codist)
CS = [Link]( ___ ,typename)
Description
CS = [Link](m,n,density) creates an m-by-n sparse codistributed array with
approximately density*m*n normally distributed nonzero double entries.
• codist — A codistributor object specifying the distribution scheme of the resulting array. If
omitted, the array is distributed using the default distribution scheme. For information on
constructing codistributor objects, see the reference pages for codistributor1d and
codistributor2dbc.
• 'noCommunication' — Specifies that no interworker communication is to be performed when
constructing the array, skipping some error checking steps.
CS = [Link]( ___ ,typename) also specifies the data type (class) of any of the
previous syntaxes. The typename input can be either "single" or "double".
Examples
With four workers, create a 1000-by-1000 sparse codistributed double array CS with approximately
1000 nonzeros. CS is distributed by its second dimension (columns).
spmd(4)
CS = [Link](1000,1000,0.001);
end
10-59
10 Functions
Create a random 500-by-1000 sparse codistributed single-precision matrix with density 0.1.
spmd(5)
DS = [Link](500,1000,0.1,"single");
end
Tips
When you use sprandn on the workers in the parallel pool, or in an independent or communicating
job, each worker sets its random generator seed to a value that depends only on the spmdIndex or
task ID. Therefore, the array on each worker is unique for that job. However, if you repeat the job,
you get the same random data.
Version History
Introduced in R2009b
You can specify the output data type by specifying the typename argument as "double" or
"single".
See Also
sprandn | rand | randn | sparse | [Link] | [Link] |
[Link]
10-60
tall
tall
Convert distributed array to equivalent tall array
Syntax
T = tall(D)
Description
T = tall(D) converts the distributed array D into a tall array. The underlying data type of T is the
same as the underlying type of D.
If the distribution of D is in the first dimension, then T has the same distribution. If the distribution of
D is in any other dimension or uses a 2-D block-cyclic codistributor then T contains a redistribution of
the underlying data in the first dimension.
Examples
First, create a distributed array directly on the workers and then convert it into the equivalent tall
array.
N = 1000;
dX = [Link](1,N)';
tX = tall(dX);
Calculate the sum of the elements of the tall array and retrieve the value back to the local workspace.
gather(sum(tX))
ans = 500500
Input Arguments
D — Distributed array to convert
distributed array
Distributed array to convert, specified as a distributed array stored in parts on the workers of the
open parallel pool.
10-61
10 Functions
Output Arguments
T — Tall array
tall array
Tall array defined in a parallel environment, returned as a tall array with the same underlying data
type as the distributed array it was converted from.
For information about how to work with tall arrays, see “Lazy Evaluation of Tall Arrays”.
Version History
Introduced in R2023b
See Also
distributed | tall | gather
Topics
“Tall Arrays for Out-of-Memory Data”
“Lazy Evaluation of Tall Arrays”
“Create and Use Distributed Arrays” on page 4-2
10-62
codistributor
codistributor
Create codistributor object for codistributed arrays
Syntax
codist = codistributor()
codist = codistributor('1d')
codist = codistributor('1d',dim)
codist = codistributor('1d',dim,part)
codist = codistributor('2dbc')
codist = codistributor('2dbc',lbgrid)
codist = codistributor('2dbc',lbgrid,blksize)
Description
There are two schemes for distributing arrays. The scheme denoted by the character vector '1d'
distributes an array along a single specified subscript, the distribution dimension, in a noncyclic,
partitioned manner. The scheme denoted by '2dbc', employed by the parallel matrix computation
software ScaLAPACK, applies only to two-dimensional arrays, and varies both subscripts over a
rectangular computational grid of labs (workers) in a blocked, cyclic manner.
codist = codistributor(), with no arguments, returns a default codistributor object with zero-
valued or empty parameters, which can then be used as an argument to other functions to indicate
that the function is to create a codistributed array if possible with default distribution. For example,
Z = zeros(..., codistributor())
R = randn(..., codistributor())
10-63
10 Functions
Examples
On four workers, create a 3-dimensional, 2-by-6-by-4 array with distribution along the second
dimension, and partition scheme [1 2 1 2]. In other words, worker 1 contains a 2-by-1-by-4
segment, worker 2 a 2-by-2-by-4 segment, etc.
spmd
dim = 2; % distribution dimension
codist = codistributor('1d',dim,[1 2 1 2],[2 6 4]);
if mod(spmdIndex,2)
L = rand(2,1,4);
else
L = rand(2,2,4);
end
A = [Link](L,codist)
end
A
On four workers, create a 20-by-5 codistributed array A, distributed by rows (over its first dimension)
with a uniform partition scheme.
spmd
dim = 1; % distribution dimension
partn = [Link](20);
codist = codistributor('1d',dim,partn,[20 5]);
L = magic(5) + spmdIndex;
A = [Link](L,codist)
end
A
Version History
Introduced in R2008b
See Also
codistributed | codistributor1d | codistributor2dbc | getCodistributor |
getLocalPart | redistribute
10-64
[Link]
[Link]
Default partition for codistributed array
Syntax
P = [Link](n)
Description
P = [Link](n) is a vector with sum(P) = n and length(P) =
spmdSize. The first rem(n,spmdSize) elements of P are equal to ceil(n/spmdSize) and the
remaining elements are equal to floor(n/spmdSize). This function is the basis for the default
distribution of codistributed arrays.
Examples
If spmdSize = 4, the following code returns the vector [3 3 2 2] on all workers:
spmd
P = [Link](10)
end
Version History
Introduced in R2009b
See Also
codistributed | [Link] | codistributor1d
10-65
10 Functions
[Link]
Default computational grid for 2-D block-cyclic distributed arrays
Syntax
grid = [Link]
Description
grid = [Link] returns a vector defining a computational grid
of nrow-by-ncol workers such that the product is the number of workers running in the current
spmd block or communicating job. To get the number of workers running in the current spmd block,
use the spmdSize function. The grid defined by [Link] is as
close to a square as possible. The following rules define the nrow and ncol of the grid:
• If the number of workers running in the current spmd block is a perfect square, nrow = ncol =
sqrt(spmdSize).
• If the number of workers running in the current spmd block is an odd power of 2, then nrow =
ncol/2 = sqrt(spmdSize/2).
• nrow <= ncol.
• If the number of workers running in the current spmd block is a prime number, nrow = 1, ncol
= spmdSize.
• nrow is the greatest integer less than or equal to sqrt(spmdSize) for which ncol =
spmdSize/nrow is also an integer.
Examples
parpool(4);
When you execute an spmd block after creating a parallel pool, by default, all available workers in the
pool run the code inside the spmd block.
View the computational grid layout of the default distribution scheme for the current spmd block.
spmd
grid = [Link]
end
Worker 3:
grid =
10-66
[Link]
2 2
Worker 4:
grid =
2 2
Worker 1:
grid =
2 2
Worker 2:
grid =
2 2
Output Arguments
grid — Default computational grid
vector
Default computational grid for 2-D block-cyclic distributed arrays in an spmd block, returned as a
vector of nrow-by-ncol workers. The product of nrow*nrow is the number of workers running the
current spmd block or communicating job.
Version History
Introduced in R2009b
See Also
codistributed | codistributor2dbc | spmdSize
10-67
10 Functions
copyFileFromStore
Namespace: parallel
Syntax
copyFileFromStore(store,keySet,fileSet)
Description
copyFileFromStore(store,keySet,fileSet) copies files from store as specified by the keys
keySet to the local file system fileSet.
Examples
Run a simulation on a parallel pool of process workers and retrieve the file storage on a client. The
file storage is a FileStore object with key-file entries. Copy files from this object as specified by
their corresponding keys using the copyFileFromStore function.
The following simulation finds the average and standard deviation of random matrices and stores the
results in the FileStore object.
type workerStatsCode
function workerStatsCode(models)
% Get the FileStore of the current job
store = getCurrentFileStore;
for i = 1:numel(models)
% Compute the average and standard deviation of random matrices
A = rand(models(i));
M = mean(A);
S = std(A);
% Save simulation results in temporary files
sourceTempFile = strcat(tempname("C:\myTempFolder"),".mat");
save(sourceTempFile,"M","S");
% Copy files to FileStore object as key-file pairs
key = strcat("result_",num2str(i));
copyFileToStore(store,sourceTempFile,key);
end
end
10-68
copyFileFromStore
store = [Link];
models = [4,8,32,20];
future = parfeval(@workerStatsCode,0,models);
wait(future);
keys(store)
Copy files from the file storage as specified by the corresponding keys "result_1" and "result_2"
to the local files "run_1.mat" and "run_2.mat".
Display all the information on the variables stored in the local files.
M 1x4 32 double
S 1x4 32 double
M 1x8 64 double
S 1x8 64 double
Input Arguments
store — File storage shared by MATLAB clients and workers
FileStore object
File storage shared by MATLAB clients and workers, specified as a FileStore object.
Keys to copy, specified as a character vector, string scalar, string array, or cell array of character
vectors or strings. keySet and fileSet must have the same number of elements.
Example: ["myDataKey" "myLogKey"]
10-69
10 Functions
Local files, specified as a character vector, string scalar, string array, or cell array of character
vectors or strings. keySet and fileSet must have the same number of elements.
Example: ["/data/[Link]" "/tmp/run_log.txt"]
Version History
Introduced in R2022a
See Also
FileStore | isKey | keys | remove | copyFileToStore
10-70
copyFileToStore
copyFileToStore
Namespace: parallel
Syntax
copyFileToStore(store,fileSet,keySet)
Description
copyFileToStore(store,fileSet,keySet) copies files from the local file system fileSet to
store using the corresponding keys keySet. If the keys already exist in store, then
copyFileToStore replaces the files associated with the specified keys.
Examples
Run a simulation on a parallel pool of process workers and retrieve the file storage on a client. The
file storage is a FileStore object with key-file entries. Copy files to this object as specified by its
corresponding keys using the copyFileToStore function.
The following simulation finds the average and standard deviation of random matrices and stores the
results in the FileStore object using copyFileToStore.
type workerStatsCode
function workerStatsCode(models)
% Get the FileStore of the current job
store = getCurrentFileStore;
for i = 1:numel(models)
% Compute the average and standard deviation of random matrices
A = rand(models(i));
M = mean(A);
S = std(A);
% Save simulation results in temporary files
sourceTempFile = strcat(tempname("C:\myTempFolder"),".mat");
save(sourceTempFile,"M","S");
% Copy files to FileStore object as key-file pairs
key = strcat("result_",num2str(i));
copyFileToStore(store,sourceTempFile,key);
end
end
pool = parpool("Processes");
10-71
10 Functions
store = [Link];
models = [4,8,32,20];
future = parfeval(@workerStatsCode,0,models);
wait(future);
Input Arguments
store — File storage shared by MATLAB clients and workers
FileStore object
File storage shared by MATLAB clients and workers, specified as a FileStore object.
Local files, specified as a character vector, string scalar, string array, or cell array of character
vectors or strings. fileSet and keySet must have the same number of elements.
Example: ["/data/[Link]" "/tmp/run_log.txt"]
Keys to add, specified as a character vector, string scalar, string array, or cell array of character
vectors or strings. fileSet and keySet must have the same number of elements.
Example: ["myDataKey" "myLogKey"]
Version History
Introduced in R2022a
See Also
FileStore | isKey | keys | remove | copyFileFromStore
10-72
createCommunicatingJob
createCommunicatingJob
Create communicating job on cluster
Syntax
j = createCommunicatingJob(cluster)
j = createCommunicatingJob( ___ ,Name=Value)
j = createCommunicatingJob( ___ ,Type=jobType)
j = createCommunicatingJob( ___ ,Profile=profileName)
Description
j = createCommunicatingJob(cluster) creates a communicating job object for the identified
cluster.
For a list of supported object properties, see [Link]. In most cases, the values you specify
override the values in the cluster profile. If you specify AttachedFiles or AdditionalPaths, the
software combines the values with the values in the applicable profile. If you specify an invalid
property name or value, the software does not create an object.
Examples
This example shows how to create and submit a pool type communicating job.
myCluster = parcluster;
j = createCommunicatingJob(myCluster,Type="pool");
Add the task to the job, using a function handle to the maxEig on page 10-74 function, which uses a
parfor-loop to calculate the maximum eigenvalue of random matrices. The function is defined at the
end of this example. The maxEig function requires a pool type communicating job to execute the
statements in the parfor-loop.
createTask(j,@maxEig,1,{100});
10-73
10 Functions
Set the number of workers required for parallel execution using the NumWorkersRange job property.
[Link] = [5 10];
submit(j);
wait(j)
out = fetchOutputs(j)
delete(j);
Supporting Function
The maxEig function uses a parfor-loop to calculate the maximum eigenvalue of randomly
generated matrices of increasing sizes.
Input Arguments
cluster — Cluster
[Link] object
• "pool" — Run the specified task function with a parallel pool. The parallel pool executes the body
of parallel functions such as parfor and spmd that are inside the task function.
You can specify the number of workers to make into a parallel pool by setting the value of the
NumWorkersRange as either:
10-74
createCommunicatingJob
• A nonnegative integer.
• A 2-element vector of nonnegative integers, which is interpreted as a range. The size of the
resulting parallel pool is as large as possible in the range requested.
One worker from the parallel pool runs the task function. So, for a pool type job on a pool of N
workers, only N—1 workers execute the parfor and spmd code in the task function.
Output Arguments
j — Job
[Link] object
Tips
• To develop and test your code, you can run batch job on a local cluster on your client machine. If
you close your MATLAB session, any batch jobs using the local cluster also stop immediately.
• When you offload work to a remote cluster, you can close the MATLAB client session while the job
is processing and retrieve information from a batch job later or in a new client session.
• When you offload computations to workers, any files that the client needs for computations must
also be available on workers. By default, the client attempts to detect and attach these files. To
turn off automatic detection, set the AutoAttachFiles property to false. If the software cannot
find all the files, or if sending files from client to worker is slow, use one of these options.
• If the files are in a folder that is not accessible on the workers, set the AttachedFiles
property. The cluster copies each file you specify from the client to the workers.
• If the files are in a folder that is accessible on the workers, you can set the AdditionalPaths
property instead. Use the AdditionalPaths property to add paths to the MATLAB search
path for each worker and avoid copying files unnecessarily from the client to the workers.
Version History
Introduced in R2012a
10-75
10 Functions
Starting in R2024a, createCommunicatingJob pool type jobs support pools with up to 2000
workers. Before R2024a, createCommunicatingJob supports pools with up to 1000 workers.
R2024a: Disable spmd communication between workers for pool type jobs
When you create a pool type communicating job, the software creates a pool with spmd
communication enabled by default. To use a parallel pool without spmd communication enabled, use
the 'SpmdEnabled' name-value argument to disable spmd support.
See Also
createJob | createTask | findJob | parcluster | recreate | submit
Topics
“Choose Batch Processing Function” on page 5-2
10-76
createJob
createJob
Create independent job on cluster
Syntax
job = createJob(myCluster)
job = createJob(myCluster,Name,Value)
Description
job = createJob(myCluster) creates an independent job on the identified cluster and an
independent job object on the client.
The job's data is stored in the location specified by the cluster's JobStorageLocation property.
In you specify a Profile and other properties, the values you specify in these property name-value
pairs can override the values in the profile.
Examples
c = parcluster;
j = createJob(c);
for i = 1:10
createTask(j,@rand,1,{10});
end
submit(j);
Wait for the job to finish, and retrieve the job results.
wait(j);
out = fetchOutputs(j);
disp(out{3})
10-77
10 Functions
0.9730 0.1454 0.7662 0.9601 0.0836 0.9843 0.2656 0.8780 0.1748 0.2
0.7104 0.6426 0.9654 0.9145 0.6432 0.4296 0.4141 0.6507 0.7349 0.9
0.3614 0.3250 0.9843 0.8676 0.5964 0.1125 0.1687 0.2207 0.8327 0.7
0.2934 0.8229 0.9601 0.1388 0.8854 0.5494 0.1708 0.6235 0.0617 0.1
0.1558 0.8728 0.1856 0.2842 0.8472 0.5912 0.8205 0.3761 0.1292 0.8
0.3421 0.2005 0.9495 0.4687 0.8467 0.1968 0.7528 0.0899 0.8172 0.3
0.6071 0.9987 0.2639 0.0828 0.7554 0.7506 0.6331 0.0035 0.8602 0.4
0.5349 0.8446 0.1578 0.1702 0.6472 0.0087 0.8810 0.3619 0.6499 0.8
0.4118 0.9079 0.4784 0.5140 0.5163 0.5712 0.1639 0.7487 0.6486 0.7
0.1020 0.0982 0.2994 0.2809 0.4726 0.4986 0.3940 0.0096 0.3214 0.6
Create an independent job and attach files in addition to those specified in the default profile.
c = parcluster;
j = createJob(c,'AttachedFiles',...
{'myapp/folderA','myapp/folderB','myapp/file1.m'});
Input Arguments
myCluster — Cluster
[Link] object
Before R2021a, use commas to separate each name and value, and enclose Name in quotes.
Example: job = createJob(myCluster, 'AdditionalPaths',["/additional/path1","/
additional/path2"]) creates an independent job on the cluster represented by myClusterand
adds path1 and path2 folders to all the workers MATLAB search path.
Cluster profile with property values to apply to the job object, specified as the comma-separated pair
consisting of 'Profile' and the profile name as a character vector or string. If you do not specify a
10-78
createJob
profile, and the cluster has a value specified in its 'Profile' property, MATLAB automatically
applies the cluster's profile. For more details about defining and applying profiles, see “Discover
Clusters and Use Cluster Profiles” on page 7-2.
Example: createJob(myCluster,'Profile',"myProfileName")
Data Types: char | string
Paths to add to MATLAB search path of the workers that execute the job, specified as character
vector, string, string array, or cell array of character vectors.
If the client and workers have different paths to the same folder, you must specify the folder using the
path on the workers. For example, if the path to the folder is /shared/data on the client and /
organization/shared/data on the workers, specify "/organization/shared/data".
If you specify relative paths such as "../myFolder", MATLAB resolves the paths relative to the
current working directory on the workers.
Example: "AdditionalPaths",["/path/to/folder1","path/to/folder2"]
Data Types: char | string | cell
Files and folders to attach to the job object, specified as a character vector, string, string array, or cell
array of character vectors. This argument makes the identified files and folders available for the
workers executing the tasks in the job.
If you specify the Profile property, and the profile or the myCluster profile already has values for
the AttachedFiles property, MATLAB appends the files and folders you specify here to the existing
AttachedFiles values.
Example: "AttachedFiles", {'data_set.m','folder_for_workers'}
Data Types: char | string | cell
Note The properties listed here are only a subset. For a full list of valid properties, see the
[Link] object reference page.
Tips
• To develop and test your code, you can run batch job on a local cluster on your client machine. If
you close your MATLAB session, any batch jobs using the local cluster also stop immediately.
• When you offload work to a remote cluster, you can close the MATLAB client session while the job
is processing and retrieve information from a batch job later or in a new client session.
• When you offload computations to workers, any files that the client needs for computations must
also be available on workers. By default, the client attempts to detect and attach these files. To
turn off automatic detection, set the AutoAttachFiles property to false. If the software cannot
find all the files, or if sending files from client to worker is slow, use one of these options.
10-79
10 Functions
• If the files are in a folder that is not accessible on the workers, set the AttachedFiles
property. The cluster copies each file you specify from the client to the workers.
• If the files are in a folder that is accessible on the workers, you can set the AdditionalPaths
property instead. Use the AdditionalPaths property to add paths to the MATLAB search
path for each worker and avoid copying files unnecessarily from the client to the workers.
Version History
Introduced before R2006a
See Also
createCommunicatingJob | createTask | findJob | parcluster | recreate | submit
Topics
“Set Environment Variables on Workers” on page 7-12
10-80
createTask
createTask
Create new task in job
Syntax
t = createTask(j,fcn,N,{x1,...,xn})
t = createTask(j,fcn,N,{C1,...,Cm})
t = createTask( ___ ,Name=Value)
t = createTask( ___ ,Profile=profileName)
Description
t = createTask(j,fcn,N,{x1,...,xn}) creates a new task in job j and returns t, the
corresponding task object. This task evaluates the function fcn with the cell array of input arguments
{x1,...,xn} and returns N output arguments.
If you attempt to create one task with arrays of cells arrays as input, createTask creates a task for
each cell array. To create one task with arrays of cell arrays as input, see “Create Single Task with
Arrays of Cell Array as Inputs” on page 10-83.
If fcn is a cell array, each element of fcn specifies a function for each task and fcn must have m
elements. If N is a numeric array, each element specifies the number of output arguments for each
task.
If fcn is a cell array or N is a numeric array, their dimensions must match those of {C1,...,Cm}.
The output t is a vector with the same number of elements as {C1,...,Cm}.
Because a communicating job has only one task, this form of vectorized task creation is not
appropriate for these jobs.
t = createTask( ___ ,Name=Value) specifies task object properties using one or more name-
value arguments. For a list of supported properties, see [Link].
Examples
Create a cluster using the default profile and then create a job.
10-81
10 Functions
c = parcluster;
j = createJob(c);
t = createTask(j,@rand,1,{10,10});
submit(j);
Wait for the job to finish running, then get the output from the task evaluation using the
fetchOutputs function.
wait(j);
taskoutput = fetchOutputs(j);
disp(taskoutput{1});
0.1349 0.3414 0.0378 0.2873 0.6815 0.1700 0.6341 0.8666 0.1985 0.0
0.6744 0.6596 0.1527 0.1777 0.8329 0.3007 0.9087 0.9242 0.2509 0.7
0.9301 0.9604 0.0199 0.4932 0.7620 0.8125 0.9334 0.4732 0.5438 0.4
0.5332 0.2081 0.7638 0.8810 0.3301 0.8027 0.9230 0.5052 0.0748 0.7
0.1150 0.0206 0.2389 0.3993 0.8738 0.4026 0.4597 0.4667 0.9900 0.7
0.6540 0.0097 0.7247 0.3138 0.4917 0.9944 0.2229 0.7484 0.7052 0.4
0.2621 0.4432 0.3819 0.3073 0.6435 0.7122 0.0043 0.2366 0.4252 0.2
0.9625 0.6220 0.1527 0.6538 0.5951 0.5486 0.6156 0.1400 0.8675 0.6
0.8972 0.9800 0.4316 0.3740 0.0846 0.9692 0.2890 0.7388 0.8969 0.8
0.3187 0.4841 0.8672 0.2539 0.1876 0.6113 0.0459 0.9253 0.6454 0.9
Use one call to create three tasks for a job, each of which uses a different function. Provide a cell
array of three cell arrays defining the input arguments for each task.
c = parcluster;
j = createJob(c);
t = createTask(j,{@rand,@magic,@ones},1,{{3,3} {3} {3,3}});
t =
10-82
createTask
whos t
t 3x1 24 [Link]
Alternatively, use a for-loop to create 150 tasks for job j. Display the properties of tasks.
Create a task that captures the worker diary, regardless of the setting in the cluster profile.
c = parcluster;
j = createJob(c);
t1 = createTask(j,@rand,1,{10,10},CaptureDiary=true);
Create a task with property values corresponding to the myMJS_Cluster cluster profile.
t2 = createTask(j,@magic,1,{10},Profile="myMJS_Cluster");
c = parcluster;
job = createJob(c);
task = createTask(job,@strjoin,1,{{{'1','1','2'},{'+','='}}});
[Link]{:}
submit(job);
wait(job);
10-83
10 Functions
outputs = fetchOutputs(job);
disp(outputs{1});
1+1=2
Input Arguments
j — Job in which software creates task
[Link] object
Job in which the software creates the task, specified as a [Link] object.
Function that the task evaluates, specified as function handle, a character vector or string array that
specifies a function name, or a cell array of function handles. Specify multiple task functions as a cell
array of function handles. The cell array must have the same number of elements as the
{C1,...,Cm} input.
Example: @zeros
Data Types: char | string | cell | function_handle
Number of outputs from fcn, specified as a nonnegative integer or an array of nonnegative integers.
Specify multiple numbers of outputs as an array of nonnegative integers. The array must have the
same number of elements as {C1,...,Cm} input.
Example: createTask(j,@zeros,1,{x,y}); specifies a single output is expected.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Input arguments to fcn, specified as a cell array. The software passes each element in the cell array
to fcn as a separate input argument.
Example: {x,y}
Data Types: cell
Input argument to each task, specified as a cell array of cell arrays. The software creates a task for
each cell array.
Example: {{x1,y1},{x2,y2},{x3,y3}}
Data Types: cell
10-84
createTask
Output Arguments
t — Task
[Link] object
Version History
Introduced before R2006a
See Also
createCommunicatingJob | createJob | findTask | recreate
10-85
10 Functions
delete
Namespace: parallel
Syntax
delete(obj)
Description
delete(obj) removes the job or task object, obj, from the local MATLAB session, and removes it
from the cluster's JobStorageLocation. When the object is deleted, references to it become
invalid. Invalid objects should be removed from the workspace with the clear command. If multiple
references to an object exist in the workspace, deleting one reference to that object invalidates the
remaining references to it. These remaining references should be cleared from the workspace with
the clear command.
When you delete a job object, this also deletes all the task objects contained in that job. Any
references to those task objects will also be invalid, and you should clear them from the workspace.
If obj is an array of objects and one of the objects cannot be deleted, the other objects in the array
are deleted and a warning is returned.
Because its data is lost when you delete an object, delete should be used only after you have
retrieved all required output data from the effected object.
Examples
Delete Job
Create a job object using the default profile. Then delete the job.
myCluster = parcluster;
j = createJob(myCluster,'Name','myjob');
t = createTask(j,@rand,1,{10});
delete(j);
clear j t
myCluster = parcluster('myProfile');
delete([Link])
10-86
delete
Use the syntax with multiple outputs of findJob to obtain the jobs by state. In this example, delete
the pending jobs.
myCluster = parcluster;
[pending queued running completed] = findJob(myCluster);
delete(pending);
Alternatively, use findJob to retrieve the jobs that match a specific state. In this example, find the
jobs in state failed and delete them.
myCluster = parcluster;
failed = findJob(myCluster,'State','failed');
delete(failed);
Input Arguments
obj — Job or task object to delete
[Link] object | [Link] object
Job or task object to delete, specified as a [Link] or [Link] object. You can create
jobs and tasks with createJob and createTask.
Data Types: [Link] | [Link]
Version History
Introduced in R2012a
See Also
batch | createJob | createTask | findJob | findTask | wait
10-87
10 Functions
delete
Namespace: parallel
Syntax
delete(poolobj)
Description
delete(poolobj) shuts down the parallel pool associated with the object poolobj, and destroys
the communicating job that comprises the pool. Subsequent parallel language features will
automatically start a new parallel pool, unless your parallel settings disable this behavior.
References to the deleted pool object become invalid. Invalid objects should be removed from the
workspace with the clear command. If multiple references to an object exist in the workspace,
deleting one reference to that object invalidates the remaining references to it. These remaining
references should be cleared from the workspace with the clear command.
Examples
poolobj = gcp('nocreate');
delete(poolobj);
Input Arguments
poolobj — Parallel pool
[Link]
Parallel pool to shut down, specified as a [Link] object. You can get the current parallel
pool with the gcp function.
Example: delete(gcp('nocreate'))
Data Types: [Link]
Version History
Introduced in R2013b
10-88
delete
See Also
gcp | parpool
10-89
10 Functions
demote
Demote job in MATLAB Job Scheduler cluster queue
Syntax
demote(job)
demote(c,job)
Description
demote(job) demotes the job object, job, in a MATLAB Job Scheduler cluster queue.
If job is not the last job in the queue, demote exchanges the position of job and the job that follows
it in the queue.
demote(c,job) demotes the job object, job, that is queued in the MATLAB Job Scheduler cluster c.
If job is not the last job in the queue, demote exchanges the position of job and the job that follows
it in the queue.
Examples
Create and submit multiple jobs to the cluster identified by the default cluster profile, assuming that
the default cluster profile uses a MATLAB Job Scheduler.
c = parcluster;
j1 = createJob(c,'Name',"Job A");
t1 = createTask(j1,@rand,1,{10,10});
j2 = createJob(c,'Name',"Job B");
t2 = createTask(j2,{@rand,@magic,@ones},1,{{3,3} {3} {3,3}});
j3 = createJob(c,'Name',"Job C");
t3 = createTask(j3,@rand,1,{10,10},CaptureDiary=true);
submit(j1);submit(j2);submit(j3);
[pjobs,qjobs,rjobs,fjobs] = findJob(c);
get(qjobs,'Name')
10-90
demote
'Job A'
'Job B'
'Job C'
demote(j1)
[pjobs,qjobs,rjobs,fjobs] = findJob(c);
get(qjobs,'Name')
'Job B'
'Job A'
'Job C'
resume(c)
Input Arguments
job — Job to demote
[Link] object
Job to demote in the MATLAB Job Scheduler cluster queue, specified as a [Link] object.
Example: job = createJob(c)
c — Cluster
[Link] object
Tips
• After a call to demote or promote, there is no change in the order of job objects contained in the
Jobs property of the MATLAB Job Scheduler cluster object. To see the scheduled order of
execution for jobs in the queue, use the findJob function in the form [pending queued
running finished] = findJob(c).
Version History
Introduced before R2006a
See Also
createJob | findJob | promote | submit
10-91
10 Functions
diary
Namespace: parallel
Syntax
diary(job)
diary(job,filename)
Description
diary(job) displays the Command Window output from the batch job in the MATLAB Command
Window. The Command Window output is captured only if the batch command included the
'CaptureDiary' argument with a value of true.
diary(job,filename) appends the Command Window output from the batch job to the specified
file.
The captured Command Window output includes only the output generated by execution of the task
function. This function does not capture output from code that runs asynchronously from the task.
Input Arguments
job — Batch job
[Link] object
Name of file to append with Command Window output text from batch job, specified as a string.
Version History
Introduced in R2008a
See Also
diary | batch | load
10-92
[Link]
[Link]
Create distributed cell array
Syntax
D = [Link](n)
D = [Link](m, n, p, ...)
D = [Link]([m, n, p, ...])
Description
D = [Link](n) creates an n-by-n distributed array of underlying class cell.
Examples
Create a distributed 1000-by-1000 cell array:
D = [Link](1000)
Version History
Introduced in R2009b
See Also
cell | [Link]
10-93
10 Functions
[Link]
Allocate space for sparse distributed matrix
Syntax
SD = [Link](M,N,nzmax)
SD = [Link]( ___ ,typename)
Description
SD = [Link](M,N,nzmax) creates an M-by-N all-zero sparse distributed matrix
with room to hold nzmax nonzeros.
SD = [Link]( ___ ,typename) also specifies the data type (class) of the sparse
distributed matrix. The typename input can be either "single", "double", or "logical".
Examples
Allocate space for a 1000-by-1000 sparse distributed matrix with room for up to 2000 nonzero
elements, then define several elements:
N = 1000;
SD = [Link](N,N,2*N);
for ii=1:N-1
SD(ii,ii:ii+1) = [ii ii];
end
Use spalloc to initialize a 10-by-10 all-zero sparse distributed single-precision matrix with room for
up to 20 nonzero elements. Define several elements in the matrix.
SD = [Link](10,10,20,"single");
SD(1:3,1:3) = magic(3);
Version History
Introduced in R2009b
You can specify the output data type by specifying the typename argument as "double",
"single", or logical.
See Also
spalloc | [Link] | sparse
10-94
[Link]
[Link]
Create distributed sparse identity matrix
Syntax
DS = [Link](n)
DS = [Link](m,n)
DS = [Link]([m,n])
DS = [Link]( ___ ,typename)
Description
DS = [Link](n) creates an n-by-n sparse distributed identity matrix of underlying
class double.
DS = [Link]( ___ ,typename) also specifies the data type (class) for any of the
previous syntaxes. The typename input can be either "single" or "double".
Examples
Create a distributed 1000-by-1000 sparse identity matrix:
N = 1000;
DS = [Link](N);
DS = [Link](400,800,"single");
Version History
Introduced in R2009b
You can specify the output data type by specifying the typename argument as "double" or
"single".
See Also
speye | [Link] | eye
10-95
10 Functions
[Link]
Create distributed sparse array of uniformly distributed pseudo-random values
Syntax
DS = [Link](m,n,density)
DS = [Link]( ___ ,typename)
Description
DS = [Link](m,n,density) creates an m-by-n sparse distributed array with
approximately density*m*n uniformly distributed nonzero double entries.
DS = [Link]( ___ ,typename) also specifies the data type (class) of the sparse
distributed array. The typename input can be either "single" or "double".
Examples
Create a 1000-by-1000 sparse distributed double array DS with approximately 1000 nonzeros.
DS = [Link](1000,1000,0.001);
Create a random 500-by-1000 sparse distributed single-precision array with density 0.1.
DS = [Link](500,1000,0.1,"single");
Tips
When you use sprand on the workers in the parallel pool, or in an independent or communicating
job, each worker sets its random generator seed to a value that depends only on the spmdIndex or
task ID. Therefore, the array on each worker is unique for that job. However, if you repeat the job,
you get the same random data.
Version History
Introduced in R2009b
You can specify the output data type by specifying the typename argument as "double" or
"single".
See Also
sprand | [Link] | rand | randn | sparse | [Link] |
[Link]
10-96
[Link]
[Link]
Create distributed sparse array of normally distributed pseudo-random values
Syntax
DS = [Link](m,n,density)
DS = [Link]( ___ ,typename)
Description
DS = [Link](m,n,density) creates an m-by-n sparse distributed array with
approximately density*m*n normally distributed nonzero double entries.
DS = [Link]( ___ ,typename) also specifies the data type (class) of the sparse
distributed array. The typename input can be either "single" or "double".
Examples
Create a 1000-by-1000 sparse distributed double array DS with approximately 1000 nonzeros.
DS = [Link](1000,1000,0.001);
Create a random 500-by-1000 sparse distributed single-precision matrix with density 0.1.
DS = [Link](500,1000,0.1,"single");
Tips
When you use sprandn on the workers in the parallel pool, or in an independent or communicating
job, each worker sets its random generator seed to a value that depends only on the spmdIndex or
task ID. Therefore, the array on each worker is unique for that job. However, if you repeat the job,
you get the same random data.
Version History
Introduced in R2009b
You can specify the output data type by specifying the typename argument as "double" or
"single".
See Also
sprandn | [Link] | rand | randn | sparse | [Link] |
[Link]
10-97
10 Functions
dload
Load distributed arrays and Composite objects
Syntax
dload filename
dload filename variables
dload -scatter ___
dload(filename)
[out1,...,outN] = dload(filename,variables)
Description
dload filename loads all variables from the file with the name filename. If you do not specify an
extension, the function assumes that the extension is .mat. The function loads the contents of
distributed arrays and Composite objects onto parallel pool workers. The function loads other data
types directly into the workspace of the MATLAB client.
• When you load distributed arrays, the function distributes the data over the current parallel pool
workers using the default distribution scheme. You do not need to have the same size pool open
when you load variables using this function.
• When you load Composite objects, the function sends the data to the current parallel pool
workers. If the Composite is too large to fit on the current parallel pool, the software does not
load the data. If the Composite is smaller than the current parallel pool, the software returns a
warning.
If a parallel pool is not open, by default the dload function starts a parallel pool of workers using the
default profile.
dload filename variables loads the specified variables from the file with the name filename.
The function does not support wildcards, nor the -regexp option. If the file does not contain one or
more of the specified variables, the software returns a warning.
dload -scatter ___ attempts to distribute nondistributed data. If dload cannot distribute the
data, it returns a warning.
dload("[Link]")
dload [Link]
10-98
dload
Examples
Load all distributed arrays from the fname MAT file into the MATLAB workspace.
Load fname, and then list the variables in the workspace again. By default, the dload function starts
a parallel pool of workers to distribute the variables.
dload [Link]
whos
You can also use the function syntax to load the variables. Clear the variables and call the dload
function.
clear X Y Z
dload("[Link]")
Create Composite objects, save them to a file, and load the data back into a different sized parallel
pool.
Create a parallel pool with four workers and use spmd statements to create Composite objects on
the client. Save the Composite objects to the mydata MAT file then clear the workspace.
p = parpool(4);
10-99
10 Functions
spmd
P = magic(1000);
Q = randn(2000);
end
dsave mydata P Q
clear P Q
delete(p);
Load the Composite objects P and Q from the MAT file. The new parallel pool is larger than the pool
you use to create the Composite objects, so the software returns a warning.
[P,Q] = dload("[Link]","P","Q");
Warning: The Composite "P" was created with a pool of size 4, and is being loaded into a Composit
Warning: The Composite "Q" was created with a pool of size 4, and is being loaded into a Composit
whos
whos("-file","student_scores.mat")
Load and distribute the studentScores table from the student_scores MAT file.
scores = dload("-scatter","student_scores.mat");
spmd
scores
end
10-100
dload
Worker 1:
This worker stores scores(1:9,:).
LocalPart: [9x26 table]
Codistributor: [1x1 codistributor1d]
Worker 2:
This worker stores scores(10:18,:).
LocalPart: [9x26 table]
Codistributor: [1x1 codistributor1d]
Worker 3:
This worker stores scores(19:26,:).
LocalPart: [8x26 table]
Codistributor: [1x1 codistributor1d]
Worker 4:
This worker stores scores(27:34,:).
LocalPart: [8x26 table]
Codistributor: [1x1 codistributor1d]
Input Arguments
filename — Name of file to load
"[Link]" (default) | string scalar | character vector
Name of the file to load, specified as a string scalar or character vector. If you do not specify
filename, the dload function searches for a MAT file named matlab. If the function cannot find the
file, it returns an error.
If you do not specify an extension for filename, dload searches for a file with the name filename
and the .mat extension.
Depending on the location of your file, filename has one of these forms.
• If the file is in the current folder or a folder on the MATLAB path, specify only the name of the file
in filename.
• If the file is not in the current folder or in a folder on the MATLAB path, specify the full or relative
path in filename.
Names of variables to load, specified as one or more string scalars or character vectors.
The dload function does not support wildcards, nor the -regexp option. If the function cannot find
one or more of the specified variables, it returns a warning.
Data Types: char | string
10-101
10 Functions
Tips
• The dload function loads a distributed array or Composite object on the workers of the existing
parallel pool. If no pool exists, the dload function starts a new parallel pool, unless automatically
starting pools is disabled in your parallel settings. If no parallel pool exists and dload cannot start
one, dload loads distributed objects but cannot load Composite objects.
Version History
Introduced in R2010a
See Also
load | Composite | distributed | dsave | parpool
10-102
dsave
dsave
Save workspace distributed arrays and Composite objects
Syntax
dsave filename
dsave filename variables
dsave(filename)
Description
dsave filename saves all variables in the current workspace, including distributed arrays and
Composite objects, to the file with the name filename. If you do not specify an extension for
filename, the function assumes the extension is .mat.
dsave filename variables saves the specified variables to the file with the name filename.
The function does not support wildcards, nor the -regexp option.
dsave [Link]
Examples
Save all variables in the workspace, including distributed arrays and Composite objects, to a MAT
file with the name fname.
dsave [Link]
If filename is a variable, you can use the function form of the syntax.
10-103
10 Functions
filename = "[Link]";
dsave(filename)
Create and save several variables to a MAT file with the name mydatafile.
D = rand(1000,"distributed");
C = Composite;
C{1} = magic(20);
X = rand(40);
Save all three variables to a file with the name mydatafile and store the file in the C:\myFolder
\myFile folder.
dsave C:\myData\mydatafile D C X
Input Arguments
filename — Name of file to save
"[Link]" (default) | string scalar | character vector
Name of the file to save, specified as a string scalar or character vector. If you do not specify
filename, the dsave function saves workspace variables to a MAT file named matlab.
If you do not specify an extension for filename, the dsave function creates a file with the name
filename and the .mat extension.
10-104
dsave
If filename does not include a full path, the dsave function saves the file to the current folder. To
save the file to a different folder, specify the full or relative path to the folder in filename. You must
have permission to write to the file.
Example: "myFile.mat2 specifies the name of the file.
Example: C:\myFolder\[Link] specifies the full path to the folder.
Data Types: char | string
Names of variables to save, specified as one or more string scalars or character vectors.
The dsave function does not support wildcards, nor the -regexp option.
Data Types: char | string
Limitations
• dsave does not support saving sparse distributed arrays.
Version History
Introduced in R2010a
See Also
save | Composite | distributed | dload | parpool
10-105
10 Functions
exist
Check whether Composite is defined on workers
Syntax
h = exist(C,labidx)
h = exist(C)
Description
h = exist(C,labidx) returns true if the entry in Composite C has a defined value on the worker
with spmdIndex labidx, false otherwise. In the general case where labidx is an array, the output
h is an array of the same size as labidx, and h(i) indicates whether the Composite entry
labidx(i) has a defined value.
If exist(C,labidx) returns true, C(labidx) does not throw an error, provided that the values of
C on those workers are serializable. The function throws an error if any labidx is invalid.
Examples
Define a variable on a random number of workers. Check on which workers the Composite entries are
defined, and get all those values:
spmd
if rand() > 0.5
c = spmdIndex;
end
end
ind = exist(c);
cvals = c(ind);
Version History
Introduced in R2008b
See Also
Composite
10-106
existsOnGPU
existsOnGPU
Namespace: [Link]
Syntax
TF = existsOnGPU(DATA)
Description
TF = existsOnGPU(DATA) returns a logical value indicating whether the gpuArray or CUDAKernel
object represented by DATA is still present on the GPU and available from your MATLAB session. The
result is false if DATA is no longer valid and cannot be used. Such arrays and kernels are invalidated
when the GPU device has been reset with any of the following:
Examples
Create a gpuArray on the selected GPU device, then reset the device. Query array's existence and
content before and after resetting.
g = gpuDevice(1);
M = gpuArray(magic(4));
M_exists = existsOnGPU(M)
M % Display gpuArray
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
reset(g);
M_exists = existsOnGPU(M)
Clear variable.
10-107
10 Functions
clear M
Version History
Introduced in R2012a
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
gpuDevice | gpuArray | CUDAKernel | reset
10-108
eye
eye
Create codistributed identity matrix
Syntax
cI = eye(n,codist)
cI = eye(n,m,codist)
cI = eye(sz,codist)
cI = eye( ___ ,datatype,codist)
Description
cI = eye(n,codist) creates an n-by-n codistributed identity matrix and uses codist to specify
the distribution of the array values across the workers.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
cI = eye(n,m,codist) creates an n-by-m codistributed identity matrix with ones on the main
diagonal and zeros elsewhere. For example, eye(2,3,"codistributed") creates a 2-by-3
codistributed array.
cI = eye(sz,codist) creates a codistributed identity matrix where the size vector sz defines the
size of cI. For example, eye([2 3],"codistributed") also creates a 2-by-3 codistributed identity
matrix.
cI = eye( ___ ,datatype,codist) creates a codistributed identity matrix with the underlying
data type datatype. For example, eye(1,"int8","codistributed") creates a codistributed 8-
bit scalar integer 1. You can use this syntax with any of the size arguments in the previous syntaxes.
You must specify codist after the array size and data type arguments.
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
10-109
10 Functions
You must specify "noCommunication" after the size, data type and codist arguments.
cI = eye( ___ ,like=p) uses the array p to create a codistributed identity matrix. You can also
specify "noCommunication" as part of the function call.
The returned array cI has the same underlying type, sparsity, and complexity (real or complex) as p.
Examples
Create a 1000-by-1000 codistributed identity matrix, distributed using the default distribution
scheme.
spmd(4)
C = eye(1000,"codistributed");
end
Create Codistributed Array with Nondefault Numeric Data Type Distributed by Columns
Create a 1000-by-1000 codistributed uint16 identity matrix, distributed by its columns. Use a
codistributor1d object to define the distribution scheme.
spmd(4)
codist = codistributor1d(2,100*[1:spmdSize]);
C = eye(1000,1000,"uint16",codist)
end
Worker 1:
This worker stores C(:,1:100).
LocalPart: [1000x100 uint16]
Codistributor: [1x1 codistributor1d]
Worker 2:
This worker stores C(:,101:300).
LocalPart: [1000x200 uint16]
Codistributor: [1x1 codistributor1d]
Worker 3:
This worker stores C(:,301:600).
LocalPart: [1000x300 uint16]
Codistributor: [1x1 codistributor1d]
Worker 4:
This worker stores C(:,601:1000).
LocalPart: [1000x400 uint16]
Codistributor: [1x1 codistributor1d]
You can also get the same codistributed array specifying the size vector.
10-110
eye
spmd(4)
C = eye([1000 1000],"uint16",codist);
end
Codistributed Identity Matrix with Size and Numeric Data Type Defined by Existing Array
First, create a codistributed array. Specify the underlying data type as single and use the default
distribution scheme.
spmd(4)
p = eye(1000,"single","codistributed");
end
Create a new codistributed array that is the same size and data type as p. Use the 2-D block-cyclic
codistributor2dbc function to define the distribution scheme.
spmd
C = eye(size(p),codistributor2dbc,"noCommunication",like=p);
end
Input Arguments
n — Size of first dimension
integer
• If n is the only integer input argument, then cI is a square n-by-n codistributed identity matrix.
• If n is 0, then cI is an empty matrix.
• If n is negative, then the function treats it as 0.
Size of the second dimension of the codistributed identity matrix, specified as an integer.
10-111
10 Functions
Data Types: double | single | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
Underlying data type of the returned array, specified as one of these options:
• "double"
• "single"
• "logical"
• "int8"
• "uint8"
• "int16"
• "uint16"
• "int32"
• "uint32"
• "int64"
• "uint64"
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p.
Version History
Introduced in R2006b
10-112
eye
See Also
[Link] | [Link] | eye | false (codistributed) | Inf
(codistributed) | NaN (codistributed) | ones (codistributed) | true
(codistributed) | zeros (codistributed)
10-113
10 Functions
false
Create codistributed array of logical 0 (false)
Syntax
cF = false(n,codist)
cF = false(sz,codist)
cF = false(sz1,...,szN,codist)
Description
cF = false(n,codist) creates an n-by-n codistributed matrix of logical zeros and uses codist to
specify the distribution of the array values across the workers.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
cF = false(sz,codist) creates a codistributed array of logical zeros where the size vector sz
defines the size of cF. For example, false([2 3],"codistributed") creates a 2-by-3
codistributed array of logical zeros.
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
cF = false( ___ ,like=p) uses the array p to return a codistributed array of logical zeros. You
can also specify "noCommunication" as part of the function call.
10-114
false
Examples
Create a 1000-by-1000 codistributed matrix of logical zeros, distributed by its second dimension
(columns).
spmd(4)
C = false(1000,"codistributed");
end
Input Arguments
n — Size of square matrix
integer
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
10-115
10 Functions
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p.
Tips
• false(n,"codistributed") is much faster and more memory efficient than
logical(zeros(n,"codistributed")).
Version History
Introduced in R2006b
See Also
false | eye (codistributed) | Inf (codistributed) | NaN (codistributed) | ones
(codistributed) | true (codistributed) | false (codistributed) | zeros
(codistributed)
10-116
fetchOutputs
fetchOutputs
Namespace: parallel
Syntax
data = fetchOutputs(j)
Description
data = fetchOutputs(j) retrieves the output arguments contained in the tasks of a finished job.
When you retrieve outputs from a job you create using createJob or createCommunicatingJob,
each row of the m-by-n cell array data contains the output arguments for each of the m tasks in the
job. Each of the rows in data has n elements, where n is the greatest number of output arguments
from any one task in the job. The n elements of a row are arrays containing the output arguments
from that task. If a task has less than n output arguments, the excess elements in the row for that
task are empty.
When you retrieve outputs from a job you create using batch:
• If you create the batch job using the fcn syntax and specify N outputs, data is a 1-by-N cell array.
• If you create the batch job using the script or expression syntaxes, data is a 1-by-1 cell array
containing a structure scalar. If you specify the Pool argument when you create the batch job, the
structure scalar contains the workspace of the worker that acts as the client. Otherwise, the
structure scalar contains the workspace of the worker that runs the job.
The output data for a job is stored in the location given by the JobStorageLocation property of the
cluster that the job runs on. When you run fetchOutputs, the output data is not removed from the
JobStorageLocation. To remove the output data, use the delete function to remove individual
tasks or entire jobs.
Tip To see if any of the tasks on the job j failed after encountering an error, check if
[Link] is empty. If the returned array is empty, none of the tasks on the job j encountered
any errors.
If some tasks completed successfully, you can use the OutputArguments property of a task to access
the output arguments of that task directly.
Examples
10-117
10 Functions
Use batch to create a job using the default cluster profile. In that job, run magic(3) on a worker
and store one output.
j = batch(@magic,1,{3});
Wait for the job to complete. Then, use fetchOutputs to retrieve output data from the job.
wait(j)
data = fetchOutputs(j);
The data retrieved is a cell array containing one output from magic(3). Index into the cell array to
get that output.
data{1}
ans =
8 1 6
3 5 7
4 9 2
Input Arguments
j — Job
[Link] object
Version History
Introduced in R2012a
See Also
fetchOutputs (Future) | batch | createJob | createCommunicatingJob
10-118
feval
feval
Evaluate kernel on GPU
Syntax
feval(kern,x1,...,xn)
[y1,...,ym] = feval(kern,x1,...,xn)
Description
feval(kern,x1,...,xn) evaluates the CUDA kernel kern with the arguments x1,...,xn. The
number of input arguments, n, must be equal to the value of the NumRHSArguments property of
kern, and their types must match the description in the ArgumentTypes property of kern. The input
data can be regular MATLAB data, GPU arrays, or both.
Examples
The three input arguments, x1, x2, and x3, correspond to the three arguments that are passed into
the CUDA function. The output arguments, y1 and y2, are gpuArray objects, and correspond to the
values of pInOut1 and pInOut2 after the CUDA kernel has executed.
Input Arguments
kern — CUDA kernel
[Link] object
10-119
10 Functions
Arguments to evaluate the kernel with, specified as MATLAB data, a gpuArray object, or a mixture of
the two. The number of these arguments must be equal to the value of the NumRHSArguments
property of the kern argument, and their types must match the description in the ArgumentTypes
property of the kern argument.
Output Arguments
y1,...,ym — Output from evaluation of kernel
gpuArray object
Output from the evaluation of the CUDA kernel, returned as a gpuArray object. The number of these
arguments must not exceed the value of the MaxNumLHSArguments property of the kern input
argument.
Version History
Introduced in R2010b
See Also
CUDAKernel | gpuArray
10-120
findJob
findJob
Find job objects in cluster
Syntax
objArray = findJob(cluster)
objArray = findJob(cluster,propertyName=Value)
[pending,queued,running,completed] = findJob( ___ )
Description
objArray = findJob(cluster) returns an array of all job objects in the cluster cluster. The
jobs in the array are in order of their ID property, indicating the sequence in which they were
created.
The object property value must match the specified value exactly. For example, if the Name property
value of a job is MyJob, then findJob does not find that object when it searches for a job with the
Name property value of myjob.
Examples
Create a cluster using the default profile and use batch to submit a random number of jobs to the
cluster.
myCluster = parcluster;
numJobs = randi(50);
for idx = 1:numJobs
job = batch(myCluster,@magic,1,{idx});
end
objArray = findJob(myCluster);
whos objArray
10-121
10 Functions
[pending,queued,running,completed] = findJob(myCluster);
[Link]
ans = 120
ans = 121
ans = 122
ans = 123
Create a cluster using the default profile and use createJob to submit jobs to the cluster.
myCluster = parcluster;
job1 = createJob(myCluster,Tag="testing");
job2 = createJob(myCluster,Name="MonteCarlo",Tag="testing");
job3 = createJob(myCluster,Name="MonteCarlo2",Tag="testing");
objArray = findJob(myCluster,Tag="testing");
[Link]
ans =
'Job23'
ans =
'MonteCarlo'
ans =
'MonteCarlo2'
Finally, narrow down the list of jobs with a Tag property value of testing by adding another search
criterion in the form of the Name property value MonteCarlo.
objArray = findJob(myCluster,Name="MonteCarlo",Tag="testing");
[Link]
ans =
'MonteCarlo'
Input Arguments
cluster — Cluster in which to search for job
[Link] object
Cluster in which to search for the job, specified as a [Link] object that represents
cluster computing resources. To create a cluster object, use the parcluster function.
10-122
findJob
Job object property name and value to find, specified as a [Link] property name-value
argument. If you specify more than one property name-value argument, findJob returns entries that
meet all of the search criteria. For a full list of job object properties, see [Link].
Example: findJob(cluster,Username="jsmith") finds job objects that have the Username
property value of jsmith.
Output Arguments
objArray — Jobs in cluster that meet search criteria
array of [Link] objects
Jobs in the cluster that meet the search criteria, returned as an array of [Link] objects.
Jobs in a completed or failed state on the cluster, returned as an array of [Link] objects.
Version History
Introduced before R2006a
See Also
parcluster | [Link]
10-123
10 Functions
findTask
Find task in job
Syntax
tasks = findTask(j)
tasks = findTask(j,taskFcn)
[pending,running,completed] = findTask(j)
tasks = findTask(j,propertyName=Value)
Description
tasks = findTask(j) returns a 1-by-N array of task objects in the job j. The tasks in the array are
in order of their ID property, indicating the sequence in which they were created.
tasks = findTask(j,taskFcn) returns an array of task objects in the job j, filtered using the
taskFcn property. taskFcn is a function handle that accepts the [Link] property as an input
argument, and returns a logical array that indicates the tasks to return.
[pending,running,completed] = findTask(j) sorts all the tasks stored in the job j by state.
Within the pending,running,completed array, the software returns the tasks in order of creation.
The object property value must match the specified value exactly. For example, if the Name property
value of a task is MyTask, then findTask does not find that object when it searches for a task with
the Name property value of mytask.
Examples
Input Arguments
j — Job in which software finds task
[Link] object
10-124
findTask
Job in which the software finds the task, specified as a [Link] object.
Function that findTask uses to filter the tasks from the job j, specified as a function handle.
Task object property name and value to find, specified as a [Link] property name-value
argument. If you specify more than one property name-value argument, findJob returns entries that
meet all of the search criteria. For a full list of task object properties, see [Link].
Example: findTask(job,Name="jsmith") finds task objects that have the Name property value of
jsmith.
Output Arguments
tasks — Tasks in job that meet search criteria
array of [Link] objects
Tasks in the job that meet the search criteria, returned as an array of [Link] objects.
Tasks in a completed or failed state on the job, returned as an array of [Link] objects.
Tips
If the job j is contained in a remote service, findTask results in a call to the remote service. This
could result in findTask taking a long time to complete, depending on the number of tasks retrieved
and the network speed. Also, if the remote service is no longer available, the software throws an
error.
Version History
Introduced before R2006a
See Also
createJob | createTask | findJob
10-125
10 Functions
for (drange)
for-loop over distributed range
Syntax
for loopVar = drange(range); statements; end;
Description
for loopVar = drange(range); statements; end; executes for-loop iterations in parallel
over a distributed range.
MATLAB partitions the range specified by range across the workers in the parallel pool, using
contiguous segments of approximately equal length. MATLAB then executes the loop body commands
in statements in a for-loop over the specified range of loopVar on each worker.
Each iteration must be independent of the other iterations, such that the iterations can be performed
in any order. No communication with other workers is allowed within the loop body.
Each worker can access local portions of codistributed arrays, but cannot access portions of
codistributed arrays that are stored on other workers. You can use loopVar to index the local part of
a codistributed array under the following conditions:
You can use the break statement to terminate the loop execution.
Examples
This example shows how to find the rank of magic squares. Access only the local portion of a
codistributed array.
spmd
r = zeros(1, 40, codistributor());
for n = drange(1:40)
r(n) = rank(magic(n));
end
end
r = gather(r);
10-126
for (drange)
spmd
m = 10000;
for p = drange(1:spmdSize)
z = rand(m,1) + i*rand(m,1);
c = sum(abs(z) < 1);
end
k = spmdPlus(c)
p = 4*k/(m*spmdSize);
end
p{1}
ans = 3.1501
This example shows how to attempt to compute Fibonacci numbers. This example does not work,
because the loop bodies are dependent. The following code produces an error:
spmd
f = zeros(1, 50, codistributor());
f(1) = 1;
f(2) = 2;
for n = drange(3:50)
f(n) = f(n-1) + f(n-2)
end
end
Caused by:
Error using codistributed/subsref (line 40)
Error using codistributed/subsref (line 40)
Inside a FOR-DRANGE loop, a subscript can only access the local
portion of a codistributed array.
Input Arguments
loopVar — Loop variable name
text
Loop body, specified as text. The series of MATLAB commands to execute in the for-loop.
statements must not include functions that perform communication, including the following
functions:
10-127
10 Functions
• codistributed
• codistributor
• gather
• spmdCat
• spmdReduce
• spmdPlus
• redistribute
Version History
Introduced in R2007b
See Also
for | spmdSize | parfor
10-128
gather
gather
Transfer distributed array, Composite object, or gpuArray object to local workspace
Syntax
X = gather(A)
[X1,X2,...,Xn] = gather(A1,A2,...,An)
X = gather(Cd,destination)
[X1,X2,...,Xn] = gather(Cd1,Cd2,...,Cdn,destination)
X = gather(Cp)
[X1,X2,...,Xn] = gather(Cp1,Cp2,...,Cpn)
Description
X = gather(A) can operate on the following array data:
• On a gpuArray: transfers the elements of A from the GPU to the local workspace and assigns
them to X.
• On a distributed array, outside an spmd statement: gathers together the elements of A from the
multiple workers to the local workspace and assigns them to X.
• On a codistributed array, inside an spmd statement or communicating job: gathers together the
elements of A and replicates them into X on every worker.
You can call gather on other data types, such as tall arrays (See gather (tall)). If the data type
does not support gathering, then gather has no effect.
Gathering GPU arrays or distributed arrays can be costly and is generally not necessary unless you
need to use your result with functions that do not support these types of arrays. For more information
on function support, see “Run MATLAB Functions on a GPU” on page 6-3 or “Run MATLAB Functions
with Distributed Arrays” on page 4-5.
X = gather(gpuArray(X)), X = gather(distributed(X)), or X =
gather(codistributed(X)) return the original array X.
10-129
10 Functions
X = gather(Cp) gathers all the elements of Composite array Cp from the multiple workers to the
local workspace and assigns them to cell array [Link] number of cells in X is dependent on number of
workers referenced by Cp.
Examples
Gather gpuArrays
Gather all of the elements from a distributed array D onto the client.
n = 10;
parpool('Processes',4);
D = distributed(magic(n)); % Distribute array to workers
M = gather(D) % Return array to client
Distribute a magic square across your workers, then gather the whole matrix onto every worker and
then onto the client. This code results in the equivalent of M = magic(n) on all workers and the
client.
n = 10;
parpool('Processes',4);
spmd
Cd = codistributed(magic(n));
M = gather(Cd); % Gather all elements to all workers
end
S = gather(Cd) % Gather elements to client
Gather all of the elements of Cd onto worker 1, for operations that cannot be performed across
distributed arrays.
n = 10;
spmd
10-130
gather
Cd = codistributed(magic(n));
out = gather(Cd,1);
if spmdIndex == 1
% Characteristic sum for this magic square:
characteristicSum = sum(1:n^2)/n;
% Ensure that the diagonal sums are equal to the
% characteristic sum:
areDiagonalsEqual = isequal ...
(trace(out),trace(flipud(out)),characteristicSum)
end
end
Worker 1:
areDiagonalsEqual =
logical
Gather all of the elements of the composite array Cp stored on parallel workers onto the client.
Use an spmd statement to create a magic square on your workers and a Composite array Cp on the
client.
n = 10
p = parpool('Processes',4);
spmd
Cp = magic(n);
end
results = gather(Cp)
results =
Input Arguments
A — Array to gather
gpuArray | distributed array | codistributed array
10-131
10 Functions
Tips
• Note that gather assembles the codistributed or distributed array in the workspaces of all the
workers on which it executes, or on the MATLAB client, respectively, but not both. If you are using
gather within an spmd statement, the gathered array is accessible on the client via its
corresponding Composite object; see “Access Worker Variables with Composites” on page 4-17. If
you are running gather in a communicating job, you can return the gathered array to the client
as an output argument from the task.
• As the gather function on a distributed or codistributed array requires communication between
all the workers, you cannot gather data from all the workers onto a single worker by placing the
function inside a conditional statement such as if spmdIndex == 1.
• You can gather gpuArray objects by right-clicking the variable in the workspace, and then
selecting Gather from GPU.
Version History
Introduced in R2006b
You can now gather gpuArray objects by right-clicking the variable in the workspace, and then
selecting Gather from GPU. This is equivalent to calling the gather function on a gpuArray.
You can now use the gather function to gather elements of a Composite array on parallel workers
to the local workspace.
Previously, when you use gather on a Composite array, MATLAB returns the same Composite
array as the output.
See Also
arrayfun | codistributed | distributed | gpuArray | Composite | pagefun
10-132
gcat
gcat
(Not recommended) Concatenate arrays on spmd workers
Note gcat is not recommended. Use spmdCat instead. For more information, see “Version History”.
Syntax
B = gcat(A)
B = gcat(A,dim)
B = gcat(A,dim,destination)
Description
B = gcat(A) horizontally concatenates the array A defined on each worker running an spmd block
or communicating job.
When you use parfor, parfeval, or parfevalOnAll to run code on a parallel pool, the workers
are independent and do not communicate with each other. If you use gcat on these workers, the
result is the same as using gcat on a client.
You can use gcat only if the array A defined on each worker can be concatenated along the second
dimension.
gcat concatenates the arrays along the second dimension, then stores the result on all workers. The
value of A is taken from each worker and concatenated in labindex order. For example,
gcat(labindex) returns 1:numlabs.
B = gcat(A,dim) concatenates the array A defined on each worker along dimension dim.
You can use gcat only if the array A concatenates along dimension dim when all arrays have
compatible sizes (the lengths of the dimensions match except for the operating dimension dim).
B = gcat(A,dim,destination) concatenates the array A defined on each worker and stores the
result on only one worker.
Examples
This example shows how to use gcat to concatenate a scalar held on each worker in an spmd block.
parpool(4);
10-133
10 Functions
Create an spmd block. By default, each worker in the pool runs the spmd block. Store the value
returned by labindex on each worker as A, then use gcat to take the value of A defined on each
worker and concatenate them.
When you use gcat, the result is stored by default on every worker. On the client, the result is a
Composite array. To get the result, index into the Composite array.
spmd
B = gcat(labindex);
end
B{1}
ans =
1 2 3 4
Input Arguments
A — Input array
scalar | vector | matrix | multidimensional array | table | timetable | ...
Input array, specified as a scalar, vector, matrix, multidimensional array, table, timetable, or any
MATLAB variable that supports concatenation.
Example: A = magic(3)
Dimension to operate along, specified as a positive integer scalar. For example, if A is a 2-by-2 matrix
on all workers, then gcat(A,1) concatenates vertically creating a 2*numlabs-by-2 matrix.
gcat(A,2) concatenates horizontally creating a 2-by-2*numlabs matrix.
Index of destination worker, specified as a positive integer scalar. The value must be less than or
equal to the value given returned when you use numlabs in the current spmd block or
communicating job. When specified, the result B from running B = gcat(A,dim,destination) is
only stored on one worker. The array B is still defined on all workers that run gcat. On the worker
with labindex equal to destination, C is the result of the concatenation. On all other workers, C is
[].
Output Arguments
B — Output array
vector | matrix | multidimensional array | table | timetable | ...
If you specify destination, B is the result of the concatenation on the worker with labindex equal
to destination. On all other workers, B is [].
10-134
gcat
Algorithms
When you use gcat(A), the value of A on each worker is concatenated with the value on other
workers.
Version History
Introduced in R2006b
To indicate their intended use within spmd blocks, gcat is renamed to spmdCat. gcat will continue
to work but is no longer recommended. To update your code, replace any instance of gcat with
spmdCat. There are no plans to remove gcat.
See Also
spmdCat
10-135
10 Functions
gcp
Get current parallel pool
Syntax
p = gcp
p = gcp("nocreate")
Description
p = gcp returns a [Link] object representing the current parallel pool. The current pool is
where parallel language features execute, such as parfor, spmd, distributed, Composite,
parfeval and parfevalOnAll.
If no parallel pool exists, gcp starts a new parallel pool and returns a pool object for that, unless
automatic pool starts are disabled in your parallel settings. If no parallel pool exists and automatic
pool starts are disabled, gcp returns an empty pool object.
p = gcp("nocreate") returns the current pool if one exists. If no pool exists, the "nocreate"
option causes gcp not to create a pool, regardless of your parallel settings.
Examples
delete(gcp("nocreate"))
Version History
Introduced in R2013b
10-136
gcp
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
Composite | delete | distributed | parfeval | parfevalOnAll | parfor | parpool | spmd
10-137
10 Functions
getAttachedFilesFolder
Identify folder on a worker where attached files are copied to
Syntax
folder = getAttachedFilesFolder
folder = getAttachedFilesFolder(filename)
Description
folder = getAttachedFilesFolder returns the path to the folder on the current worker where
attached files are copied to. Attached files are specified by the AttachedFiles of the job that the
worker is currently running.
Attached files are specified by the AttachedFiles of the job that the worker is currently running. A
match is found if a file or folder specified in the AttachedFiles property ends with filename. If a
folder is specified in the AttachedFiles property, no matches can be found for any files in that
folder.
If only one file or folder matches, folder is the path to that file or folder. If multiple files or folders
match, folder is a cell array containing every matching path. If filename does not match the name
of an attached file or folder, folder is an empty cell array.
Examples
Use the addAttachedFiles function to attach a folder to a parallel pool, then use the
getAttachedFilesFolder function to find the folder on workers.
p = parpool(4);
The current directory contains two folders myFolder1 and myFolder2, containing files
[Link] and [Link] respectively.
dir myFolder*/*
10-138
getAttachedFilesFolder
. .. [Link]
. .. [Link]
addAttachedFiles(p,{'myFolder1','myFolder2'});
When you use addAttachedFiles, the folders are copied to workers. Each copied folder will have a
unique name on the workers.
Then, use getAttachedFilesFolder on the workers to get the path to the copy of 'myFolder1'.
Use readtable to read the file [Link] in the folder.
parfor i = 1
folder = getAttachedFilesFolder('myFolder1');
filepath = fullfile(folder, '[Link]');
t = readtable(filepath);
end
Input Arguments
filename — Name of file or folder
string | character vector
Name of file or folder to search for in the attached files available on the current worker, specified as a
string or character vector. Attached files are specified by the AttachedFiles of the job that the
worker is currently running.
Example: "[Link]"
Data Types: string | char
Output Arguments
folder — Attached files folder
character vector | cell array
Folder containing attached files available on the current worker, specified as a character vector or
cell array.
If filename is specified, folder is the path or paths matching filename. If only one file or folder
matches, filename is the path to that file or folder. If multiple files or folders match, filename is a
cell array containing every matching path. If filename does match the name of an attached file or
folder, folder is an empty cell array.
If filename is not specified, folder is the path containing attached files available to the worker.
10-139
10 Functions
Version History
Introduced in R2012a
See Also
Functions
addAttachedFiles | getCurrentCluster | getCurrentJob | getCurrentTask |
getCurrentWorker
10-140
get
get
Namespace: parallel
Syntax
valueSet = get(store,keySet)
Description
valueSet = get(store,keySet) returns the values from the ValueStore object store as
specified by the keys keySet. valueSet is a cell array containing the returned values, which are in
the same order as their corresponding keys in keySet.
Examples
Run a simulation on workers and retrieve the data storage of the job on a client. The data storage is a
ValueStore object with key-value entries. Get values from this object as specified by its
corresponding keys.
The following simulation finds the inverse of random matrices and stores the results in the
ValueStore object.
type workerInvCode
function workerInvCode(models)
% Get the ValueStore of the current job
store = getCurrentValueStore;
for i = 1:numel(models)
% Store simulation results in the ValueStore object
pause(1);
key = strcat("result_",num2str(i));
store(key) = inv(rand(models(i)));
end
end
models = [4,8,32,20];
c = parcluster;
job = batch(c,@workerInvCode,0,{models});
wait(job);
store = [Link];
Get the entry value as specified by the key "result_1" from the object.
10-141
10 Functions
val2 = store("result_1")
val2 = 4×4
Get multiple values as specified by the keys "result_3" and "result_4" from the object.
valArray = get(store,["result_3","result_4"])
Input Arguments
store — Data storage shared by MATLAB clients and workers
ValueStore object
Data storage shared by MATLAB clients and workers, specified as a ValueStore object.
Keys to retrieve values at, specified as a character vector, string scalar, string array, or cell array of
character vectors or strings.
Tips
• To return only one entry value as specified by key, you can also use the syntax value =
store(key).
Version History
Introduced in R2022a
See Also
ValueStore | isKey | keys | remove | put
10-142
getCodistributor
getCodistributor
Codistributor object for existing codistributed array
Syntax
codist = getCodistributor(D)
Description
codist = getCodistributor(D) returns the codistributor object of codistributed array D.
Properties of the object are Dimension and Partition for 1-D distribution; and BlockSize,
LabGrid, and Orientation for 2-D block cyclic distribution. For any one codistributed array,
getCodistributor returns the same values on all workers. The returned codistributor object is
complete, and therefore suitable as an input argument for [Link].
Examples
Get the codistributor object for a 1-D codistributed array that uses default distribution on 4 workers:
spmd (4)
I1 = eye(64,codistributor1d());
codist1 = getCodistributor(I1)
dim = [Link]
partn = [Link]
end
Get the codistributor object for a 2-D block cyclic codistributed array that uses default distribution on
4 workers:
spmd (4)
I2 = eye(128,codistributor2dbc());
codist2 = getCodistributor(I2)
blocksz = [Link]
partn = [Link]
ornt = [Link]
end
spmd (4)
isComplete(codist1)
isComplete(codist2)
end
Version History
Introduced in R2009b
10-143
10 Functions
See Also
codistributed | [Link] | getLocalPart | redistribute
10-144
getCurrentCluster
getCurrentCluster
Get cluster object from a worker in a cluster
Syntax
c = getCurrentCluster
Description
c = getCurrentCluster returns the [Link] object that the current worker is
associated with. Use getCurrentCluster to get information from the cluster during a computation,
such as the host name of the cluster's head node, credentials for the user that submitted a job, or the
job storage location.
Examples
Use the Host property to find the host name of the head node of the cluster which submitted the
current task.
On a worker, use getCurrentCluster to get the current cluster object c from a worker on the
cluster c.
c = getCurrentCluster;
Then, use the Host property to get the host name of the head node of the cluster.
host = [Link];
You can use the cluster object returned by getCurrentCluster to submit jobs.
On a worker, use getCurrentCluster to get the current cluster object c from a worker on the
cluster c.
c = getCurrentCluster;
You can use batch, createJob, or createCommunicatingJob to submit jobs to this cluster.
j = batch(c,@magic,1,{3});
10-145
10 Functions
Tip Avoid submitting jobs from a worker currently working on a job or task. When you create and
submit jobs from a worker, you can recursively create and submit jobs. Recursive submission can
create infinitely nested submissions which use a significant amount of the cluster's resources.
Output Arguments
c — Cluster object
[Link] | []
Version History
Introduced in R2012a
See Also
getAttachedFilesFolder | getCurrentJob | getCurrentTask | getCurrentWorker
10-146
getCurrentJob
getCurrentJob
Get job object from a worker running a job
Syntax
j = getCurrentJob
Description
j = getCurrentJob returns the [Link] object that the current worker is associated with.
Use getCurrentJob to get information from the job during a computation, such as the running
duration or attached files.
Examples
Use getCurrentJob and RunningDuration property to find the running duration of the job that a
worker is associated with.
On a worker, use getCurrentJob to get the current job object j from a worker running the job j.
j = getCurrentJob;
Then, use the RunningDuration property to get the running duration of the job.
howLong = [Link];
Output Arguments
j — Job object
[Link] | []
Job object, specified as a [Link] or empty double. When you use getCurrentJob on a
worker, j is the [Link] object that the current worker is associated with. When you use
getCurrentJob on the client, j is an empty double.
Data Types: [Link]
Version History
Introduced before R2006a
10-147
10 Functions
See Also
getAttachedFilesFolder | getCurrentCluster | getCurrentTask | getCurrentWorker
10-148
getCurrentFileStore
getCurrentFileStore
Get file storage of current job or pool
Syntax
store = getCurrentFileStore
Description
store = getCurrentFileStore gets the FileStore object of the current job or pool on a worker.
Use the store to copy files from workers that can be retrieved by clients later, even while the job is
still running. If getCurrentFileStore is executed in a MATLAB session that is not a worker, you
get an empty result.
Examples
Run a simulation on workers and retrieve the file storage of the job on a client. The file storage is a
FileStore object with key-file entries.
The following simulation finds the average and standard deviation of random matrices and stores the
results in the FileStore object.
type workerStatsCode
function workerStatsCode(models)
% Get the FileStore of the current job
store = getCurrentFileStore;
for i = 1:numel(models)
% Compute the average and standard deviation of random matrices
A = rand(models(i));
M = mean(A);
S = std(A);
% Save simulation results in temporary files
sourceTempFile = strcat(tempname("C:\myTempFolder"),".mat");
save(sourceTempFile,"M","S");
% Copy files to FileStore object as key-file pairs
key = strcat("result_",num2str(i));
copyFileToStore(store,sourceTempFile,key);
end
end
The following callback function is executed when a file is copied to the FileStore object.
type fileNewEntry
function fileNewEntry(store,key)
destination = strcat(key,".mat");
10-149
10 Functions
models = [4,8,32,20];
c = parcluster;
job = batch(c,@workerStatsCode,0,{models});
Retrieve the FileStore object on the client while the job is still running. Show the progress of the
job.
store = [Link];
[Link] = @fileNewEntry;
wait(job);
Display all the information on the variables stored in the file "result_3.mat".
Output Arguments
store — File storage shared by MATLAB clients and workers
FileStore object | empty double
File storage shared by MATLAB clients and workers, returned as a FileStore object or an empty
double.
Version History
Introduced in R2022a
See Also
FileStore | isKey | keys | remove | copyFileToStore | copyFileFromStore |
getCurrentValueStore
10-150
getCurrentTask
getCurrentTask
Get task object from a worker running a task
Syntax
t = getCurrentTask
Description
t = getCurrentTask returns the [Link] object that the current worker is associated
with. Use getCurrentTask to get information from the task during a computation, such as the
running duration.
Examples
Use getCurrentTask and RunningDuration property to find the running duration of the task that
a worker is associated with.
On a worker, use getCurrentTask to get the current task object t from a worker running the task
t.
t = getCurrentTask;
Then, use the RunningDuration property to get the running duration of the task.
howLong = [Link]
Output Arguments
t — Task object
[Link] | []
Task object, specified as a [Link] or empty double. When you use getCurrentTask on a
worker, t is the [Link] object that the current worker is associated with. When you use
getCurrentTask on the client, t is an empty double.
Data Types: [Link]
Version History
Introduced before R2006a
10-151
10 Functions
See Also
getAttachedFilesFolder | getCurrentCluster | getCurrentJob | getCurrentWorker
10-152
getCurrentValueStore
getCurrentValueStore
Get data storage of current job or pool
Syntax
store = getCurrentValueStore
Description
store = getCurrentValueStore gets the ValueStore object of the current job or pool on a
worker. Use the store to send data from workers back to clients during the execution of a job. If
getCurrentValueStore is executed in a MATLAB session that is not a worker, you get an empty
result.
Examples
Run a simulation on workers and retrieve the data storage of the job on a client. The data storage is a
ValueStore object with key-value entries.
The following simulation finds the singular values of random matrices and stores the results in the
ValueStore object.
type workerSvdCode
function workerSvdCode(models)
% Get the ValueStore of the current job
store = getCurrentValueStore;
for i = 1:numel(models)
% Store simulation results in the ValueStore object
pause(1)
key = strcat("result_",num2str(i));
store(key) = svd(rand(models(i)));
store("progress") = i/numel(models);
end
end
The following callback function is executed when an entry is added to the ValueStore object.
type handleNewEntry
function handleNewEntry(store,key)
if strcmp(key,"progress")
fprintf("Progress update: %.2f %%\n",store(key)*100);
else
fprintf("Result %s added\n",key);
end
end
10-153
10 Functions
models = [8,16,32,20];
c = parcluster;
job = batch(c,@workerSvdCode,0,{models});
Retrieve the ValueStore object on the client while the job is still running. Show the progress of the
job.
store = [Link];
[Link] = @handleNewEntry;
wait(job);
Get the entry value as specified by the key "result_1" from the object.
val1 = store("result_1")
val1 =
4.3318
1.2988
1.1040
0.8813
0.5711
0.3991
0.2092
0.1048
Output Arguments
store — Data storage shared by MATLAB clients and workers
ValueStore object | empty double
Data storage shared by MATLAB clients and workers, returned as a ValueStore object or an empty
double.
Version History
Introduced in R2022a
See Also
ValueStore | isKey | keys | remove | put | get | getCurrentFileStore
10-154
getCurrentWorker
getCurrentWorker
Get worker object from current worker
Syntax
w = getCurrentWorker
Description
w = getCurrentWorker returns the current worker, as a [Link] object. Use
getCurrentWorker to get information from the worker during a computation, such as the worker
host name.
Examples
Use the Host property to find the host name of the current worker.
w = getCurrentWorker;
Then, use the Host property to get the host name of the worker.
host = [Link];
Output Arguments
w — Worker object
[Link] | []
Version History
Introduced before R2006a
See Also
getAttachedFilesFolder | getCurrentCluster | getCurrentJob | getCurrentTask
10-155
10 Functions
getDebugLog
Read output messages from job run in CJS cluster
Syntax
str = getDebugLog(cluster,job_or_task)
Arguments
str Variable to which messages are returned as a character vector
expression.
cluster Cluster object referring to Microsoft Windows HPC Server (or CCS),
Spectrum LSF, PBS Pro, or TORQUE cluster, created by parcluster.
job_or_task Object identifying job or task whose messages you want.
Description
str = getDebugLog(cluster,job_or_task) returns any output written to the standard output
or standard error stream by the job or task identified by job_or_task, being run in the cluster
identified by cluster.
Examples
This example shows how to create and submit a communicating job, and how to retrieve the job's
debug log. Assume that you already have a cluster profile called My3pCluster that defines the
properties of the cluster.
c = parcluster('My3pCluster');
j = createCommunicatingJob(c);
createTask(j,@spmdIndex,1,{});
submit(j);
getDebugLog(c,j);
Version History
Introduced before R2006a
See Also
createCommunicatingJob | createJob | createTask | parcluster
10-156
getJobClusterData
getJobClusterData
Get specific user data for job on third-party cluster
Syntax
userdata = getJobClusterData(cluster,job)
Description
userdata = getJobClusterData(cluster,job) returns data stored for the job job that was
derived from the third-party cluster cluster. You store job user data with the function
setJobClusterData. For example, you can store the third-party scheduler's external ID for a job, so
that the function specified in GetJobStateFcn can later query the scheduler about the state of the
job.
For more information and examples on using these functions and properties, see “Plugin Scripts for
Generic Schedulers” (MATLAB Parallel Server).
Input Arguments
cluster — Third-party cluster
[Link] object
Job from which you want to retrieve the stored data, specified as a [Link] object.
Output Arguments
userdata — Information previously stored for this job
array
Information previously stored for this job, returned as any MATLAB array. For example, you can store
job user data as a scalar, vector, matrix, cell array, character array, table, or structure.
Version History
Introduced in R2012a
See Also
setJobClusterData
10-157
10 Functions
getJobFolder
Folder on client where jobs are stored
Syntax
joblocation = getJobFolder(cluster,job)
Description
joblocation = getJobFolder(cluster,job) returns the path to the folder on disk where files
are stored for the specified job and cluster. This folder is valid only the client session, not necessarily
the workers.
Version History
Introduced in R2012a
See Also
getJobFolderOnCluster | parcluster
10-158
getJobFolderOnCluster
getJobFolderOnCluster
Folder on cluster where jobs are stored
Syntax
joblocation = getJobFolderOnCluster(cluster,job)
Description
joblocation = getJobFolderOnCluster(cluster,job) returns the path to the folder on disk
where files are stored for the specified job and cluster. This folder is valid only in worker MATLAB
sessions. An error results if the HasSharedFilesystem property of the cluster is false.
Version History
Introduced in R2012a
See Also
getJobFolder | parcluster
10-159
10 Functions
getLocalPart
Local portion of codistributed array
Syntax
L = getLocalPart(A)
Description
L = getLocalPart(A) returns the local portion of a codistributed array.
Examples
Create an array and then distributed the array across all workers. Get the local part on each worker.
parpool("Processes",4);
spmd
A = magic(4); % replicated on all workers
D = codistributed(A, codistributor1d(1));
L = getLocalPart(D)
end
Worker 1:
L =
16 2 3 13
Worker 2:
L =
5 11 10 8
Worker 3:
L =
9 7 6 12
Worker 4:
L =
4 14 15 1
Version History
Introduced in R2009b
10-160
getLocalPart
See Also
codistributed | codistributor
10-161
10 Functions
getLogLocation
Log location for job or task
Syntax
logfile = getLogLocation(cluster,cj)
logfile = getLogLocation(cluster,it)
Description
logfile = getLogLocation(cluster,cj) for a third-party cluster cluster and communicating
job cj, returns the location where the log data should be stored for the whole job cj.
This function can be useful during submission, to instruct the third-party cluster to put worker output
logs in the correct location.
Version History
Introduced in R2012a
See Also
parcluster
10-162
getTaskSchedulerIDs
getTaskSchedulerIDs
Namespace: [Link]
Syntax
schedulerIDs = getTaskSchedulerIDs(job)
Description
schedulerIDs = getTaskSchedulerIDs(job) returns the SchedulerID of each task on the job
job. Note that SchedulerID applies only to third-party schedulers.
Examples
Create a cluster object by using parcluster. In the code below, change MyThirdPartyScheduler
to the name of the profile of your third-party scheduler.
c = parcluster('MyThirdPartyScheduler');
Create a job and create some tasks for it. Then, submit the job.
job = createJob(c);
for idx = 1:2
createTask(job,@ode45,2,{@vdp1,[0,10],[idx,0]});
end
submit(job)
To get the scheduler IDs of the tasks on the job, use getTaskSchedulerIDs. You can use these IDs
to refer to the corresponding jobs on the third-party scheduler.
getTaskSchedulerIDs(job)
In this case, the scheduler has assigned the ID 4933 to this job.
wait(job);
out = fetchOutputs(job)
10-163
10 Functions
When you are done retrieving information from the job, delete it to clean up its data.
delete(job);
clear job
Input Arguments
job — Job
[Link] object
Job object that represents the job on the third-party scheduler, specified as a [Link] object.
Example: job = createJob(parcluster);
Data Types: [Link]
Output Arguments
schedulerIDs — Scheduler IDs
cell array of character vectors
Version History
Introduced in R2019b
See Also
parcluster | [Link]
Topics
“Install MATLAB Parallel Server for Other Third-Party Schedulers” (MATLAB Parallel Server)
10-164
globalIndices
globalIndices
Global indices for local part of codistributed array
Syntax
K = globalIndices(C,dim)
K = globalIndices(C,dim,lab)
[E,F] = globalIndices(C,dim)
[E,F] = globalIndices(C,dim,lab)
K = globalIndices(codist,dim,lab)
[E,F] = globalIndices(codist,dim,lab)
Description
globalIndices tells you the relationship between indices on a local part and the corresponding
index range in a given dimension on the codistributed array. The globalIndices method on a
codistributor object allows you to get this relationship without actually creating the array.
Examples
Create a 2-by-22 codistributed array among four workers, and view the global indices on each lab:
spmd
C = zeros(2,22,codistributor1d(2,[6 6 5 5]));
if spmdIndex == 1
K = globalIndices(C,2) % returns K = 1:6.
elseif spmdIndex == 2
[E,F] = globalIndices(C,2) % returns E = 7, F = 12.
end
K = globalIndices(C,2,3) % returns K = 13:17.
[E,F] = globalIndices(C,2,4) % returns E = 18, F = 22.
end
10-165
10 Functions
Use globalIndices to load data from a file and construct a codistributed array distributed along its
columns, i.e., dimension 2. Notice how globalIndices makes the code not specific to the number of
workers and alleviates you from calculating offsets or partitions.
spmd
siz = [1000,1000];
codistr = codistributor1d(2,[],siz);
Version History
Introduced in R2008a
See Also
getLocalPart | spmdIndex
10-166
gop
gop
(Not recommended) Reduce arrays on spmd workers
Note gop is not recommended. Use spmdReduce instead. For more information, see “Version
History”.
Syntax
B = gop(fcn,A)
B = gop(fcn,A,destination)
Description
B = gop(fcn,A) uses the function fcn to reduce the array A defined on each worker running an
spmd block or communicating job.
For example, gop(@plus,A) returns the sum of the arrays A defined on each worker.
MATLAB uses the fcn function to reduce the array A defined on each worker by calling the function
N-1 times.
When you use parfor, parfeval, or parfevalOnAll to run code on a parallel pool, the workers
are independent and do not communicate with each other. If you use gop on these workers, the result
is the same as using gop on a client.
B = gop(fcn,A,destination) reduces the array A defined on each worker and stores the result
on only one worker.
Examples
This example shows how to use gop to calculate the maximum value for x across all workers.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool will run the code inside the spmd block.
Run labindex on each worker in the spmd block, and store the result in a scalar A. Use gop and max
to calculate the maximum value of A from each worker.
10-167
10 Functions
When you use gop, by default the result is stored on every worker. On the client, C is a Composite
array. To get the result, index into the Composite array.
spmd
A = labindex;
C = gop(@max,A);
end
disp(C{1})
Input Arguments
A — Input array
scalar | vector | matrix | multidimensional array | table | timetable | ...
Reduction function, specified as a function handle. The function must take two input arguments.
Example: fcn = @max
Data Types: function_handle
Index of destination worker, specified as a positive integer scalar. The value must be less than or
equal to the value given by numlabs, the number of workers running the current spmd block or
communicating job. When specified, the result of gop(fcn,A,destination) is only stored on one
worker. On the worker with labindex equal to destination, C is the result of the operation. On all
other workers, C is [].
Example: 1
Algorithms
When you use gop(fcn,A), fcn is used to combine the value of A from each worker.
To ensure that your spmd block or communicating job always produces the same results, specify fcn
as an associative function.
10-168
gop
Version History
Introduced before R2006a
To indicate their intended use within spmd blocks, gop is renamed to spmdReduce. gop will continue
to work but is no longer recommended. To update your code, replace any instance of gop with
spmdReduce. There are no plans to remove gop.
Extended Capabilities
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
The gop function fully supports GPU arrays. To run the function on a GPU, specify the input data as a
gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-3.
If x is a gpuArray, data transfer between multiple GPUs in a parallel pool uses fast peer-to-peer
communication, including NVLink, if available.
10-169
10 Functions
See Also
spmdReduce
Topics
“Use spmdReduce to Achieve MPI_Allreduce Functionality” on page 4-21
10-170
gplus
gplus
(Not recommended) Add arrays from workers in an spmd block
Note gplus is not recommended. Use spmdPlus instead. For more information, see “Version
History”.
Syntax
C = gplus(A)
C = gplus(A,destination)
Description
C = gplus(A) add the arrays A stored on each worker in the current spmd block or communicating
job.
Tip When you offload computations using parfor and parfeval, each computation is run by only
one worker at a time. These workers are independent and do not communicate with each other. If you
use gplus on these workers, then C is equal to A.
The function gplus adds the arrays when A has a compatible size on each worker.
C = gplus(A,destination) computes the sum of the arrays and stores the result on only one
worker. On the worker with labindex equal to destination, C is equal to the sum. On all other
workers, C is [].
Examples
This example shows how to use gplus to add a scalar held on each worker in an spmd block.
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool will run the code inside the spmd block.
Run labindex on each worker in the spmd block, and store the result in a scalar A. Use gplus to
add the value of A from each worker.
When you use gplus, by default the result is stored on every worker. On the client, C is a Composite
array. To get the result, index into the Composite array.
10-171
10 Functions
spmd
A = labindex;
C = gplus(A);
end
disp(C{1})
10
Input Arguments
A — Input array
scalar | vector | matrix | multidimensional array
Index of target worker, specified as a positive integer scalar. The value must be less than or equal to
the value given by numlabs, the number of workers running the current spmd block or
communicating job. When specified, the result of gplus(A,destination) is only stored on one
worker. On the worker with labindex equal to destination, C is equal to the sum. On all other
workers, C is [].
Example: 1
Algorithms
When you use gplus(A), the value of A on each worker is added to the value on other workers.
10-172
gplus
Version History
Introduced in R2006b
To indicate their intended use within spmd blocks, gplus is renamed to spmdPlus. gplus will
continue to work but is no longer recommended. To update your code, replace any instance of gplus
with spmdPlus. There are no plans to remove gplus.
See Also
spmdPlus
10-173
10 Functions
gpuDeviceCount
Namespace: [Link]
Syntax
n = gpuDeviceCount
n = gpuDeviceCount(countMode)
[n,indx] = gpuDeviceCount( ___ )
Description
n = gpuDeviceCount returns the number of GPU devices present in your local machine, as
reported by the GPU device driver. All devices reported by the driver are counted, including devices
that are not supported in MATLAB and devices that are not available for use in the current MATLAB
session.
[n,indx] = gpuDeviceCount( ___ ) also returns the indices of the counted GPU devices for any
of the previous syntaxes. Use this syntax when you want to select or examine the counted GPU
devices.
Examples
Determine the number of GPU devices available in your computer and their indices.
[n,indx] = gpuDeviceCount
n = 2
indx =
1 2
gpuDeviceTable
ans =
Index Name ComputeCapability DeviceAvailable DeviceSelected
_____ __________________ _________________ _______________ ______________
10-174
gpuDeviceCount
If you have access to several GPUs, you can perform your calculations on multiple GPUs in parallel
using a parallel pool.
To determine the number of GPUs that are available for use in MATLAB, use the gpuDeviceCount
function.
availableGPUs = gpuDeviceCount("available")
availableGPUs = 3
Start a parallel pool with as many workers as available GPUs. For best performance, MATLAB assigns
a different GPU to each worker by default.
parpool("Processes",availableGPUs);
To identify which GPU each worker is using, call gpuDevice inside an spmd block. The spmd block
runs gpuDevice on every worker.
spmd
gpuDevice
end
Use parallel language features, such as parfor or parfeval, to distribute your computations to
workers in the parallel pool. If you use gpuArray enabled functions in your computations, these
functions run on the GPU of the worker. For more information, see “Run MATLAB Functions on a
GPU” on page 6-3. For an example, see “Run MATLAB Functions on Multiple GPUs” on page 6-19.
When you are done with your computations, shut down the parallel pool. You can use the gcp
function to obtain the current parallel pool.
delete(gcp("nocreate"));
If you want to use a different choice of GPUs, then you can use gpuDevice to select a particular GPU
on each worker, using the GPU device index. You can obtain the index of each GPU device in your
system using the gpuDeviceCount function.
Suppose you have three GPUs available in your system, but you want to use only two for a
computation. Obtain the indices of the devices.
[availableGPUs,gpuIndx] = gpuDeviceCount("available")
availableGPUs = 3
gpuIndx = 1×3
1 2 3
useGPUs = [1 3];
10-175
10 Functions
Start your parallel pool. Use an spmd block and gpuDevice to associate each worker with one of the
GPUs you want to use, using the device index. The spmdIndex function identifies the index of each
worker.
parpool("Processes",numel(useGPUs));
spmd
gpuDevice(useGPUs(spmdIndex));
end
As a best practice, and for best performance, assign a different GPU to each worker.
When you are done with your computations, shut down the parallel pool.
delete(gcp("nocreate"));
Input Arguments
countMode — Device count mode
"all" (default) | "supported" | "available"
• "all" — Count all GPU devices reported by the GPU device driver. The count includes devices
that are not supported in MATLAB and devices that are not available for use in the current
MATLAB session.
• "supported" — Count only GPU devices that are supported by the current version of MATLAB.
• "available" — Count only GPU devices that are available for use in the current MATLAB
session.
Example: "available"
Data Types: char | string
Output Arguments
n — Number of GPU devices
positive scalar
Indices of GPU devices, returned as a numeric vector. Each element of indx is the device index of a
counted GPU device. Use the device index to select or query the GPU device using the gpuDevice
function.
Version History
Introduced in R2010b
10-176
gpuDeviceCount
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
arrayfun | feval | gpuDevice | CUDAKernel | gpuDeviceTable | gpuArray
Topics
“GPU Computing Requirements” on page 6-13
10-177
10 Functions
gpuDeviceTable
Namespace: [Link]
Syntax
tbl = gpuDeviceTable
tbl = gpuDeviceTable(props)
Description
tbl = gpuDeviceTable returns a table of properties of all GPU devices detected in your system.
The table displays the value of the Index, Name, ComputeCapability, DeviceAvailable, and
DeviceSelected properties of each GPU device detected in your system. Each row of the table
contains the properties of a single GPU device.
Examples
Use gpuDeviceTable to query and compare the properties of all GPUs in your system at a glance.
tbl = gpuDeviceTable
tbl =
2×5 table
Both devices are available for use in this MATLAB session. The selected GPU device, with index 1, has
a higher compute capability than the device with index 2.
Alternatively, you can determine how many GPU devices are available, inspect some of their
properties, and select a device to use from the MATLAB® desktop. On the Home tab, in the
Environment area, select Parallel > Select GPU Environment.
10-178
gpuDeviceTable
Use gpuDeviceTable to query and compare the specific properties of all GPUs in your system.
Compare the compute capability, total memory, multiprocessor count, and availability of the GPU
devices in your system.
tbl = gpuDeviceTable(["Index","ComputeCapability",...
"TotalMemory","MultiprocessorCount","DeviceAvailable"])
tbl =
2×5 table
Input Arguments
props — GPU device properties
string array | cell array
GPU device properties, specified as a string array or a cell array of character vectors. Each element
of props must be one of the properties returned by gpuDevice.
The variables of the output table are the properties specified by props, in the same order as provided
in props.
Example: ["Name","ComputeCapability","AvailableMemory"]
Data Types: char | string | cell
10-179
10 Functions
Output Arguments
tbl — Table of GPU device properties
table
The default variables of tbl are Index, Name, ComputeCapability, DeviceAvailable, and
DeviceSelected. If you specify the props argument, then the output table contains only the
specified properties.
Version History
Introduced in R2021a
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
gpuDevice | gpuDeviceCount | gpuArray
Topics
“GPU Computing Requirements” on page 6-13
10-180
gpurng
gpurng
Control random number generation on the GPU
Syntax
gpurng("default")
gpurng(seed)
gpurng(seed,generator)
gpurng(generator)
gpurng(S)
S = gpurng
S = gpurng( ___ )
Description
gpurng("default") initializes the GPU random number generator using the default algorithm and
seed. The default algorithm is the Threefry generator with seed 0. The random numbers produced
are the same as if you had restarted MATLAB.
The gpurng function controls the global GPU stream, which determines how the rand, randi,
randn, and randperm functions produce a sequence of random numbers on the GPU. To create one
or more independent streams separate from the global GPU stream, see
[Link].
gpurng(seed) specifies the seed for the GPU random number generator using the current generator
algorithm.
• Specify seed as a nonnegative integer, such as gpurng(1), to initialize the GPU random number
generator with that seed.
• Specify seed as "shuffle" to initialize the generator seed based on the current time so that
rand, randi, randn, and randperm produce different sequences of numbers after each time you
call gpurng.
gpurng(seed,generator) also specifies the algorithm for the GPU random number generator to
use. For example, gpurng(2,"philox") initializes the Philox 4x32 generator with a seed of 2.
gpurng(generator) specifies the algorithm for the GPU random number generator to use with a
seed of 0. This syntax is equivalent to gpurng(0,generator).
gpurng(S) initializes the state of the random number generator based on settings contained in a
structure S with fields Type, Seed, and State. The structure S must be a structure that is returned
by a previous call to S = gpurng or S = gpurng(__).
S = gpurng returns the current state of the random number generator as a structure S with fields
Type, Seed, and State.
S = gpurng( ___ ) returns the current state of the random number generator in a structure S
before changing the settings using the specified arguments.
10-181
10 Functions
Note The default algorithm and seed for the random number generator in the MATLAB Settings
Window window affect random numbers generated on the CPU only and do not affect calls to
gpurng("default").
Examples
Capture the GPU generator settings, and set the state of the CPU random number generator to match
the GPU generator settings. Create predictable arrays of random numbers on the CPU and GPU.
Restore the generator type and seed to their default values on both the CPU and the GPU.
gpurng("default")
rng("default")
Save the default seed and generator type of the GPU random number generator.
GPUdef = gpurng
Set the CPU random number generator to match the default GPU settings.
rng(GPUdef)
rGPU = rand(1,10,"gpuArray")
rGPU =
0.3640 0.5421 0.6543 0.7436 0.0342 0.8311 0.7040 0.2817 0.1163 0.5
rCPU = rand(1,10)
rCPU = 1×10
0.3640 0.5421 0.6543 0.7436 0.0342 0.8311 0.7040 0.2817 0.1163 0.5
The seed and generator type are the same for both the GPU and the CPU, so the arrays are the same.
isequal(rGPU,rCPU)
ans = logical
1
10-182
gpurng
The gpurng state does not save the settings for the transformation applied to generate a normally
distributed set of random numbers. Even though the seed and the generator type are the same on the
GPU and the CPU, the set of normally distributed random numbers is different.
nGPU = randn(1,1000,"gpuArray");
nCPU = randn(1,1000);
figure
hold on
histogram(nGPU)
histogram(nCPU)
legend("GPU","CPU")
title("Normally Distributed Random Numbers")
xlabel("Value")
ylabel("Count")
hold off
The statistics of the normal distribution of random numbers are the same on the GPU and the CPU.
By default, the CPU uses the Ziggurat transformation, while the GPU uses the BoxMuller
algorithm for the Threefry generator. The only transformation method supported on both the CPU
and GPU is the Inversion transform.
You can change the transformation method on the GPU using [Link].
10-183
10 Functions
Input Arguments
seed — Random number seed
0 (default) | nonnegative integer | "shuffle"
Random number seed, specified as a nonnegative integer or "shuffle". The seed specifies the
starting point for the algorithm to generate random numbers. Specify the seed as a nonnegative
integer when you want reproducible results. The default seed is 0.
When you specify the seed as "shuffle", the software initializes the generator seed based on the
current time, resulting in a different sequence of random numbers after each call to gpurng.
Example: gpurng(7)
Random number generator, specified as a character vector or string for any valid random number
generator that supports multiple streams and substreams. Three random number generator
algorithms are supported on the GPU.
For more information on the differences between generating random numbers on the GPU and CPU,
see “Control Random Number Streams on Workers” on page 5-15.
Example: gpurng("Philox")
Previous random number generator state, specified as a structure previously created using S =
gpurng.
Example: S = gpurng captures the current state of the random number generator, and gpurng(S)
restores the generator to those settings.
Data Types: struct
Output Arguments
S — Random number generator state
structure
Random number generator state, returned as a structure with fields Type, Seed, and State.
10-184
gpurng
Example: S = gpurng captures the current state of the random number generator, and gpurng(S)
restores the generator to those settings.
Data Types: struct
Version History
Introduced in R2011b
Use the new syntax gpurng(generator) to specify the algorithm for the random number generator
to use. This syntax allows you to set the random number algorithm without specifying the seed,
where gpurng uses a seed of 0. This syntax is equivalent to gpurng(0,generator). For example,
gpurng("philox") initializes the Philox 4x32 generator with a seed of 0.
Starting in R2019a, the default random number generator for parallel computations is changed to
Threefry. This generator offers performance enhancements for parallel calculations over the
previous default. In releases up to R2018b, the default random number generator for parallel
computations is CombRecursive.
With a different default generator, MATLAB generates different random numbers sequences by
default in the context of parallel computations. However, statistics of these calculations remain
unaffected. Therefore, you might want to update any code that relies on the specific random numbers
being generated, but most calculations on the random numbers are unaffected.
To set the generator to the settings used by default in R2018b and earlier on GPU arrays, use the
following command.
gpurng(0,"CombRecursive")
Starting in R2018a, the function [Link] is renamed to gpurng. Replace all instances of
[Link] with gpurng.
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
rng | gpuArray | [Link]
10-185
10 Functions
Topics
“Random Number Streams on a GPU” on page 6-72
“Generating Random Numbers on a GPU” on page 6-75
10-186
gputimeit
gputimeit
Time required to run function on GPU
Syntax
t = gputimeit(F)
t = gputimeit(F,numOutputs)
Description
t = gputimeit(F) measures the typical time, in seconds, required to run the function specified by
the function handle F. The function handle accepts no external input arguments, but you can define it
with input arguments to its internal function call.
Examples
This example shows how to measure the time to calculate sum(A.' .* B, 1) on a GPU, where A is
a 12000-by-400 matrix and B is 400-by-12000.
A = rand(12000,400,'gpuArray');
B = rand(400,12000,'gpuArray');
f = @() sum(A.' .* B, 1);
t = gputimeit(f)
0.0026
Compare the time to run svd on a GPU, with one versus three output arguments.
X = rand(1000,'gpuArray');
f = @() svd(X);
t3 = gputimeit(f,3)
1.0622
t1 = gputimeit(f,1)
0.2933
Input Arguments
F — Function to measure
function handle
10-187
10 Functions
Number of output arguments to use in the function call, specified as a scalar integer.
If the function specified by F has a variable number of outputs, numOutputs specifies which syntax
gputimeit uses to call the function. For example, the svd function returns a single output, s, or
three outputs, [U,S,V]. Set numOutputs to 1 to time the s = svd(X) syntax, or set it to 3 to time
the [U,S,V] = svd(X) syntax.
Limitations
• The function F must not call tic or toc.
• You cannot use tic and toc to measure the execution time of gputimeit itself.
Tips
gputimeit is preferable to timeit for functions that use the GPU, because it ensures that all
operations on the GPU have finished before recording the time and compensates for the overhead.
For operations that do not use a GPU, timeit offers greater precision.
Version History
Introduced in R2013b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
gpuArray | wait (GPUDevice)
10-188
help
help
Help for toolbox functions in Command Window
Syntax
help class/function
Arguments
class A Parallel Computing Toolbox object class, for example, [Link],
[Link], or [Link].
function A function or property of the specified class. To see what functions or
properties are available for a class, see the methods or properties
reference page.
Description
help class/function returns command-line help for the specified function of the given class.
If you do not know the class for the function, use class(obj), where function is of the same class
as the object obj.
Examples
Get help on functions or properties from Parallel Computing Toolbox object classes.
help [Link]/createJob
help [Link]/cancel
help [Link]/wait
c = parcluster();
j1 = createJob(c);
class(j1)
[Link]
help [Link]/createTask
help [Link]/AdditionalPaths
Version History
Introduced before R2006a
See Also
methods
10-189
10 Functions
Inf
Create codistributed array of all Inf values
Syntax
cI = Inf(n,codist)
cI = Inf(sz,codist)
cI = Inf(sz1,...,szN,codist)
cI = Inf( ___ ,datatype,codist)
Description
cI = Inf(n,codist) creates an n-by-n codistributed matrix of all Inf values and uses codist to
specify the distribution of the array values across the workers.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
cI = Inf(sz,codist) creates a codistributed array of all Inf values where the size vector sz
defines the size of cI. For example, Inf([2 3],"codistributed") creates a 2-by-3 codistributed
array.
cI = Inf( ___ ,datatype,codist) creates a codistributed array of all Inf values with the
underlying type datatype. For example, Inf(1,"single","codistributed") creates a
codistributed single integer Inf. You can use this syntax with any of the size arguments in the
previous syntaxes. You must specify codist after the array size and data type arguments.
cI = Inf( ___ ,"noCommunication") creates a codistributed array of all Inf values without
using communication between workers.
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
10-190
Inf
You must specify "noCommunication" after the size, data type and codist arguments.
cI = Inf( ___ ,like=p) uses the array p to create a codistributed array of all Inf values. You can
also specify "noCommunication" as part of the function call.
The returned array cI has the same underlying type, sparsity, and complexity (real or complex) as p.
Examples
Create a 1000-by-1000 codistributed matrix of Inf values, distributed by its second dimension
(columns).
spmd(4)
C = Inf(1000,"codistributed");
end
Create a 1000-by-1000 codistributed single matrix of Inf values, distributed by its columns.
spmd(4)
codist = codistributor1d(2,100*[1:spmdSize]);
C = Inf(1000,1000,"single",codist);
end
Input Arguments
n — Size of square matrix
integer
10-191
10 Functions
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
Underlying data type of the returned array, that is the data type of its elements, specified as one of
these options:
• "double"
• "single"
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p. The underlying data type of the codistributed array p
must be single or double.
Data Types: single | double
Version History
Introduced in R2006b
See Also
Inf | eye (codistributed) | false (codistributed) | NaN (codistributed) | ones
(codistributed) | true (codistributed) | zeros (codistributed)
10-192
isaUnderlying
isaUnderlying
(Not recommended) True if distributed array's underlying elements are of specified class
Syntax
TF = isaUnderlying(D, 'classname')
Description
TF = isaUnderlying(D, 'classname') returns true if the elements of distributed or
codistributed array D are either an instance of classname or an instance of a class derived from
classname. isaUnderlying supports the same values for classname as the MATLAB isa function
does.
Examples
N = 1000;
D_uint8 = ones(1,N,'uint8','distributed');
D_cell = [Link](1,N);
isUint8 = isaUnderlying(D_uint8,'uint8') % returns true
isDouble = isaUnderlying(D_cell,'double') % returns false
Version History
Introduced in R2010a
See Also
isa | underlyingType | isUnderlyingType | mustBeUnderlyingType
10-193
10 Functions
iscodistributed
True for codistributed array
Syntax
tf = iscodistributed(X)
Description
tf = iscodistributed(X) returns true for a codistributed array, or false otherwise. For a
description of codistributed arrays, see “Nondistributed Versus Distributed Arrays” on page 4-36.
Examples
With a running parallel pool,
spmd
L = ones(100,1);
D = ones(100,1,'codistributed');
iscodistributed(L) % returns false
iscodistributed(D) % returns true
end
Version History
Introduced in R2009b
See Also
isdistributed
10-194
isComplete
isComplete
True if codistributor object is complete
Syntax
tf = isComplete(codist)
Description
tf = isComplete(codist) returns true if codist is a completely defined codistributor, or false
otherwise. For a description of codistributed arrays, see “Nondistributed Versus Distributed Arrays”
on page 4-36.
Version History
Introduced in R2009b
See Also
codistributed | codistributor
10-195
10 Functions
isdistributed
True for distributed array
Syntax
tf = isdistributed(X)
Description
tf = isdistributed(X) returns true for a distributed array, or false otherwise. For a
description of a distributed array, see “Nondistributed Versus Distributed Arrays” on page 4-36.
Examples
With a running parallel pool,
L = ones(100,1);
D = ones(100,1,'distributed');
isdistributed(L) % returns false
isdistributed(D) % returns true
Version History
Introduced in R2006b
See Also
iscodistributed
10-196
isequal
isequal
Namespace: parallel
Syntax
isequal(C1,C2)
isequal(C1,C2,C3,...)
Description
isequal(C1,C2) returns logical 1 (true) if clusters C1 and C2 have the same property values, or
logical 0 (false) otherwise.
isequal(C1,C2,C3,...) returns true if all clusters are equal. isequal can operate on arrays of
clusters. In this case, the arrays are compared element by element.
When comparing clusters, isequal does not compare the contents of the clusters' Jobs property.
Examples
Compare clusters after some properties are modified.
c1 = parcluster('Processes');
[Link] = 2; % Modify cluster
[Link]('Processes2') % Create new profile
c2 = parcluster('Processes2'); % Make cluster from new profile
isequal(c1,c2)
Version History
Introduced in R2012a
See Also
parcluster
10-197
10 Functions
isgpuarray
Determine whether input is gpuArray
Syntax
TF = isgpuarray(X)
Description
TF = isgpuarray(X) returns logical 1 (true) if X is a gpuArray, and logical 0 (false) otherwise.
You can use this function with an if statement to avoid executing code that expects gpuArray input.
Examples
X = rand(3,3);
Y = gpuArray(X);
isgpuArray(Y)
ans =
1
isgpuarray(X)
ans =
0
Input Arguments
X — Input variable
workspace variable
Version History
Introduced in R2020b
10-198
isgpuarray
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
The isgpuarray function fully supports GPU arrays. To run the function on a GPU, specify the input
data as a gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-3.
See Also
gpuArray | gather | existsOnGPU | canUseGPU
Topics
“Establish Arrays on a GPU” on page 6-15
“Run MATLAB Functions on a GPU” on page 6-3
10-199
10 Functions
isKey
Namespace: parallel
Syntax
TF = isKey(store,keySet)
Description
TF = isKey(store,keySet) returns a logical array containing 1 (true) for each key as specified
in keySet that exists in the ValueStore or FileStore object store, and 0 (false) otherwise.
Examples
Run a simulation on workers and retrieve the data storage of the job on a client. The data storage is a
ValueStore object with key-value entries. Check whether the specified keys exist in this object.
The following simulation finds the inverse of random matrices and stores the results in the
ValueStore object.
type workerInvCode
function workerInvCode(models)
% Get the ValueStore of the current job
store = getCurrentValueStore;
for i = 1:numel(models)
% Store simulation results in the ValueStore object
pause(1);
key = strcat("result_",num2str(i));
store(key) = inv(rand(models(i)));
end
end
models = [4,8,32,20];
c = parcluster;
job = batch(c,@workerInvCode,0,{models});
wait(job);
store = [Link];
keys(store)
10-200
isKey
Check whether the following specified keys exist in the ValueStore object.
TF = isKey(store,["result_2", "result_5", "result_3"])
1 0 1
Run a simulation on a parallel pool of process workers and retrieve the file storage on a client. The
file storage is a FileStore object with key-file entries. Check whether the specified keys exist in this
object.
The following simulation finds the average and standard deviation of random matrices and stores the
results in the FileStore object.
type workerStatsCode
function workerStatsCode(models)
% Get the FileStore of the current job
store = getCurrentFileStore;
for i = 1:numel(models)
% Compute the average and standard deviation of random matrices
A = rand(models(i));
M = mean(A);
S = std(A);
% Save simulation results in temporary files
sourceTempFile = strcat(tempname("C:\myTempFolder"),".mat");
save(sourceTempFile,"M","S");
% Copy files to FileStore object as key-file pairs
key = strcat("result_",num2str(i));
copyFileToStore(store,sourceTempFile,key);
end
end
10-201
10 Functions
models = [4,8,32,20];
future = parfeval(@workerStatsCode,0,models);
wait(future);
keys(store)
Check whether the following specified keys exist in the FileStore object.
Input Arguments
store — Data or file storage shared by MATLAB clients and workers
ValueStore object | FileStore object
Data or file storage shared by MATLAB clients and workers, specified as a ValueStore or
FileStore object.
Keys to search for, specified as a character vector, string scalar, string array, or cell array of character
vectors or strings.
Version History
Introduced in R2022a
See Also
ValueStore | FileStore | keys | remove | put | get | copyFileToStore | copyFileFromStore
10-202
isreplicated
isreplicated
True for replicated array
Syntax
tf = isreplicated(X)
Description
tf = isreplicated(X) returns true for a replicated array, or false otherwise. For a description
of a replicated array, see “Nondistributed Versus Distributed Arrays” on page 4-36. isreplicated
also returns true for a Composite X if all its elements are identical.
Examples
With an open parallel pool,
spmd
A = magic(3);
t = isreplicated(A) % returns t = true
B = magic(spmdIndex);
f = isreplicated(B) % returns f = false
end
Tips
isreplicated(X) requires checking for equality of the array X across all workers. This might
require extensive communication and time. isreplicated is most useful for debugging or error
checking small arrays. A codistributed array is not replicated.
Version History
Introduced in R2006b
See Also
iscodistributed | isdistributed
10-203
10 Functions
jobStartup
File for user-defined options to run when job starts
Syntax
jobStartup(job)
Description
jobStartup(job) runs automatically on a worker the first time that worker evaluates a task for a
particular job. You do not call this function from the client session, nor explicitly as part of a task
function.
To define the job initialization actions on the worker, add MATLAB code to the jobStartup.m file.
The worker looks for jobStartup.m in this order, executing the first one it finds:
matlabroot/toolbox/parallel/user/jobStartup.m
matlabroot/toolbox/parallel/user/jobStartup.m
For more details on jobStartup and its implementation, see the text in the installed jobStartup.m
file.
Input Arguments
job — Job for which startup options are executed
[Link] object
Job for which the startup options are executed, specified as a [Link] object.
Version History
Introduced before R2006a
See Also
poolStartup | taskFinish | taskStartup
10-204
keys
keys
Namespace: parallel
Syntax
keySet = keys(store)
Description
keySet = keys(store) returns a string array containing all the keys in the ValueStore or
FileStore object store.
Examples
Run a simulation on workers and retrieve the data storage of the job on a client. The data storage is a
ValueStore object with key-value entries. Show the keys of this object.
The following simulation finds the inverse of random matrices and stores the results in the
ValueStore object.
type workerInvCode
function workerInvCode(models)
% Get the ValueStore of the current job
store = getCurrentValueStore;
for i = 1:numel(models)
% Store simulation results in the ValueStore object
pause(1);
key = strcat("result_",num2str(i));
store(key) = inv(rand(models(i)));
end
end
models = [4,8,32,20];
c = parcluster;
job = batch(c,@workerInvCode,0,{models});
wait(job);
store = [Link];
keySet = keys(store)
10-205
10 Functions
Run a simulation on a parallel pool of process workers and retrieve the file storage on a client. The
file storage is a FileStore object with key-file entries. Show the keys of this object.
The following simulation finds the average and standard deviation of random matrices and stores the
results in the FileStore object.
type workerStatsCode
function workerStatsCode(models)
% Get the FileStore of the current job
store = getCurrentFileStore;
for i = 1:numel(models)
% Compute the average and standard deviation of random matrices
A = rand(models(i));
M = mean(A);
S = std(A);
% Save simulation results in temporary files
sourceTempFile = strcat(tempname("C:\myTempFolder"),".mat");
save(sourceTempFile,"M","S");
% Copy files to FileStore object as key-file pairs
key = strcat("result_",num2str(i));
copyFileToStore(store,sourceTempFile,key);
end
end
pool = parpool('Processes');
store = [Link];
models = [4,8,32,20];
future = parfeval(@workerStatsCode,0,models);
wait(future);
keys(store)
10-206
keys
Input Arguments
store — Data or file storage shared by MATLAB clients and workers
ValueStore object | FileStore object
Data or file storage shared by MATLAB clients and workers, specified as a ValueStore or
FileStore object.
Version History
Introduced in R2022a
See Also
ValueStore | FileStore | isKey | remove | put | get | copyFileToStore |
copyFileFromStore
10-207
10 Functions
labindex
(Not recommended) Index of the current worker in an spmd block
Note labindex is not recommended. Use spmdIndex instead. For more information, see “Version
History”.
Syntax
id = labindex
Description
id = labindex returns the index of the worker currently executing the function in an spmd block.
When workers run an spmd block or a communicating job begins execution, a unique index is
assigned to each worker. The value of labindex is an integer between 1 and numlabs.
A worker gets the same id inside every spmd block for the duration of a given parallel pool.
Examples
p = parpool('local',2);
spmd
labindex
end
Worker 1:
1
Worker 2:
2
parfor a=1:4
[a,labindex]
end
ans =
3 1
ans =
2 1
ans =
1 1
10-208
labindex
ans =
4 1
Tips
In an spmd block, because you have access to all workers individually and control what gets executed
on them, each worker has a unique labindex.
However, inside a parfor-loop, labindex always returns a value of 1 on all workers in all iterations.
Version History
Introduced before R2006a
To indicate their intended use within spmd blocks, labindex is renamed to spmdIndex. labindex
will continue to work but is no longer recommended. To update your code, replace any instance of
labindex with spmdIndex. There are no plans to remove labindex.
See Also
spmdIndex
10-209
10 Functions
labBarrier
(Not recommended) Synchronize workers in an spmd block
Note labBarrier is not recommended. Use spmdBarrier instead. For more information, see
“Version History”.
Syntax
labBarrier
Description
labBarrier stops all workers in the current spmd block or communicating job from executing code
until every worker calls labBarrier.
Tip When you offload computations using parfor and parfeval, each computation is run by only
one worker at a time. These workers are independent and do not communicate with each other. If you
use labBarrier on these workers, the function has no effect.
Use labBarrier when you need to synchronize workers, such as when workers use shared
resources such as a file handle.
Examples
This example shows how to use labBarrier to synchronize workers in an spmd block.
Create a parallel pool with 4 workers. By default, spmd is supported on all process-backed pools.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool will run the code inside the spmd block.
Create an spmd block, and run pause on each worker for a random amount of time to simulate some
computationally expensive work. Use tic and toc to time the execution on each worker.
spmd
tic
pause(5*rand);
toc
end
10-210
labBarrier
Worker 2:
Elapsed time is 0.702969 seconds.
Worker 3:
Elapsed time is 1.807292 seconds.
Worker 1:
Elapsed time is 4.651690 seconds.
Worker 4:
Elapsed time is 4.694443 seconds.
To synchronize the workers after each worker runs pause, use labBarrier. In the following code,
all workers wait for the slowest worker to finish its computation. The elapsed time on each worker is
now the same, except for slight numerical noise.
spmd
tic
pause(5*rand);
labBarrier;
toc
end
Lab 1:
Elapsed time is 4.758529 seconds.
Lab 2:
Elapsed time is 4.758529 seconds.
Lab 3:
Elapsed time is 4.743785 seconds.
Lab 4:
Elapsed time is 4.743739 seconds.
Version History
Introduced before R2006a
To indicate their intended use within spmd blocks, labBarrier is renamed to spmdBarrier.
labBarrier will continue to work but is no longer recommended. To update your code, replace any
instance of labBarrier with spmdBarrier. There are no plans to remove labBarrier.
See Also
spmdBarrier
10-211
10 Functions
labBroadcast
(Not recommended) Send data to all workers in an spmd block
Note labBroadcast is not recommended. Use spmdBroadcast instead. For more information, see
“Version History”.
Syntax
B = labBroadcast(source,A)
B = labBroadcast(source)
Description
B = labBroadcast(source,A) sends the data A to every worker in the current spmd block or
communicating job.
Tip When you offload computations using parfor and parfeval, each computation is run by only
one worker at a time. These workers are independent and do not communicate with each other. If you
use labBroadcast on these workers, the function has no effect.
The data is broadcast from the worker with labindex equal to source.
B = labBroadcast(source) receives the data B on each worker running the current spmd block
or communicating job. The data B is equal to the data A sent from the worker with labindex equal to
source.
Examples
This example shows how to broadcast an array from one worker to other workers in an spmd block.
Create a parallel pool with 4 workers. By default, labBroadcast is supported on all process-backed
pools.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool will run the code inside the spmd block.
Create an spmd block. On the worker with labindex equal to 1, create an array. Use labBroadcast
to send the array to all workers. On each other worker, use labBroadcast to receive the array.
10-212
labBroadcast
spmd
source = 1;
if labindex == source
A = magic(3);
B = labBroadcast(source, A);
else
B = labBroadcast(source);
end
B
end
Worker 1:
B =
8 1 6
3 5 7
4 9 2
Worker 2:
B =
8 1 6
3 5 7
4 9 2
Worker 3:
B =
8 1 6
3 5 7
4 9 2
Worker 4:
B =
8 1 6
3 5 7
4 9 2
On the client, inspect the Composite A. The array A is only defined on the worker with labindex
equal to 1.
A =
10-213
10 Functions
Worker 4: No data
Input Arguments
source — Worker index
positive integer scalar
Index of the worker that is sending data, specified as a positive integer scalar. This value must be
greater than or equal to 1 and less than or equal to numlabs.
Example: 1
A — Sent data
scalar | vector | matrix | multidimensional array | table | timetable | ...
Data sent from the worker with labindex equal to source, specified as any MATLAB variable that
can be saved and loaded.
Example: magic(3)
Output Arguments
B — Received data
scalar | vector | matrix | multidimensional array | table | timetable
Data received on the worker, specified as a scalar, vector, matrix, multidimensional array, table, or
timetable.
Tips
A worker that calls labBroadcast may return before other workers. When you need synchronized
workers in an spmd block or communicating job, such as when you close a shared resource, use
labBarrier after calling labBroadcast.
Version History
Introduced before R2006a
To indicate their intended use within spmd blocks, labBroadcast is renamed to spmdBroadcast.
labBroadcast will continue to work but is no longer recommended. To update your code, replace
any instance of labBroadcast with spmdBroadcast. There are no plans to remove labBroadcast.
Extended Capabilities
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
10-214
labBroadcast
The labBroadcast function fully supports GPU arrays. To run the function on a GPU, specify the
input data as a gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-
3.
If data is a gpuArray, data transfer between multiple GPUs in a parallel pool uses fast peer-to-peer
communication, including NVLink, if available.
See Also
spmdBroadcast
10-215
10 Functions
labProbe
(Not recommended) Determine if data is available for the current worker in an spmd to receive
Note labProbe is not recommended. Use spmdProbe instead. For more information, see “Version
History”.
Syntax
tf = labProbe
tf = labProbe(source)
tf = labProbe('any')
tf = labProbe('any',tag)
tf = labProbe(source,tag)
[tf,sources,tags] = labProbe( ___ )
Description
tf = labProbe tests if data is available for the current worker in an spmd block or communicating
job to receive using labReceive.
Tip When you offload computations using parfor and parfeval, each computation is run by only
one worker at a time. These workers are independent and do not communicate with each other. If you
use labProbe on these workers, the function has no effect.
If data is available, labProbe returns logical 1 (true); otherwise, it returns logical 0 (false).
tf = labProbe(source) tests if data is available for the current worker to receive from the
worker with labindex equal to source.
tf = labProbe('any') tests if the sent data is available for the current worker to receive from
any worker.
tf = labProbe('any',tag) tests if data sent with the tag tag is available for the current worker
to receive from any worker.
tf = labProbe(source,tag) tests if data sent with the tag tag is available for the current
worker to receive from the worker with labindex equal to source.
[tf,sources,tags] = labProbe( ___ ) tests if data is available for the current worker to
receive, returns the labindex of the workers that are sending data as source, and returns the tags
of data available to receive as tag.
Examples
10-216
labProbe
This example shows how to determine if data is available to be received on workers in an spmd block
or communicating job.
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool will run the code inside the spmd block.
Create an spmd block. On the worker with labindex equal to 1, create an array. Use labSend to
send the array to the worker with labindex equal to 2.
Use labBarrier to guarantee that labProbe is called on workers after data has been sent from the
worker with labindex equal to 1. Then, use labProbe to test if data is available for each worker to
receive. Use labReceive to collect the data.
spmd
switch labindex
case 1
A = magic(3);
labSend(A,2);
end
labBarrier;
tf = labProbe
if tf
labReceive;
end
end
Worker 1:
tf =
logical
Worker 2:
tf =
logical
Worker 3:
tf =
logical
10-217
10 Functions
Worker 4:
tf =
logical
Input Arguments
source — Worker index
positive integer scalar | 'any'
Index of the source worker, specified as a positive integer scalar or the character vector 'any'. The
value must be less than or equal to the value given by numlabs, the number of workers running the
current spmd block or communicating job. When specified as a positive integer scalar, labProbe
returns logical 1 (true) if data is available to be received by the current worker from the worker with
labindex equal to source. When not specified, labProbe returns logical 1 (true) if data is
available to be received by the current worker from any worker.
Example: 1
Tag attached to data, specified as 0 or a positive integer scalar. When specified, labProbe returns
logical 1 (true) if data sent using labSend with tag equal to tag is available to be received by the
current worker.
Example: 314159
Output Arguments
sources — Worker indices
positive integer scalar
Index of workers that has sent data not yet received by the current worker, specified as a positive
integer scalar or empty. The values are equal to labindex on each of the workers that sent data. If
no data is available to be received, sources is [].
Tag attached to data sent from workers that has not yet received by the current worker, specified as a
positive integer scalar or empty. If no data is available to be received, tags is [].
Version History
Introduced before R2006a
10-218
labProbe
To indicate their intended use within spmd blocks, labProbe is renamed to spmdProbe. labProbe
will continue to work but is no longer recommended. To update your code, replace any instance of
labProbe with spmdProbe. There are no plans to remove labProbe.
See Also
spmdProbe
10-219
10 Functions
labReceive
(Not recommended) Receive data from another worker in an spmd block
Note labReceive is not recommended. Use spmdReceive instead. For more information, see
“Version History”.
Syntax
B = labReceive
B = labReceive(source)
B = labReceive('any')
B = labReceive('any',tag)
B = labReceive(source,tag)
[B,source,tag] = labReceive( ___ )
Description
B = labReceive receives data sent from any worker in the current spmd block or communicating
job.
Tip When you offload computations using parfor and parfeval, each computation is run by only
one worker at a time. These workers are independent and do not communicate with each other. If you
use labReceive on these workers, the function has no effect.
When a worker runs labReceive, execution of other commands is blocked until the worker receives
the data.
B = labReceive(source) receives data sent from the worker with labindex equal to source.
B = labReceive('any',tag) receives data sent with the tag tag from any worker.
B = labReceive(source,tag) receives data sent with the tag tag from the worker with
labindex equal to source.
[B,source,tag] = labReceive( ___ ) receives data sent from another worker, returns the index
source of the source worker, and returns the tag tagwith the data.
Examples
This example shows how to send data between workers in an spmd block or communicating job.
10-220
labReceive
Create a parallel pool with 4 workers. By default, spmd is supported on all process-backed pools.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool will run the code inside the spmd block.
Create an spmd block. On the worker with labindex equal to 1, create an array. Use labSend to
send the array to the worker with labindex equal to 2.
spmd
switch labindex
case 1
A = magic(3)
labSend(A,2);
case 2
B = labReceive
end
end
Worker 1:
A =
8 1 6
3 5 7
4 9 2
Worker 2:
B =
8 1 6
3 5 7
4 9 2
Input Arguments
source — Worker index
positive integer scalar
Index of the worker sending data, specified as a positive integer scalar. The value must be less than
or equal to the value given by numlabs, the number of workers running the current spmd block or
communicating job. When specified, labReceive returns data sent from the worker with labindex
equal to source. When not specified, labReceive receives data sent from any worker.
Example: 1
Tag attached to data, specified as 0 or a positive integer scalar. When specified, labReceive returns
data with sent to the current worker using labSend with the tag argument equal to tag.
10-221
10 Functions
Example: 314159
Output Arguments
source — Worker index
positive integer scalar | 'any'
Index of the worker sending data, specified as a positive integer scalar or the character vector
'any'. The value is equal to labindex on the worker that sent the received data.
Tag attached to data received by the current worker, specified as a positive integer scalar.
Version History
Introduced before R2006a
To indicate their intended use within spmd blocks, labReceive is renamed to spmdReceive.
labReceive will continue to work but is no longer recommended. To update your code, replace any
instance of labReceive with spmdReceive. There are no plans to remove labReceive.
Extended Capabilities
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
The labReceive function fully supports GPU arrays. To run the function on a GPU, specify the input
data as a gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-3.
If data is a gpuArray, data transfer between multiple GPUs in a parallel pool uses fast peer-to-peer
communication, including NVLink, if available.
See Also
spmdReceive
10-222
labSend
labSend
(Not recommended) Send data to another worker in an spmd block
Note labSend is not recommended. Use spmdSend instead. For information on updating your code,
see “Version History”.
Syntax
labSend(A,destination)
labSend( ___ ,tag)
Description
labSend(A,destination) sends data A from the current worker in an spmd block or
communicating job to another worker.
Tip When you offload computations using parfor and parfeval, each computation is run by only
one worker at a time. These workers are independent and do not communicate with each other. If you
use labSend on these workers, the function has no effect.
The function labSend sends data to the worker or workers specified by destination.
labSend( ___ ,tag) sends data with the tag tag. When you use labSend to send data between
workers, multiple items of data can wait to be collected. When you send multiple items of data to a
worker, add a tag to each item to distinguish between the items.
Examples
This example shows how to send data between workers in an spmd block or communicating job.
Create a parallel pool with 4 workers. By default, spmd is supported on all process-backed pools.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool will run the code inside the spmd block.
Create an spmd block. On the worker with labindex equal to 1, create an array. Use labSend to
send the array to the worker with labindex equal to 2.
10-223
10 Functions
case 1
A = magic(3)
labSend(A,2);
case 2
B = labReceive
end
end
Worker 1:
A =
8 1 6
3 5 7
4 9 2
Worker 2:
B =
8 1 6
3 5 7
4 9 2
Input Arguments
A — Data to send
scalar | vector | matrix | multidimensional array | table | timetable | ...
Data to send from the current worker, specified as a scalar, vector, matrix, multidimensional array,
table, timetable, or any MATLAB variable.
Example: magic(3)
Indices of the worker or workers receiving data, specified as a positive integer scalar or vector. The
values must be less than or equal to the value given by numlabs, the number of workers running the
current spmd block or communicating job.
Example: [2 3 4]
Tag attached to data, specified as 0 or a positive integer scalar. When specified, labReceive returns
data with sent to the current worker using labSend with the tag argument specified as tag.
Example: 314159
Tips
A worker that sends data using labSend may return before the receiving worker receives the data.
When you need synchronized workers in an spmd block or communicating job, such as when you
close a shared resource, use labBarrier after calling labSend and labReceive.
10-224
labSend
Version History
Introduced before R2006a
To indicate their intended use within spmd blocks, labSend is renamed to spmdSend. labSend will
continue to work but is no longer recommended. To update your code, replace any instance of
labSend with spmdSend. There are no plans to remove labSend.
Extended Capabilities
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
The labSend function fully supports GPU arrays. To run the function on a GPU, specify the input data
as a gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-3.
If data is a gpuArray, data transfer between multiple GPUs in a parallel pool uses fast peer-to-peer
communication, including NVLink, if available.
See Also
spmdSend
10-225
10 Functions
labSendReceive
(Not recommended) Simultaneously send and receive data on a worker in an spmd block
Syntax
B = labSendReceive(destination,source,A)
B = labSendReceive( ___ ,tag)
Description
B = labSendReceive(destination,source,A) sends data from the current worker in an spmd
block or communicating job to a destination, and receives data from a source. The array A is sent
from the current worker to the worker with labindex is equal to destination. The current worker
receives data from the worker with labindex equal to source.
labSend(A,destination);
B = labReceive(source);
B = labSendReceive( ___ ,tag) sends and receives data with the tag tag. When you use
labSendReceive to send data between workers, multiple items of data can wait to be collected.
When you send multiple items of data to a worker, add a tag to each item to distinguish between the
items.
Examples
This example shows how to use labSendReceive to send data between workers in an spmd block or
communicating job.
Create a parallel pool with 4 workers. By default, spmd is supported on all process-backed pools.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool will run the code inside the spmd block.
Create an spmd block. You can use mod and labSendReceive to send and receive data in a chain of
workers. Use labSendReceive to send data to the worker with labindex one higher than the
current worker's index, mod numlabs. Receive data from the worker with labindex one lower than
the current worker's index, mod numlabs. When you use modulo division, the worker with labindex
10-226
labSendReceive
equal to 1 receives from the worker with labindex equal to numlabs. The worker with labindex
equal to 1 receives from the worker with labindex equal to numlabs.
spmd
A = 2*labindex;
A = labSendReceive(source, destination, A)
end
Worker 1:
A =
Worker 2:
A =
Worker 3:
A =
Worker 4:
A =
Input Arguments
destination — Worker index
positive integer scalar | empty array
Index of the destination worker, specified as a positive integer scalar or empty array. The destination
worker receives data from the current worker. destination must be less than or equal to the value
given by numlabs, the number of workers running the current spmd block or communicating job.
If this argument is empty, the function does not send any data.
Example: 2
Index of the source worker, specified as a positive integer scalar or empty array. The current worker
waits until it receives data from the source worker. destination must be less than the value given
by numlabs, the number of workers running the current spmd block or communicating job.
10-227
10 Functions
If this argument is empty, the function does not receive any data.
Example: 1
A — Data to send
scalar | vector | matrix | multidimensional array | table | timetable
Data to send from the current worker, specified as a scalar, vector, matrix, multidimensional array,
table, or timetable.
Example: magic(3)
Tag attached to data, specified as 0 or a positive integer scalar. When specified, labSendReceive
sends data with the tag tag from the current worker, and returns data sent with the tag tag to the
current worker.
Example: 314159
Version History
Introduced in R2006b
See Also
spmdSendReceive
10-228
length
length
Length of parallel object array
Syntax
L = length(obj)
Description
L = length(obj) returns the length of a parallel object array obj. It is equivalent to the command
max(size(obj)).
Examples
Create a job and assign a random number of tasks to generate a 10-by-10 random matrix.
L = length([Link])
L = 41
Input Arguments
obj — object array
object | object array
Object to examine, specified as a single parallel object or parallel object array. A parallel object can
be a distributed, codistributed, gpuArray, Composite, [Link], or [Link]
object.
Example: L = length(distributed(1:10))
Version History
Introduced before R2006a
10-229
10 Functions
See Also
distributed | codistributed | gpuArray | Composite | createJob | createTask
10-230
listAutoAttachedFiles
listAutoAttachedFiles
Namespace: parallel
Syntax
listAutoAttachedFiles(obj)
Description
listAutoAttachedFiles(obj) performs a dependency analysis on all the task functions, or on the
batch job script or function. Then it displays a list of the code files that are already or going to be
automatically attached to the job or task object obj.
If obj is a parallel pool, the output lists the files that have already been attached to the parallel pool
following an earlier dependency analysis. The dependency analysis runs if a parfor or spmd block
errors due to an undefined function. At that point any files, functions, or scripts needed by the
parfor or spmd block are attached if possible.
Examples
Employ a cluster profile to automatically attach code files to a job. Set the AutoAttachFiles
property for a job in the cluster's profile. If this property value is true, then all jobs you create on that
cluster with this profile will have the necessary code files automatically attached. This example
assumes that the cluster profile myAutoCluster has that setting.
obj = batch(myScript,'profile','myAutoCluster');
listAutoAttachedFiles(obj)
Programmatically set a job to automatically attach code files, and then view a list of those files for
one of the tasks in the job.
10-231
10 Functions
The files returned in the output listing are those that analysis has determined to be required for the
workers to evaluate the function myFun, and which automatically attach to the job.
Input Arguments
obj — Pool, job, or task
[Link] object | [Link] object | job object | task object
If obj is a job, the AutoAttachFiles property must be true. If obj is a task, the
AutoAttachFiles property of the parent job must be true.
Example: obj = parpool('Processes');
Example: obj = batch(@magic,1,{3});
Version History
Introduced in R2013a
See Also
batch | createCommunicatingJob | createJob | createTask | parpool | parcluster
Topics
“Add and Modify Cluster Profiles” on page 7-5
10-232
load
load
Namespace: parallel
Syntax
load(j)
load(j,variables)
S = load( ___ )
Description
load(j) loads all variables from a batch job j that ran a script or expression. The variables are
assigned into the current workspace. If a variable in the current workspace exists with the same
name, it is overwritten.
The workspace variables from a job are stored in the location given by the JobStorageLocation
property of the cluster that the job runs on. When you run load, this data is not removed from the
JobStorageLocation. To remove the workspace data, use the delete function to remove
individual tasks or entire jobs.
Tip To see if any of the tasks on the job j failed after encountering an error, check if
[Link] is empty. If the returned array is empty, none of the tasks on the job j encountered
any errors.
If some tasks completed successfully, you can use the OutputArguments property of a task to access
the output arguments of that task directly.
load(j,variables) loads variables from the job j into the current workspace.
S = load( ___ ) creates a structure containing variables from the job. For example, S = load(j)
loads all variables from the job j into S.
Examples
10-233
10 Functions
Assign the value 3 to the variable x. Then, use batch to create a job using the default cluster profile.
In that job, run the expression 'y = magic(x)' on a worker.
x = 3;
j = batch('y = magic(x)');
When you create the job, the variable x is automatically copied from the client workspace to the
worker that runs the batch job.
Wait for the job to complete. Then, use load to load the variables from the job into the client
workspace.
wait(j)
load(j);
The variables x and y are now available on the client. Display the values in y.
ans =
8 1 6
3 5 7
4 9 2
Input Arguments
j — Batch job
[Link] object
Batch job, specified as a [Link] object. To create a batch job, use batch.
Names of variables to load, specified as one or more character vectors or string scalars.
Example: load(j,'A*')
Example: load(j,'A','B*','C')
Example: load(j,'-regexp','^Mon',^Tues')
10-234
load
Output Arguments
S — Loaded variables
structure scalar
Version History
Introduced in R2008a
See Also
fetchOutputs | batch | createJob | createCommunicatingJob
10-235
10 Functions
logout
Log out of MATLAB Job Scheduler cluster
Syntax
logout(c)
Description
logout(c) logs you out of the MATLAB Job Scheduler cluster, c. Any subsequent call to a privileged
action requires you to re-authenticate with a valid password. Logging out is useful when you are
finished working on a shared machine.
Input Arguments
c — Cluster to log out of
[Link] object
Version History
Introduced in R2012a
See Also
changePassword
10-236
mapreducer
mapreducer
Define parallel execution environment for mapreduce and tall arrays
Syntax
mapreducer
mapreducer(0)
mapreducer(poolobj)
mapreducer(hadoopCluster)
mapreducer(mr)
mr = mapreducer( ___ )
mr = mapreducer( ___ ,'ObjectVisibility','Off')
Description
mapreducer defines the execution environment for mapreduce or tall arrays. Use the mapreducer
function to change the execution environment to use a different cluster or to switch between serial
and parallel development.
The default execution environment uses either the local MATLAB session, or a parallel pool if you
have Parallel Computing Toolbox. If you have Parallel Computing Toolbox installed, when you use the
tall or mapreduce functions, MATLAB automatically starts a parallel pool of workers, unless you
have changed the default settings. By default, a parallel pool uses local workers, typically one worker
for each core in your machine. If you turn off the Automatically create a parallel pool option, then
you must explicitly start a pool if you want to use parallel resources. See “Specify Your Parallel
Settings” on page 1-35.
When working with tall arrays, use mapreducer to set the execution environment prior to creating
the tall array. Tall arrays are bound to the current global execution environment when they are
constructed. If you subsequently change the global execution environment, then the tall array is
invalid, and you must recreate it.
Note In MATLAB, you do not need to specify configuration settings using mapreducer because
mapreduce algorithms and tall array calculations automatically run in the local MATLAB session
only. If you also have Parallel Computing Toolbox, then you can use the additional mapreducer
configuration options listed on this page for running in parallel. If you have MATLAB Compiler, then
you can use separate mapreducer configuration options for running in deployed environments.
mapreducer with no input arguments creates a new mapreducer execution environment with all the
defaults and sets this to be the current mapreduce or tall array execution environment. You can use
gcmr to get the current mapreducer configuration.
• If you have default settings (Automatically create a parallel pool is enabled), and you have not
opened a parallel pool, then mapreducer opens a pool using the default cluster profile, sets gcmr
to a mapreducer based on this pool and returns this mapreducer.
10-237
10 Functions
• If you have opened a parallel pool, then mapreducer sets gcmr to a mapreducer based on the
current pool and returns this mapreducer.
• If you have disabled Automatically create a parallel pool, and you have not opened a parallel
pool, then mapreducer sets gcmr to a mapreducer based on the local MATLAB session, and
mapreducer returns this mapreducer.
mapreducer(0) specifies that mapreduce or tall array calculations run in the MATLAB client
session without using any parallel resources.
mapreducer(poolobj) specifies a parallel pool for parallel execution of mapreduce or tall arrays.
poolobj is a [Link] object. The default pool is the current pool that is returned or opened
by gcp.
mapreducer(mr) sets the global execution environment for mapreduce or tall arrays, using a
previously created MapReducer object, mr, if its ObjectVisibility property is 'On'.
mr = mapreducer( ___ ) returns a MapReducer object to specify the execution environment. You
can define several MapReducer objects, which enables you to swap execution environments by
passing one as an input argument to mapreduce or mapreducer.
Examples
Develop in Serial and Then Use Local Workers or Cluster
If you want to develop in serial and not use local workers or your specified cluster, enter:
mapreducer(0);
If you use mapreducer to change the execution environment after creating a tall array, then the tall
array is invalid and you must recreate it. To use local workers or your specified cluster again, enter:
mapreducer(gcp);
If you have turned off the Automatically create a parallel pool option, then you must explicitly
start a pool if you want to use parallel resources. See “Specify Your Parallel Settings” on page 1-35
for details.
This code shows how you can use mapreducer to set the execution environment to your local
MATLAB session and then specify a local parallel pool.
>> mapreducer(0)
>> parpool('Processes',1);
Starting parallel pool (parpool) using the 'Processes' profile ...
Connected to 1 workers.
10-238
mapreducer
>> gather(min(tall(rand(1000,1))))
ans =
5.2238e-04
Input Arguments
poolobj — Pool for parallel execution
gcp (default) | [Link] object
Output Arguments
mr — Execution environment for mapreduce and tall arrays
mapReducer object
Execution environment for mapreduce and tall arrays, returned as a MapReducer object.
If the ObjectVisibility property of mr is set to 'On', then mr defines the default execution
environment for all mapreduce algorithms and tall array calculations. If the ObjectVisibility
property is 'Off', you can pass mr as an input argument to mapreduce to explicitly specify the
execution environment for that particular call.
You can define several MapReducer objects, which enables you to swap execution environments by
passing one as an input argument to mapreduce or mapreducer.
Tips
One of the benefits of developing your algorithms with tall arrays is that you only need to write the
code once. You can develop your code locally, then use mapreducer to scale up and take advantage
of the capabilities offered by Parallel Computing Toolbox, MATLAB Parallel Server, or MATLAB
Compiler, without needing to rewrite your algorithm.
Version History
Introduced in R2014b
10-239
10 Functions
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
mapreduce | gcmr | gcp | [Link] | tall
Topics
“Big Data Workflow Using Tall Arrays and Datastores” on page 4-93
“Use Tall Arrays on a Parallel Pool” on page 4-96
“Use Tall Arrays on a Spark Cluster” on page 4-99
“Run mapreduce on a Parallel Pool” on page 4-103
“Run mapreduce on a Hadoop Cluster” on page 4-106
“Specify Your Parallel Settings” on page 1-35
10-240
methods
methods
List functions of object class
Syntax
methods(obj)
out = methods(obj)
Description
methods(obj) displays the names of all methods for the class of which obj is an instance.
Examples
Create cluster, job, and task objects, and display the names of the public methods of these objects.
c = parcluster("Processes");
methods(c)
j = createJob(c);
methods(j)
t = createTask(j,@rand,1,{3});
methods(t)
Create a distributed object and store the list of public methods of the distributed object in a
cell array.
d = rand(1000,'distributed');
m = methods(d);
Input Arguments
obj — Input object or array of objects
MATLAB object
10-241
10 Functions
Output Arguments
out — List of methods
cell array
Version History
Introduced before R2006a
See Also
help | parcluster | gpuArray | createJob | createTask
10-242
mexcuda
mexcuda
Compile MEX functions or PTX files for GPU computation
Syntax
mexcuda filenames
mexcuda option1 ... optionN filenames
Description
mexcuda filenames compiles and links source files into a shared library called a MEX file,
executable from within MATLAB. The function compiles MEX files written using the CUDA C++
framework with the NVIDIA nvcc compiler, allowing the files to define and launch GPU kernels. In
addition, the mexcuda function exposes the GPU MEX API to allow the MEX file to read and write
GPU arrays.
mexcuda is an extension of the MATLAB mex function. Only a subset of the compilers supported by
the mex function are supported by mexcuda. For more information, see “Supported Host Compilers”
on page 6-126.
mexcuda option1 ... optionN filenames builds with the specified build options. The
option1 ... optionN arguments supplement or override the default mexcuda build configuration.
You can use the most of the options available in mex with mexcuda.
Examples
Compile a simple MEX function to create the function myMexFunction from a CUDA C++ source
file.
mexcuda [Link]
Use the nvcc compiler in the NVIDIA CUDA Toolkit to compile a PTX file instead of the mexcuda
function.
10-243
10 Functions
Use verbose mode to display the compile and link commands and other information useful for
troubleshooting.
mexcuda -v [Link]
mexcuda -c [Link]
mexcuda [Link]
The first line compiles to [Link] (Windows) or myMexFunction.o (UNIX), and the
second links to create the function myMexFunction.
Compile code that uses dynamic parallelism, defining kernels that launch other kernels.
Compile a MEX function that makes use of the CUDA image primitives library, npp, which is installed
at C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\x64\[Link].
mexcuda '-LC:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\x64' -lnppi [Link]
Input Arguments
filenames — One or more file names
character vector
One or more file names, including name and file extension, specified as a character vector. If the file
is not in the current folder, specify the full path to the file. File names can be any combination of:
10-244
mexcuda
The first source code file listed in filenames is the name of the binary MEX file. To override this
naming convention, use the '-output' option.
Data Types: char
One or more build options, specified as one of these values. Options can appear in any order on any
platform, except where indicated.
Most options available for the mex function are supported. In addition, the following options are also
available.
Option Description
-dynamic Dynamic parallelism: compiles MEX files that define kernels that
launch other kernels.
-ptx Generate a parallel thread execution file (.ptx). The generated PTX
file can be used with CUDAKernel to run kernels directly from
MATLAB. Does not compile a MEX file.
-G Generate debug information for device code. This makes it possible
to step through kernel code line by line in one of NVIDIA's
debugging applications (NSight or cuda-gdb). To enable debugging
of host code use -g.
Option Reason
-compatibleArrayDims Use of the MATLAB large-array-handling API is implicit, and cannot
be overridden.
All other options for mex are supported for mexcuda. See the documentation for mex for details.
Tips
• The CUDA toolkit installed with MATLAB does not contain all libraries that are available in the
CUDA toolkit. If you want to use a specific library that is not installed with MATLAB, install the
CUDA toolkit. You can check which CUDA toolkit version MATLAB supports using gpuDevice. For
more information about the CUDA Toolkit, see “Install CUDA Toolkit (Optional)” on page 6-126.
• If the CUDA toolkit is not detected or is not a supported version, mexcuda compiles the CUDA
code using the NVIDIA nvcc compiler installed with MATLAB. To check which compiler mexcuda
is using, use the -v flag for verbose output in the mexcuda command.
• If you have installed the CUDA toolkit in a non-default location, you can specify the location of
nvcc on your system by storing it in the environment variable MW_NVCC_PATH. You can set this
variable using the MATLAB setenv command. For example,
setenv("MW_NVCC_PATH","/usr/local/CUDA/bin")
Version History
Introduced in R2015b
10-245
10 Functions
See Also
mex | CUDAKernel
Topics
“Accessing Advanced CUDA Features Using MEX” on page 6-129
“Run MEX Functions Containing CUDA Code” on page 6-124
“Run CUDA or PTX Code on GPU” on page 6-117
10-246
mpiLibConf
mpiLibConf
Location of MPI implementation
Syntax
[primaryLib,extras] = mpiLibConf
Description
[primaryLib,extras] = mpiLibConf returns the message passing interface (MPI)
implementation library that communicating jobs use. primaryLib is the name of the shared library
file containing the MPI entry points. extras specifies the names of other libraries that the MPI
library requires.
To supply an alternative MPI implementation, create a file with the name mpiLibConf and the .m
extension, and place it on the MATLAB path. The recommended location is matlabroot/toolbox/
parallel/user. Your mpiLibConf file must be higher on the path of the cluster workers than
matlabroot/toolbox/parallel/mpi. Setting mpiLibConf as a file dependency for this purpose
does not work. After your mpiLibConf file is in place, update the toolbox path caching by running
this command in the MATLAB Command Window.
rehash toolboxcache
Examples
Use the mpiLibConf function to display the current MPI implementation library for communicating
jobs.
[primaryLib,extras] = mpiLibConf
primaryLib =
'[Link]'
extras =
0×0 empty cell array
Output Arguments
primaryLib — Name of primary MPI implementation library
character vector
Name of the primary MPI implementation library that communicating jobs use, returned as a
character vector.
Data Types: char
10-247
10 Functions
Names of the other libraries that the primary MPI library needs, returned as a cell array of character
vectors.
Data Types: cell
Tips
The MPI library must support all MPI-1 functions. Additionally, the MPI library must support null
arguments to MPI_Init, as defined in section 4.2 of the MPI-2 standard. The library must also use an
mpi.h header file that is fully compatible with MPICH2.
You must launch the workers using the version of mpiexec that corresponds to the MPI library you
are using. You often need to launch the corresponding process management daemons on the cluster
before calling mpiexec.
Version History
Introduced before R2006a
See Also
rehash
Topics
“Use Different MPI Builds on UNIX Systems” (MATLAB Parallel Server)
“Toolbox Path Caching in MATLAB”
10-248
mpiprofile
mpiprofile
Profile parallel communication and execution times
Syntax
mpiprofile
mpiprofile on <options>
mpiprofile off
mpiprofile reset
mpiprofile viewer
mpiprofile resume
mpiprofile clear
mpiprofile status
stats = mpiprofile('info')
mpiprofile('viewer',stats)
Description
mpiprofile enables or disables the parallel profiler data collection on a MATLAB worker running in
a parallel pool. You can use mpiprofile either from the MATLAB client or directly from the worker
from within an spmd block. When you run mpiprofile from the MATLAB client, mpiprofile
performs the action on the MATLAB workers.
mpiprofile aggregates statistics on execution time and communication times. mpiprofile collects
statistics in a manner similar to running the profile command on each MATLAB worker. By default,
the parallel profiling extensions include array fields that collect information on communication with
each of the other workers.
mpiprofile on <options> starts the parallel profiler and clears previously recorded profile
statistics.
10-249
10 Functions
Option Description
-messagedetail default This option specifies the detail at which
communication information is stored.
-messagedetail simplified
-messagedetail default collects information on
-messagedetail off a per-worker instance.
mpiprofile off stops the parallel profiler. To reset the state of the profiler and disable collecting
communication information, use mpiprofile reset.
mpiprofile reset turns off the parallel profiler and resets the data collection back to the standard
profiler. If you do not call reset, subsequent profile commands will collect MPI information.
mpiprofile viewer stops the profiler and opens the graphical profile browser with parallel
options. The output is an HTML report displayed in the profiler window. The file listing at the bottom
of the function profile page shows several columns to the left of each line of code. In the summary
page:
mpiprofile resume restarts the profiler without clearing previously recorded function statistics.
stats = mpiprofile('info') stops the parallel profiler and returns a structure containing the
profiler statistics. stats contains the same fields as returned by profile('info'), with the
following additional fields in the FunctionTable entry. All these fields are recorded on a per-
function and per-line basis, except for the *PerLab fields.
10-250
mpiprofile
Field Description
BytesSent Records the quantity of data sent
BytesReceived Records the quantity of data received
TimeWasted Records communication waiting time
CommTime Records the communication time
CommTimePerLab Vector of communication receive time for each worker
TimeWastedPerLab Vector of communication waiting time for each worker
BytesReceivedPerLab Vector of data received from each worker
The three *PerLab fields are collected only on a per-function basis, and you can turn them off by
typing the following command:
When you run it from the MATLAB client, stats = mpiprofile('info') returns information from
all workers. When you run it on a worker, mpiprofile('info') returns the profile information
specific to that worker.
mpiprofile does not accept -timer clock options, because the communication timer clock must
be real.
For more information and examples on using the parallel profiler, see “Profiling Parallel Code” on
page 8-34.
Examples
Turn on the profiler. With default settings, turning on the profiler will create a parallel pool
automatically if there is not one already created.
mpiprofile on
A = rand(1000,'distributed');
b = sum(A, 2);
x = A\b;
mpiprofile viewer
10-251
10 Functions
The parallel profiler collects information about the execution of code on each worker and the
communications between the workers. After you profile your parallel code with mpiprofile, start
the graphical viewer by calling mpiprofile viewer.
R = rand(1e3,'distributed');
mpiprofile on
R = R*R;
mpiprofile viewer
The parallel profile viewer, opens with the Function Summary Report first, in the same way as the
standard profiler. In this view you can see profile information from any single lab or from multiple
labs simultaneously. It initially shows all functions executed on lab 1. You can then choose via the
listbox options to see profiling information from any lab.
In this view you can see Aggregate information using the Manual Comparison Selection listboxes.
When you select an Aggregate in this view, the profiler accumulates and displays the specified data
about all of the executed functions. For example,
• max Time Aggregate lists every function called in the program, and for each function, the data
from the lab that spent the most time executing it.
• min Time >0 Aggregate lists every function called in the program, and for each function, the
statistics from the lab that spent the least time executing it.
• To re-sort the table by a different field simply click the related column title (e.g. Total Comm
Time).
• To select a function and go to the Function Detail Report, click any function name that appears in
the Function Name column.
• To compare profiling information from different labs, use the Comparison listboxes and buttons
(found in the top of each page). Comparison information always displays in a maroon color font.
• To find which lab the main profiling data (black or blue text) comes from, look at the orange
highlighted text at the top of the displayed page or in the top toolbar.
The Function Detail Report displays information on the individual lines executed inside the current
function for each lab. This includes a Busy Lines table which can be used to compare the top five
lines of code on different labs. This report is only fully functional if the profiled MATLAB files are
available on the client MATLAB path.
10-252
mpiprofile
The Function Detail Report is different from the Function Summary Report in several ways:
• The report is generated for one function at a time. The function name is displayed at the top of the
page, in green or orange. Green highlighting indicates that the function spent very little (or no)
time in communication. Orange highlighting indicates more than 20% of the time was spent in
communication or waiting for communication.
• Every listbox option takes into account the last function you clicked. The current function can be
changed, if need be, by clicking the Home button in the top toolbar, which also takes you back to
the Function Summary Report.
• Profile information Aggregates from multiple labs are calculated only on a per function basis.
Therefore in the Function Detail Report, selecting max Time Aggregate displays information
from the one lab that took longest executing the current function.
• Comparisons of profiling information are only available in the top five lines shown in the Busy
Lines table (the first table from the top unless there is a parents table).
The Plot View is shown whenever you click a plot option in the Show Figures listbox. The plots
show communication and timing information from all the labs for the given function. There are two
types of plots (Histograms and Per Worker Images). The Plot Time Histograms and Plot All Per
Worker Communication options show three figures using the corresponding communication fields
returned by the mpiprofile info command.
• Plot Time Histograms shows histograms for Total Time, Total Communication Time, and
Communication Waiting Time.
• Plot All Per Worker Communication shows 2D color coded image plots for Data Received,
Receive Communication Time, and Communication Waiting Time.
• The Plot Communication Time Per Worker option in the Show Figures listbox shows only the
Receive Communication Time chart and therefore is faster to generate.
• Overall session plots: If you are in the Function Summary Report and you have not selected any
function the plots are generated for all code executed (with the profiler on).
• Per function plots: If you are in the Function Detail Report after having selected a function,
clicking any of the available plots (in the listbox shown below) will take you to the function specific
Plot View.
You can always tell which plot mode you are using by looking at the titles of each figure. The titles
show the name of the current function (or all functions when showing data for the entire session).
The titles also include the name of the profiling field being displayed (e.g., Communication Time,
Total Time). If you want to see the data for the entire profiling session after having selected a specific
function, click Home to go back to the Function Summary Report then select your desired plot (using
the listbox shown below).
10-253
10 Functions
Version History
Introduced in R2007b
Starting in R2025a, you can now profile parallel code on workers in a thread-based parallel pool.
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
profile | mpiSettings
Topics
“Profile Parallel Code” on page 8-43
10-254
mpiSettings
mpiSettings
Configure options for MPI communication
Syntax
mpiSettings('DeadlockDetection',DeadlockDetection)
mpiSettings('MessageLogging',MessageLogging)
mpiSettings('MessageLoggingDestination',MessageLoggingDestination)
Description
mpiSettings('DeadlockDetection',DeadlockDetection) toggles deadlock detection on
workers on or off. When DeadlockDectection is on, a worker can return an error if a deadlock is
detected during calls to spmdReceive and spmdSend. Although it is not necessary to enable
deadlock detection on all workers, this is the most useful option.
Examples
Turn off deadlock detection for all workers in the current parallel pool in an spmd block.
spmd
mpiSettings('DeadlockDetection','off');
end
Set deadlock detection and MPI logging for a communicating job inside the jobStartup.m file for
that job.
The jobStartup.m file runs automatically on a worker before the job starts. For information about
the jobStartup.m file, see jobStartup.
Add the following code to the jobStartup.m file for the communicating job.
mpiSettings('DeadlockDetection','on');
myLogFname = sprintf('%s_%[Link]',tempname,spmdIndex);
10-255
10 Functions
mpiSettings('MessageLoggingDestination','File',myLogFname);
mpiSettings('MessageLogging','on');
Input Arguments
DeadlockDetection — Deadlock detection option
on | off
Deadlock detection option during communication between workers, specified as a comma separated
pair of DeadlockDetection and one of these values:
• 'on' – Enable deadlock detection. This is the default state inside spmd statements.
• 'off' – Disable deadlock detection. This is the default state for communicating jobs.
Once the setting has been changed for a worker in a parallel pool, the setting stays in effect until the
parallel pool is closed.
If you are using a large number of workers, you might experience a performance increase if you
disable deadlock detection. If some workers do not call spmdSend or spmdReceive for long periods
of times, deadlock detection can cause communication errors. If you encounter errors, try disabling
deadlock detection.
Example: spmd;mpiSettings('DeadlockDetection','off');end;
Data Types: logical
MPI message logging option during communication between workers, specified as a comma
separated pair of MessageLogging and one of these values:
• 'CommandWindow' – Send MPI logging information to the MATLAB Command Window. If the task
within a communicating job is set to capture Command Window output, you can find the MPI
logging information in the task's CommandWindowOutput property.
• 'stdout' – Send MPI logging information to the standard output for the MATLAB process. If you
are using a MATLAB Job Scheduler, this is the mjs service log file.
• 'File','filename' – Send MPI logging information to the file specified as filename.
10-256
mpiSettings
Tips
• Setting the MessageLoggingDestination does not automatically enable message logging. A
separate call is required to enable message logging.
• You must call the mpiSettings function on the worker, not the client. To change MPI
communication settings within a communicating job, use mpiSettings in the task function, or in
the user-defined options in the jobStartup.m, and taskStartup.m files.
To change the MPI communication settings for all workers in a parallel pool, use mpiSettings in
the poolStartup file.
For more information, see the jobStartup, taskStartup, and poolStartup functions.
Version History
Introduced before R2006a
See Also
jobStartup | taskStartup | spmd
10-257
10 Functions
mxGPUCopyFromMxArray (C)
Copy mxArray to mxGPUArray
C Syntax
#include "gpu/mxGPUArray.h"
mxGPUArray* mxGPUCopyFromMxArray(mxArray const * const mp)
Arguments
mp
Pointer to an mxArray that contains either GPU or CPU data.
Returns
Pointer to an mxGPUArray.
Description
mxGPUCopyFromMxArray produces a new mxGPUArray object with the same characteristics as the
input mxArray.
• If the input mxArray contains a gpuArray, the output is a new copy of the data on the GPU.
• If the input mxArray contains numeric or logical CPU data, the output is copied to the GPU.
Either way, this function always allocates memory on the GPU and allocates a new mxGPUArray
object on the CPU. Use mxGPUDestroyGPUArray to delete the result when you are done with it.
Version History
Introduced in R2013a
See Also
mxGPUCopyGPUArray | mxGPUDestroyGPUArray
10-258
mxGPUCopyGPUArray (C)
mxGPUCopyGPUArray (C)
Duplicate (deep copy) mxGPUArray object
C Syntax
#include "gpu/mxGPUArray.h"
mxGPUArray* mxGPUCopyGPUArray(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray.
Returns
Pointer to an mxGPUArray.
Description
mxGPUCopyGPUArray produces a new array on the GPU and copies the data, and then returns a new
mxGPUArray that refers to the copy. Use mxGPUDestroyGPUArray to delete the result when you are
done with it.
Version History
Introduced in R2013a
See Also
mxGPUCopyFromMxArray | mxGPUDestroyGPUArray
10-259
10 Functions
mxGPUCopyImag (C)
Copy imaginary part of mxGPUArray
C Syntax
#include "gpu/mxGPUArray.h"
mxGPUArray* mxGPUCopyImag(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray. The target gpuArray must be full, not sparse.
Returns
Pointer to an mxGPUArray.
Description
mxGPUCopyImag copies the imaginary part of GPU data, and returns a new mxGPUArray object that
refers to the copy. The returned array is real, with element values equal to the imaginary values of
the input, similar to how the MATLAB imag function behaves. If the input is real rather than complex,
the function returns an array of zeros.
Use mxGPUDestroyGPUArray to delete the result when you are done with it.
Version History
Introduced in R2013a
See Also
mxGPUCopyReal | mxGPUDestroyGPUArray
10-260
mxGPUCopyReal (C)
mxGPUCopyReal (C)
Copy real part of mxGPUArray
C Syntax
#include "gpu/mxGPUArray.h"
mxGPUArray* mxGPUCopyReal(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray. The target gpuArray must be full, not sparse.
Returns
Pointer to an mxGPUArray.
Description
mxGPUCopyReal copies the real part of GPU data, and returns a new mxGPUArray object that refers
to the copy. If the input is real rather than complex, the function returns a copy of the input.
Use mxGPUDestroyGPUArray to delete the result when you are done with it.
Version History
Introduced in R2013a
See Also
mxGPUCopyImag | mxGPUDestroyGPUArray
10-261
10 Functions
mxGPUCreateComplexGPUArray (C)
Create complex GPU array from two real gpuArrays
C Syntax
#include "gpu/mxGPUArray.h"
mxGPUArray* mxGPUCreateComplexGPUArray(mxGPUArray const * const mgpR,
mxGPUArray const * const mgpI)
Arguments
mgpRmgpI
Pointers to mxGPUArray data containing real and imaginary coefficients. The target gpuArrays
must be full, not sparse.
Returns
Pointer to an mxGPUArray.
Description
mxGPUCreateComplexGPUArray creates a new complex mxGPUArray from two real mxGPUArray
objects. The function allocates memory on the GPU and copies the data. The inputs must both be real,
and have matching sizes and classes. Use mxGPUDestroyGPUArray to delete the result when you are
done with it.
Version History
Introduced in R2013a
See Also
mxGPUDestroyGPUArray
10-262
mxGPUCreateFromMxArray (C)
mxGPUCreateFromMxArray (C)
Create read-only mxGPUArray object from input mxArray
C Syntax
#include "gpu/mxGPUArray.h"
mxGPUArray const * mxGPUCreateFromMxArray(mxArray const * const mp)
Arguments
mp
Pointer to an mxArray that contains either GPU or CPU data.
Returns
Pointer to a read-only mxGPUArray object.
Description
mxGPUCreateFromMxArray produces a read-only mxGPUArray object from an mxArray.
• If the input mxArray contains a gpuArray, this function extracts a reference to the GPU data
from an mxArray passed as an input to the function.
• If the input mxArray contains CPU data, the data is copied to the GPU, but the returned object is
still read-only.
This function allocates a new mxGPUArray object on the CPU. Use mxGPUDestroyGPUArray to
delete the result when you are done with it.
Version History
Introduced in R2013a
See Also
mxGPUCopyFromMxArray | mxGPUCreateGPUArray | mxGPUDestroyGPUArray
10-263
10 Functions
mxGPUCreateGPUArray (C)
Create mxGPUArray object, allocating memory on GPU
C Syntax
#include "gpu/mxGPUArray.h"
mxGPUArray* mxGPUCreateGPUArray(mwSize const ndims,
mwSize const * const dims,
mxClassID const cid,
mxComplexity const ccx,
mxGPUInitialize const init0)
Arguments
ndims
mwSize type specifying the number of dimensions in the created mxGPUArray.
dims
Pointer to an mwSize vector specifying the sizes of each dimension in the created mxGPUArray.
cid
mxClassID type specifying the element class of the created mxGPUArray.
ccx
mxComplexity type specifying the complexity of the created mxGPUArray.
init0
mxGPUInitialize type specifying whether to initialize elements values to 0 in the created
mxGPUArray.
Returns
Pointer to an mxGPUArray.
Description
mxGPUCreateGPUArray creates a new mxGPUArray object with the specified size, type, and
complexity. It also allocates the required memory on the GPU, and initializes the memory if requested.
This function allocates a new mxGPUArray object on the CPU. Use mxGPUDestroyGPUArray to
delete the object when you are done with it.
Version History
Introduced in R2013a
10-264
mxGPUCreateGPUArray (C)
See Also
mxGPUCreateFromMxArray | mxGPUDestroyGPUArray
10-265
10 Functions
mxGPUCreateMxArrayOnCPU (C)
Create mxArray for returning CPU data to MATLAB with data from GPU
C Syntax
#include "gpu/mxGPUArray.h"
mxArray* mxGPUCreateMxArrayOnCPU(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray.
Returns
Pointer to an mxArray object containing CPU data that is a copy of the GPU data.
Description
mxGPUCreateMxArrayOnCPU copies the GPU data from the specified mxGPUArray into an mxArray
on the CPU for return to MATLAB. This is similar to the gather function. After calling this function,
the input mxGPUArray object is no longer needed and you can delete it with
mxGPUDestroyGPUArray.
Version History
Introduced in R2013a
See Also
mxGPUCreateMxArrayOnGPU | mxGPUDestroyGPUArray
10-266
mxGPUCreateMxArrayOnGPU (C)
mxGPUCreateMxArrayOnGPU (C)
Create mxArray for returning GPU data to MATLAB
C Syntax
#include "gpu/mxGPUArray.h"
mxArray* mxGPUCreateMxArrayOnGPU(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray.
Returns
Pointer to an mxArray object containing GPU data.
Description
mxGPUCreateMxArrayOnGPU puts the mxGPUArray into an mxArray for return to MATLAB. The
data remains on the GPU and the returned class in MATLAB is gpuArray. After this call, the
mxGPUArray object is no longer needed and can be destroyed.
Version History
Introduced in R2013a
See Also
mxGPUCreateMxArrayOnCPU | mxGPUDestroyGPUArray
10-267
10 Functions
mxGPUDestroyGPUArray (C)
Delete mxGPUArray object
C Syntax
#include "gpu/mxGPUArray.h"
mxGPUDestroyGPUArray(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray.
Description
mxGPUDestroyGPUArray deletes an mxGPUArray object on the CPU. Use this function to delete an
mxGPUArray object you created with:
• mxGPUCreateGPUArray
• mxGPUCreateFromMxArray
• mxGPUCopyFromMxArray
• mxGPUCopyReal
• mxGPUCopyImag, or
• mxGPUCreateComplexGPUArray.
This function clears memory on the GPU, unless some other mxArray holds a reference to the same
data. For example, if the mxGPUArray was extracted from an input mxArray, or wrapped in an
mxArray for an output, then the data remains on the GPU.
Version History
Introduced in R2013a
See Also
mxGPUCopyFromMxArray | mxGPUCopyImag | mxGPUCopyReal | mxGPUCreateComplexGPUArray |
mxGPUCreateFromMxArray | mxGPUCreateGPUArray
10-268
mxGPUGetClassID (C)
mxGPUGetClassID (C)
mxClassID associated with data on GPU
C Syntax
#include "gpu/mxGPUArray.h"
mxClassID mxGPUGetClassID(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray.
Returns
mxClassID type.
Description
mxGPUGetClassID returns an mxClassID type indicating the underlying class of the input data.
Version History
Introduced in R2013a
See Also
mxGPUGetComplexity
10-269
10 Functions
mxGPUGetComplexity (C)
Complexity of data on GPU
C Syntax
#include "gpu/mxGPUArray.h"
mxComplexity mxGPUGetComplexity(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray.
Returns
mxComplexity type.
Description
mxGPUGetComplexity returns an mxComplexity type indicating the complexity of the GPU data.
Version History
Introduced in R2013a
See Also
mxGPUGetClassID
10-270
mxGPUGetData (C)
mxGPUGetData (C)
Raw pointer to underlying data
C Syntax
#include "gpu/mxGPUArray.h"
void* mxGPUGetData(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray on the GPU. The target gpuArray must be full, not sparse.
Returns
Pointer to data.
Description
mxGPUGetData returns a raw pointer to the underlying data. Cast this pointer to the type of data that
you want to use on the device. It is your responsibility to check that the data inside the array has the
appropriate type, for which you can use mxGPUGetClassID.
Version History
Introduced in R2013a
See Also
mxGPUGetClassID | mxGPUGetDataReadOnly
10-271
10 Functions
mxGPUGetDataReadOnly (C)
Read-only raw pointer to underlying data
C Syntax
#include "gpu/mxGPUArray.h"
void const* mxGPUGetDataReadOnly(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray on the GPU. The target gpuArray must be full, not sparse.
Returns
Read-only pointer to data.
Description
mxGPUGetDataReadOnly returns a read-only raw pointer to the underlying data. Cast it to the type
of data that you want to use on the device. It is your responsibility to check that the data inside the
array has the appropriate type, for which you can use mxGPUGetClassID.
Version History
Introduced in R2013a
See Also
mxGPUGetClassID | mxGPUGetData
10-272
mxGPUGetDimensions (C)
mxGPUGetDimensions (C)
mxGPUArray dimensions
C Syntax
#include "gpu/mxGPUArray.h"
mwSize const * mxGPUGetDimensions(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray.
Returns
Pointer to a read-only array of mwSize type.
Description
mxGPUGetDimensions returns a pointer to an array of mwSize indicating the dimensions of the
input argument. Use mxFree to delete the output.
Version History
Introduced in R2013a
See Also
mxGPUGetComplexity | mxGPUGetNumberOfDimensions
10-273
10 Functions
mxGPUGetNumberOfDimensions (C)
Size of dimension array for mxGPUArray
C Syntax
#include "gpu/mxGPUArray.h"
mwSize mxGPUGetNumberOfDimensions(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray.
Returns
mwSize type.
Description
mxGPUGetNumberOfDimensions returns the size of the dimension array for the mxGPUArray input
argument, indicating the number of its dimensions.
Version History
Introduced in R2013a
See Also
mxGPUGetComplexity | mxGPUGetDimensions
10-274
mxGPUGetNumberOfElements (C)
mxGPUGetNumberOfElements (C)
Number of elements on GPU for array
C Syntax
#include "gpu/mxGPUArray.h"
mwSize mxGPUGetNumberOfElements(mxGPUArray const * const mgp)
Arguments
mgp
Pointer to an mxGPUArray.
Returns
mwSize type.
Description
mxGPUGetNumberOfElements returns the total number of elements on the GPU for this array.
Version History
Introduced in R2013a
See Also
mxGPUGetComplexity | mxGPUGetDimensions | mxGPUGetNumberOfDimensions
10-275
10 Functions
mxGPUIsSame (C)
Determine if two mxGPUArrays refer to same GPU data
C Syntax
#include "gpu/mxGPUArray.h"
int mxGPUIsSame(mxGPUArray const * const mgp1,
mxGPUArray const * const mgp2)
Arguments
mgp1mgp2
Pointers to mxGPUArray.
Returns
int type.
Description
mxGPUIsSame returns an integer indicating if two mxGPUArray pointers refer to the same GPU data:
Version History
Introduced in R2013a
See Also
mxGPUIsValidGPUData
10-276
mxGPUIsSparse (C)
mxGPUIsSparse (C)
Determine if mxGPUArray contains sparse GPU data
C Syntax
#include "gpu/mxGPUArray.h"
int mxGPUIsSparse(mxGPUArray const * mp);
Arguments
mp
Pointer to an mxGPUArray to be queried for sparse data.
Returns
Integer indicating true result:
Version History
Introduced in R2015a
See Also
mxGPUIsValidGPUData | mxIsGPUArray
10-277
10 Functions
mxGPUIsValidGPUData (C)
Determine if mxArray is pointer to valid GPU data
C Syntax
#include "gpu/mxGPUArray.h"
int mxGPUIsValidGPUData(mxArray const * const mp)
Arguments
mgp
Pointer to an mxArray.
Returns
int type.
Description
mxGPUIsValidGPUData indicates if the mxArray is a pointer to valid GPU data
If the GPU device is reinitialized in MATLAB with gpuDevice, all data on the device becomes invalid,
but the CPU data structures that refer to the GPU data still exist. This function checks whether the
mxArray is a container of valid GPU data, and returns one of the following values:
Version History
Introduced in R2013a
See Also
mxIsGPUArray
10-278
mxGPUSetDimensions (C)
mxGPUSetDimensions (C)
Modify number of dimensions and size of each dimension
C Syntax
#include "gpu/mxGPUArray.h"
void mxGPUSetDimensions(mxGPUArray * const mgp, mwSize const * const dims, mwSize const ndims);
Arguments
mgp
Pointer to an mxGPUArray
dims
Dimensions array. Each element in the dimensions array contains the size of the array in that
dimension. For example, in C, setting dims[0] to 5 and dims[1] to 7 establishes a 5-by-7
mxGPUArray.
The dims array must not increase the overall size of the mxGPUArray. This array must contain at
least ndims elements.
ndims
Number of dimensions.
Description
Call mxGPUSetDimensions to reshape an existing mxGPUArray. mxGPUSetDimensions does not
reallocate memory.
Version History
Introduced in R2018b
See Also
mxGPUGetDimensions (C)
10-279
10 Functions
mxInitGPU (C)
Initialize MATLAB GPU library on currently selected device
C Syntax
#include "gpu/mxGPUArray.h"
int mxInitGPU()
Returns
int type with one of the following values:
Description
Before using any CUDA code in your MEX file, initialize the MATLAB GPU library if you intend to use
any mxGPUArray functionality in MEX or any GPU calls in MATLAB. There are many ways to initialize
the MATLAB GPU API, including:
• Call mxInitGPU at the beginning of your MEX file before any CUDA code.
• Call gpuDevice(deviceIndex) in MATLAB before running any MEX code.
• Create a gpuArray in MATLAB before running any MEX code.
You should call mxInitGPU at the beginning of your MEX file, unless you have an alternate way of
guaranteeing that the MATLAB GPU library is initialized at the start of your MEX file.
If the library is initialized, this function returns without doing any work. If the library is not
initialized, the function initializes the default device. Note: At present, a MATLAB MEX file can work
with only one GPU device at a time.
Version History
Introduced in R2013a
See Also
gpuArray | gpuDevice
10-280
mxIsGPUArray (C)
mxIsGPUArray (C)
Determine if mxArray contains GPU data
C Syntax
#include "gpu/mxGPUArray.h"
int mxIsGPUArray(mxArray const * const mp);
Arguments
mp
Pointer to an mxArray that might contain gpuArray data.
Returns
Integer indicating true result:
Version History
Introduced in R2013a
See Also
mxGPUIsSparse | mxGPUIsValidGPUData
10-281
10 Functions
NaN
Create codistributed array of all NaN values
Syntax
cN = NaN(n,codist)
cN = NaN(sz,codist)
X = NaN(sz1,...,szN,codist)
cN = NaN( ___ ,datatype,codist)
Description
cN = NaN(n,codist) creates an n-by-n codistributed matrix of all NaN values and uses codist to
specify the distribution of the array values across the workers.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
cN = NaN(sz,codist) creates a codistributed array of all NaN values where the size vector sz
defines the size of cN. For example, NaN([2 3],"codistributed") creates a 2-by-3 codistributed
array.
cN = NaN( ___ ,datatype,codist) creates a codistributed array of all NaN values with the
underlying type datatype. For example, NaN(1,"single","codistributed") creates a
codistributed single integer NaN. You can use this syntax with any of the size arguments in the
previous syntaxes. You must specify codist after the array size and data type arguments.
cN = NaN( ___ ,"noCommunication") creates a codistributed array of all NaN values without
using communication between workers.
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
10-282
NaN
cN = NaN( ___ ,like=p) uses the array p to create a codistributed array of all NaN values. You can
also specify "noCommunication" as part of the function call.
The returned array cI has the same underlying type, sparsity, and complexity (real or complex) as p.
Examples
Create a 1000-by-1000 codistributed double matrix of NaN values, distributed by its second
dimension (columns).
spmd(4)
C = NaN(1000,"codistributed");
end
Create a 1000-by-1000 codistributed single matrix of NaN values, distributed by its columns.
spmd(4)
codist = codistributor1d(2,100*[1:spmdSize]);
C = NaN(1000,1000,"single",codist);
end
Input Arguments
n — Size of square matrix
integer
10-283
10 Functions
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
Underlying data type of the returned array, that is the data type of its elements, specified as one of
these options:
• "double"
• "single"
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p. The underlying data type of the codistributed array p
must be single or double.
Data Types: single | double
Version History
Introduced in R2006b
See Also
NaN | eye (codistributed) | false (codistributed) | Inf (codistributed) | ones
(codistributed) | true (codistributed) | zeros (codistributed)
10-284
numlabs
numlabs
(Not recommended) Number of workers running current spmd block
Note numlabs is not recommended. Use spmdSize instead. For more information, see “Version
History”.
Syntax
n = numlabs
Description
n = numlabs returns the number of workers running the current spmd block or communicating job.
This value is the maximum value that can be used with labSend and labReceive.
Examples
This example shows how to run numlabs inside and outside an spmd block.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool will run the code inside the spmd block.
Run numlabs inside and outside an spmd block. In the block, the returned value is equal to the
number of workers. Outside the block, the returned value is 1.
spmd
disp(numlabs)
end
disp(numlabs)
Worker 1:
4
Worker 2:
4
Worker 3:
4
Worker 4:
4
10-285
10 Functions
Output Arguments
n — Number of workers
positive integer scalar
Number of workers running the current spmd block or communicating job, specified as an integer. In
an spmd block, numlabs returns the number of workers running the spmd block. Outside an spmd
block, numlabs is 1.
When you create a communicating job using createCommunicatingJob, you can run a function or
script on N workers. When one of the workers runs numlabs, the returned value is N.
Version History
Introduced before R2006a
To indicate their intended use within spmd blocks, numlabs is renamed to spmdSize. numlabs will
continue to work but is no longer recommended. To update your code, replace any instance of
numlabs with spmdSize. There are no plans to remove numlabs.
See Also
spmdSize
10-286
ones
ones
Create codistributed array of all ones
Syntax
cO = ones(n,codist)
cO = ones(sz,codist)
cO = ones(sz1,...,szN,codist)
cO = ones( ___ ,datatype,codist)
Description
cO = ones(n,codist) creates an n-by-n codistributed matrix of ones and uses codist to specify
the distribution of the array values across the workers.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
cO = ones(sz,codist) creates a codistributed array of ones where the size vector sz defines the
size of cO. For example, ones([2 3],"codistributed") creates a 2-by-3 codistributed array.
cO = ones( ___ ,datatype,codist) creates a codistributed array of ones with the underlying
type datatype. For example, ones(1,"int8","codistributed") creates a codistributed 8-bit
scalar integer 1. You can use this syntax with any of the size arguments in the previous syntaxes. You
must specify codist after the array size and data type arguments.
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
10-287
10 Functions
You must specify "noCommunication" after the size, data type and codist arguments.
cO = ones( ___ ,like=p) uses the array p to create a codistributed array of ones. You can also
specify "noCommunication" as part of the function call.
The returned array cI has the same underlying type, sparsity, and complexity (real or complex) as p.
Examples
Create a 1000-by-1000 codistributed double matrix of ones, distributed by its second dimension
(columns).
spmd(4)
C = ones(1000,"codistributed");
end
Input Arguments
n — Size of square matrix
integer
10-288
ones
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
Underlying data type of the returned array, specified as one of these options:
• "double"
• "single"
• "logical"
• "int8"
• "uint8"
• "int16"
• "uint16"
• "int32"
• "uint32"
• "int64"
• "uint64"
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p.
Version History
Introduced in R2006b
10-289
10 Functions
See Also
ones | eye (codistributed) | false (codistributed) | Inf (codistributed) | NaN
(codistributed) | true (codistributed) | zeros (codistributed)
10-290
pagefun
pagefun
Apply function to each page of distributed or GPU array
Syntax
A = pagefun(FUN,B)
A = pagefun(FUN,B1,...,Bn)
[A1,...,Am] = pagefun(FUN, ___ )
Description
A = pagefun(FUN,B) applies the function specified by FUN to each page of the distributed or GPU
array B. The result A contains each page of results such that A(:,:,I,J,...) =
FUN(B(:,:,I,J,...)). A is a distributed or GPU array, depending on the array type of B. FUN is a
handle to a function that takes a two-dimensional input argument.
If you plan to make several calls to pagefun, it is more efficient to first convert that array to a
distributed or GPU array.
[A1,...,Am] = pagefun(FUN, ___ ) returns multiple output arrays A1,...,Am when the
function FUN returns m output values. pagefun calls FUN each time with as many outputs as there are
in the call to pagefun, that is, m times. If you call pagefun with more output arguments than
supported by FUN, MATLAB generates an error. FUN can return output arguments having different
data types, but the data type of each output must be the same each time FUN is called.
Examples
Create two GPU arrays, A and B. A is a two-dimensional array (a matrix) and B is a three-dimensional
array, where the first two dimensions are just like a matrix, but the third dimension represents pages
of elements.
M = 300; % output number of rows
K = 500; % matrix multiply inner dimension
N = 1000; % output number of columns
P = 200; % number of pages
A = rand(M,K,"gpuArray");
B = rand(K,N,P,"gpuArray");
Apply a matrix multiplication (mtimes) to each page of arrays A and B using pagefun.
C = pagefun(@mtimes,A,B);
s = size(C) % returns M-by-N-by-P
10-291
10 Functions
s = 1×3
Create two higher-dimensional arrays, D and E. D is an array with five dimensions and E is an array
with six dimensions.
Apply a matrix multiplication (mtimes) to each page of arrays D and E using pagefun. The
dimensions with size 1 are implicitly expanded to match the size of the other array in that dimension.
F = pagefun(@mtimes,D,E);
s = size(F) % M-by-N-by-P1-by-P2-by-P3-by-P4
s = 1×6
3 2 10 17 4 12
Input Arguments
FUN — Function
function handle
Function applied to each page of the inputs, specified as a function handle. For each output
argument, FUN must return values of the same class each time it is called.
10-292
pagefun
• @qr — For GPU arrays, the syntax [__] = pagefun(@qr,__) only supports one input array and
does not support returning the permutation matrix
• @rot90
• @svd — For GPU arrays, the row and column sizes of each page must not be larger than 32-by-32
• @transpose
• @tril
• @triu
If the inputs are distributed arrays, the supported values for FUN also include:
• @lu
B — Input array
distributed array | GPU array
Input arrays, specified as distributed arrays, GPU arrays, or arrays. At least one of the inputs
B1,...,Bn, must be a distributed or GPU array. Using both distributed and GPU array as inputs is
not supported. Each array that is stored in CPU memory is converted to a distributed or GPU array
before the function is evaluated. If you plan to make several calls to pagefun with the same array, it
is more efficient to first convert that array to a distributed or GPU array.
Output Arguments
A — Output array
distributed array | GPU array
Version History
Introduced in R2013b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
arrayfun | gather | gpuArray
10-293
10 Functions
[Link]
Namespace: [Link]
Syntax
[Link](jobID)
Description
[Link](jobID) terminates the AWS Batch
job with the ID jobID.
Note This function requires the Parallel Computing Toolbox plugin for MATLAB Parallel Server with
AWS Batch. For an example of how to use the function, see the plugin scripts.
Input Arguments
jobID — ID of the AWS Batch job
character vector | string scalar
Version History
Introduced in R2019b
See Also
[Link] |
[Link].deleteJobFilesFromS3 |
[Link]
10-294
[Link].deleteJobFilesFromS3
[Link]
mS3
Namespace: [Link]
Syntax
[Link].deleteJobFilesFromS3(job,s3Bucket,s3Prefix)
Description
[Link].deleteJobFilesFromS3(job,s3Bucket,s3Prefix)
deletes the files for job, which are located in the folder s3://s3Bucket/s3Prefix, from Amazon
S3.
Note This function requires the Parallel Computing Toolbox plugin for MATLAB Parallel Server with
AWS Batch. For an example of how to use the function, see the plugin scripts.
Input Arguments
job — MATLAB job
[Link] object
s3Bucket — S3 bucket
character vector | string scalar
S3 bucket where the job files are stored, specified as a character vector or string scalar.
Data Types: char | string
Prefix of the S3 location that contains the job files, specified as a character vector or a string scalar.
Data Types: char | string
Version History
Introduced in R2019b
10-295
10 Functions
See Also
[Link].uploadJobFilesToS3 |
[Link].downloadJobFilesFromS3
10-296
[Link].downloadJobFilesFromS3
[Link]
sFromS3
Namespace: [Link]
Syntax
[Link].downloadJobFilesFromS3(job,s3Bucket,
s3Prefix)
Description
[Link].downloadJobFilesFromS3(job,s3Bucket,
s3Prefix) downloads the output files for job job from the Amazon S3 bucket s3Bucket and saves
them to the JobStorageLocation of the cluster. This function expects output files stored in zip files
under the prefix s3Prefix/stageOut in the Amazon S3 bucket s3Bucket.
Note This function requires the Parallel Computing Toolbox plugin for MATLAB Parallel Server with
AWS Batch. For an example of how to use the function, see the plugin scripts.
Input Arguments
job — MATLAB job
[Link] object
s3Bucket — S3 bucket
character vector | string scalar
S3 bucket to download job files from, specified as a character vector or string scalar.
Data Types: char | string
Prefix of the S3 location in the S3 bucket s3Bucket that contains the output files for job, specified
as a character vector or string array.
Data Types: char | string
Version History
Introduced in R2019b
10-297
10 Functions
See Also
[Link].uploadJobFilesToS3 |
[Link].deleteJobFilesFromS3
10-298
[Link]
[Link]
Files
Namespace: [Link]
Syntax
[Link](job,taskIDs,logStreams)
Description
[Link](job,taskIDs,logStreams)
downloads log files for the tasks in job with the IDs taskIDs from the log streams logStreams in
AWS CloudWatch Logs, and saves them to the JobStorageLocation of the cluster.
Note This function requires the Parallel Computing Toolbox plugin for MATLAB Parallel Server with
AWS Batch. For an example of how to use the function, see the plugin scripts.
Input Arguments
job — MATLAB AWS Batch job
[Link] object
ID of the tasks to download logs for, specified as a numeric vector. Each task ID must have a
corresponding log stream in logStreams.
Data Types: double
Amazon CloudWatch log streams that contain the log information for each task, specified as a cell
array of character vectors or string array. Each log stream must have a corresponding task ID in
taskIDs. You can get this information from the output of
[Link].
For more information on log streams, see the Amazon CloudWatch documentation.
Data Types: string | cell
10-299
10 Functions
Version History
Introduced in R2019b
See Also
[Link] |
[Link]
10-300
[Link]
[Link]
Namespace: [Link]
Syntax
info = [Link](job)
Description
info = [Link](job) returns a table with
information on each task in the MATLAB AWS Batch job.
Note This function requires the Parallel Computing Toolbox plugin for MATLAB Parallel Server with
AWS Batch. For an example of how to use the function, see the plugin scripts.
Input Arguments
job — MATLAB AWS Batch job
[Link] object
Output Arguments
info — Task information
table
10-301
10 Functions
Note that AWS only returns information for AWS Batch jobs in the SUCCEEDED or FAILED state over
the last 24 hours. After 24 hours elapses, Status is "UNKNOWN" and LogStreamName is "".
Data Types: table
Version History
Introduced in R2019b
See Also
[Link]
10-302
[Link]
[Link]
Namespace: [Link]
Syntax
schedulerID = [Link](arraySize,
jobName,jobQueue,jobDefinition,command,environmentVariableNames,
environmentVariableValues)
Description
schedulerID = [Link](arraySize,
jobName,jobQueue,jobDefinition,command,environmentVariableNames,
environmentVariableValues) submits a job of size arraySize to the AWS Batch job queue
jobQueue. The job has the name jobName, job definition jobDefinition. The container that runs
the AWS Batch job receives and processes the command command. The job runs with the environment
variables environmentVariableNames and values environmentVariableValues. This function
returns an AWS Batch job ID.
For information about AWS Batch job queues, job definitions, and the command passed to the
container that runs the AWS Batch job, see the AWS Batch documentation.
Note This function requires the Parallel Computing Toolbox plugin for MATLAB Parallel Server with
AWS Batch. For an example of how to use the function, see the plugin scripts.
Input Arguments
arraySize — Size of job
positive integer
Size of the job, specified as a positive integer. If arraySize is greater than 1, then
submitBatchJob submits an array job. Otherwise, submitBatchJob submits a nonarray job.
Job name for the AWS Batch job, specified as a character vector or string scalar. For more
information, see the AWS Batch documentation.
Data Types: char | string
AWS Batch job queue to submit the AWS Batch job to, specified as a character vector or string scalar.
For more information, see the AWS Batch documentation.
Data Types: char | string
10-303
10 Functions
AWS Batch job definition for the AWS Batch job, specified as a character vector or string scalar. For
more information, see the AWS Batch documentation.
Data Types: char | string
Command to pass to the container that runs the AWS Batch job, specified as a character vector or
string scalar. For more information, see the AWS Batch documentation.
Data Types: char | string
Names of the environment variables to create on the AWS Batch job, specified as a cell array of
character vectors or string array. Each variable must have a corresponding value in
environmentVariableValues.
Data Types: cell | string
Values of the environment variables to create on the AWS Batch job, specified as a cell array of
character vectors or string array. Each value must have a corresponding variable in
environmentVariableValues.
Data Types: cell | string
Output Arguments
schedulerID — Scheduler ID
string scalar
Version History
Introduced in R2019b
See Also
[Link] |
[Link].uploadJobFilesToS3 |
[Link] |
[Link] |
[Link].downloadJobFilesFromS3
10-304
[Link].uploadJobFilesToS3
[Link]
S3
Namespace: [Link]
Syntax
s3Prefix = [Link].uploadJobFilesToS3(job,s3Bucket)
Description
s3Prefix = [Link].uploadJobFilesToS3(job,s3Bucket)
uploads the input files for job to the Amazon S3 bucket s3Bucket under the prefix s3Prefix/
stageIn/, where s3Prefix is a randomly generated string.
Note This function requires the Parallel Computing Toolbox plugin for MATLAB Parallel Server with
AWS Batch. For an example of how to use the function, see the plugin scripts.
Input Arguments
job — MATLAB job
[Link] object
s3Bucket — S3 bucket
character vector | string scalar
S3 bucket to upload job input files to, specified as a character vector or string scalar.
Data Types: char | string
Output Arguments
s3Prefix — Prefix of S3 location
string scalar
Prefix of the S3 location in the S3 bucket s3Bucket to which uploadJobFilesToS3 uploads files.
s3Prefix is a randomly generated string.
Data Types: char | string
Version History
Introduced in R2019b
10-305
10 Functions
See Also
[Link].downloadJobFilesFromS3 |
[Link].deleteJobFilesFromS3 |
[Link]
10-306
[Link]
[Link]
Create Hadoop cluster object
Syntax
hadoopCluster = [Link]
hadoopCluster = [Link](Name,Value)
Description
hadoopCluster = [Link] creates a [Link] object
representing the Hadoop cluster.
You use the resulting object as input to the mapreduce and mapreducer functions, for specifying the
Hadoop cluster as the parallel execution environment for tall arrays and mapreduce.
Examples
This example shows how to create and use a [Link] object to set a Hadoop
cluster as the mapreduce parallel execution environment.
hadoopCluster = [Link]('HadoopInstallFolder','/host/hadoop-install');
mr = mapreducer(hadoopCluster);
This example shows how to create and use a [Link] object to set a Hadoop
cluster as the tall array parallel execution environment.
hadoopCluster = [Link](...
'HadoopInstallFolder','/host/hadoop-install', ...
'SparkInstallFolder','/host/spark-install');
mr = mapreducer(hadoopCluster);
Before R2021a, use commas to separate each name and value, and enclose Name in quotes.
Example: 'HadoopInstallFolder','/share/hadoop/a1.2.1'
10-307
10 Functions
Path to Hadoop application configuration file, specified as the comma-separated pair consisting of
'HadoopConfigurationFile' and a character vector.
Path to Hadoop installation on the local machine, specified as the comma-separated pair consisting of
'HadoopInstallFolder' and a character vector. If this property is not set, the default is the value
specified by the environment variable HADOOP_PREFIX, or if that is not set, then HADOOP_HOME.
Path to Spark enabled Hadoop installation on worker machines, specified as the comma-separated
pair consisting of 'SparkInstallFolder' and a character vector. If this property is not set, the
default is the value specified by the environment variable SPARK_PREFIX, or if that is not set, then
SPARK_HOME.
Output Arguments
hadoopCluster — Hadoop cluster
[Link] object
Version History
Introduced in R2014b
See Also
mapreduce | mapreducer
Topics
“Use Tall Arrays on a Spark Cluster” on page 4-99
“Run mapreduce on a Hadoop Cluster” on page 4-106
“Read and Analyze Hadoop Sequence File”
10-308
[Link]
[Link]
(Not recommended) Names of all available cluster profiles
Syntax
ALLPROFILES = [Link]
[ALLPROFILES, DEFAULTPROFILE] = [Link]
Description
ALLPROFILES = [Link] returns a cell array containing the names of all
available profiles.
The cell array ALLPROFILES always contains a profile called local for the local cluster, and always
contains the default profile. If the default profile has been deleted, or if it has never been set,
[Link] returns local as the default profile.
You can create and change profiles using the saveProfile or saveAsProfile methods on a cluster
object. Also, you can create, delete, and change profiles through the Cluster Profile Manager.
Examples
Display the names of all the available profiles and set the first in the list to be the default profile.
allNames = [Link]()
[Link](allNames{1});
Version History
Introduced in R2012a
See Also
[Link]
10-309
10 Functions
[Link]
Namespace: [Link]
Syntax
allProfiles = [Link]
[allProfiles, defaultProfile] = [Link]
Description
allProfiles = [Link] returns a cell array containing the names of all the
available profiles.
The allProfile output always contains a profile called 'Processes' for the local cluster, and
always contains the default profile. If you delete or have not set the default profile,
[Link] returns 'Processes' as the default profile.
You can create and change profiles by using the saveProfile or saveAsProfile functions on a
cluster object. You can create, delete, and change profiles by using the Cluster Profile Manager. To
access the Cluster Profile manager, in the Environment area of the MATLAB desktop Home tab,
click Parallel and then click Create and Manage Clusters.
Examples
Display the names of all the available profiles and set the first in the list as the default.
allProfiles = [Link]
oldProfile = [Link](allProfiles{1});
This example shows how to display the names of all the available profiles and find the properties of
the last profile.
allNames = [Link]
allNames =
10-310
[Link]
Get the properties of the cluster identified by the last profile name in the list.
lastCluster = parcluster(allNames{end})
lastCluster =
MJS Cluster
Properties:
Name: WebCluster
Profile: WebCluster
Modified: false
Host: [Link]
Username: user1
NumWorkers: 200
NumThreads: 1
NumBusyWorkers: 72
NumIdleWorkers: 128
Associated Jobs:
Number Pending: 10
Number Queued: 0
Number Running: 12
Number Finished: 123
Version History
Introduced in R2022b
See Also
[Link] | [Link] | [Link]
10-311
10 Functions
[Link]
(Not recommended) Examine or set default cluster profile
Syntax
p = [Link]
oldprofile = [Link](newprofile)
Description
p = [Link] returns the name of the default cluster profile.
If the default profile has been deleted, or if it has never been set,
[Link] returns 'Processes' as the default profile.
You can save modified profiles with the saveProfile or saveAsProfile method on a cluster
object. You can create, delete, import, and modify profiles with the Cluster Profile Manager,
accessible from the MATLAB desktop Home tab Environment area by selecting Parallel > Create
and Manage Clusters.
Examples
Display the names of all available profiles and set the first in the list to be the default.
allProfiles = [Link]
[Link](allProfiles{1});
Version History
Introduced in R2012a
10-312
[Link]
See Also
[Link]
10-313
10 Functions
[Link]
Namespace: [Link]
Syntax
p = [Link]
oldProfile = [Link](newProfile)
Description
p = [Link] returns the name of the default cluster profile.
If you delete or have not set the default profile, [Link] returns 'Processes'
as the previous default profile.
You can save modified profiles by using the saveProfile or saveAsProfile functions on a cluster
object. You can create, delete, import, and modify profiles with the Cluster Profile Manager. To access
the Cluster Profile manager, in the Environment area of the MATLAB desktop Home tab, click
Parallel and then click Create and Manage Clusters.
Examples
Display the names of all the available profiles and set the first in the list as the default.
allProfiles = [Link]
oldProfile = [Link](allProfiles{1});
Set the profile named 'Profile2' as the new default. To backup the old profile name, store the old
profile name in a variable with the name 'oldDefault'.
oldDefault = [Link]('Profile2');
strcmp(oldDefault,'MyProfile')
ans =
10-314
[Link]
logical
Tips
• If you set a new default profile, you can keep the old profile in your MATLAB workspace in case
you need to reset the default profile.
Version History
Introduced in R2022b
See Also
[Link] | [Link]
10-315
10 Functions
[Link]
Export one or more profiles to file
Syntax
[Link](profileName, filename)
[Link]({profileName1,profileName2,...,profileNameN},filename)
Description
[Link](profileName, filename) exports the profile with the name
profileName to specified filename. The extension .mlsettings is appended to the filename, unless
already there.
[Link]({profileName1,profileName2,...,profileNameN},filename)
exports the profiles with the specified names to filename.
Examples
Export the profile named MyProfile to the file [Link].
[Link]('MyProfile','MyExportedProfile')
def_profile = [Link]();
[Link](def_profile,'MyDefaultProfile')
allProfiles = [Link]();
% Remove 'Processes' from allProfiles
notProcesses = ~strcmp(allProfiles,'Processes');
profilesToExport = allProfiles(notProcesses);
if ~isempty(profilesToExport)
[Link](profilesToExport,'AllProfiles');
end
Version History
Introduced in R2012a
See Also
[Link] | [Link]
10-316
[Link]
[Link]
Query and set forward compatibility for GPU devices
Syntax
tf = [Link]
[Link](tf)
Description
tf = [Link] returns true if forward compatibility
for GPU devices is enabled and false otherwise. The default is false.
When forward compatibility is disabled, you cannot perform computations using a GPU device with
an architecture that was released after the version of MATLAB you are using was built.
If you enable forward compatibility, then the first time you run new code on the GPU in MATLAB,
there is a brief delay while the driver recompiles the libraries.
Caution Enabling forward compatibility can result in wrong answers and unexpected behavior
during GPU computations.
For more information, see “Forward Compatibility for GPU Devices” on page 10-318.
Examples
If you have a GPU with an architecture that was released after the version of MATLAB you are using,
by default, you cannot use that GPU to perform computations in MATLAB. To use that GPU in
MATLAB, enable forward compatibility for GPU devices.
tf = [Link]
tf =
0
[Link](1)
10-317
10 Functions
Select and use the GPU device. After you have enabled forward compatibility, then the first time you
run new code on the GPU in MATLAB, there is a brief delay while the driver recompiles the libraries.
gpuDevice(2);
A = ones(100,"gpuArray");
Input Arguments
tf — Forward compatibility status to set
true or 1 | false or 0
Note Starting in R2020b, forward compatibility for GPU devices is disabled by default.
In R2020a and earlier releases, you cannot disable forward compatibility for GPU devices.
Enable forward compatibility to use a GPU device with an architecture that was released after your
version of MATLAB.
When you enable forward compatibility, the first time you run new code on the GPU in MATLAB, there
is a brief delay while the driver recompiles the libraries. To prevent a recurrence of these delays,
increase the CUDA cache size. For instructions on how to increase the CUDA cache size, see
“Increase the CUDA Cache Size” on page 10-319.
Caution Enabling forward compatibility can result in wrong answers and unexpected behavior
during GPU computations.
The degree of success of recompilation of device libraries varies depending on the device
architecture and the CUDA that MATLAB uses. In some cases, forward compatibility does not work as
expected and recompilation of the libraries results in errors.
For example, forward compatibility from CUDA version 10.0–10.2 (MATLAB versions R2019a,
R2019b, R2020a, and R2020b) to Ampere (compute capability 8.x) has limited functionality.
You can enable forward compatibility for GPU devices using either of these methods.
10-318
[Link]
To increase the CUDA cache size, set the CUDA_CACHE_MAXSIZE environment variable to a minimum
of 536870912 (512 MB).
To set environment variables on the MATLAB client, use the setenv function. If you are using
parallel workers, see “Set Environment Variables on Workers” on page 7-12.
Version History
Introduced in R2020b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
gpuDeviceCount | gpuDevice | gpuArray
Topics
“GPU Computing Requirements” on page 6-13
“Run MATLAB Functions on a GPU” on page 6-3
“Identify and Select a GPU Device” on page 6-10
“Establish Arrays on a GPU” on page 6-15
10-319
10 Functions
[Link]
Create independent random number streams on a GPU
Syntax
s = [Link](gentype)
[s1,s2,...] = [Link](gentype,NumStreams=N)
[ ___ ] = [Link](gentype,Name=Value)
Description
s = [Link](gentype) creates a single random number stream that
uses the random number generator algorithm specified by gentype.
Note The [Link] object creation function is a more concise alternative when
you want to create a single stream.
Examples
You can create multiple independent random number streams that have the same generator, seed,
and normal transformations. Here, several independent streams are created and then used to
generate independent streams of random numbers.
streams =
Now, you can use each stream to generate random numbers. In this example, you create a matrix in
which each row is generated from a different random number stream.
x = zeros(3,10,"gpuArray");
for i=1:3
10-320
[Link]
x(i,:) = rand(streams{i},1,10);
end
x
x =
0.9576 0.0054 0.2543 0.0540 0.1697 0.1365 0.7560 0.1312
0.3084 0.3396 0.6758 0.5145 0.7909 0.7709 0.3386 0.1168
0.5218 0.5625 0.7090 0.5854 0.5067 0.6528 0.5095 0.8777
Input Arguments
gentype — Random number generator algorithm
"Threefry" | "Philox" | "CombRecursive"
Random number generator algorithm, specified as one of the following three random number
generator algorithms supported on the GPU.
For more information on the differences between generating random numbers on the GPU and CPU,
see “Random Number Streams on a GPU” on page 6-72.
Example: [Link]("Philox")
Before R2021a, use commas to separate each name and value, and enclose Name in quotes.
Example: [Link]("Philox",Seed=10) creates a single random
number stream using the Philox 4x32 generator algorithm with seed 10.
Number of independent streams to be created, specified as a positive integer. The streams are
independent in a pseudorandom sense. The streams are not necessarily independent from streams
created at other times.
Indices of the streams created in this function call, specified as a positive integer or vector of positive
integers. The default value is 1:N, where N is the value specified with the NumStreams parameter.
10-321
10 Functions
The values provided for StreamIndices must be less than or equal to the value provided for
NumStreams.
Random number seed, specified as a nonnegative integer or as "shuffle". The seed specifies the
starting point for the algorithm to generate random numbers. Specify Seed as an integer when you
want reproducible results. Specifying Seed as "shuffle" seeds the generator based on the current
time.
The normal transformation algorithm to use when generating normally distributed random numbers
generated using the randn function, specified as "BoxMuller" or "Inversion".
The "BoxMuller" option supports the "Threefry" and "Philox" generator types only.
Option to return the stream objects as a cell array, specified as 0 (false) or 1 (true).
Output Arguments
s — Random number stream
[Link] object
Tips
• If you create multiple streams by calling [Link] several times, the
streams are not necessarily independent of each other. To create independent streams from
separate calls of [Link]:
• Specify the same set of values for gentype, NumStreams, and Seed in each case.
• Specify a different value for StreamIndices that is between 1 and the NumStreams value in
each case.
Version History
Introduced in R2011b
10-322
[Link]
See Also
[Link] | [Link] | gpurng |
[Link] |
[Link]
Topics
“Random Number Streams on a GPU” on page 6-72
“Generating Random Numbers on a GPU” on page 6-75
“Establish Arrays on a GPU” on page 6-15
10-323
10 Functions
[Link]
Get current global GPU random number stream
Syntax
stream = [Link]
Description
stream = [Link] returns the current global random
number stream on the GPU.
Note The gpurng function is a more concise alternative for many uses of
[Link].
Examples
defaultStr = [Link]
defaultStr =
If you change the global stream, you can use the stream defaultStr to restore the default settings.
For example, suppose that you change the global stream to a different stream.
newStr = [Link]("CombRecursive",NormalTransform="Inversion");
defaultStr = [Link](newStr)
defaultStr =
defaultStr is no longer the current global GPU stream. Once you finish your calculations using the
new global stream settings, you can reset the stream to the default settings.
newStr = [Link](defaultStr)
newStr =
10-324
[Link]
Display defaultStr.
defaultStr
defaultStr =
Output Arguments
stream — Global GPU random number stream
[Link] object
Global random number stream for generating random numbers on a GPU, returned as a
[Link] object.
Version History
Introduced in R2011b
See Also
[Link] | gpurng | [Link] |
[Link]
Topics
“Random Number Streams on a GPU” on page 6-72
“Generating Random Numbers on a GPU” on page 6-75
“Establish Arrays on a GPU” on page 6-15
10-325
10 Functions
[Link]
List random number generator algorithms on the GPU
Syntax
[Link]
Description
[Link] lists the generator algorithms that can be used when creating a
random number stream with [Link] or
[Link].
Examples
When you use [Link], MATLAB displays a list of the available random
number generators.
[Link]
For more information on the differences between generating random numbers on the GPU and CPU,
see “Random Number Streams on a GPU” on page 6-72.
Version History
Introduced in R2011b
10-326
[Link]
See Also
[Link] | gpurng | [Link] |
[Link] | [Link]
Topics
“Random Number Streams on a GPU” on page 6-72
“Generating Random Numbers on a GPU” on page 6-75
“Establish Arrays on a GPU” on page 6-15
10-327
10 Functions
[Link]
Set GPU global random number stream
Syntax
prevStream = [Link](stream)
Description
prevStream = [Link](stream) replaces the global
random number stream with the stream specified by stream.
Examples
You can change the global random number stream on the GPU and store the old settings for the
global stream. First, define the random number stream that you want to set as the new global stream.
newStr =
oldStr = [Link](newStr)
oldStr =
oldStr holds the settings for the previous global random number stream on the GPU. The new global
stream is newStr.
newStr
newStr =
10-328
[Link]
The functions rand, randi, and randn draw random numbers from the new global stream using the
"Philox" generator algorithm. If you use a GPU random number stream, then the results are
returned as a gpuArray.
Input Arguments
stream — New global random number stream
[Link] object
New global random number stream on the GPU, specified as a [Link] object.
stream replaces the previous global stream.
Output Arguments
prevStream — Previous global random number stream
[Link] object
Version History
Introduced in R2011b
See Also
[Link] | gpurng | [Link] |
[Link]
Topics
“Random Number Streams on a GPU” on page 6-72
“Generating Random Numbers on a GPU” on page 6-75
“Establish Arrays on a GPU” on page 6-15
10-329
10 Functions
[Link]
Import cluster profiles from file
Syntax
profile = [Link](filename)
Description
profile = [Link](filename) imports the profiles stored in the specified
file, filename, and returns the names of the imported profiles. If filename has no extension, the
function assumes .mlsettings is the file extension. You must specify the file extension for
configuration files with the .mat extension.
Configuration MAT files contain only one profile, but profile MLSETTINGS files can contain one or
more profiles. If the file contains only one profile, then profile is a character vector that reflects the
name of the profile. If the file contains multiple profiles, then profile is a cell array of character
vectors. If a profile with the same name as an imported profile already exists, the function adds an
extension to the name of the imported profile.
You can use the imported profile with any functions that support profiles.
[Link] does not set any of the imported profiles as the default. To set a default
profile, use the [Link] function.
During the import, [Link] upgrades profiles that you exported in a previous
release. Configurations are automatically converted to cluster profiles.
Imported profiles are saved as a part of your MATLAB settings, so these profiles are available in
subsequent MATLAB sessions without importing again.
Examples
Import a profile from the [Link] file and set it as the default cluster profile.
profile_main = [Link]('ProfileMain');
[Link](profile_main)
Import all the profiles from the [Link] file, and use the first one to open a
parallel pool.
profs = [Link]('ManyProfiles');
parpool(profs{1})
Import a configuration from the [Link] file, and set it as the default parallel
profile.
10-330
[Link]
old_conf = [Link]('[Link]')
[Link](old_conf)
Input Arguments
filename — File name of profile to import
string array | character vector
Output Arguments
profile — Name of imported profile
character vector | cell array of character vectors
Name of the imported profile, returned as a character vector or a cell array of character vectors.
Version History
Introduced in R2012a
See Also
[Link] | [Link] | [Link]
10-331
10 Functions
parcluster
Create cluster object
Syntax
c = parcluster
c = parcluster(profile)
Description
c = parcluster returns a cluster object representing the cluster identified by the default cluster
profile, with the cluster object properties set to the values defined in that profile. Use a cluster object
in functions such as parpool or batch.
Examples
This examples shows different ways of creating a cluster object from the default profile.
Find the cluster identified by the default parallel computing cluster profile, with the cluster object
properties set to the values defined in that profile.
myCluster = parcluster;
View the name of the default profile and find the cluster identified by it. Open a parallel pool on the
cluster.
defaultProfile = [Link]
myCluster = parcluster(defaultProfile);
parpool(myCluster);
Find a particular cluster using the profile named 'MyProfile', and create an independent job on
the cluster.
myCluster = parcluster('MyProfile');
j = createJob(myCluster);
Input Arguments
profile — Cluster profile
string scalar | character vector
10-332
parcluster
You can save modified profiles with the saveProfile or saveAsProfile method on a cluster
object. You can create, delete, import, and modify profiles with the Cluster Profile Manager,
accessible from the MATLAB desktop Home tab Environment area by selecting Parallel > Create
and Manage Clusters. For more information, see “Discover Clusters and Use Cluster Profiles” on
page 7-2.
Example: parcluster('MyCluster')
Data Types: char | string
Version History
Introduced in R2012a
See Also
createJob | [Link] | [Link] | parpool |
[Link]
10-333
10 Functions
parfeval
Namespace: parallel
Syntax
F = parfeval(fcn,numFcnOut,X1,...,Xm)
F = parfeval(pool,fcn,numFcnOut,X1,...,Xm)
Description
F = parfeval(fcn,numFcnOut,X1,...,Xm) schedules the function fcn to be run. MATLAB runs
the function using a parallel pool if one is available. Otherwise, it runs the function in serial.
You can share your parallel code that uses this syntax with MATLAB users who do not have Parallel
Computing Toolbox.
MATLAB asynchronously evaluates the function fcn on each worker with the specified input
arguments X1,…Xm, and returns numFcnOut output arguments.
MATLAB returns the Future object F before the function fcn finishes running. You can use
fetchOutputs to retrieve the results from the future. To stop running the function fcn, use the
cancel function. For more information about futures, see Future.
If a parallel pool is open, MATLAB uses that parallel pool to run the function fcn.
If a parallel pool is not open, the behavior depends on whether automatic pool creation is enabled.
• Automatic pool creation is enabled — MATLAB starts a parallel pool using the default cluster
profile, then uses that parallel pool to run the function fcn. Automatic pool creation is enabled by
default.
You can manually force this behavior by specifying parpool to the pool argument pool.
• Automatic pool creation is disabled — MATLAB runs the function fcn using deferred execution.
You can manually force this behavior by specifying [Link] to the pool argument
pool.
To run code in the background, see the MATLAB function page parfeval.
Examples
10-334
parfeval
Submit a single request to the parallel pool. Retrieve the outputs by using the fetchOutputs
function.
f = parfeval(@magic,1,10);
value = fetchOutputs(f);
value(1)
ans = 92
Specify multiple future requests in a for-loop, and collect the results in a vector as they become
available. For efficiency, preallocate an array of future objects before you start the loop.
f(1:10) = [Link];
for idx = 1:10
f(idx) = parfeval(@magic,1,idx);
end
Retrieve the individual future outputs as they become available by using fetchNext. If no element of
the FevalFuture object array is available when you call fetchNext, MATLAB waits until an
element becomes available.
magicResults = cell(1,10);
for idx = 1:10
[completedIdx,value] = fetchNext(f);
magicResults{completedIdx} = value;
fprintf("Got result with index: %d.\n",completedIdx)
end
Use parfeval to compute the sum of the elements in each column of a 1000-by-1000 matrix on the
pool myClusterPool. Retrieve the results.
f = parfeval(myClusterPool,@sum,1,rand(1000));
results = fetchOutputs(f)'
10-335
10 Functions
results = 1000×1
509.8296
483.2762
505.1542
479.3408
489.2463
512.2336
495.8580
499.5442
487.5374
491.4364
⋮
This example shows how to update a user interface as computations complete. When you offload
computations to workers using parfeval, all user interfaces are responsive while workers perform
the computations. You can use waitbar to create a simple user interface.
• Use afterEach to update the user interface after each computation completes.
• Use afterAll to update the user interface after all the computations complete.
Use waitbar to create a figure handle, h. When you use afterEach or afterAll, the waitbar
function updates the figure handle. For more information about handle objects, see “Handle Object
Behavior”.
h = waitbar(0,'Waiting...');
Use parfeval to calculate the real part of the eigenvalues of random matrices. With default settings,
parfeval creates a parallel pool automatically if one has not already been created. For efficiency,
preallocate an array of Future objects.
f(1:100) = [Link];
for idx = 1:100
f(idx) = parfeval(@(n) real(eig(randn(n))),1,5e2);
end
You can use afterEach to automatically invoke functions on each of the results of the parfeval
computations. Use afterEach to schedule another set of future objects to compute the largest value
in each of the output arrays after each future in the f completes.
maxFuture = afterEach(f,@max,1);
10-336
parfeval
You can use the State property to obtain the status of futures. Define an anonymous function that
updates the fractional wait bar length of h to the fraction of Future objects that have finished
executing. The updateWaitbar anonymous function computes the mean of a logical array in which
an element is true if the State property of the corresponding Future object in f is "finished".
Use afterEach and updateWaitbar to update the fractional wait bar length after each future in
maxFuture completes. Use afterAll and delete to close the wait bar after all the computations
are complete.
updateWaitbarFutures = afterEach(f,updateWaitbar,0);
afterAll(updateWaitbarFutures,@(~) delete(h),0)
Use afterAll and histogram to show a histogram of the results in maxFuture after all the futures
complete.
showsHistogramFuture = afterAll(maxFuture,@histogram,0);
10-337
10 Functions
Input Arguments
fcn — Function to run on worker
function handle
10-338
parfeval
Number of output arguments requested from the function fcn, specified as a nonnegative integer.
numFcnOut is the number of output arguments you request when you run fcn(X1,...,Xm).
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Input arguments, specified as a comma-separated list of variables or expressions. The parallel pool
worker inputs these arguments to the function fcn.
pool — Pool
[Link] object
Example: parpool("Processes");
Example: backgroundPool;
Output Arguments
F — Future
[Link] object
Version History
Introduced in R2013b
Starting in R2021b, you can now run parfeval in serial with no pool. This behavior allows you to
share parallel code that you write with users who do not have Parallel Computing Toolbox.
When you use the syntax parfeval(fcn,numFcnOut,X1,...,Xm), MATLAB tries to use an open
parallel pool if you have Parallel Computing Toolbox. If a parallel pool is not open, MATLAB will
create one if automatic pool creation is enabled.
If parallel pool creation is disabled or if you do not have Parallel Computing Toolbox, the function is
evaluated in serial. In previous releases, MATLAB threw an error instead.
10-339
10 Functions
Extended Capabilities
Automatic Parallel Support
Accelerate code by automatically running computation in parallel using Parallel Computing Toolbox™.
For more information, see “Run MATLAB Functions with Automatic Parallel Support” on page 1-9.
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
parfeval | cancel | ticBytes | tocBytes | afterEach | afterAll | fetchNext |
fetchOutputs | [Link] | parfevalOnAll | parpool | wait | Future |
pctRunOnAll
Topics
“Query and Cancel parfeval Futures” on page 3-5
“Plot During Parameter Sweep with parfeval” on page 3-31
10-340
parfevalOnAll
parfevalOnAll
Namespace: parallel
Syntax
F = parfevalOnAll(p,fcn,numFcnOut,X1,...,Xm)
F = parfevalOnAll(fcn,numFcnOut,X1,...,Xm)
Description
F = parfevalOnAll(p,fcn,numFcnOut,X1,...,Xm) requests the asynchronous execution of the
function fcn on all workers in the parallel pool p. The parfevalOnAll function evaluates fcn on
each worker with input arguments X1,...,Xm and returns numFcnOut output arguments. You can
obtain the results from the Future object F when all workers have completed running fcn.
Note Use parfevalOnAll instead of parfor or spmd if you want to use clear. This preserves
workspace transparency. See “Ensure Transparency in parfor-Loops or spmd Statements” on page 2-
51.
Examples
You can use the parfevalOnAll function to run a clean up function on all the workers while
preserving workspace transparency.
For example. to unload a mex file before deleting temporary folders for distributing simulations, run
the clear function on all the workers using parfevalOnAll. Because clear has 0 output
arguments, specify 0 to the numFcnOut input argument of parfevalOnAll.
parfevalOnAll(@clear,0,"mex");
To close all Simulink model windows on all the workers, run the bdclose using the parfevalOnAll
function.
p = gcp; % Get the current parallel pool
f = parfevalOnAll(p,@bdclose,0,"all");
In both cases, wait for completion and verify success by using the fetchOutputs function. Even
when you do not request output arguments, you can use fetchOutputs on the future to check for
errors from the workers.
10-341
10 Functions
fetchOutputs(f)
Input Arguments
p — Parallel pool
[Link] object
Parallel pool of workers, specified as a [Link] object. You can create a parallel pool by
using the parpool function.
Number of output arguments requested from the function fcn, specified as a nonnegative integer.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Input arguments, specified as a comma-separated list of variables or expressions. The parallel pool
worker inputs these arguments to the function fcn.
Output Arguments
F — Future
[Link] object
Version History
Introduced in R2013b
Starting in R2021b, you can now run parfevalOnAll in serial with no pool. This behavior allows you
to share parallel code that you write with users who do not have Parallel Computing Toolbox.
10-342
parfevalOnAll
If parallel pool creation is disabled or if you do not have Parallel Computing Toolbox, the function is
evaluated in serial. In previous releases, MATLAB threw an error instead.
Extended Capabilities
Automatic Parallel Support
Accelerate code by automatically running computation in parallel using Parallel Computing Toolbox™.
For more information, see “Run MATLAB Functions with Automatic Parallel Support” on page 1-9.
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
cancel | fetchNext | fetchOutputs | [Link] | parfeval | parpool | wait |
pctRunOnAll
10-343
10 Functions
parfor
Execute for-loop iterations in parallel on workers
Syntax
parfor loopVar = initVal:endVal; statements; end
parfor (loopVar = initVal:endVal,M); statements; end
parfor (loopVar = initVal:endVal,opts); statements; end
parfor (loopVar = initVal:endVal,cluster); statements; end
parfor (loopVar = initVal:endVal,pool); statements; end
Description
parfor loopVar = initVal:endVal; statements; end executes for-loop iterations in
parallel on workers in a parallel pool.
MATLAB executes the loop body commands in statements for values of loopVar between initVal
and endVal. loopVar specifies a vector of integer values increasing by 1. If you have Parallel
Computing Toolbox, the iterations of statements can execute on a parallel pool of workers on your
multi-core computer or cluster. As with a for-loop, you can include a single line or multiple lines in
statements.
To find out how parfor can help increase your throughput, see “Decide When to Use parfor” on page
2-2.
• Loop iterations are executed in parallel in a nondeterministic order. This means that you might
need to modify your code to use parfor. For more help, see “Convert for-Loops into parfor-
Loops” on page 2-7.
• Loop iterations must be consecutive, increasing integer values.
• The body of the parfor-loop must be independent. One loop iteration cannot depend on a
previous iteration, because the iterations are executed in a nondeterministic order. For more help,
see “Ensure That parfor-Loop Iterations Are Independent” on page 2-10.
• You cannot use a parfor-loop inside another parfor-loop. For more help, see “Nested parfor and
for-Loops and Other parfor Requirements” on page 2-13.
By default, MATLAB uses the available workers in your parallel pool. You can change the default
number of workers in your parallel pool using the PreferredPoolNumWorkers property of the
default profile. For all factors that can affect your default pool size, see “Factors That Affect Pool
Size” on page 1-32. You can override the default number of workers in a parallel pool by using the
parpool function. When no workers are available in the pool or M is zero, MATLAB still executes the
loop body in a nondeterministic order, but not in parallel. Use this syntax to switch between parallel
and serial execution when testing your code.
10-344
parfor
With this syntax, to execute the iterations in parallel, you must have a parallel pool of workers. By
default, if you execute parfor, you automatically create a parallel pool of workers on the parallel
environment defined by your default profile. The default parallel environment is Processes. You can
change your profile in Parallel Settings. For more details, see “Specify Your Parallel Settings” on
page 1-35.
Examples
Create a parfor-loop for a computationally intensive task and measure the resulting speedup.
In the MATLAB Editor, enter the following for-loop. To measure the time elapsed, add tic and toc.
tic
n = 200;
A = 500;
a = zeros(1,n);
for i = 1:n
a(i) = max(abs(eig(rand(A))));
end
toc
Run the new script, and run it again. The first run is slower than the second run, because the parallel
pool has to be started, and you have to make the code available to the workers. Note the elapsed time
for the second run.
10-345
10 Functions
By default, MATLAB automatically opens a parallel pool of workers on your local machine.
Observe that you speed up your calculation by converting the for-loop into a parfor-loop on four
workers. You might reduce the elapsed time further by increasing the number of workers in your
parallel pool. For more information, see “Convert for-Loops into parfor-Loops” on page 2-7 and “Scale
Up parfor-Loops to Cluster and Cloud” on page 2-55.
You can specify the maximum number of workers M for a parfor-loop. Set M =0 to run the body of
the loop in the desktop MATLAB, without using workers, even if a pool is open. When M = 0,
MATLAB still executes the loop body in a nondeterministic order, but not in parallel, so that you can
check whether your parfor-loops are independent and suitable to run on workers. This is the
simplest way to allow you to debug the contents of a parfor-loop. You cannot set breakpoints
directly in the body of the parfor-loop, but you can set breakpoints in functions called from the body
of the parfor-loop.
Specify M = 0 to run the body of a parfor-loop in the desktop MATLAB, even if a pool is open.
To control the number of workers in your parallel pool, see “Specify Your Parallel Settings” on page 1-
35 and parpool.
To measure how much data is transferred to and from the workers in your current parallel pool, add
ticBytes(gcp) and tocBytes(gcp) before and after the parfor-loop. Use gcp as an argument to
get the current parallel pool.
delete(gcp('nocreate'))
tic
ticBytes(gcp);
n = 200;
A = 500;
a = zeros(1,n);
parfor i = 1:n
a(i) = max(abs(eig(rand(A))));
end
tocBytes(gcp)
toc
Run the new script, and run it again. The first run is slower than the second run, because the parallel
pool has to be started, and you have to make the code available to the workers.
10-346
parfor
By default, MATLAB automatically opens a parallel pool of workers on your local machine.
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
...
BytesSentToWorkers BytesReceivedFromWorkers
__________________ ________________________
1 15340 7024
2 13328 5712
3 13328 5704
4 13328 5728
Total 55324 24168
You can use the ticBytes and tocBytes results to examine the amount of data transferred to and
from the workers in a parallel pool. In this example, the data transfer is small. For more information
about parfor-loops, see “Decide When to Use parfor” on page 2-2 and “Convert for-Loops into
parfor-Loops” on page 2-7.
Create a cluster object using the parcluster function, and create a set of parfor options with it.
By default, parcluster uses your default cluster profile. Check your default profile on the MATLAB
Home tab, in Parallel > Select Parallel Environment.
cluster = parcluster;
To run parfor computations directly in the cluster, pass the cluster object as the second input
argument to parfor.
When you use this approach, parfor can use all the available workers in the cluster, and workers
become available as soon as the loop completes. This approach is also useful if your cluster does not
support parallel pools. If you want to control other options, including partitioning of iterations, use
parforOptions.
values = [3 3 3 7 3 3 3];
parfor (i=1:numel(values),cluster)
out(i) = norm(pinv(rand(values(i)*1e3)));
end
Use this syntax to run parfor on a large cluster without consuming workers for longer than necessary.
You can specify the pool to run a parfor-loop when you want to use a pool other than the pool the
gcp function returns.
Start a parallel pool of 30 workers on a cluster with the profile name myCluster
myClusterPool = parpool("myCluster",30);
Create a pool partition using the first 12 workers from the pool.
parforWorkers = [Link](1:12);
parforPool = partition(myClusterPool,"Workers",parforWorkers);
10-347
10 Functions
To run the parfor-loop on the pool partition, pass the parforPool pool object as the second input
argument to parfor.
values = [3 8 5 7 3 12 3];
parfor(idx = 1:numel(values),parforPool)
a(idx) = norm(pinv(rand(values(i)*1e3)));
end
Input Arguments
loopVar — Loop index
integer
Loop index variable with initial value initVal and final value endVal. The variable can be any
numeric type and the value must be an integer.
Make sure that your parfor-loop variables are consecutive increasing integers. For more help, see
“Troubleshoot Variables in parfor-Loops” on page 2-21.
The range of the parfor-loop variable must not exceed the supported range. For more help, see
“Avoid Overflows in parfor-Loops” on page 2-21.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Initial value loop index variable, loopVar. The variable can be any numeric type and the value must
be an integer. With endVal, specifies the parfor range vector, which must be of the form M:N.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Final value loop index variable, loopVar. The variable can be any numeric type and the value must
be an integer. With initVal, specifies the parfor range vector, which must be of the form M:N.
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Loop body, specified as text. The series of MATLAB commands to execute in the parfor-loop.
You might need to modify your code to use parfor-loops. For more help, see “Convert for-Loops into
parfor-Loops” on page 2-7
Do not nest parfor-loops, see “Nested parfor and for-Loops and Other parfor Requirements” on page
2-13.
Maximum number of workers running in parallel, specified as a nonnegative integer. If you specify an
upper limit, MATLAB uses no more than this number, even if additional workers are available. If you
10-348
parfor
request more workers than the number of available workers, then MATLAB uses the maximum
number of workers available at the time of the call. If the loop iterations are fewer than the number
of workers, some workers perform no work.
If parfor cannot run on multiple workers (for example, if only one core is available or M is 0),
MATLAB executes the loop in a serial manner. In this case, MATLAB still executes the loop body in a
nondeterministic order. Use this syntax to switch between parallel and serial when testing your code.
parfor options, specified as a ClusterOptions object. Use the parforOptions function to create
a set of parfor options.
Example: opts = parforOptions(parcluster);
cluster — Cluster
[Link]
Cluster, specified as a [Link] object, on which parfor runs. To create a cluster object,
use the parcluster function.
Example: cluster = parcluster('Processes')
Data Types: [Link]
Tips
• Use a parfor-loop when:
• You have many loop iterations of a simple calculation. parfor divides the loop iterations into
groups so that each thread can execute one group of iterations.
• You have some loop iterations that take a long time to execute.
• Do not use a parfor-loop when an iteration in your loop depends on the results of other
iterations.
Reductions are one exception to this rule. A reduction variable accumulates a value that depends
on all the iterations together, but is independent of the iteration order. For more information, see
“Reduction Variables” on page 2-35.
• When you use parfor, you have to wait for the loop to complete to obtain your results. Your client
MATLAB is blocked and you cannot break out of the loop early. If you want to obtain intermediate
results, or break out of a for-loop early, try parfeval instead.
• Unless you specify a cluster object, a parfor-loop runs on the existing parallel pool. If no pool
exists, parfor starts a new parallel pool, unless the automatic starting of pools is disabled in your
parallel settings. If there is no parallel pool and parfor cannot start one, the loop runs serially in
the client session.
10-349
10 Functions
• If the AutoAttachFiles property in the cluster profile for the parallel pool is set to true,
MATLAB performs an analysis on a parfor-loop to determine what code files are necessary for its
execution, see listAutoAttachedFiles. Then MATLAB automatically attaches those files to the
parallel pool so that the code is available to the workers.
• You cannot call scripts directly in a parfor-loop. However, you can call functions that call scripts.
• Do not use clear inside a parfor loop because it violates workspace transparency. See “Ensure
Transparency in parfor-Loops or spmd Statements” on page 2-51.
• You can run Simulink models in parallel with the parsim command instead of using parfor-loops.
For more information and examples of using Simulink in parallel, see “Running Multiple
Simulations” (Simulink).
• For GPU computations:
• Do not use a parfor-loop if you have a single GPU and your loop iterations all use the same
GPU. GPUs contain many microprocessors that can perform computations in parallel and trying
to further parallelize GPU computations using a parfor-loop is unlikely to speed up your code.
• Use a parfor-loop if you have multiple GPUs and your computations use GPU-enabled
functions. For more information about using multiple GPUs in a parfor-loop, see “Run
MATLAB Functions on Multiple GPUs” on page 6-19.
Version History
Introduced in R2008a
You can now specify the parallel pool that the parfor function uses to evaluate statements. Use this
syntax to evaluate parfor statements on a pool other than the pool the gcp function returns.
Starting in R2024b, you can now use colon-vector indexing expressions to index sliced input and
output variables in parfor-loops. The colon-vector indexing expression must be in the form j:k or
j:k:l.
For example, to assign values only to columns 3 to 7 of the output variable out, use the vector 3:7 as
a subscript when you index the sliced variable.
out = zeros(10);
parfor i = 1:10
out(i,3:7) = rand(1,5);
end
You can use either simple broadcast variables or scalar integer constants in the colon-vector indexing
expressions. Temporary variables or complicated expressions are not supported.
Starting in R2024a, you can now specify the maximum number of workers when running parfor-
loops on a thread-based parallel pool.
10-350
parfor
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
for | gcp | listAutoAttachedFiles | parpool | parfeval | ticBytes | tocBytes | send |
afterEach | parforOptions
Topics
“Decide When to Use parfor” on page 2-2
“Convert for-Loops into parfor-Loops” on page 2-7
“Ensure That parfor-Loop Iterations Are Independent” on page 2-10
“Nested parfor and for-Loops and Other parfor Requirements” on page 2-13
“Troubleshoot Variables in parfor-Loops” on page 2-21
“Scale Up parfor-Loops to Cluster and Cloud” on page 2-55
“Specify Your Parallel Settings” on page 1-35
“Run Parallel Simulations” (Simulink)
10-351
10 Functions
parforOptions
Options set for parfor
Syntax
opts = parforOptions(cluster)
opts = parforOptions(pool)
opts = parforOptions( ___ ,Name,Value)
Description
opts = parforOptions(cluster) creates a set of options for parfor using the cluster object
cluster. To specify options for a parfor-loop, use the parfor (loopVar=initVal:endval,
opts); statements; end syntax.
opts = parforOptions(pool) creates a set of options for parfor using the pool object pool.
When you create multiple pools, use this syntax to specify which pool to run the parfor-loop on.
Tip When you run a parfor-loop, MATLAB automatically uses a parallel pool to run the loop, if one
is available.
If you only need to run a parfor-loop using your default cluster profile or an available parallel pool,
consider using the parfor loopVar=initVal:endval; statements; end syntax instead of
using parforOptions.
opts = parforOptions( ___ ,Name,Value) creates a set of options for parfor using one or
more name-value arguments. For example, use parforOptions(pool,"MaxNumWorkers",M) to
run a parfor-loop using the pool object pool and a maximum of M workers. Specify name-value
arguments after all other input arguments.
Examples
Create a cluster object using the parcluster function, and create a set of parfor options with it.
By default, parcluster uses your default cluster profile. Check your default profile on the
MATLAB® Home tab, in Parallel > Select Parallel Environment.
cluster = parcluster;
opts = parforOptions(cluster);
To run parfor computations directly in the cluster, pass the parfor options as the second input
argument to parfor.
When you use this approach, parfor can use all the available workers in the cluster, and workers
become available as soon as the loop completes. This approach is also useful if your cluster does not
support parallel pools.
10-352
parforOptions
values = [3 3 3 7 3 3 3];
parfor (i=1:numel(values),opts)
out(i) = norm(pinv(rand(values(i)*1e3)));
end
Use this syntax to run parfor on a large cluster without consuming workers for longer than necessary.
You can control how parfor divides iterations into subranges for the workers with parforOptions.
Controlling the range partitioning can optimize performance of a parfor-loop. For best performance,
try to split into subranges that are:
• Large enough that the computation time is large compared to the overhead of scheduling the
subrange
• Small enough that there are enough subranges to keep all workers busy
To partition iterations into subranges of fixed size, create a set of parfor options, set
'RangePartitionMethod' to 'fixed', and specify a subrange size with 'SubrangeSize'.
opts = parforOptions(parcluster,'RangePartitionMethod','fixed','SubrangeSize',2);
Pass the parfor options as the second input argument to parfor. In this case, parfor divides
iterations into three groups of 2 iterations.
values = [3 3 3 3 3 3];
parfor (i=1:numel(values),opts)
out(i) = norm(pinv(rand(values(i)*1e3)));
end
To partition iterations into subranges of varying size, pass a function handle to the
'RangePartitionMethod' name-value pair. This function must return a vector of subrange sizes,
and their sum must be equal to the number of iterations. For more information on this syntax, see
“RangePartitionMethod” on page 10-0 .
Pass the parfor options as the second input argument to parfor. In this case, parfor divides
iterations into four groups of 2, 1, 1, and 2 iterations.
values = [3 3 7 7 3 3];
parfor (i=1:numel(values),opts)
out(i) = norm(pinv(rand(values(i)*1e3)));
end
You can use parforOptions to run parfor on the workers of a parallel pool. Use this approach
when you want to reserve a fixed number of workers for the parfor-loop. You can also have finer
control on how parfor divides iterations for workers.
10-353
10 Functions
Create a parallel pool using the parpool function. By default, parpool uses your default profile.
Check your default profile on the MATLAB Home tab, in Parallel > Select Parallel Environment.
Create a set of parfor options with the parallel pool object, and specify options. For example, specify
subranges of fixed size 2 as the partitioning method.
p = parpool;
opts = parforOptions(p,'RangePartitionMethod','fixed','SubrangeSize',2);
Pass the parfor options as the second input argument to the parfor function. parfor runs the loop
body on the parallel pool and divides iterations according to opts.
values = [3 3 3 3 3 3];
parfor (i=1:numel(values),opts)
out(i) = norm(pinv(rand(values(i)*1e3)));
end
When you run parfor with or without a parallel pool, by default, MATLAB performs an automatic
dependency analysis on the loop body. MATLAB transfers required files to the workers before running
the statements. In some cases, you must explicitly transfer those files to the workers. For more
information, see “Identify Program Dependencies”.
If you are using parfor without a parallel pool, use parforOptions to transfer files. Create a
cluster object using the parcluster option. Create a set of parfor options with the cluster object
using the parforOptions function. To transfer files to the workers, use the 'AttachedFiles'
name-value pair.
cluster = parcluster;
opts = parforOptions(cluster,'AttachedFiles',{'[Link]'});
Pass the parfor options as the second input argument to the parfor function. The workers can
access the required files in the loop body.
parfor (i=1:2,opts)
M = csvread('[Link]',0,2*(i-1),[0,2*(i-1),1,1+2*(i-1)]);
out(i) = norm(rand(ceil(norm(M))*1e3));
end
Input Arguments
cluster — Cluster
[Link] object
pool — Pool
[Link] object
10-354
parforOptions
Example: parpool('Processes');
Example: backgroundPool;
Before R2021a, use commas to separate each name and value, and enclose Name in quotes.
Example: opts = parforOptions(cluster,"AttachedFiles","[Link]");
Method for partitioning iterations into subranges, specified as "auto", "fixed", or a function
handle. A subrange is a contiguous block of loop iterations that parfor runs as a group on a worker.
Use this argument to optimize the performance of your parfor-loop by specifying how iterations are
distributed across workers.
When you use a pool to run the loop, nw is the number of workers in the parallel pool. When
you use a cluster to run the loop without a pool, nw is the NumWorkers property of the cluster.
• sizes is an integer vector of subrange sizes. For any value of n and nw, the sum of the vector
sizes must be equal to n.
Example: parforOptions(cluster,"RangePartitionMethod","auto")
Example: parforOptions(cluster,"RangePartitionMethod",@(n,nw) ones(1,n))
10-355
10 Functions
When you use this argument, you must specify the RangePartitionMethod argument as "fixed".
Example: parforOptions(cluster,"RangePartitionMethod","fixed","SubrangeSize",5)
Folders to add to the MATLAB search path of each worker running the parfor-loop, specified as a
character vector, string scalar, string array, or cell array of character vectors.
The folders are added to the search path of the workers when you run the parfor-loop. When the
parfor-loop finishes, these folders are removed from the search path of the workers.
If the client and workers have different paths to the same folder, specify the folder using the path on
the workers. For example, if the path to the folder is /shared/data on the client and /
organization/shared/data on the workers, specify "/organization/shared/data".
If you specify relative paths such as "../myFolder", the paths are resolved relative to the current
working directory on the workers.
Specify AdditionalPaths to avoid copying files unnecessarily from the client to workers. Specify
AdditionalPaths only when the files are available on the workers. If the files are not available, use
AttachedFiles to send files to the workers.
Example: opts = parforOptions(cluster,"AdditionalPaths",["/additional/path1","/
additional/path2"])
Files and folders to send to each worker running the parfor-loop, specified as a character vector,
string scalar, string array, or cell array of character vectors.
The files and folders are sent to workers when you run the parfor-loop. When the parfor-loop
finishes, these files and folders are removed from the file system of each worker.
If you specify relative paths such as "../myFolder", the paths are resolved relative to the current
working directory on the client.
If the files are available on the workers, specify AdditionalPaths instead. When you specify
AdditionalPaths, you avoid copying files unnecessarily from the client to workers.
10-356
parforOptions
If you specify AutoAddClientPath as true, the user-added entries are added to the path of each
worker when you run the parfor-loop. When the parfor-loop finishes, these entries are removed
from the path of each worker.
When you offload computations to workers, any files that are required for computations on the client
must also be available on the workers. If you specify AutoAttachFiles as true, the client attempts
to automatically detect and attach such files. If you specify AutoAttachFiles as false, you turn off
automatic detection on the client. If automatic detection cannot find all the files, or if sending files
from client to worker is slow, use the following arguments.
• If the files are in a folder that is not accessible on the workers, specify the files using the
AttachedFiles argument. The cluster copies each file you specify from the client to workers.
• If the files are in a folder that is accessible on the workers, you can use the AdditionalPaths
argument instead. Use the AdditionalPaths argument to add paths to the MATLAB search path
of each worker and avoid copying files unnecessarily from the client to workers.
Automatically detected files are sent to workers when you run the parfor-loop. When the parfor-
loop finishes, these files and folders are removed from the file system of each worker.
• If you specify MaxNumWorkers as a finite positive integer, your parfor-loop will run with a
maximum of MaxNumWorkers workers.
• If you specify MaxNumWorkers as Inf, your parfor-loop will run with as many workers as are
available.
Version History
Introduced in R2019a
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
10-357
10 Functions
See Also
parfor | parpool | parcluster
Topics
“Profile Parallel Code” on page 8-43
10-358
parpool
parpool
Create parallel pool on cluster
Syntax
parpool
parpool(poolsize)
parpool(resources)
parpool(resources,poolsize)
parpool( ___ ,Name=Value)
poolobj = parpool( ___ )
Description
parpool starts a parallel pool of workers using the default profile. With default settings, MATLAB
starts a pool on the local machine with one worker per physical CPU core up to the limit set in the
default profile. For more information on parallel settings, see “Specify Your Parallel Settings” on page
1-35.
In general, the pool size is specified by the PreferredPoolNumWorkers property of the default
profile. For all factors that can affect your pool size, see “Factors That Affect Pool Size” on page 1-32.
parpool enables the full functionality of the parallel language features in MATLAB by creating a
special job on a pool of workers, and connecting the MATLAB client to the parallel pool. Parallel
language features include parfor, parfeval, parfevalOnAll, spmd, and distributed. If
possible, the working folder on the workers is set to match that of the MATLAB client session.
parpool(poolsize) creates and returns a pool with the specified number of workers. poolsize
can be a positive integer or a range specified as a 2-element vector of integers. If poolsize is a
range, the resulting pool has size as large as possible in the range requested.
Specifying the poolsize overrides any value specified in the PreferredPoolNumWorkers property,
and starts a pool of exactly that number of workers, even if it has to wait for them to be available.
Most clusters have a maximum number of workers they can start. If the profile specifies a MATLAB
Job Scheduler cluster, parpool reserves its workers from among those already running and available
under that MATLAB Job Scheduler. If the profile specifies a local or third-party scheduler, parpool
instructs the scheduler to start the workers for the pool.
parpool( ___ ,Name=Value) applies the specified values for certain properties when starting the
pool.
poolobj = parpool( ___ ) returns a [Link] object to the client workspace representing
the pool on the cluster. You can use the pool object to programmatically delete the pool or to access
its properties. Use delete(pool) to shut down the parallel pool.
Examples
10-359
10 Functions
Start a parallel pool using the default profile to define the number of workers. With default settings,
the default pool is on the local machine.
parpool
You can create pools on different types of parallel environments on your local machine.
For more information on parallel environments, see “Choose Between Thread-Based and Process-
Based Environments” on page 1-43.
Create an object representing the cluster identified by the default profile, and use that cluster object
to start a parallel pool. The pool size is determined by the default profile.
c = parcluster
parpool(c)
Start a parallel pool with the default profile, and pass two code files to the workers.
parpool(AttachedFiles=["mod1.m","mod2.m"])
If you have access to several GPUs, you can perform your calculations on multiple GPUs in parallel
using a parallel pool.
To determine the number of GPUs that are available for use in MATLAB, use the gpuDeviceCount
function.
10-360
parpool
availableGPUs = gpuDeviceCount("available")
availableGPUs = 3
Start a parallel pool with as many workers as available GPUs. For best performance, MATLAB assigns
a different GPU to each worker by default.
parpool("Processes",availableGPUs);
To identify which GPU each worker is using, call gpuDevice inside an spmd block. The spmd block
runs gpuDevice on every worker.
spmd
gpuDevice
end
Use parallel language features, such as parfor or parfeval, to distribute your computations to
workers in the parallel pool. If you use gpuArray enabled functions in your computations, these
functions run on the GPU of the worker. For more information, see “Run MATLAB Functions on a
GPU” on page 6-3. For an example, see “Run MATLAB Functions on Multiple GPUs” on page 6-19.
When you are done with your computations, shut down the parallel pool. You can use the gcp
function to obtain the current parallel pool.
delete(gcp("nocreate"));
If you want to use a different choice of GPUs, then you can use gpuDevice to select a particular GPU
on each worker, using the GPU device index. You can obtain the index of each GPU device in your
system using the gpuDeviceCount function.
Suppose you have three GPUs available in your system, but you want to use only two for a
computation. Obtain the indices of the devices.
[availableGPUs,gpuIndx] = gpuDeviceCount("available")
availableGPUs = 3
gpuIndx = 1×3
1 2 3
useGPUs = [1 3];
Start your parallel pool. Use an spmd block and gpuDevice to associate each worker with one of the
GPUs you want to use, using the device index. The spmdIndex function identifies the index of each
worker.
parpool("Processes",numel(useGPUs));
10-361
10 Functions
spmd
gpuDevice(useGPUs(spmdIndex));
end
As a best practice, and for best performance, assign a different GPU to each worker.
When you are done with your computations, shut down the parallel pool.
delete(gcp("nocreate"));
Create a parallel pool with the default profile, and later delete the pool.
poolobj = parpool;
delete(poolobj)
Input Arguments
poolsize — Size of parallel pool
positive integer | 2-element vector of integers
Size of the parallel pool, specified as a positive integer or a range specified as a 2-element vector of
integers. If poolsize is a range, the resulting pool has size as large as possible in the range
requested. Set the default preferred number of workers in the cluster profile.
Resources to start the pool on, specified as "Processes", "Threads", a cluster profile name or
cluster object.
• "Processes" – Starts a pool of process workers on the local machine. For more information on
process-based environments, see “Choose Between Thread-Based and Process-Based
Environments” on page 1-43.
10-362
parpool
• "Threads" – Starts a pool of thread workers on the local machine. For more information on
thread-based environments, see “Choose Between Thread-Based and Process-Based
Environments” on page 1-43.
• Profile name – Starts a pool on the cluster specified by the profile. For more information on cluster
profiles, see “Discover Clusters and Use Cluster Profiles” on page 7-2.
• Cluster object – Starts a pool on the cluster specified by the cluster object. Use parcluster to
get a cluster object.
Example: parpool("Processes")
Example: parpool("Threads")
Example: parpool("myClusterProfile",16)
Example: c = parcluster; parpool(c)
Data Types: char | string | [Link]
Before R2021a, use commas to separate each name and value, and enclose Name in quotes.
Example: AttachedFiles="myFun.m"
Paths to add to the MATLAB search path of the workers at the time of pool creation, specified as a
character vector, string or string array, or cell array of character vectors.
The default search path might not be the same on the workers as it is on the client; the path
difference could be the result of different current working folders (cwd), platforms, or network file
system access. Specifying the AdditionalPaths name-value argument helps ensure that workers
look for files, such as code files, data files, or model files, in the correct locations.
You can use AdditionalPaths to access files in a shared file system. Note that path representations
can vary depending on the target machines. AdditionalPaths must be the paths as seen by the
machines in the cluster. For example, if Z:\data on your local Windows machine is /network/data
to your Linux cluster, then add the latter to AdditionalPaths. If you use a datastore, use
'AlternateFileSystemRoots' instead to deal with other representations. For more information,
see “Set Up Datastore for Processing on Different Machines or Clusters”.
Note that AdditionalPaths only helps to find files when you refer to them using a relative path or
file name, and not an absolute path.
Example: "/network/data/"
Data Types: char | string | cell
10-363
10 Functions
Files to attach to pool, specified as a character vector, string or string array, or cell array of character
vectors.
parpool starts a parallel pool and passes the identified files to the workers in the pool. The files
specified here are appended to the AttachedFiles property specified in the applicable parallel
profile to form the complete list of attached files. The AttachedFiles property name is case
sensitive, and must appear as shown.
Example: ["myFun.m","myFun2.m"]
Data Types: char | cell
Flag to specify if user-added entries on the client path are added to path of each worker at startup,
specified as a logical value.
Data Types: logical
Names of environment variables to copy from the client session to the workers, specified as a
character vector, string or string array, or cell array of character vectors. The names specified here
are appended to the EnvironmentVariables property specified in the applicable parallel profile to
form the complete list of environment variables. Any variables listed which are not set are not copied
to the workers. These environment variables are set on the workers for the duration of the parallel
pool.
Data Types: char | cell
Flag to specify if spmd support is enabled on the pool, specified as a logical value. You can disable
support only on a local or MATLAB Job Scheduler cluster. parfor iterations do not involve
communication between workers. Therefore, if SpmdEnabled is false, a parfor-loop continues
even if one or more workers aborts during loop execution.
Data Types: logical
Time in minutes after which the pool shuts down if idle, specified as an integer greater than zero. A
pool is idle if it is not running code on the workers. By default the IdleTimeout property value is the
same as the value in your parallel settings. For more information on parallel settings, see “Specify
Your Parallel Settings” on page 1-35.
Example: pool = parpool(IdleTimeout=120)
Output Arguments
poolobj — Access to parallel pool from client
[Link] object
10-364
parpool
Tips
• The pool status indicator in the lower-left corner of the desktop shows the client session
connection to the pool and the pool status. Click the icon for a menu of supported pool actions.
• cd
• addpath
• rmpath
This behavior allows you to set the working folder and the command search path on all the
workers, so that subsequent pool activities such as parfor-loops execute in the proper context.
When changing folders or adding a path with cd or addpath on clients with Windows operating
systems, the value sent to the workers is the UNC path for the folder if possible. For clients with
Linux operating systems, it is the absolute folder location.
If any of these commands does not work on the client, it is not executed on the workers either. For
example, if addpath specifies a folder that the client cannot access, the addpath command is not
executed on the workers. However, if the working folder can be set on the client, but cannot be set
as specified on any of the workers, you do not get an error message returned to the client
Command Window.
Be careful of this slight difference in behavior in a mixed-platform environment where the client is
not the same platform as the workers, where folders local to or mapped from the client are not
available in the same way to the workers, or where folders are in a nonshared file system. For
example, if you have a MATLAB client running on a Microsoft Windows operating system while the
MATLAB workers are all running on Linux operating systems, the same argument to addpath
cannot work on both. In this situation, you can use the function pctRunOnAll to assure that a
command runs on all the workers.
10-365
10 Functions
Another difference between client and workers is that any addpath arguments that are part of
the matlabroot folder are not set on the workers. The assumption is that the MATLAB install
base is already included in the workers' paths. The rules for addpath regarding workers in the
pool are:
addpath("P1",
"P2",
"C:\Applications\matlab\T3",
"C:\Applications\matlab\T4",
"P5",
"C:\Applications\matlab\T6",
"P7",
"P8");
Because T3, T4, and T6 are subfolders of matlabroot, they are not set on the workers' paths. So
on the workers, the pertinent part of the path resulting from this command is:
P1
P2
<worker original matlabroot folders...>
P5
P7
P8
• If you are using Macintosh or Linux, and see problems during large parallel pool creation, see
“Recommended System Limits for Macintosh and Linux” on page 2-78.
Version History
Introduced in R2013b
Add folders to the MATLAB search path of workers in the parallel pool using the AdditionalPaths
name-value argument to ensure that workers look for files in the correct locations.
Starting in R2024a, parpool supports pools with up to 2000 workers. Before R2024a, parpool
supports pools with up to 1000 workers.
10-366
parpool
Starting in R2022b, the local profile has been renamed to Processes. There are no plans to
remove local. To start a parallel pool of process workers on the local machine, use Processes
instead.
Starting in R2022b, you can now specify the pool size of a thread-based parallel pool using the
parpool(poolsize) syntax.
See Also
Composite | delete | distributed | gcp | [Link] |
[Link] | parfor | parfeval | parfevalOnAll | pctRunOnAll | spmd |
parcluster
Topics
“Specify Your Parallel Settings” on page 1-35
“Discover Clusters and Use Cluster Profiles” on page 7-2
“Pass Data to and from Worker Sessions” on page 5-12
“Set Environment Variables on Workers” on page 7-12
10-367
10 Functions
partition
Namespace: parallel
Syntax
newPool = partition(pool,"MaxNumWorkersPerHost",MaxNumWorkersPerHost)
newPool = partition(pool,"MaxNumWorkersPerGPU",MaxNumWorkersPerGPU)
newPool = partition(pool,"Workers",Workers)
[newPool,remainingPool] = partition(pool, ___ )
Description
partition divides an existing parallel pool into pool partitions, allowing you to use specific
resources from the existing pool. Use the partition function to create pools that target specific
resources or to create multiple pools to execute more than one parallel workflow at a time.
A host is a machine that runs MATLAB workers. On a local pool, the host is your computer. On a
cluster pool, the hosts are the machines within the cluster. A cluster pool can have workers running
on multiple hosts.
If a host runs fewer pool workers than the number of workers you request, the partition function
allocates all available workers from that host to newPool.
A GPU must be attached to the same host as a MATLAB worker to be assigned to the worker. If the
partition function is unable to assign the requested number of workers to a GPU, the function
allocates all workers that it can assign to the GPU to newpool. On hosts with multiple GPUs, the
number of MATLAB workers and GPUs on the host determines the maximum number of workers that
the partition function can assign to each GPU. On hosts that do not have a GPU, the partition
function returns an empty pool unless other hosts in the pool have GPUs.
This partitioning method uses the result of the gpuDevice function on each parallel pool worker to
determine which worker is associated with which GPU. The partition function considers only
workers with an allocated GPU and does not modify the property values of any GPU. The partition
function executes code on all workers in pool to gather gpuDevice information. If any worker is
busy executing a parfeval computation, the partition function waits until the parfeval
computation completes.
10-368
partition
Examples
Partition a parallel pool to allocate one worker per GPU, which is useful for GPU-intensive
computations.
For this example, the myCluster profile requests a parallel pool with four GPUs. Start a parallel pool
of 12 workers using the myCluster profile.
pool = parpool("myCluster",12);
[gpuWorkers,cpuWorkers] = partition(pool,"MaxNumWorkersPerGPU",1);
You can use the CPU pool to execute work at the same time as the GPU pool.
Allocating one worker per host can be beneficial for tasks that require a significant amount of
memory or CPU resources per worker.
Start a parallel pool with 15 workers using the remote cluster profile myMJSCluster. The
myMJSCluster creates a pool with three hosts.
myClusterPool = parpool("myMJSCluster",15);
[perHostPool,remainingPool] = partition(myClusterPool,"MaxNumWorkersPerHost",1);
10-369
10 Functions
Isolating a single worker can be useful when you need to run tasks on a dedicated worker.
Start a parallel pool, and use the Workers property of the pool object to obtain the
[Link] objects for the workers in the pool.
pool = parpool("Processes");
allWorkers = [Link];
Partition the pool to isolate the first worker in the allWorkers array.
[singleWkrPool,remainingPool] = partition(pool,"Workers",allWorkers(1));
singleWkrPool =
Connected: true
NumWorkers: 1
Busy: false
Cluster: Processes (Local Cluster)
AttachedFiles: {}
AutoAddClientPath: true
FileStore: [1x1 [Link]]
ValueStore: [1x1 [Link]]
IdleTimeout: 30 minutes (26 minutes remaining)
SpmdEnabled: true
Input Arguments
pool — Input pool object
[Link] object
The partition function attempts to assign at least MaxNumWorkersPerGPU workers to each unique
GPU of the input pool. If a GPU has fewer than MaxNumWorkersPerGPU assigned workers,
partition selects all available workers.
10-370
partition
To obtain [Link] objects, you can use the Workers property of the input pool. You can
also use the getCurrentWorker function on the pool workers you want to target to return their
[Link] objects.
Example: allWorkers = [Link];
Output Arguments
newPool — Parallel pool with partitioned workers
[Link] object
Tips
• The pool partition contains some workers from the input pool therefore both the input pool and its
partitions can schedule work on the same workers. Consequently, using one pool can delay the
execution of work on other pools. Deleting any pool instance deletes the underlying collection of
workers and any parallel job running on the pool. All pools using the same collection of resources
become invalid. If you no longer need a pool partition, allow the instance to go out of scope rather
than explicitly deleting it.
• The NumWorkers property value of the pool partition reflects the number of workers the pool can
use.
• The new pool shares some properties with the input pool. Changes to these properties affect all
pools. These shared properties are:
• AttachedFiles
• FileStore
• ValueStore
• IdleTimeout
Version History
Introduced in R2025a
10-371
10 Functions
See Also
Functions
parpool
Objects
[Link] | [Link]
Topics
“Partition Parallel Pools to Optimize Resource Use” on page 7-14
“Partition Pools for Efficient Resource Management in Concurrent Parallel Workflows” on page 7-36
10-372
pause
pause
Pause MATLAB Job Scheduler queue
Syntax
pause(mjs)
Description
pause(mjs) pauses the processing of jobs in the queue of the MATLAB Job Scheduler cluster
represented by the [Link] object mjs. Jobs waiting in the queued state do not
run. Jobs that are already running are paused after completion of tasks that are already running. No
further jobs or tasks run until you call the resume function for the cluster.
If the MATLAB Job Scheduler is already paused, the pause function has no effect.
Examples
This example shows how to pause processing the jobs in the queue of a MATLAB Job Scheduler
cluster.
Create a cluster object that represents the MATLAB Job Scheduler cluster with the cluster profile
MJS_profile.
c = parcluster(MJS_profile);
pause(c);
To resume processing the jobs in the cluster queue, use the resume function.
resume(c);
Input Arguments
mjs — MATLAB Job Scheduler cluster
[Link] cluster object
Version History
Introduced before R2006a
10-373
10 Functions
See Also
resume | wait
Topics
“Program Independent Jobs for a Supported Scheduler” on page 5-34
10-374
pctconfig
pctconfig
Configure settings for Parallel Computing Toolbox client session or MATLAB Parallel Server workers
Syntax
pctconfig(Name,Value)
config = pctconfig(Name,Value,...)
config = pctconfig()
Description
pctconfig(Name,Value) sets configuration properties for the client session or workers using
name-value arguments.
Name-value arguments can be in any format supported by the set function, i.e., character vectors,
structures, and cell arrays. If you provide name-value arguments using a structure, the structure field
names must be the property names and the field values must specify the property values.
config = pctconfig() returns the current configuration settings as the structure config. If you
have not set any values, these are the default values.
Examples
This example shows how to configure the settings for a Parallel Computing Toolbox client session.
config = pctconfig()
config =
Set the current client session port range to 21000-22000 with hostname fdm4.
pctconfig('hostname','fdm4','portrange',[21000 22000]);
10-375
10 Functions
pctconfig('hostname','[Link]');
This example shows how to specify which listening ports a MATLAB Parallel Server worker must
open.
Set the worker to open a listening port in the range 27350 – 27424 using the poolStartup.m file.
The poolStartup.m file runs automatically on a worker each time the worker forms part of a
parallel pool. For information about the poolStartup.m file, see poolStartup. Add the following
code to the poolStartup.m file:
pctconfig(portrange=[27350 27424])
Before R2021a, use commas to separate each name and value, and enclose Name in quotes.
Example: 'hostname','[Link]'
This property is useful when the client computer is known by more than one hostname. Specify a
hostname by which the cluster nodes can contact the client computer. Parallel Computing Toolbox
supports both short hostnames and fully qualified domain names.
Range of ports to use when opening a listening port, specified as one of the following:
• two-element vector — Specify the range of ports to use, in the form [minport, maxport]
• 0 — Specify ephemeral ports
By default, the client session searches for available ports to communicate with MATLAB Parallel
Server workers.
MATLAB Parallel Server workers use the range of port numbers to listen for connections from the
client session when you create an interactive parallel pool. To open a listening port on a worker,
specify a value for 'portrange' in the poolStartup file. For an example, see “Configure Settings
on Worker” on page 10-376.
10-376
pctconfig
Output Arguments
config — Configuration settings
structure
Tips
The values set by this function do not persist between MATLAB client or worker sessions. To ensure
your configuration settings are correct, use pctconfig before calling any other Parallel Computing
Toolbox functions.
Version History
Introduced in R2008a
Use the pctconfig function with the 'portrange' name-value argument to open listening ports on
MATLAB Parallel Server workers.
10-377
10 Functions
pctRunDeployedCleanup
Clean up after deployed parallel applications
Syntax
pctRunDeployedCleanup
Description
pctRunDeployedCleanup performs necessary cleanup so that the client JVM can properly
terminate when the deployed application exits. All deployed applications that use Parallel Computing
Toolbox functionality need to call pctRunDeployedCleanup after the last call to Parallel Computing
Toolbox functionality.
After calling pctRunDeployedCleanup, you should not use any further Parallel Computing Toolbox
functionality in the current MATLAB session.
Version History
Introduced in R2010a
10-378
pctRunOnAll
pctRunOnAll
Run command on client and on all workers in parallel pool
Syntax
pctRunOnAll command
Description
pctRunOnAll command runs the specified command on all the workers in the parallel pool and on
the client. The function also prints any command-line output in the client Command Window. The
specified command runs in the workspace of the workers and does not return any variables. Use this
function to perform any setup changes on all the workers in the parallel pool and the client.
Note If you use pctRunOnAll to run commands that modify the MATLAB search path in a mixed-
platform environment, the commands can generate a warning on the client while executing properly
on the workers. For example, if your workers are all running on a Linux operating system and your
client is running on a Microsoft Windows operating system, an addpath command with Linux-
compatible paths warns on the Windows-based client.
Examples
Use the pctRunOnAll function to run commands on the client and all workers.
Change the working folder on the client and all workers to the project folder.
pctRunOnAll cd /opt/projects/c1456
Use the system command to execute the system command hostname on the client and all the
workers. Return the output in cmdout.
Input Arguments
command — MATLAB command to run
MATLAB command
10-379
10 Functions
MATLAB command to run, specified as a MATLAB command with any necessary input and output
arguments.
Example: clear functions
Limitations
• pctRunOnAll does not support thread-based pools, such as those you create by calling
parpool("Threads") and the backgroundPool.
Alternative Functionality
Alternatively, to modify the MATLAB search path in a mixed-platform environment, use the
parfevalOnAll function to run commands on only the workers.
Version History
Introduced in R2008a
See Also
parpool | parfevalOnAll | parfeval
Topics
“Run Code on Parallel Pools” on page 1-28
10-380
pload
pload
(Removed) Load file into parallel session
Note pload has been removed. Use dload instead. For more information, see Version History.
Syntax
pload(fileroot)
Arguments
fileroot Part of filename common to all saved files being loaded.
Description
pload(fileroot) loads the data from the files named [fileroot num2str(spmdIndex)] into
the workers running a communicating job. The files should have been created by the psave
command. The number of workers should be the same as the number of files. The files should be
accessible to all the workers. Any codistributed arrays are reconstructed by this function. If
fileroot contains an extension, the character representation of the spmdIndex will be inserted
before the extension. Thus, pload('abc') attempts to load the file [Link] on worker 1,
[Link] on worker 2, and so on.
Examples
Create three variables — one replicated, one variant, and one codistributed. Then save the data. (This
example works in a communicating job or in pmode, but not in a parfor or spmd block.)
clear all;
rep = speye(spmdSize);
var = magic(spmdIndex);
D = eye(spmdSize,codistributor());
psave('threeThings');
Clear the workspace on all the workers and confirm there are no variables.
clear all
whos
Load the previously saved data into the workers. Confirm its presence.
pload('threeThings');
whos
isreplicated(rep)
iscodistributed(D)
10-381
10 Functions
Version History
Introduced in R2006b
The pload function has been removed. To load data on the workers, in the form of Composite arrays
or distributed arrays, use the dload instead.
The pload function issues a warning that it will be removed in a future release.
See Also
dload
10-382
pmode
pmode
(Removed) Interactive Parallel Command Window
Note pmode has been removed. Use spmd instead. For more information, see Version History.
Syntax
pmode start
pmode start numworkers
pmode start prof numworkers
pmode quit
pmode exit
pmode client2lab clientvar workers workervar
pmode lab2client workervar worker clientvar
pmode cleanup prof
Description
pmode allows the interactive parallel execution of MATLAB commands. pmode achieves this by
defining and submitting a communicating job, and opening a Parallel Command Window connected to
the workers running the job. The workers then receive commands entered in the Parallel Command
Window, process them, and send the command output back to the Parallel Command Window.
Variables can be transferred between the MATLAB client and the workers.
pmode start starts pmode, using the default profile to define the cluster and number of workers.
(The initial default profile is Processes; you can change it by using the function
[Link].) You can also specify the number of workers using pmode start
numworkers.
pmode start prof numworkers starts pmode using the Parallel Computing Toolbox profile prof
to locate the cluster, submits a communicating job with the number of workers identified by
numworkers, and connects the Parallel Command Window with the workers. If the number of
workers is specified, it overrides the minimum and maximum number of workers specified in the
profile.
pmode quit or pmode exit stops the pmode job, deletes it, and closes the Parallel Command
Window. You can enter this command at the MATLAB prompt or the pmode prompt.
pmode client2lab clientvar workers workervar copies the variable clientvar from the
MATLAB client to the variable workervar on the workers identified by workers. If workervar is
omitted, the copy is named clientvar. workers can be either a single index or a vector of indices.
You can enter this command at the MATLAB prompt or the pmode prompt.
pmode lab2client workervar worker clientvar copies the variable workervar from the
worker identified by worker, to the variable clientvar on the MATLAB client. If clientvar is
omitted, the copy is named workervar. You can enter this command at the MATLAB prompt or the
pmode prompt. Note: If you use this command in an attempt to transfer a codistributed array to the
client, you get a warning, and only the local portion of the array on the specified worker is
10-383
10 Functions
transferred. To transfer an entire codistributed array, first use the gather function to assemble the
whole array into the worker workspaces.
pmode cleanup prof deletes all communicating jobs created by pmode for the current user
running on the cluster specified in the profile prof, including jobs that are currently running. The
profile is optional; the default profile is used if none is specified. You can enter this command at the
MATLAB prompt or the pmode prompt.
You can invoke pmode as either a command or a function, so the following are equivalent.
Examples
In this example, the pmode prompt (P>>) indicates commands entered in the Parallel Command
Window. Other commands are entered in the MATLAB Command Window.
Start pmode using the default profile to identify the cluster and number of workers.
pmode start
Version History
Introduced in R2006b
The pmode function has been removed. To execute commands interactively on multiple workers, use
spmd instead.
The pmode function issues a warning that it will be removed in a future release.
See Also
spmd
10-384
poll
poll
Retrieve data sent to pollable data queue
Syntax
data = poll(pollablequeue)
data = poll(pollablequeue,timeout)
[data,tf] = poll( ___ )
Description
data = poll(pollablequeue) retrieves one item of data from the
[Link] object specified by pollablequeue.
• If data is in the queue, poll returns the oldest item of data in the queue, even if the queue is
closed.
• If no data is in the queue, poll returns [].
• If the queue is closed and no data is in the queue, poll returns [].
• If data is in the queue, poll returns the oldest item of data in the queue, even if the queue is
closed.
• If no data is in the queue, poll waits up to timeout seconds. If the queue receives data before
timeout seconds elapse, poll returns that item. If no data is received in the queue before
timeout seconds elapse, poll returns [].
• If the queue is closed or is closed during timeout and no data is in the queue, poll does not wait
and returns [].
[data,tf] = poll( ___ ) tries to retrieve data from the queue. If poll returns data, tf is true.
You can use this syntax with any of the input argument combinations in the previous syntaxes. For
example, [data,tf] = poll(pollablequeue,5) waits to retrieve data from the queue
pollablequeue for five seconds.
Examples
Run a parfor-loop, and send a message, such as data with the value 1.
parfor idx = 1
send(p,idx);
end
10-385
10 Functions
poll(p)
This example shows how to return intermediate results from a worker to the client and to display the
result on the client.
Construct a PollableDataQueue. A PollableDataQueue is most useful for sending and polling for
data during asynchronous function evaluations using parfeval or parfevalOnAll.
q = [Link];
Start a timer and send the data queue as input to the function for parfeval execution on the pool.
Display the time elapsed and the data returned.
f = parfeval(@workerFcn, 0, q);
msgsReceived = 0;
starttime = tic;
while msgsReceived < 2
[data, gotMsg] = poll(q, 1);
if gotMsg
fprintf('Got message: %s after %.3g seconds\n', ...
data, toc(starttime));
msgsReceived = msgsReceived + 1;
else
fprintf('No message available at %.3g seconds\n', ...
toc(starttime));
end
end
function workerFcn(q)
send(q,'start');
pause(3);
send(q,'stop');
end
The first message is returned in 0.39 s after you have executed parfeval. In that time the data and
function for parfeval have been serialized, sent over to the workers, deserialized and set running.
When you start the code, the worker sends some data, which is serialized, sent over the network back
to the client and put on a data queue. poll notes this operation and returns the value to the client
10-386
poll
function. Then the time taken since parfeval was called is displayed. Note a delay of 3 s while the
worker is computing something (in this case a long pause).
Input Arguments
pollablequeue — Pollable data queue
PollableDataQueue
The destination behavior of the queue, set using the Destination argument of the
[Link] function, determines where you can poll for data:
You must call poll on the client or worker in which you created the pollable data queue.
If you close a PollableDataQueue using the close function, you can no longer send data to the
queue but you can continue poll for data in the queue.
Example: data = poll(pollablequeue);
Optional timeout interval (in seconds) used to block poll before returning, specified as a scalar.
Example: data = poll(pollablequeue,timeout);
Output Arguments
data — Message or data
scalar | vector | matrix | array | string | character vector
Flag to specify if data has been returned, returned as a logical true or false.
Example: [data,tf] = poll(pollablequeue,timeout);
Data Types: logical
Version History
Introduced in R2017a
10-387
10 Functions
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
Functions
afterEach | send | parfor | parpool | parfeval | parfevalOnAll
Objects
PollableDataQueue | DataQueue
Topics
“Transfer Data Between Workers Using Pollable Data Queues” on page 3-44
“Send Messages to Workers Using Pollable Data Queues” on page 3-36
“Receive Communication on Workers” on page 3-23
10-388
Pool Dashboard
Pool Dashboard
Monitor and visualize activity on parallel pools
Description
Use the Pool Dashboard to collect and visualize monitoring data for interactive parallel pools.
• Collect monitoring data on how pool workers execute parallel constructs like parfor, parfeval,
and spmd.
• Track the amount of data (in bytes) the client and workers send and receive.
• Understand the time each worker spends processing their portion of the parallel code.
• Examine communication patterns and identify bottlenecks and load-balancing issues.
10-389
10 Functions
Examples
This example shows how to use the Pool Dashboard to diagnose performance bottlenecks in parallel
computations with parfor.
You have a computational task that calculates the maximum absolute eigenvalue of a 2-by-2
submatrix extracted from a large matrix. Initially, you implement this task using a for-loop. To
accelerate the computation, you convert the for-loop into a parfor-loop, and run the parfor-loop
on a pool with six workers. When you compare the execution times, the parfor-loop takes
significantly longer than the serial for-loop. You can use the Pool Dashboard to investigate why the
execution time for the parfor-loop is much larger than the serial for-loop.
To start collecting monitoring data, in the Monitoring section, select Start Monitoring. Start a
parallel pool if you do not currently have an open parallel pool.
To collect monitoring data, in the MATLAB Command Window, run this code.
n = 10000;
data = magic(n);
out = zeros(n,1);
parfor idx = 2:n
thisData = idx*data(idx-1:idx,idx-1:idx);
out(idx) = max(abs(eig(thisData)));
end
Visualize the monitoring data. In the Monitoring section, select Update. The Pool Dashboard
displays the monitoring results.
10-390
Pool Dashboard
Review the monitoring data. The Timeline graph shows a visual representation of the time the
workers and client spend running the parfor-loop and transferring data. Dark blue indicates time
spent running the parfor-loop, light blue represents time spent sending data, and magenta
represents time spent receiving data. You can observe that the workers spend the first two to three
seconds of the computation receiving data from the client. Some workers also spend a considerable
amount of time waiting to receive data from the client.
The Worker Summary table below the Timeline graph summarizes the information in the Timeline
graph. To view the whole table, click the three dots on the right of the Worker Summary table and
select Maximize.
The workers spend a short time running the computations compared to transferring data. You can
observe that the client sends a total of 4.47 GB of data to the workers and the workers each receive
762.95 MB of data while executing the parfor-loop. The parfor-loop requires all the workers to
receive a copy of the input data, which introduces data transfer overheads to the computation that
the for-loop does not have. The high parallel overhead dominates the computing time and this
indicates the for-loop does not benefit from conversion into a parfor-loop.
10-391
10 Functions
However, if you need to run a parfor-loop multiple times using the same set of data, you can
optimize the parfor-loop by transferring the input data to the workers only once using a Constant
object. This is a one off cost, and the workers have access to the data until you clear the Constant
object.
To understand how using a Constant object optimizes the parfor-loop, run this code in the
Command Window.
n = 10000;
data = magic(n);
out = zeros(n,1);
C = [Link](data);
Visualize the monitoring data. On the Monitoring tab, in the Monitoring section, select Update.
The Pool Dashboard updates the displayed monitoring results.
10-392
Pool Dashboard
To view the monitoring data for only the parfor-loop that uses the Constant object, in the Parallel
Constructs panel, select the last row in the table. When you use the Constant object to transfer data
to the workers before you run the parfor-loop, the workers only spend time running the
computations.
10-393
10 Functions
Programmatic Use
parpoolDashboard opens the Pool Dashboard.
Limitations
• Pool Dashboard is not supported on parallel pools of thread workers.
• Pool Dashboard is not supported on batch parallel pools. For a programmatic workflow, use an
ActivityMonitor object instead. For details, see “Programmatically Collect Pool Monitoring
Data” on page 8-26.
• The Timeline graph only displays information for a maximum of 32 workers.
10-394
Pool Dashboard
Version History
Introduced in R2025a
See Also
Functions
results | stop | start
Objects
ActivityMonitor | ActivityMonitorResults
Topics
“Monitor Pool Workers with Pool Dashboard” on page 8-2
“Optimize parfor-Loops with Pool Dashboard” on page 8-18
10-395
10 Functions
poolStartup
File for user-defined options to run on each worker when parallel pool starts
Syntax
poolStartup
Description
poolStartup runs automatically on a worker each time the worker forms part of a parallel pool. You
do not call this function from the client session, nor explicitly as part of a task function.
To define the pool initialization on the worker, add MATLAB code to the poolStartup.m file. The
worker looks for poolStartup.m in this order, executing the first one it finds:
matlabroot/toolbox/parallel/user/poolStartup.m
matlabroot/toolbox/parallel/user/poolStartup.m
Use the poolStartup function to run startup code required for parallel execution on the parallel
pool. For example, you might want to include code for using mpiSettings. Because jobStartup
and taskStartup execute before poolStartup, they are not suited to pool-specific code. Use
taskStartup for setup code on your worker regardless of whether the task is from an independent
job, communicating job, or using a parallel pool. Use poolStartup to setup code for pool usage only.
For further details on poolStartup and its implementation, see the text in the installed
poolStartup.m file.
Version History
Introduced in R2010a
See Also
jobStartup | taskFinish | taskStartup
10-396
promote
promote
Promote job in MATLAB Job Scheduler cluster queue
Syntax
promote(job)
promote(c,job)
Description
promote(job) promotes the job object, job, that is in a MATLAB Job Scheduler cluster queue.
If job is not the first job in the queue, promote exchanges the position of job and the job before it in
the queue.
promote(c,job) promotes the job object, job, that is queued in the MATLAB Job Scheduler cluster
c.
If job is not the first job in the queue, promote exchanges the position of job and the job before it in
the queue.
Examples
Create and submit multiple jobs to the cluster identified by the default cluster profile, assuming that
the default cluster profile uses a MATLAB Job Scheduler.
c = parcluster;
j1 = createJob(c,'Name',"Job A");
t1 = createTask(j1,@rand,1,{10,10});
j2 = createJob(c,'Name',"Job B");
t2 = createTask(j2,{@rand,@magic,@ones},1,{{3,3} {3} {3,3}});
j3 = createJob(c,'Name',"Job C");
t3 = createTask(j3,@rand,1,{10,10},CaptureDiary=true);
submit(j1);submit(j2);submit(j3);
[pjobs,qjobs,rjobs,fjobs] = findJob(c);
get(qjobs,'Name')
10-397
10 Functions
'Job A'
'Job B'
'Job C'
promote(j3)
[pjobs,qjobs,rjobs,fjobs] = findJob(c);
get(qjobs,'Name')
'Job A'
'Job C'
'Job B'
resume(c)
Input Arguments
job — Job to promote
[Link] object
Job to promote in a MATLAB Job Scheduler cluster queue, specified as a [Link] object.
Example: job = createJob(c)
c — Cluster
[Link] object
Tips
• After a call to promote or demote, there is no change in the order of job objects contained in the
Jobs property of the MATLAB Job Scheduler cluster object. To see the scheduled order of
execution for jobs in the queue, use the findJob function in the form [pending queued
running finished] = findJob(c).
Version History
Introduced before R2006a
See Also
createJob | demote | findJob | submit
10-398
psave
psave
(Removed) Save data from communicating job session
Note psave has been removed. Use dsave instead. For more information, see Version History.
Syntax
psave(fileroot)
Arguments
fileroot Part of filename common to all saved files.
Description
psave(fileroot) saves the data from the workers' workspace into the files named [fileroot
num2str(spmdIndex)]. The files can be loaded by using the pload command with the same
fileroot, which should point to a folder accessible to all the workers. If fileroot contains an
extension, the character representation of the spmdIndex is inserted before the extension. Thus,
psave('abc') creates the files '[Link]', '[Link]', etc., one for each worker.
Examples
Create three arrays — one replicated, one variant, and one codistributed. Then save the data. (This
example works in a communicating job or in pmode, but not in a parfor or spmd block.)
clear all;
rep = speye(spmdSize);
var = magic(spmdIndex);
D = eye(spmdSize,codistributor());
psave('threeThings');
Clear the workspace on all the workers and confirm there are no variables.
clear all
whos
Load the previously saved data into the workers. Confirm its presence.
pload('threeThings');
whos
isreplicated(rep)
iscodistributed(D)
10-399
10 Functions
Version History
Introduced in R2006b
The psave function has been removed. To save data on the workers, in the form of Composite arrays
or distributed arrays, use dsave instead.
The psave function issues a warning that it will be removed in a future release.
See Also
dsave
10-400
put
put
Namespace: parallel
Syntax
put(store,keySet,valueSet)
Description
put(store,keySet,valueSet) adds key-value pairs to the ValueStore object store. valueSet
is a cell array of values that is added to store using the corresponding keys keySet. If the keys
already exist in store, then put replaces the values for the specified keys.
Examples
Run a simulation on workers and retrieve the data storage of the job on a client. The data storage is a
ValueStore object with key-value entries. Add entries to this object as specified by their
corresponding keys.
The following simulation finds the inverse of random matrices and stores the results in the
ValueStore object.
type workerInvCode
function workerInvCode(models)
% Get the ValueStore of the current job
store = getCurrentValueStore;
for i = 1:numel(models)
% Store simulation results in the ValueStore object
pause(1);
key = strcat("result_",num2str(i));
store(key) = inv(rand(models(i)));
end
end
models = [4,8,32,20];
c = parcluster;
job = batch(c,@workerInvCode,0,{models});
wait(job);
Retrieve the ValueStore object on the client. Show the keys of the object.
store = [Link];
keys(store)
10-401
10 Functions
Add multiple key-value entries as specified by the keys "matrix_2" and "result_2" to the object.
Show the keys of the updated object.
put(store,["matrix_2","result_2"],{rand(4),inv(rand(4))})
keys(store)
Input Arguments
store — Data storage shared by MATLAB clients and workers
ValueStore object
Data storage shared by MATLAB clients and workers, specified as a ValueStore object.
Keys to add, specified as a character vector, string scalar, string array, or cell array of character
vectors or strings. keySet and valueSet must have the same number of elements.
Values to add, specified as a cell array. keySet and valueSet must have the same number of
elements.
Tips
• To add only one key-value entry as specified by key, you can also use the syntax store(key) =
value.
Version History
Introduced in R2022a
See Also
ValueStore | isKey | keys | remove | get
10-402
rand
rand
Create codistributed array of uniformly distributed random numbers
Syntax
cR = rand(n,codist)
cR = rand(sz,codist)
cR = rand(sz1,...,szN,codist)
cR = rand( ___ ,datatype,codist)
Description
cR = rand(n,codist) creates an n-by-n codistributed matrix of uniformly distributed random
numbers and uses codist to specify the distribution of the array values across the workers. Each
element in cR is between 0 and 1.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
10-403
10 Functions
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
You must specify "noCommunication" after the size, data type and codist arguments.
cR = rand( ___ ,like=p) uses the array p to create a codistributed array of uniformly distributed
random numbers. You can also specify "noCommunication" as part of the function call.
The returned array cR has the same underlying type, sparsity, and complexity (real or complex) as p.
Examples
Create a 1000-by-1000 codistributed double matrix of rands, distributed by its second dimension
(columns).
spmd(4)
C = rand(1000,"codistributed");
end
Input Arguments
n — Size of square matrix
integer
10-404
rand
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
Underlying data type of the returned array, specified as one of these options:
• "double"
• "single"
• "logical"
• "int8"
• "uint8"
• "int16"
• "uint16"
• "int32"
• "uint32"
• "int64"
• "uint64"
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p.
10-405
10 Functions
Version History
Introduced in R2006b
See Also
rand | randi (codistributed) | randn (codistributed) | [Link] |
[Link]
Topics
“Control Random Number Streams on Workers” on page 5-15
“Random Number Streams on a GPU” on page 6-72
10-406
randi
randi
Create codistributed array of uniformly distributed random integers
Syntax
cR = randi(r,n,codist)
cR = randi(r,sz,codist)
cR = randi(r,sz1,...,szN,codist)
cR = randi( ___ ,datatype,codist)
Description
cR = randi(r,n,codist) creates an n-by-n codistributed matrix of uniformly distributed random
integers in the range defined by r and uses codist to specify the distribution of the array values
across the workers.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
10-407
10 Functions
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
You must specify "noCommunication" after the size, data type and codist arguments.
cR = randi( ___ ,like=p) uses the array p to create a codistributed array of uniformly distributed
random integers. You can also specify "noCommunication" as part of the function call.
The returned array cR has the same underlying type, sparsity, and complexity (real or complex) as p.
Examples
Create a 1000-by-1000 codistributed double matrix of randi values from 0 to 12, distributed by its
second dimension (columns).
spmd(4)
C = randi([0 12],1000,"codistributed");
end
Create a 1000-by-1000 codistributed single matrix of randi values from 1 to 4, distributed by its
columns.
spmd(4)
codist = codistributor1d(2,100*[1:spmdSize]);
C = randi(4,1000,1000,"single",codist);
end
Input Arguments
r — Range of output values
integer scalar | integer vector
10-408
randi
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
Underlying data type of the returned array, specified as one of these options:
• "double"
• "single"
• "logical"
• "int8"
• "uint8"
10-409
10 Functions
• "int16"
• "uint16"
• "int32"
• "uint32"
• "int64"
• "uint64"
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p.
Version History
Introduced in R2014a
See Also
randi | rand (codistributed) | randn (codistributed)
Topics
“Control Random Number Streams on Workers” on page 5-15
“Random Number Streams on a GPU” on page 6-72
10-410
randn
randn
Create codistributed array of normally distributed random numbers
Syntax
cR = randn(n,codist)
cR = randn(sz,codist)
cR = randn(sz1,...,szN,codist)
cR = randn( ___ ,datatype,codist)
Description
cR = randn(n,codist) creates an n-by-n codistributed matrix of normally distributed random
numbers and uses codist to specify the distribution of the array values across the workers. Each
element in cR is between 0 and 1.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
10-411
10 Functions
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
You must specify "noCommunication" after the size, data type and codist arguments.
cR = randn( ___ ,like=p) uses the array p to create a codistributed array of normally distributed
random numbers. You can also specify "noCommunication" as part of the function call.
The returned array cR has the same underlying type, sparsity, and complexity (real or complex) as p.
Examples
Create a 1000-by-1000 codistributed double matrix of randn values, distributed by its second
dimension (columns).
spmd(4)
C = randn(1000,"codistributed");
end
Create a 1000-by-1000 codistributed single matrix of randn values, distributed by its columns.
spmd(4)
codist = codistributorId(2,100*[1:spmdSize]);
C = randn(1000,1000,"single",codist);
end
Input Arguments
n — Size of square matrix
integer
10-412
randn
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
Underlying data type of the returned array, specified as one of these options:
• "double"
• "single"
• "logical"
• "int8"
• "uint8"
• "int16"
• "uint16"
• "int32"
• "uint32"
• "int64"
• "uint64"
10-413
10 Functions
Output Arguments
datatype — Array underlying data type
"double" (default) | "single" | "logical" | "int8" | "uint8" | ...
Underlying data type of the returned array, specified as one of these options:
• "double"
• "single"
• "logical"
• "int8"
• "uint8"
• "int16"
• "uint16"
• "int32"
• "uint32"
• "int64"
• "uint64"
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p.
Version History
Introduced in R2006b
See Also
randn | rand (codistributed) | randi (codistributed) | [Link] |
[Link] | spmdIndex
Topics
“Control Random Number Streams on Workers” on page 5-15
“Random Number Streams on a GPU” on page 6-72
10-414
recreate
recreate
Create new job from existing job
Syntax
newjob = recreate(oldjob)
newjob = recreate(oldjob,'Tasks',tasksToRecreate)
newjob = recreate(oldjob,'TaskState',states)
newjob = recreate(oldjob,'TaskID',ids)
Description
newjob = recreate(oldjob) creates a new job object based on an existing job, containing the
same tasks and options as oldjob. The old job can be in any state; the new job state is pending. If
oldjob was created using batch, then MATLAB automatically submits the new job.
Examples
This approach is useful when tasks depend on a file that is not present anymore.
Create a new job using the default cluster profile. In this example, it is the local parallel pool.
cluster = parcluster;
job = createJob(cluster);
Create several tasks. In particular, create a task that depends on a MAT file that does not exist.
createTask(job,@() 'Task1',1);
createTask(job,@() load('[Link]'),1);
Submit the job, and wait for it to finish. Because the MAT file in the second task does not exist, the
job fails. If you call fetchOutputs on job to retrieve the results, you get an error. Check the error
using the Error property of the corresponding task.
10-415
10 Functions
submit(job);
wait(job);
[Link](2).Error
ans =
ParallelException with properties:
identifier: 'MATLAB:load:couldNotReadFile'
message: 'Unable to find file or directory '[Link]'.'
cause: {}
remotecause: {[1×1 MException]}
stack: [1×1 struct]
Correction: []
Create the MAT file referenced from the second task using the save function. To create a new job
with the tasks that resulted in an error, use the 'Tasks' name-value pair in recreate, and provide
the hasError function. If you want to select a different set of tasks, you can define your own
function.
str = 'Task2';
save myData str
newjob = recreate(job,'Tasks',@hasError);
Submit the new job, wait for its completion, and fetch the outputs. Because the MAT file now exists,
the job does not fail.
submit(newjob);
wait(newjob);
out = fetchOutputs(newjob);
out{1}
newJob = recreate(myJob)
This example shows how to recreate an independent job, which has only pending tasks from the job
oldIndependentJob.
newJob = recreate(oldIndependentJob,'TaskState','pending');
10-416
recreate
This example shows how to recreate an independent job, which has only the tasks with IDs 21 to 32
from the job oldIndependentJob.
newJob = recreate(oldIndependentJob,'TaskID',[21:32]);
This example shows how to find and recreate all failed jobs submitted by user Mary. Assume the
default cluster is the one Mary had submitted her jobs to.
c = parcluster();
failedjobs = findJob(c,'Username','Mary','State','failed');
for m = 1:length(failedjobs)
newJob(m) = recreate(failedjobs(m));
end
Input Arguments
oldjob — Original job
[Link]
To rerun tasks containing errors or warnings, use this syntax with the predefined functions
@hasError and hasWarnings.
Example: newJob = recreate(oldjob,'Tasks',@hasError | @hasWarnings);
Data Types: [Link] | logical | function_handle
State of the tasks to duplicate, specified as a string or cell array of strings. states represents the
state of the required tasks to recreate from oldjob. Valid states are 'pending', 'running',
'finished', and 'failed'.
10-417
10 Functions
Version History
Introduced in R2014a
See Also
createCommunicatingJob | createJob | createTask | findJob | submit
10-418
redistribute
redistribute
Redistribute codistributed array with another distribution scheme
Syntax
D2 = redistribute(D1,codist)
Description
D2 = redistribute(D1,codist) redistributes a codistributed array D1 and returns D2 using the
distribution scheme defined by the codistributor object codist.
Examples
Redistribute an array according to the distribution scheme of another array.
spmd
% First, create a magic square distributed by columns:
M = codistributed(magic(10),codistributor1d(2,[1 2 3 4]));
Version History
Introduced in R2006b
See Also
codistributed | codistributor | [Link]
10-419
10 Functions
remove
Namespace: parallel
Syntax
remove(store,keySet)
Description
remove(store,keySet) removes key-value or key-file pairs from the ValueStore or FileStore
object store as specified by the keys keySet.
Examples
Run a simulation on workers and retrieve the data storage of the job on a client. The data storage is a
ValueStore object with key-value entries. Remove entries from this object as specified by their
corresponding keys.
The following simulation finds the inverse of random matrices and stores the results in the
ValueStore object.
type workerInvCode
function workerInvCode(models)
% Get the ValueStore of the current job
store = getCurrentValueStore;
for i = 1:numel(models)
% Store simulation results in the ValueStore object
pause(1);
key = strcat("result_",num2str(i));
store(key) = inv(rand(models(i)));
end
end
Retrieve the ValueStore object on the client. Show the keys of the object.
store = [Link];
keys(store)
10-420
remove
"result_2"
"result_3"
"result_4"
Remove multiple entries as specified by the keys "result_1" and "result_4" from the object.
remove(store,["result_1","result_4"]);
You can also remove an entry using the syntax store(key) = []. Remove the entry as specified by
the key "result_3" from the object.
store("result_3") = [];
keys(store)
ans =
"result_2"
Run a simulation on a parallel pool of process workers and retrieve the file storage on a client. The
file storage is a FileStore object with key-file entries. Remove entries from this object as specified
by its corresponding keys.
The following simulation finds the average and standard deviation of random matrices and stores the
results in the FileStore object.
type workerStatsCode
function workerStatsCode(models)
% Get the FileStore of the current job
store = getCurrentFileStore;
for i = 1:numel(models)
% Compute the average and standard deviation of random matrices
A = rand(models(i));
M = mean(A);
S = std(A);
% Save simulation results in temporary files
sourceTempFile = strcat(tempname("C:\myTempFolder"),".mat");
save(sourceTempFile,"M","S");
% Copy files to FileStore object as key-file pairs
key = strcat("result_",num2str(i));
copyFileToStore(store,sourceTempFile,key);
end
end
pool = parpool('Processes');
10-421
10 Functions
store = [Link];
models = [4,8,32,20];
future = parfeval(@workerStatsCode,0,models);
wait(future);
keys(store)
Remove the key-file entries as specified by the keys "result_1" and "result_2" from the object.
Show the keys of the updated object.
remove(store,["result_1","result_2"]);
keys(store)
Input Arguments
store — Data or file storage shared by MATLAB clients and workers
ValueStore object | FileStore object
Data or file storage shared by MATLAB clients and workers, specified as a ValueStore or
FileStore object.
Keys of entries to remove, specified as a character vector, string scalar, string array, or cell array of
character vectors or strings.
Tips
• For a ValueStore object, you can also use the syntax store(key) = [] to remove only one
key-value entry as specified by key.
Version History
Introduced in R2022a
10-422
remove
See Also
ValueStore | FileStore | isKey | keys | put | get | copyFileToStore | copyFileFromStore
10-423
10 Functions
reset
Namespace: [Link]
Syntax
reset(gpudev)
Description
reset(gpudev) resets the GPU device and clears its memory of gpuArray and CUDAKernel data.
The GPU device identified by gpudev remains the selected device, but all gpuArray and
CUDAKernel objects in MATLAB representing data on that device are invalid. The CachePolicy
property of the device is reset to the default. For more information, see gpuDevice.
Examples
D = gpuDevice;
M = eye(4,"gpuArray")
M =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
reset(D);
D =
CUDADevice with properties:
10-424
reset
Show that the gpuArray variable name is still in the MATLAB workspace.
whos
D 1x1 8 [Link]
M 4x4 0 gpuArray
M =
clear M
Input Arguments
gpudev — GPU device
GPU device
GPU device, specified as a GPUDevice object that represents the currently selected device
Tips
After you reset a GPU device, any variables representing arrays or kernels on the device are invalid;
you should clear or redefine them.
Version History
Introduced in R2012a
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
gpuDevice | gpuArray | CUDAKernel
10-425
10 Functions
results
Namespace: [Link]
Syntax
monitorResults = results(monitor)
Description
monitorResults = results(monitor) retrieves the pool activity monitoring results from the
ActivityMonitor object monitor.
• If the ActivityMonitor object is still collecting activity monitoring data, results retrieves the
activity monitoring results collected so far.
• If the ActivityMonitor object is not monitoring pool activity, results retrieves all collected
monitoring data.
Examples
Create an ActivityMonitor object to start collecting pool monitoring data. With default settings,
[Link] automatically starts an interactive parallel pool using the
default profile if one does not exist.
monitor = [Link];
Submit multiple parfeval computations to compute magic squares. Wait for all tasks to complete.
f(1:100) = [Link];
for idx = 1:100
f(idx) = parfeval(@magic,1,idx);
end
wait(f);
Use the results function to obtain the monitoring results. Visualize the monitoring results in the
Pool Dashboard.
monitoringResults = results(monitor);
parpoolDashboard(monitoringResults)
10-426
results
Input Arguments
monitor — Pool activity monitor
ActivityMonitor object
Output Arguments
monitorResults — Pool activity monitoring results
ActivityMonitorResults object | ActivityMonitorResults object array
If you have not previously started the ActivityMonitor object, the results function returns a 0-
by-0 ActivityMonitorResults object array with empty StartTime and EndTime object
properties.
10-427
10 Functions
To visualize the pool activity monitoring results in the Pool Dashboard, use the parpoolDashboard
function.
Version History
Introduced in R2025a
See Also
Functions
stop | start
Objects
ActivityMonitor | ActivityMonitorResults
Tools
Pool Dashboard
10-428
resume
resume
Resume processing queue in MATLAB Job Scheduler
Syntax
resume(mjs)
Description
resume(mjs) resumes processing jobs in the queue of the MATLAB Job Scheduler cluster
represented by the [Link] object mjs. The MATLAB Job Scheduler then runs the
jobs waiting in the queued state.
If the MATLAB Job Scheduler is not paused, the resume function has no effect.
Examples
This example shows how to resume processing the paused queue of a MATLAB Job Scheduler.
Create a cluster object that represents the MATLAB Job Scheduler cluster with the cluster profile
MJS_profile.
c = parcluster(MJS_profile);
pause(c)
Resume the processing of the jobs in the cluster queue by using the resume function.
resume(c);
Input Arguments
mjs — MATLAB Job Scheduler cluster
[Link] cluster object
Version History
Introduced before R2006a
See Also
pause | wait
10-429
10 Functions
saveAsProfile
Save cluster properties to specified profile
Description
saveAsProfile(cluster,profileName) saves the properties of the cluster object to the specified
profile, and updates the cluster Profile property value to indicate the new profile name.
Examples
Create a cluster, then modify a property and save the properties to a new profile. The new profile now
specifies 3 workers.
myCluster = parcluster('Processes');
[Link] = 3;
saveAsProfile(myCluster,'Processes2');
Version History
Introduced in R2012a
See Also
parcluster | saveProfile | [Link]
10-430
saveProfile
saveProfile
Save modified cluster properties to its current profile
Syntax
saveProfile(cluster)
Description
saveProfile(cluster) saves the modified properties on the cluster object to the profile specified
by the cluster Profile property, and sets the Modified property to false. If the cluster Profile
property is empty, the software throws an error.
Examples
This example shows how to create a cluster, modify a property, and save the change to the profile.
myCluster = parcluster('Processes')
myCluster =
Local Cluster
Properties:
Profile: Processes
Modified: false
Host: HOSTNAME
NumWorkers: 4
NumThreads: 1
[Link] = 3
myCluster =
Local Cluster
Properties:
Profile: Processes
Modified: true
Host: HOSTNAME
NumWorkers: 3
NumThreads: 1
Save the modified profile of the cluster by using the saveProfile function.
saveProfile(myCluster);
myCluster
10-431
10 Functions
myCluster =
Local Cluster
Properties:
Profile: Processes
Modified: false
Host: HOSTNAME
NumWorkers: 3
NumThreads: 1
After saving, the Processes profile now matches the current property settings, so the
[Link] property is false.
Input Arguments
cluster — Cluster
[Link] object
Version History
Introduced in R2012a
See Also
parcluster | saveAsProfile | [Link]
10-432
setConstantMemory
setConstantMemory
Set some constant memory on GPU
Syntax
setConstantMemory(kern,sym,val)
setConstantMemory(kern,sym1,val1,sym2,val2,...)
Description
setConstantMemory(kern,sym,val) sets the constant memory in the CUDA kernel kern with
symbol name sym to contain the data in val. val can be any numeric array, including a gpuArray.
The function errors if the named symbol does not exist or if it is not big enough to contain the
specified data. You can partially fill a constant.
There is no automatic data-type conversion for constant memory, so you must make sure that the
supplied data is of the correct type for the constant memory symbol that you are filling.
Examples
If KERN represents a CUDA kernel whose CU file contains these includes and constant definitions:
#include "tmwtypes.h"
__constant__ int32_t N1;
__constant__ int N2; // Assume 'int' is 32 bits
__constant__ double CONST_DATA[256];
You can fill these with MATLAB data by running these commands:
KERN = [Link](ptxFile,cudaFile);
setConstantMemory(KERN,'N1',int32(10));
setConstantMemory(KERN,'N2',int32(10));
setConstantMemory(KERN,'CONST_DATA',1:10);
setConstantMemory(KERN,'N1',int32(10),'N2',int32(10),'CONST_DATA',1:10);
Input Arguments
kern — CUDA kernel
[Link] object
10-433
10 Functions
Symbol name of the constant memory of the CUDA kernel, specified as a character vector. The
function errors if the named symbol does not exist or if it is not big enough to contain the specified
data
Data to assign to a specific constant memory, specified as a numeric array or a gpuArray object.
Version History
Introduced in R2012a
See Also
gpuArray | CUDAKernel
10-434
setJobClusterData
setJobClusterData
Set specific user data for job on third-party cluster
Syntax
setJobClusterData(cluster,job,userdata)
Arguments
cluster Cluster object identifying the third-party cluster running the job
job Job object identifying the job for which to store data
userdata Information to store for this job
Description
setJobClusterData(cluster,job,userdata) stores data for the job job that is running on the
cluster cluster. You can later retrieve the information with the function getJobClusterData. For
example, it might be useful to store the third-party scheduler's external ID for this job, so that the
function specified in GetJobStateFcn can later query the scheduler about the state of the job. Or
the stored data might be an array with the scheduler's ID for each task in the job.
For more information and examples on using these functions and properties, see “Plugin Scripts for
Generic Schedulers” (MATLAB Parallel Server).
Version History
Introduced in R2012a
See Also
getJobClusterData
10-435
10 Functions
shutdown
Shut down cloud cluster
Syntax
shutdown(cluster)
shutdown(MJScluster,'At',D)
shutdown(MJScluster,'After',event)
shutdown(MJScluster,'After',numhours)
Description
shutdown(cluster) shuts down the cluster immediately.
shutdown(MJScluster,'At',D) shuts down the cluster at the time specified by the datetime,
datenum, or datevec D. D is interpreted in the local time zone of the MATLAB client unless D is a
datetime with a non-empty TimeZone property.
shutdown(MJScluster,'After',event) shuts down the cluster after the specified event event
has occurred. event can be 'never' or 'idle'. A cluster is 'idle' immediately when there are no
running jobs, queued jobs, or running pools. The cluster is eligible for shutdown if 'idle' for more
than 5 minutes, and is guaranteed to shut down within 60 minutes.
Examples
shutdown(cluster);
Specify date and time to terminate a cluster using a datetime. If the datetime has an empty
TimeZone property, the datetime is interpreted in the local time zone of the MATLAB client.
shutdown(MJSCluster,'At',datetime(2017,2,22,19,0,0,'TimeZone','local'));
shutdown(MJSCluster,'After','never');
10-436
shutdown
Input Arguments
cluster — MATLAB Parallel Server for Cloud Center cluster
cluster object (default)
MATLAB Parallel Server for Cloud Center cluster, specified as cluster object created using
parcluster.
Example: shutdown(cluster);
MATLAB Parallel Server for Cloud Center cluster, specified as cluster object created using
parcluster.
Example: shutdown(MJScluster);
Date and time, specified as a datetime, datenum, or datevec. D is interpreted in the local time
zone of the MATLAB client unless D is a datetime with a non-empty TimeZone property.
Example:
shutdown(MJSCluster,'At',datetime(2017,2,22,19,0,0,'TimeZone','local'));
Event to shut down the cluster, specified as 'never' or 'idle'. A cluster is 'idle' immediately
when there are no running jobs, queued jobs, or running pools. The cluster is eligible for shutdown if
'idle' for more than 5 minutes, and is guaranteed to shut down within 60 minutes.
Example: shutdown(MJSCluster,'After','idle');
Number of hours after which the cluster shuts down, specified as scalar, measured from the time you
call shutdown.
Example: shutdown(MJSCluster,'After',10);
Version History
Introduced in R2017a
10-437
10 Functions
See Also
datetime | start | wait (cluster) | parcluster | [Link] | parpool
10-438
sparse
sparse
Create codistributed sparse matrix
Syntax
S = sparse(A)
S = sparse(m,n)
S = sparse(m,n,typename)
S = sparse(i,j,v)
S = sparse(i,j,v,m,n)
S = sparse(i,j,v,m,n,nz)
Description
S = sparse(A) converts a full codistributed matrix to sparse form by removing any zero elements.
You can save memory by converting a matrix that contains many zeros to sparse storage.
S = sparse(m,n,typename) also specifies the data type (class) for the codistributed sparse
matrix. The typename input can be either "single" or "double".
S = sparse(i,j,v) creates a codistributed sparse matrix S from the triplets i, j, and v. The
number of rows in S is set by the maximum value of i, and the number of columns in S is set by the
maximum value of j. The matrix has space allotted for length(v) nonzero elements.
Each of the inputs i, j, and v must have either 1 or N elements, such that each non-scalar input has
the same number of elements.
S = sparse(i,j,v,m,n,nz) allocates space for nz nonzero elements. Use this syntax to allocate
extra space for nonzero values to be filled in after construction.
Examples
Create a 1000-by-1000 codistributed dense triangular matrix, distributed by its second dimension
(columns). Convert the codistributed matrix into a codistributed sparse matrix.
spmd(4)
C = triu(rand(1000,1000,"codistributed"));
S = sparse(C);
end
10-439
10 Functions
Input Arguments
A — Input matrix
full codistributed matrix | sparse codistributed matrix
Input matrix, specified as a full or sparse codistributed matrix. If A is already sparse, then
sparse(A) returns A.
Subscript pairs, specified as separate arguments of scalars, vectors, or matrices. If i and j are not
scalars, i(k), j(k), and v(k) specify the value of S(i(k),j(k)) as:
S(i(k),j(k)) = v(k)
If i or j is a scalar, the function uses that value to specify multiple elements in S. For example if only
i is a scalar, j(k) and v(k) specify the value of S(i,j(k)) as:
S(i,j(k)) = v(k)
If i and j have identical values for several elements in v, then sparse aggregates the values in v
that have repeated indices. The aggregation behavior depends on the data type of the values in v:
v — Values
scalar | vector | matrix
Values, specified as a scalar, vector, or matrix. The underlying type of v must be double or logical.
If v is not a scalar, i(k), j(k), and v(k) specify the value of S(i(k),j(k)) as:
S(i(k),j(k)) = v(k)
If v is a scalar, the function uses that value to specify multiple elements in S. For example if only v is
a scalar, i(k) and j(k) specify the value of S(i(k),j(k)) as:
S(i(k),j(k)) = v
Any elements in v that are zero are ignored, as are the corresponding subscripts in i and j.
sparse sets the number of rows and columns in the output matrix before ignoring any zero elements
in v. Therefore, if you set any values in v to 0, the size of the output matrix will not change.
Size of each dimension, specified as separate arguments of integers. The underlying type of m and n
must be double. m is the row size and n is the column size. If you specify m, you must specify n.
If you do not specify m and n, then sparse uses the default values m = max(i) and n = max(j).
These maxima are computed before any zeros in v are removed.
10-440
sparse
Storage allocation for nonzero elements, specified as a nonnegative integer. The underlying type of m
and n must be double.
The default value is max([numel(i), numel(j), numel(v), 1]). nz must be greater than or
equal to this value.
For the sparse matrix S, the nnz function returns the number of nonzero elements in the matrix, and
the nzmax function returns the amount of storage allocated for nonzero matrix elements. If nnz(S)
and nzmax(S) return different results, then more storage might be allocated than is actually
required. For this reason, set nz only if you want to fill in values.
• "double"
• "single"
You can only specify the typename argument with the m,n argument.
Version History
Introduced in R2006b
You can specify the output data type by specifying the typename argument as "double" or
"single".
See Also
sparse | [Link] | [Link]
10-441
10 Functions
spmd
Execute code in parallel on workers of parallel pool
Syntax
spmd
statements
end
Description
spmd, statements, end defines an spmd statement on a single line. MATLAB executes the spmd
body denoted by statements on several MATLAB workers simultaneously. Each worker can operate
on a different data set or different portion of distributed data, and can communicate with other
participating workers while performing the parallel computations. The spmd statement can be used
only if you have Parallel Computing Toolbox. To execute the statements in parallel, you must first
create a pool of MATLAB workers using parpool or have your parallel settings allow the automatic
start of a pool.
Inside the body of the spmd statement, each MATLAB worker has a unique value of spmdIndex,
while spmdSize denotes the total number of workers executing the block in parallel. Within the body
of the spmd statement, communication functions for communicating jobs (such as spmdSend and
spmdReceive) can transfer data between the workers.
Values returning from the body of an spmd statement are converted to Composite objects on the
MATLAB client. A Composite object contains references to the values stored on the remote MATLAB
workers, and those values can be retrieved using cell-array indexing. The actual data on the workers
remains available on the workers for subsequent spmd execution, so long as the Composite exists on
the client and the parallel pool remains open.
By default, MATLAB uses all workers in the pool. When there is no pool active, MATLAB will create a
pool and use all the workers from that pool. If your settings do not allow automatic pool creation,
MATLAB executes the block body locally and creates Composite objects as necessary. You cannot
execute an spmd block if any worker is busy executing a parfeval request, unless you use spmd(0).
For more information about spmd and Composite objects, see “Distribute Arrays and Run SPMD” on
page 4-113.
Note Use parfevalOnAll instead of parfor or spmd if you want to use clear. This preserves
workspace transparency. See “Ensure Transparency in parfor-Loops or spmd Statements” on page 2-
51.
spmd(n), statements, end uses n to specify the exact number of MATLAB workers to evaluate
statements, provided that n workers are available from the parallel pool. If there are not enough
workers available, an error is thrown. If n is zero, MATLAB executes the block body locally and
creates Composite objects, the same as if there is no pool available.
10-442
spmd
spmd(pool, ___ ), statements, end evaluates statements on the parallel pool specified by the
[Link] object pool. Use this syntax when you want to evaluate spmd statements on a pool
other than the pool the gcp function returns.
Examples
Create a parallel pool, and perform a simple calculation in parallel using spmd. MATLAB executes the
code inside the spmd on all workers in the parallel pool.
parpool(3);
spmd
q = magic(spmdIndex + 2);
end
figure
subplot(1,3,1), imagesc(q{1});
subplot(1,3,2), imagesc(q{2});
subplot(1,3,3), imagesc(q{3});
10-443
10 Functions
When you are done with computations, you can delete the current parallel pool.
delete(gcp);
If you have access to several GPUs, you can perform your calculations on multiple GPUs in parallel
using a parallel pool.
To determine the number of GPUs that are available for use in MATLAB, use the gpuDeviceCount
function.
availableGPUs = gpuDeviceCount("available")
availableGPUs = 3
Start a parallel pool with as many workers as available GPUs. For best performance, MATLAB assigns
a different GPU to each worker by default.
parpool("Processes",availableGPUs);
10-444
spmd
To identify which GPU each worker is using, call gpuDevice inside an spmd block. The spmd block
runs gpuDevice on every worker.
spmd
gpuDevice
end
Use parallel language features, such as parfor or parfeval, to distribute your computations to
workers in the parallel pool. If you use gpuArray enabled functions in your computations, these
functions run on the GPU of the worker. For more information, see “Run MATLAB Functions on a
GPU” on page 6-3. For an example, see “Run MATLAB Functions on Multiple GPUs” on page 6-19.
When you are done with your computations, shut down the parallel pool. You can use the gcp
function to obtain the current parallel pool.
delete(gcp("nocreate"));
If you want to use a different choice of GPUs, then you can use gpuDevice to select a particular GPU
on each worker, using the GPU device index. You can obtain the index of each GPU device in your
system using the gpuDeviceCount function.
Suppose you have three GPUs available in your system, but you want to use only two for a
computation. Obtain the indices of the devices.
[availableGPUs,gpuIndx] = gpuDeviceCount("available")
availableGPUs = 3
gpuIndx = 1×3
1 2 3
useGPUs = [1 3];
Start your parallel pool. Use an spmd block and gpuDevice to associate each worker with one of the
GPUs you want to use, using the device index. The spmdIndex function identifies the index of each
worker.
parpool("Processes",numel(useGPUs));
spmd
gpuDevice(useGPUs(spmdIndex));
end
As a best practice, and for best performance, assign a different GPU to each worker.
When you are done with your computations, shut down the parallel pool.
delete(gcp("nocreate"));
10-445
10 Functions
myClusterPool = parpool("myMJSCluster",15);
spmdWorkers = [Link](1:6);
[spmdPool,otherPool] = partition(myClusterPool,"Workers",spmdWorkers);
approx1 = piApprox{1};
fprintf("pi : %.18f\n" + ...
"Approximation: %.18f\n" + ...
"Error : %g\n", pi,approx1,abs(pi - approx1));
pi : 3.141592653589793116
Approximation: 3.141592653589793116
Error : 0
Input Arguments
pool — Pool evaluating statements
[Link] object
Tips
• An spmd block runs on the workers of the existing parallel pool. If no pool exists, spmd will start a
new parallel pool, unless the automatic starting of pools is disabled in your parallel settings. If
there is no parallel pool and spmd cannot start one, the code runs serially in the client session.
• If the AutoAttachFiles property in the cluster profile for the parallel pool is set to true,
MATLAB performs an analysis on an spmd block to determine what code files are necessary for its
execution, then automatically attaches those files to the parallel pool job so that the code is
available to the workers.
• For information about restrictions and limitations when using spmd, see “Run Single Programs on
Multiple Data Sets” on page 4-6.
10-446
spmd
• For information about the performance of spmd and other parallel programming constructs, see
“Choose Between spmd, parfor, and parfeval” on page 4-30.
Version History
Introduced in R2008b
You can now specify the parallel pool that the spmd function uses to evaluate statements. Use this
syntax to evaluate spmd statements on a pool other than the pool the gcp function returns.
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
batch | Composite | spmdReduce | spmdIndex | [Link] | parpool |
spmdSize
10-447
10 Functions
spmdBarrier
Synchronize workers in spmd block
Syntax
spmdBarrier
Description
spmdBarrier stops all workers in the current spmd block or communicating job from executing code
until every worker calls spmdBarrier.
When you offload computations using parfor and parfeval, only one worker at a time runs each
computation. These workers are independent and do not communicate with each other. If you apply
spmdBarrier to these workers, the function has no effect.
Use spmdBarrier to synchronize workers, for example, when workers use shared resources such as
a file handle.
If only one worker is running on the current spmd block, execution continues immediately. To
determine the number of workers running the current spmd block, use the spmdSize function. The
spmdSize function returns a value of 1 outside of an spmd block or communicating job.
Examples
This example shows how to use spmdBarrier to synchronize workers in an spmd block.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool run the code inside the spmd block.
Create an spmd block. Pause each worker for a random amount of time to simulate some
computationally expensive work. Use tic and toc to time the execution on each worker.
spmd
tic
pause(5*rand);
toc
end
Worker 2:
Elapsed time is 0.702969 seconds.
Worker 3:
Elapsed time is 1.807292 seconds.
Worker 1:
10-448
spmdBarrier
To synchronize the workers after each worker runs pause, use spmdBarrier. All the workers wait
for the slowest worker to finish its computation. The elapsed time on each worker is now the same,
except for small numerical noise.
spmd
tic
pause(5*rand);
spmdBarrier;
toc
end
Worker 1:
Elapsed time is 4.758529 seconds.
Worker 2:
Elapsed time is 4.758529 seconds.
Worker 3:
Elapsed time is 4.743785 seconds.
Worker 4:
Elapsed time is 4.743739 seconds.
Version History
Introduced in R2022b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
spmdBroadcast | spmdIndex | spmdReceive | spmdSend | spmdSendReceive
10-449
10 Functions
spmdBroadcast
Send data to all workers in spmd block
Syntax
B = spmdBroadcast(source,A)
B = spmdBroadcast(source)
Description
B = spmdBroadcast(source,A) sends the data A to every worker in the current spmd block or
communicating job.
When you offload computations using parfor and parfeval, only one worker at a time runs each
computation. These workers are independent and do not communicate with each other. If you apply
spmdBroadcast to these workers, the function has no effect.
The worker whose index in the current spmd block is equal to source broadcasts the data. To get the
worker index, use the spmdIndex function.
B = spmdBroadcast(source) receives the data B on each worker running the current spmd block
or communicating job. The data B is equal to the data A sent from the worker with an index equal to
source.
Examples
This example shows how to broadcast an array from one worker to other workers in an spmd block.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool run the code inside the spmd block.
Create an spmd block. On the worker whose index is equal to 1, create an array. Use
spmdBroadcast to send the array to all workers. On each other worker, use spmdBroadcast to
receive the array.
spmd
source = 1;
if spmdIndex == source
A = magic(3);
B = spmdBroadcast(source, A);
else
B = spmdBroadcast(source);
10-450
spmdBroadcast
end
B
end
Worker 1:
B =
8 1 6
3 5 7
4 9 2
Worker 2:
B =
8 1 6
3 5 7
4 9 2
Worker 3:
B =
8 1 6
3 5 7
4 9 2
Worker 4:
B =
8 1 6
3 5 7
4 9 2
On the client, inspect the Composite A. Only the worker whose index is 1 contains a definition of A.
A =
Input Arguments
source — Index of worker sending data
positive integer
Index of the worker that is sending data, specified as a positive integer. This value must be greater
than or equal to 1 and less than or equal to the number of workers running the current spmd block.
10-451
10 Functions
To determine the number of workers running the current spmd block, use the spmdSize function.
The spmdSize function returns a value of 1 outside of an spmd block or communicating job.
Example: 1
A — Sent data
MATLAB variable | ...
Data sent from the worker whose index is equal to source, specified as any MATLAB variable that
can be saved and loaded.
Example: magic(3)
Output Arguments
B — Received data
MATLAB variable
Data returned on the worker, specified as a scalar, vector, matrix, multidimensional array, table, or
timetable.
Tips
A worker that calls spmdBroadcast might finish execution before other workers. When you need
synchronized workers in an spmd block or communicating job, such as when you close a shared
resource, use spmdBarrier after calling spmdBroadcast.
Version History
Introduced in R2022b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
The spmdBroadcast function fully supports GPU arrays. To run the function on a GPU, specify the
input data as a gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-
3.
If data is a gpuArray, data transfer between multiple GPUs in a parallel pool uses fast peer-to-peer
communication, including NVLink, if available.
See Also
spmdBarrier | spmdIndex | spmdSendReceive
10-452
spmdCat
spmdCat
Concatenate arrays on spmd workers
Syntax
B = spmdCat(A)
B = spmdCat(A,dim)
B = spmdCat(A,dim,destination)
Description
B = spmdCat(A) horizontally concatenates the array A defined on each worker running an spmd
block or communicating job.
When you use parfor, parfeval, or parfevalOnAll to run code on a parallel pool, the workers
are independent and do not communicate with each other. If you use spmdCat on these workers, the
result is the same as using spmdCat on a client.
You can use spmdCat only if A can be concatenated along the second dimension.
This function concatenates the arrays along the second dimension, then stores the result on all the
workers. The function takes the value of A from each worker and concatenates the results in order of
the worker index. To get the index of a worker, use the spmdIndex function. For example,
spmdCat(spmdIndex) returns 1:spmdSize , where spmdSize is the number of workers running
the current spmd block or communicating job.
You can use spmdCat only if A concatenates along the dimension dim when all the arrays have
compatible sizes. The arrays have compatible sizes when the lengths of the dimensions match except
for the operating dimension dim).
Examples
This example shows how to use spmdCat to concatenate a scalar held on each worker in an spmd
block.
Create an spmd block. By default, each worker in the pool runs the spmd block. Store the value
returned by spmdIndex on each worker as A, then use spmdCat to concatenate the values of A
defined on each worker.
10-453
10 Functions
Unless you specify a destination, the spmdCat function stores the result of concatenation on every
worker. On the client, the result is a Composite object. To get the result, index into the Composite
object.
spmd
B = spmdCat(spmdIndex);
end
B{1}
ans =
1 2 3 4
Input Arguments
A — Input array
MATLAB variable | ...
Input array, specified as a scalar, vector, matrix, multidimensional array, table, timetable, or any
MATLAB variable that supports concatenation.
Example: A = magic(3)
dim — Dimension
2 (default) | positive integer
Dimension, specified as a positive integer. For example, if A is a 2-by-2 matrix on all workers, then
spmdCat(A,1) concatenates A vertically and returns a 2N-by-2 matrix, where N is the number of
workers running the current spmd block. Calling spmdCat(A,2) concatenates horizontally and
returns a 2-by-2N matrix.
Index of destination worker, specified as a positive integer. The value of this input must be less than
or equal to the output of the spmdSize function in the current spmd block or communicating job.
When you specify this input, the function stores the value of B only on the worker with this index. The
B output is still defined on all the workers that run spmdCat. On the worker whose index is equal to
destination, B is the result of the concatenation. On all the other workers, B is [].
Output Arguments
B — Output array
MATLAB variable | ...
If you specify destination, B is the result of the concatenation on the worker whose index is equal
to destination. On all the other workers, B is [].
10-454
spmdCat
Algorithms
This figure shows how the spmdCat function concatenates A with the value on other workers when
you call spmdCat(A).
Version History
Introduced in R2022b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
cat | spmdReduce | spmdIndex | spmdSize
10-455
10 Functions
spmdIndex
Index of current worker in spmd block
Syntax
id = spmdIndex
Description
id = spmdIndex returns the index of the worker currently executing the function in an spmd block
or a communicating job. When workers run an spmd block or a communicating job begins execution,
a unique index is assigned to each worker.
The value of spmdIndex is an integer between 1 and the number of workers running in the current
spmd block or communicating job. To get the number of workers running the current spmd block, use
the spmdSize function.
A worker gets the same value id inside every spmd block for the duration of a parallel pool.
Examples
p = parpool('Threads',2);
spmd
spmdIndex
end
Worker 1:
1
Worker 2:
2
View the indices of workers in a parpool loop run in the same two worker pool, p.
parfor a=1:4
[a,spmdIndex]
end
ans =
3 1
ans =
2 1
ans =
1 1
10-456
spmdIndex
ans =
4 1
Output Arguments
id — Index of current worker
positive integer
Index of current worker, specified as a positive integer. The value of this input must be less than or
equal to the output of the spmdSize function in the current spmd block or communicating job.
Tips
In an spmd block, because you have access to all workers individually and control what the workers
execute, each worker has a unique index.
However, inside a parfor-loop, spmdIndex always returns a value of 1 on all workers in all
iterations.
Version History
Introduced in R2022b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
spmdSendReceive | spmdSize
10-457
10 Functions
spmdPlus
Add arrays from workers in spmd block
Syntax
C = spmdPlus(A)
C = spmdPlus(A,destination)
Description
C = spmdPlus(A) add the arrays A stored on each worker in the current spmd block or
communicating job and stores the result C on all the workers.
When you offload computations using parfor and parfeval, only one worker at a time runs each
computation. These workers are independent and do not communicate with each other. If you apply
spmdPlus to these workers, the function has no effect.
You can use spmdPlus only when A has a compatible size on each worker.
C = spmdPlus(A,destination) adds the arrays and stores the result on only one worker. On the
worker whose index is equal to destination, C is equal to the sum. On all other workers, C is []. To
get the worker index, use the spmdIndex function.
Examples
This example shows how to use spmdPlus to add a scalar held on each worker in an spmd block.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool run the code inside the spmd block.
Run spmdIndex on each worker in the spmd block and store the result in a scalar A. Use spmdPlus
to add the value of A from each worker.
Unless you specify a destination, the spmdPlus function stores the result on every worker. On the
client, C is a Composite object. To get the result, index into the Composite object.
spmd
A = spmdIndex;
C = spmdPlus(A);
end
disp(C{1})
10-458
spmdPlus
10
Input Arguments
A — Input array
scalar | vector | matrix | multidimensional array
Index of the target worker, specified as a positive integer. The value of this input must be less than or
equal to the number of workers running the current spmd block or communicating job.
When you specify this input, the function stores the value of C on only one worker. On the worker
whose index is equal to destination, C is equal to the sum. On all the other workers, C is [].
Example: 1
Output Arguments
C — sum of arrays in spmd block
scalar | vector | matrix | multidimensional array
Sum of arrays on each worker in an spmd block or communicating job, returned as any MATLAB
variable of the same type as A.
If you specify destination, the function stores the value of C on the worker whose index is equal to
destination. On all the other workers, C is [].
Algorithms
This figure shows how the spmdCat function adds A to the value on other workers when you call
spmdPlus(A).
10-459
10 Functions
Version History
Introduced in R2022b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
spmdReduce | spmdIndex
10-460
spmdProbe
spmdProbe
Determine whether data is available to current worker in spmd block
Syntax
tf = spmdProbe
tf = spmdProbe(source)
tf = spmdProbe('any')
tf = spmdProbe('any',tag)
tf = spmdProbe(source,tag)
[tf,sourceOut,tagOut] = spmdProbe( ___ )
Description
tf = spmdProbe tests whether data is available to the current worker in an spmd block or
communicating job. If it is 1, the worker can receive the data using spmdReceive.
When you offload computations using parfor and parfeval, only one worker at a time runs each
computation. These workers are independent and do not communicate with each other. If you apply
spmdProbe to these workers, the function has no effect.
If the data is available, spmdProbe returns a logical 1 (true). Otherwise, spmdProbe returns a
logical 0 (false).
To use spmdProbe, the number of workers running the current spmd block must be greater than 1.
tf = spmdProbe(source) tests whether data is available for the current worker to receive from
the worker whose index is equal to source.
tf = spmdProbe('any') tests whether the sent data is available for the current worker to receive
from any worker.
tf = spmdProbe('any',tag) tests whether data sent with the tag tag is available for the current
worker to receive from any worker.
tf = spmdProbe(source,tag) tests whether data sent with the tag tag is available for the
current worker to receive from the worker whose index is equal to source.
[tf,sourceOut,tagOut] = spmdProbe( ___ ) tests whether data is available for the current
worker to receive, returns the index of the worker that is sending data as sourceOut, and returns
the tag of available data as tagOut. If multiple items of data are available, spmdProbe returns the
index and tag of the first matching message.
Examples
This example shows how to determine whether data is available for workers in an spmd block or
communicating job to receive.
10-461
10 Functions
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool run the code inside the spmd block.
Create an spmd block. On the worker whose index is equal to 1, create an array. Use spmdSend to
send the array to the worker whose index is equal to 2.
Use spmdBarrier to synchronise the workers after the worker whose index is equal to 1 sends the
data. Then, use spmdProbe to test whether the data is available for each worker to receive. Use
spmdReceive to collect the available data.
spmd
switch spmdIndex
case 1
A = magic(3);
spmdSend(A,2);
end
spmdBarrier;
tf = spmdProbe
if tf
spmdReceive;
end
end
Worker 1:
tf =
logical
Worker 2:
tf =
logical
Worker 3:
tf =
logical
Worker 4:
tf =
10-462
spmdProbe
logical
Input Arguments
source — Index of source worker
positive integer | 'any'
Index of the source worker, specified as a positive integer or 'any'. The value of this input must be
less than or equal to the number of workers running the current spmd block or communicating job.
When you specify this input as a positive integer, spmdProbe returns a logical 1 (true) if data is
available for the current worker to receive from the worker whose index is equal to source.
When you specify this input as 'any', spmdProbe returns a logical 1 (true) if the data is available
for the current worker to receive from any worker.
When you do not specify this input, spmdProbe returns a logical 1 (true) if the data is available for
the current worker to receive from any worker.
Example: 1
Message tag, specified as a nonnegative integer. When you specify this input, spmdProbe returns a
logical 1 (true) if the data sent using spmdSend with the tag equal to tag is available for the current
worker to receive.
Example: 314159
Output Arguments
sourceOut — Index of worker sending data
positive integer | empty array
Index of the worker sending data that the current worker is yet to receive, returned as a positive
integer or an empty array. The value is equal to index of the worker that sent data.
Message tag of the data that the current worker has not yet received, returned as a nonnegative
integer or an empty array. If no data is available to be received, tagOut is [].
Version History
Introduced in R2022b
10-463
10 Functions
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
spmdIndex | spmdReceive | spmdSend | spmdSendReceive
10-464
spmdReceive
spmdReceive
Receive data from another worker in spmd block
Syntax
B = spmdReceive
B = spmdReceive(source)
B = spmdReceive('any')
B = spmdReceive('any',tag)
B = spmdReceive(source,tag)
[B,sourceOut,tagOut] = spmdReceive( ___ )
Description
B = spmdReceive receives data B sent to the current worker from any worker in the current spmd
block or communicating job.
When you offload computations using parfor and parfeval, only one worker at a time runs each
computation. These workers are independent and do not communicate with each other. If you apply
spmdReceive to these workers, the function has no effect.
When a worker runs spmdReceive, the function blocks the execution of other commands until the
worker receives the data.
To use spmdReceive, the number of workers running the current spmd block must be greater than
1. To get the number of workers running the current spmd block, use the spmdSize function.
B = spmdReceive(source) receives data sent from the worker whose index is equal to source. To
get the index of a worker, use the spmdIndex function.
B = spmdReceive('any',tag) receives data sent with the tag tag from any worker.
B = spmdReceive(source,tag) receives data sent with the tag tag from the worker whose index
is equal to source.
[B,sourceOut,tagOut] = spmdReceive( ___ ) receives data sent from another worker, returns
the index sourceOut of the source worker, and returns the tag tagOut with the data.
Examples
This example shows how to send data between workers in an spmd block or communicating job.
parpool(4);
10-465
10 Functions
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool run the code inside the spmd block.
Create an spmd block. On the worker whose index is equal to 1, create an array. Use spmdSend to
send the array to the worker whose index is equal to 2 and use spmdReceive to collect the data.
spmd
switch spmdIndex
case 1
A = magic(3)
spmdSend(A,2);
case 2
B = spmdReceive
end
end
Worker 1:
A =
8 1 6
3 5 7
4 9 2
Worker 2:
B =
8 1 6
3 5 7
4 9 2
This example shows how to tag and send data between workers in an spmd block or communicating
job.
Create an spmd block. On the worker whose index is equal to 1, create two arrays A1 and A2. Before
and between creating arrays, pause the execution using the pause function to simulate some work.
Then, use spmdSend to send the matrices to the worker whose index is equal to 2.
Tag each matrix with an integer. On the worker whose index is equal to 2, use spmdReceive to
collect the data.
tic
spmd
switch spmdIndex
case 1
pause(5);
A1 = magic(1)
pause(5);
10-466
spmdReceive
A2 = magic(2)
spmdSend(A1,2,1);
spmdSend(A2,2,2);
case 2
B1 = spmdReceive('any',1)
B2 = spmdReceive('any',2)
end
end
toc
Worker 1:
A1 =
A2 =
1 3
4 2
Worker 2:
B1 =
B2 =
1 3
4 2
In some cases, you can improve the performance of your code by moving some work from one worker
to another. Move some work from the worker whose index is equal to 1 to the worker whose index is
equal to 2. When you use tags, you can easily move calculations from one worker to another without
updating code on the receiving worker.
tic
spmd
switch spmdIndex
case 1
pause(5);
A1 = magic(1)
spmdSend(A1,2,1);
case 2
B2 = spmdReceive('any',2)
B1 = spmdReceive('any',1)
case 3
pause(5);
A2 = magic(2)
spmdSend(A2,2,2);
end
end
toc
10-467
10 Functions
Worker 1:
A1 =
Worker 2:
B2 =
1 3
4 2
B1 =
Worker 3:
A2 =
1 3
4 2
Input Arguments
source — Index of worker sending data
positive integer | 'any'
Index of the worker sending data, specified as a positive integer or 'any'. The value of this input
must be less than or equal to the number of workers running the current spmd block or
communicating job.
When you specify this input, spmdReceive returns the data sent from the worker whose index is
equal to source.
When you specify this input as 'any', spmdReceive returns data sent from any worker.
When you do not specify this input, spmdReceive returns data sent from any worker.
Example: 1
Message tag, specified as a nonnegative integer. When you specify this input, spmdReceive returns
data that is sent to the current worker using the spmdSend function. The tag argument is equal to
the tag sent to the current worker.
Example: 314159
10-468
spmdReceive
Output Arguments
B — Data received by current worker
MATLAB variable | ...
Data received by the current worker, specified as a scalar, vector, matrix, multidimensional array,
table, timetable, or any other MATLAB variable.
Example: magic(3)
Index of the worker sending data, returned as a positive integer or 'any'. The value of this input is
equal to the index of the worker that sent the received data.
Message tag of the data that the current worker receives, returned as a nonnegative integer.
Tips
Tags have many uses, for example:
• Use tags to save memory by only loading arrays on workers when you need the data.
• Use tags to create code that does not depend on the index of the sending worker.
Version History
Introduced in R2022b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
The spmdReceive function fully supports GPU arrays. To run the function on a GPU, specify the input
data as a gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-3.
If data is a gpuArray, data transfer between multiple GPUs in a parallel pool uses fast peer-to-peer
communication, including NVLink, if available.
See Also
spmdBarrier | spmdIndex | spmdProbe | spmdSendReceive | spmdSend
10-469
10 Functions
spmdReduce
Reduce arrays on spmd workers
Syntax
B = spmdReduce(fcn,A)
B = spmdReduce(fcn,A,destination)
Description
B = spmdReduce(fcn,A) uses the function fcn to reduce the array A defined on each worker
running an spmd block or communicating job. The function stores the result B of reduction on every
worker.
For example, spmdReduce(@plus,A) returns the sum of the arrays A defined on each worker.
MATLAB uses the fcn function to reduce AJ by calling the function N - 1 times.
• N is the number of workers running the spmd block or communicating job. To get the number of
workers running the current spmd block, use the spmdSize function
• Aj is the array A defined on spmd worker whose index is j.
To ensure that your spmd block or communicating job always produces the same results, specify fcn
as an associative function.
When you use parfor, parfeval, or parfevalOnAll to run code on a parallel pool, the workers
are independent and do not communicate with each other. If you use spmdReduce on these workers,
the result is the same as using spmdReduce on a client.
Examples
This example shows how to use spmdReduce to calculate the maximum value of an array across all
workers.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool run the code inside the spmd block.
Run spmdIndex on each worker in the spmd block and store the result in A. Use spmdReduce and
max to calculate the maximum value of A from each worker.
10-470
spmdReduce
Unless you specify a destination, spmdReduce stores the result on every worker. On the client, the
results is a Composite object. To get the result, index into the Composite object.
spmd
A = spmdIndex;
B = spmdReduce(@max,A);
end
disp(B{1})
Input Arguments
A — Input array
MATLAB variable | ...
Input array, specified as a scalar, vector, matrix, multidimensional array, table, timetable, or any
MATLAB variable that supports concatenation.
Example: A = magic(3)
Reduction function, specified as a function handle. The reduction function must take two input
arguments.
Example: fcn = @max
Data Types: function_handle
Index of the destination worker, specified as a positive integer or an empty array. The value of this
input must be less than or equal to the number of workers running the current spmd block or
communicating job.
When you specify this input, the function stores the value of B only on the worker with this index. On
the worker whose index is equal to destination, B is the result of the operation. On all other
workers, B is [].
Example: 1
Algorithms
This figure shows how the spmdReduce function uses fcn when you call spmdReduce(fcn,A).
10-471
10 Functions
Version History
Introduced in R2022b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
The spmdReduce function fully supports GPU arrays. To run the function on a GPU, specify the input
data as a gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-3.
If x is a gpuArray, data transfer between multiple GPUs in a parallel pool uses fast peer-to-peer
communication, including NVLink, if available.
10-472
spmdReduce
See Also
spmdBarrier | spmdIndex | spmdSize
Topics
“Use spmdReduce to Achieve MPI_Allreduce Functionality” on page 4-21
10-473
10 Functions
spmdSend
Send data to another worker in spmd block
Syntax
spmdSend(A,destination)
spmdSend( ___ ,tag)
Description
spmdSend(A,destination) sends data A from the current worker in an spmd block or
communicating job to the workers specified by destination.
When you offload computations using parfor and parfeval, only one worker at a time runs each
computation. These workers are independent and do not communicate with each other. If you apply
spmdSend to these workers, the function has no effect.
To use spmdSend, the number of workers running the current spmd block must be greater than 1. To
get the number of workers running the current spmd block, use the spmdSize function.
spmdSend( ___ ,tag) sends data with the tag tag. When you use spmdSend to send data between
workers, multiple items of data can wait to be collected. When you send multiple items of data to a
worker, add a tag to each item to distinguish between the items.
Examples
This example shows how to send data between workers in an spmd block or communicating job.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool run the code inside the spmd block.
Create an spmd block. On the worker whose index is equal to 1, create an array. Use spmdSend to
send the array to the worker whose index is equal to 2 and use spmdReceive to collect the data.
spmd
switch spmdIndex
case 1
A = magic(3)
spmdSend(A,2);
case 2
B = spmdReceive
end
end
10-474
spmdSend
Worker 1:
A =
8 1 6
3 5 7
4 9 2
Worker 2:
B =
8 1 6
3 5 7
4 9 2
This example shows how to tag and send data between workers in an spmd block or communicating
job.
parpool(4);
Create an spmd block. On the worker whose index is equal to 1, create two arrays A1 and A2. Before
and between creating arrays, pause the execution using the pause function to simulate some work.
Then, use spmdSend to send the matrices to the worker whose index is equal to 2.
Tag each matrix with an integer. On the worker whose index is equal to 2, use spmdReceive to
collect the data.
tic
spmd
switch spmdIndex
case 1
pause(5);
A1 = magic(1)
pause(5);
A2 = magic(2)
spmdSend(A1,2,1);
spmdSend(A2,2,2);
case 2
B1 = spmdReceive('any',1)
B2 = spmdReceive('any',2)
end
end
toc
Worker 1:
A1 =
10-475
10 Functions
A2 =
1 3
4 2
Worker 2:
B1 =
B2 =
1 3
4 2
In some cases, you can improve the performance of your code by moving some work from one worker
to another. Move some work from the worker whose index is equal to 1 to the worker whose index is
equal to 2. When you use tags, you can easily move calculations from one worker to another without
updating code on the receiving worker.
tic
spmd
switch spmdIndex
case 1
pause(5);
A1 = magic(1)
spmdSend(A1,2,1);
case 2
B2 = spmdReceive('any',2)
B1 = spmdReceive('any',1)
case 3
pause(5);
A2 = magic(2)
spmdSend(A2,2,2);
end
end
toc
Worker 1:
A1 =
Worker 2:
B2 =
1 3
4 2
B1 =
10-476
spmdSend
Worker 3:
A2 =
1 3
4 2
Input Arguments
A — Data to send
MATLAB variable
Data to send from the current worker, specified as a scalar, vector, matrix, multidimensional array,
table, timetable, or any other MATLAB variable.
Example: magic(3)
Indices of the workers receiving data, specified as a positive integer or vector of positive integers.
The indices must be less than or equal to the number of workers running the current spmd block or
communicating job.
Example: [2 3 4]
Message tag, specified as nonnegative integer. When you specify this input, spmdSend sends data
with this tag. If you receive the data on another worker using spmdReceive, that function returns
the tag in its tagOut output.
Example: 314159
Tips
1 Tags have many uses, for example:
• Use tags to save memory by only loading arrays on workers when you need the data.
• Use tags to create code that does not depend on the index of the sending worker.
2 A worker that sends data using spmdSend might finish execution before the receiving worker
receives the data. When you need synchronized workers in an spmd block or communicating job,
such as when you close a shared resource, use spmdBarrier after calling spmdSend and
spmdReceive.
Version History
Introduced in R2022b
10-477
10 Functions
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
GPU Arrays
Accelerate code by running on a graphics processing unit (GPU) using Parallel Computing Toolbox™.
The spmdSend function fully supports GPU arrays. To run the function on a GPU, specify the input
data as a gpuArray. For more information, see “Run MATLAB Functions on a GPU” on page 6-3.
If data is a gpuArray, data transfer between multiple GPUs in a parallel pool uses fast peer-to-peer
communication, including NVLink, if available.
See Also
spmdBarrier | spmdIndex | spmdProbe | spmdReceive | spmdSendReceive | spmdSize
10-478
spmdSendReceive
spmdSendReceive
Simultaneously send and receive data on worker in spmd block
Syntax
B = spmdSendReceive(destination,source,A)
B = spmdSendReceive( ___ ,tag)
Description
B = spmdSendReceive(destination,source,A) sends data A from the current worker in an
spmd block or communicating job to the destination, and receives data from the source. The
array A is sent from the current worker to the worker whose index is equal to destination. The
current worker receives data B sent to the current worker from the worker whose index is equal to
source.
When you use this syntax, the computation is equivalent to the worker sending and receiving data by
running these lines of code simultaneously:
spmdSend(A,destination);
B = spmdReceive(source);
B = spmdSendReceive( ___ ,tag) sends and receives data with the tag tag. When you use
spmdSendReceive to send data between workers, multiple items of data can wait to be collected.
When you send multiple items of data to a worker, add a tag to each item to distinguish between the
items.
Examples
This example shows how to use spmdSendReceive to send data between workers in an spmd block
or communicating job.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool run the code inside the spmd block.
Create an spmd block. Use mod and spmdSendReceive to send and receive data in a chain of
workers.
Use spmdSendReceive to send data to the worker whose index is greater by one than the index of
the current worker, modulo the number of workers running the current spmd block. Receive data
from the worker with an index that is less by one than the index of the current worker, modulo the
number of workers running the current spmd block.
10-479
10 Functions
When you use modulo division, the worker whose index is equal to 1 receives data from the worker
whose index is equal to the number of workers running the current spmd block.
spmd
A = 2*spmdIndex;
A = spmdSendReceive(destination,source,A)
end
Worker 1:
A =
12
Worker 2:
A =
2
Worker 3:
A =
4
Worker 4:
A =
6
Worker 5:
A =
8
Worker 6:
A =
10
Input Arguments
destination — Index of destination worker
positive integer | empty array
Index of the destination worker, specified as a positive integer or an empty array. The destination
worker receives data from the current worker. This input must be less than or equal to the number of
workers running the current spmd block or communicating job.
If this argument is an empty array, the function does not send any data.
Example: 2
Index of the source worker, specified as a positive integer or an empty array. The current worker
waits until it receives data from the source worker. This value must be less than the number of
workers running the current spmd block or communicating job.
If this argument is an empty array, the function does not receive any data.
Example: 1
10-480
spmdSendReceive
A — Data to send
MATLAB variable
Data to send from the current worker, specified as a scalar, vector, matrix, multidimensional array,
table, timetable, or any other MATLAB variable.
Example: magic(3)
Message tag, specified as a nonnegative integer. When you specify this input, spmdSendReceive
sends data with the tag tag from the current worker, and returns data sent with the tag tag to the
current worker.
Example: 314159
Tips
Tags have many uses, for example:
• Use tags to save memory by only loading arrays on workers when you need the data.
• Use tags to create code that does not depend on the index of the sending worker.
Version History
Introduced in R2022b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
spmdBarrier | spmdIndex | spmdProbe | spmdReceive | spmdSend | spmdSize
10-481
10 Functions
spmdSize
Number of workers running current spmd block
Syntax
n = spmdSize
Description
n = spmdSize returns the number of workers running the current spmd block or communicating
job. This value is the maximum value that you can use as the destination input to spmdSend and
source input to spmdReceive.
Examples
This example shows how to run spmdSize inside and outside an spmd block.
parpool(4);
When you execute an spmd block after creating a parallel pool, by default all available workers in the
pool run the code inside the spmd block.
Run spmdSize inside and outside an spmd block. In the block, the returned value is equal to the
number of workers. Outside the block, the returned value is 1.
spmd
disp(spmdSize)
end
disp(spmdSize)
Worker 1:
4
Worker 2:
4
Worker 3:
4
Worker 4:
4
10-482
spmdSize
Output Arguments
n — Number of workers
positive integer
Number of workers running the current spmd block or communicating job, returned as a positive
integer. In an spmd block, n is the number of workers running the spmd block. Outside an spmd
block, n is 1.
When you create a communicating job using createCommunicatingJob, you can run a function or
script on n workers. When one of the workers runs spmdSize, the returned value is n.
Version History
Introduced in R2022b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
spmdIndex | spmdSendReceive | createCommunicatingJob
10-483
10 Functions
start
Start cloud cluster
Syntax
start(cluster)
Description
start(cluster) starts the specified MATLAB Parallel Server for Cloud Center cluster, if it is not
already running. If the cluster is already running or in the process of shutting down, then
start(cluster) returns immediately, and the state of the cluster is not changed.
Examples
• From the MATLAB Parallel > Discover Clusters user interface. For more information, see
“Discover Clusters and Use Cluster Profiles” on page 7-2.
• By downloading it from Cloud Center. For more information, see MathWorks Cloud Center
documentation.
Input Arguments
cluster — MATLAB Parallel Server for Cloud Center cluster
cluster object (default)
MATLAB Parallel Server for Cloud Center cluster, specified as cluster object created using
parcluster.
Example: start(cluster)
Version History
Introduced in R2017a
10-484
start
See Also
parcluster | shutdown | wait (cluster) | [Link] | parpool
10-485
10 Functions
start
Namespace: [Link]
Syntax
start(monitor)
Description
start(monitor) starts collecting pool activity monitoring data using the ActivityMonitor object,
monitor.
Use the start function to restart monitoring pool activity with an ActivityMonitor object that has
previously stopped monitoring activity.
If monitor is already monitoring pool activity, the software discards any results collected.
Examples
pool = parpool("myCluster",4);
Create an ActivityMonitor object to collect monitoring data for the pool but do not start collecting
data immediately.
monitor = [Link](pool,Start=false);
Create some large data on the client, then build a Constant object, C, transferring the data to the
pool only once.
data = rand(1000);
C = [Link](data);
Start collecting pool monitoring data using the ActivityMonitor object, monitor.
start(monitor)
Run multiple parfor-loops accessing the Constant object, C. For efficiency, preallocate the results
array.
x = eye(5);
for ii = 1:5
parfor jj = 1:5
10-486
start
x(ii,jj) = [Link](ii,jj);
end
end
Stop the activity monitor and retrieve the monitoring results collected during the execution of the
parfor-loops.
monitoringResults = stop(monitor);
Create an ActivityMonitor object to start collecting pool monitoring data. With default settings,
[Link] automatically starts an interactive parallel pool using the
default profile if one does not exist.
monitor = [Link];
Submit multiple parfeval computations to compute magic squares. Wait for all tasks to complete.
f(1:100) = [Link];
for idx = 1:100
f(idx) = parfeval(@magic,1,idx);
end
wait(f);
Use the stop function to stop collecting monitoring data and retrieve the monitoring results.
monitoringResults = stop(monitor);
Input Arguments
monitor — Pool activity monitor
ActivityMonitor object
Version History
Introduced in R2025a
See Also
Functions
results | stop
10-487
10 Functions
Objects
ActivityMonitor | ActivityMonitorResults
Tools
Pool Dashboard
10-488
stop
stop
Namespace: [Link]
Syntax
monitorResults = stop(monitor)
Description
monitorResults = stop(monitor) stops collecting pool activity monitoring data and retrieves all
pool activity monitoring results from the ActivityMonitor object, monitor.
Examples
Create an ActivityMonitor object to start collecting pool monitoring data. With default settings,
[Link] automatically starts an interactive parallel pool using the
default profile if one does not exist.
monitor = [Link];
Submit multiple parfeval computations to compute magic squares. Wait for all tasks to complete.
f(1:100) = [Link];
for idx = 1:100
f(idx) = parfeval(@magic,1,idx);
end
wait(f);
Use the stop function to stop collecting monitoring data and retrieve the monitoring results.
Visualize the monitoring results in the Pool Dashboard.
monitoringResults = stop(monitor);
parpoolDashboard(monitoringResults)
10-489
10 Functions
Input Arguments
monitor — Pool activity monitor
ActivityMonitor object
Output Arguments
monitorResults — Pool activity monitoring results
ActivityMonitorResults object | ActivityMonitorResults object array
If you have not previously started the ActivityMonitor object, the stop function returns a 0-by-0
ActivityMonitorResults object array with empty StartTime and EndTime object properties.
To visualize the pool activity monitoring results in the Pool Dashboard, use the parpoolDashboard
function.
10-490
stop
Version History
Introduced in R2025a
See Also
Functions
results | start
Objects
ActivityMonitorResults | ActivityMonitor
Tools
Pool Dashboard
10-491
10 Functions
submit
Queue job in scheduler
Syntax
submit(j)
Description
submit(j) queues the job object j in its cluster queue. The cluster used for this job was determined
when the job was created.
Examples
c1 = parcluster('Profile1');
j1 = createJob(c1);
t1 = createTask(j1,@rand,1,{8,4});
submit(j1);
Input Arguments
j — Job to queue
job object
Job to queue, specified as a job object. To create a job object, use the createJob function.
Tips
When a job is submitted to a cluster queue, the job's State property is set to queued, and the job is
added to the list of jobs waiting to be executed.
The jobs in the waiting list are executed in a first in, first out manner; that is, the order in which they
were submitted, except when the sequence is altered by promote, demote, cancel, or delete.
10-492
submit
Version History
Introduced before R2006a
See Also
createCommunicatingJob | createJob | findJob | parcluster | promote | recreate
10-493
10 Functions
subsasgn
Subscripted assignment for Composite
Syntax
C(i) = {B}
C(1:end) = {B}
C([i1,i2]) = {B1,B2}
C{i} = B
Description
subsasgn assigns remote values to Composite objects. The values reside on the workers in the
current parallel pool.
Version History
Introduced in R2008b
See Also
subsasgn | Composite | subsref
10-494
subsref
subsref
Subscripted reference for Composite
Syntax
B = C(i)
B = C([i1,i2,...])
B = C{i}
[B1,B2,...] = C{[i1,i2,...]}
Description
subsref retrieves remote values of a Composite object from the workers in the current parallel pool.
Version History
Introduced in R2008b
See Also
subsref | Composite | subsasgn
10-495
10 Functions
taskFinish
User-defined options to run on worker when task finishes
Syntax
taskFinish(task)
Arguments
task The task being evaluated by the worker
Description
taskFinish(task) runs automatically on a worker each time the worker finishes evaluating a task
for a particular job. You do not call this function from the client session, nor explicitly as part of a task
function.
You add MATLAB code to the taskFinish.m file to define anything you want executed on the worker
when a task is finished. The worker looks for taskFinish.m in the following order, executing the
one it finds first:
matlabroot/toolbox/parallel/user/taskFinish.m
Version History
Introduced before R2006a
See Also
jobStartup | poolStartup | taskStartup
10-496
taskStartup
taskStartup
User-defined options to run on worker when task starts
Syntax
taskStartup(task)
Arguments
task The task being evaluated by the worker.
Description
taskStartup(task) runs automatically on a worker each time the worker evaluates a task for a
particular job. You do not call this function from the client session, nor explicitly as part of a task
function.
You add MATLAB code to the taskStartup.m file to define task initialization on the worker. The
worker looks for taskStartup.m in the following order, executing the one it finds first:
matlabroot/toolbox/parallel/user/taskStartup.m
Version History
Introduced before R2006a
See Also
jobStartup | poolStartup | taskFinish
10-497
10 Functions
send
Namespace: [Link]
Syntax
send(queue,data)
send(pollablequeue,data)
Description
send(queue,data) sends a message or data with the value data to the DataQueue specified by
queue. Call afterEach to pass each of the pending messages to the function specified by
afterEach.
Use the send and poll functions together with a pollable data queue to transfer and retrieve
messages or data between the client and workers.
Examples
Create a DataQueue, and use afterEach to set up a callback function that displays data from the
queue on the client.
q = [Link];
afterEach(q,@disp);
Run a parfor-loop, and send a message to the queue. When the message arrives on the client, it is
passed to the afterEach callback function, @disp.
parfor i = 1:3
send(q,i);
end;
For more details on listening for data using a DataQueue, see afterEach.
10-498
send
p = [Link];
f = parfeval(@send,0,p,1);
wait(f);
poll(p)
ans = 1
This example shows a function that creates a parfor wait bar. Create a DataQueue, and use
afterEach to specify the function to execute each time the queue receives data. This example calls a
subfunction that updates the wait bar.
Create a parfor-loop to carry out a computationally demanding task in MATLAB. Use send to send
some dummy data on each iteration of the parfor-loop. When the queue receives the data,
afterEach calls nUpdateWaitbar in the client MATLAB, and you can observe the wait bar
progress.
function a = parforWaitbar
D = [Link];
h = waitbar(0,'Please wait ...');
afterEach(D,@nUpdateWaitbar);
N = 200;
p = 1;
parfor i = 1:N
a(i) = max(abs(eig(rand(400))));
send(D,i);
end
function nUpdateWaitbar(~)
waitbar(p/N,h);
p = p + 1;
end
end
10-499
10 Functions
Input Arguments
queue — Data queue
[Link]
Message or data sent to a data queue, specified as any data type that can be serialized.
Example: send(queue,data);
If you close a PollableDataQueue using the close function, you can no longer send data to the
queue. Any attempt to send data to the queue results in an error.
Example: p = [Link];
Version History
Introduced in R2017a
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
Functions
afterEach | poll | close | parfor | parpool
10-500
send
Objects
DataQueue | [Link]
10-501
10 Functions
ticBytes
Namespace: parallel
Syntax
ticBytes(pool)
startState = ticBytes(pool)
Description
ticBytes(pool) starts counting the number of bytes transferred to each worker in the pool, so
that later tocBytes(pool) can measure the amount of data (and associated metadata) transferred
to each worker between the two calls.
Use the ticBytes (pool) and tocBytes (pool) functions together to measure how much data is
transferred to and from the workers in a parallel pool. You can use ticBytes and tocBytes while
executing parallel language constructs and functions, such as parfor, spmd, or parfeval. Use
ticBytes and tocBytes to pass around less data and optimize your code.
startState = ticBytes(pool) saves the state to an output argument, startState, so that you
can simultaneously record the number of bytes transferred for multiple pairs of ticBytes and
tocBytes calls. Use the value of startState as an input argument for a subsequent call to
tocBytes.
Examples
a = 0;
b = rand(100);
ticBytes(gcp);
parfor i = 1:100
a = a + sum(b(:, i));
end
tocBytes(gcp)
BytesSentToWorkers BytesReceivedFromWorkers
__________________ ________________________
1 42948 7156
2 36548 7156
3 27500 4500
4 27500 4500
Total 1.345e+05 23312
10-502
ticBytes
Workers might transfer different numbers of bytes, because each worker might carry out different
numbers of loop iterations.
Measure the minimum and average number of bytes transferred while running a parfor loop nested
in a for loop.
REPS = 10;
minBytes = Inf;
ticBytes(gcp); % ticBytes, pair 1
for ii=1:REPS
a = 0;
b = rand(100);
startS = ticBytes(gcp) % ticBytes, pair 2
parfor i = 1:100
a = a + sum(b(:, i));
end
bytes = tocBytes(gcp, startS) % tocBytes, pair 2
minBytes = min(bytes, minBytes)
end
Note that nesting a parfor-loop in a for-loop can be slow due to overhead, see “Convert Nested for-
Loops to parfor-Loops” on page 2-14.
Input Arguments
pool — Parallel pool
[Link] object | [Link] object
Output Arguments
startState — Starting state
TicBytesResult
Version History
Introduced in R2016b
10-503
10 Functions
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
tocBytes | parfor | gcp | spmd | parfeval | parpool
10-504
tocBytes
tocBytes
Namespace: parallel
Read how many bytes have been transferred since calling ticBytes
Syntax
tocBytes(pool)
bytes = tocBytes(pool)
tocBytes(pool,startState)
bytes = tocBytes(pool,startState)
Description
tocBytes(pool) reads how many bytes have been transferred since calling ticBytes. The function
displays the total number of bytes transferred to and from each of the workers in a parallel pool
after the most recent execution of ticBytes.
Use the ticBytes (pool) and tocBytes (pool) functions together to measure how much data (and
associated metadata) is transferred to and from the workers in a parallel pool. You can use ticBytes
and tocBytes while executing parallel language constructs and functions, such as parfor, spmd, or
parfeval. Use ticBytes and tocBytes to pass around less data and optimize your code.
bytes = tocBytes(pool) returns the number of bytes transferred to and from each of the
workers in the parallel pool.
tocBytes(pool,startState) displays the total number of bytes transferred in the parallel pool
after the ticBytes command that generated startState.
bytes = tocBytes(pool,startState) returns the number of bytes transferred to and from each
of the workers in the parallel pool after the ticBytes command that generated startState.
Examples
Use tocBytes(gcp,startS) to measure the amount of data (and associated metadata) transferred.
a = 0;
b = rand(100);
startS = ticBytes(gcp);
parfor i = 1:100
a = a + sum(b(:, i));
end
tocBytes(gcp,startS)
BytesSentToWorkers BytesReceivedFromWorkers
10-505
10 Functions
__________________ ________________________
1 42948 7156
2 36548 7156
3 27500 4500
4 27500 4500
Total 1.345e+05 23312
Workers might transfer different numbers of bytes, because each worker might carry out different
numbers of loop iterations.
Use bytes = tocBytes(gcp) to measure the amount of data (and associated metadata)
transferred.
ticBytes(gcp);
spmd
rand(100);
end
bytes = tocBytes(gcp)
bytes =
13448 1208
13448 1208
13448 1208
13448 1208
Workers transfer the same number of bytes, because each worker carries out the same number of
loop iterations.
Measure the minimum and average number of bytes transferred while running a parfor loop nested
in a for loop.
REPS = 10;
minBytes = Inf;
ticBytes(gcp); % ticBytes, pair 1
for ii=1:REPS
a = 0;
b = rand(100);
startS = ticBytes(gcp) % ticBytes, pair 2
parfor i = 1:100
a = a + sum(b(:, i));
end
bytes = tocBytes(gcp, startS) % tocBytes, pair 2
minBytes = min(bytes, minBytes)
end
10-506
tocBytes
Note that nesting a parfor-loop in a for-loop can be slow due to overhead, see “Convert Nested for-
Loops to parfor-Loops” on page 2-14.
Input Arguments
pool — Parallel pool
[Link] object | [Link] object
Output Arguments
bytes — Bytes transferred
tocBytes(pool)
Bytes transferred, returned as a matrix of size numWorkers x 2. This matrix contains the number of
bytes transferred to and from each of the workers in the parallel pool. bytes returns values in bytes
without headings. Use tocBytes(pool) without an output argument to get Sent and Received
headings, worker numbers, and values in bytes in the Command Window output.
Example: bytes = tocBytes(pool);
Version History
Introduced in R2016b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
ticBytes | parfor | spmd | gcp | parfeval | parpool
10-507
10 Functions
true
Create codistributed array of logical 1 (true)
Syntax
cT = true(n,codist)
cT = true(sz,codist)
cT = true(sz1,...,szN,codist)
Description
cT = true(n,codist) creates an n-by-n codistributed matrix of logical ones and uses codist to
specify the distribution of the array values across the workers.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
cT = true(sz,codist) creates a codistributed array of logical ones where the size vector sz
defines the size of cT. For example, true([2 3],"codistributed") creates a 2-by-3 codistributed
array.
cT = true( ___ ,"noCommunication") creates a codistributed array of logical ones without using
communication between workers. You can use this syntax with any of the input arguments in the
previous syntaxes.
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
cT = true( ___ ,like=p) uses the array p to return a codistributed array of logical ones. You can
also specify "noCommunication" as part of the function call.
10-508
true
Examples
Create a 1000-by-1000 codistributed matrix of trues, distributed by its second dimension (columns).
spmd(4)
C = true(1000,"codistributed");
end
Input Arguments
n — Size of square matrix
integer
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
10-509
10 Functions
• Beyond the second dimension, true ignores trailing dimensions with a size of 1. For example,
true([3 1 1 1],"codistributed") produces a 3-by-1 codistributed vector of logical ones.
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p.
Tips
• true(n,"codistributed") is much faster and more memory efficient than
logical(ones(n,"codistributed")).
Version History
Introduced in R2006b
See Also
true | eye (codistributed) | false (codistributed) | Inf (codistributed) | NaN
(codistributed) | ones (codistributed) | zeros (codistributed)
10-510
updateAttachedFiles
updateAttachedFiles
Namespace: parallel
Syntax
updateAttachedFiles(poolobj)
Description
updateAttachedFiles(poolobj) checks all the attached files of the specified parallel pool to see
if they have changed, and replicates any changes to each of the workers in the pool. This checks files
that were attached (by a profile or parpool argument) when the pool was started and those
subsequently attached with the addAttachedFiles command.
Examples
poolobj = gcp;
updateAttachedFiles(poolobj)
Input Arguments
poolobj — Parallel pool
[Link] object | [Link] object
Version History
Introduced in R2013b
See Also
addAttachedFiles | gcp | listAutoAttachedFiles | parpool
Topics
“Add and Modify Cluster Profiles” on page 7-5
10-511
10 Functions
validateGPU
Validate GPU devices
Syntax
validateGPU
validateGPU("all")
validateGPU(ind)
Description
validateGPU validates the currently selected GPU device. If no GPU device is selected, then the
function validates the default device.
Tip Validating your GPU device is not required. Use the validateGPU function to diagnose problems
with your GPU setup.
Examples
Validate the currently selected GPU device. If no GPU device is selected, the function validates the
default device. The validateGPU function prints the validation steps performed and an indication of
whether each step passed, failed, or was skipped. If a validation step fails, the function prints a
diagnostic message.
validateGPU
10-512
validateGPU
Validate all GPU devices present in your system. The validateGPU function performs a series of
system validation checks once, and then a series of device validation steps once for each device
detected.
validateGPU("all")
validateGPU(2)
10-513
10 Functions
If you have multiple GPU devices, then you can validate several using a single call to validateGPU
by passing a vector of device indices as input. For example, to validate GPU devices 1 and 2, call
validateGPU([1 2]).
Input Arguments
ind — Indices of GPU devices
integer | vector of integers
Indices of GPU devices to validate, specified as an integer or vector of integers in the range 1 to
gpuDeviceCount.
Example: 2
Example: [1 3]
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Tips
• To validate remote GPUs, start a parallel pool using your cluster with as many workers as there
are GPUs, then call validateGPU inside an spmd block.
cluster = parcluster("myRemoteGPUCluster");
pool = parpool(cluster,numGPUs);
spmd
validateGPU
end
For more information about using remote GPUs, see “Work with Remote GPUs” on page 6-25.
10-514
validateGPU
Algorithms
List of Validation Steps
The validateGPU performs these device-level validation steps. If you validate more than one device,
then these steps are repeated for each device.
Version History
Introduced in R2024b
See Also
gpuDeviceTable | gpuDevice | gpuDeviceCount | canUseGPU
Topics
“Identify and Select a GPU Device” on page 6-10
“GPU Computing Requirements” on page 6-13
10-515
10 Functions
[Link]
Validate parallel environment profile
Syntax
[Link]
[Link](profile)
[Link]( ___ ,Name=Value)
Description
[Link] validates the default parallel environment or cluster profile.
The [Link] function prints the validation stages performed and an indication
of whether each stage passed, failed, or was skipped.
If a validation stage fails, the function saves a validation report to the temporary folder.
Examples
Validate the default profile. The [Link] function prints the validation stages
performed and an indication of whether each stage passed, failed, or was skipped.
[Link]
10-516
[Link]
Validate the Threads profile. The [Link] function only runs the Parallel
pool test (parpool) validation stage for thread type profiles.
[Link]("Threads")
Validate the profile for a remote MATLAB® Job Scheduler cluster, myCluster, using 5 workers. Run
only the "parcluster", "pool-job", and "parpool" stages. Save the validation results to a
report file with the name "[Link]". The [Link] function prints
the validation stages performed and an indication of whether each stage passed or failed.
[Link]("myCluster",NumWorkersToUse=5,StagesToRun=["parcluster","pool-job","parp
10-517
10 Functions
To ensure that you have successfully integrated MATLAB Parallel Server into your Spark cluster and
that your profile is correctly configured, validate the Spark profile named "SparkProfile1". The
validation fails because of an incorrectly configured profile and [Link]
automatically saves a report to the temporary folder.
[Link]("SparkProfile1")
Beginning validation for cluster profile 'SparkProfile1'
Cluster connection test (parcluster)
Stage started at 14:10:26.
Unable to find Spark. Set the SPARK_HOME environment variable to a valid
Spark installation folder or use the 'SparkInstallFolder' name-value
parameter.
..........................................................................FAILED
You can validate a profile noninteractively at the command line using the -batch MATLAB startup
option. To learn more about MATLAB startup options, see “Commonly Used Startup Options”.
In a command-line prompt, validate the profile for a remote cluster, mySlurmCluster, using 4
workers. Skip the "parpool" stage. Save the validation results to a report file with the name
'[Link]'. The [Link] function prints the validation stages
performed and an indication of whether each stage passed or failed.
10-518
[Link]
Input Arguments
profile — Parallel environment or cluster profile
character vector | string
Parallel environment or cluster profile, specified as a character vector or string. If you do not specify
a profile, [Link] validates the default profile.
Example: "Processes"
Example: "Threads"
Example: "myMJSCluster"
Data Types: char | string
Number of workers to use in validation, specified as a nonnegative integer. Use this argument to
validate the profile with fewer workers than those specified in the profile's
PreferredPoolNumWorkers or NumWorkers property.
Example: NumWorkersToUse=4
10-519
10 Functions
Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
Validation stages to run, specified as a string array or cell array of character vectors with one or more
of these stage values:
Some stages are only available for certain parallel environment or cluster types. You cannot specify
this argument if you specify the StagesToSkip argument. To learn more about each stage, see “List
of Validation Stages” on page 10-521.
Example: StagesToRun=["parcluster","parpool"]
Data Types: char | string | cell
Validation stages to skip, specified as a string array or cell array of character vectors with one or
more of these stage values:
Some stages are only available for certain parallel environment or cluster types. You cannot specify
this argument if you specify the StagesToRun argument. To learn more about each stage, see “List
of Validation Stages” on page 10-521.
Example: StagesToSkip=["parcluster","spmd-job"]
Data Types: char | string | cell
10-520
[Link]
Limitations
• When you validate a profile for the Threads parallel environment, [Link]
runs only the Parallel pool test (parpool) stage.
Algorithms
List of Validation Stages
Version History
Introduced in R2025a
See Also
Functions
[Link] | [Link] | saveAsProfile
Topics
“Discover Clusters and Use Cluster Profiles” on page 7-2
10-521
10 Functions
wait
Namespace: parallel
Syntax
wait(j)
wait(j,state)
tf = wait(j,state,timeout)
Description
wait(j) blocks execution in the client session until the job identified by the object j reaches the
'finished' state or fails. The 'finished' state occurs when all the job's tasks are finished
processing on the workers.
Note Simulink models cannot run while a MATLAB session is blocked by wait. If you must run
Simulink from the MATLAB client while also running jobs, do not use wait
wait(j,state) blocks execution in the client session until the specified job object changes state to
the value of state. Valid states to wait for are "queued", "running", and "finished".
If the object is currently or was previously in the specified state, MATLAB does not wait and the
function returns immediately. For example, if you run wait(j,"queued") for a job already in the
"finished" state, the function returns immediately.
tf = wait(j,state,timeout) blocks execution until the job reaches the specified state, or until
timeout seconds elapse, whichever happens first. tf is false if timeout is exceeded before state
is reached.
Examples
Submit a job to the queue, and wait for it to finish running before retrieving its results.
submit(j);
wait(j,"running")
diary(j)
Submit a batch job and wait for it to finish before retrieving its variables.
10-522
wait
j = batch('myScript');
wait(j)
load(j)
Input Arguments
j — Job to wait
[Link] object
Job object whose change in state to wait for, specified as a [Link] object.
Value of the job object's State property to wait for, specified as one of the following:
• "queued"
• "running"
• "finished"
Output Arguments
tf — True or false result
true or 1 | false or 0
If the job reaches state successfully, the function returns tf as true. If timeout is exceeded before
state is reached, then tf is false.
Version History
Introduced in R2008a
See Also
pause | resume | wait (Future) | wait (GPUDevice) | [Link]
10-523
10 Functions
wait (cluster)
Wait for cloud cluster to change state
Syntax
wait(cluster)
wait(cluster,state)
OK = wait(cluster,state,timeout)
Description
wait(cluster) blocks execution in the client MATLAB session until cluster reaches the 'online'
state. The 'online' state indicates that the cluster is running and you can use all requested workers
to run jobs.
wait(cluster,state) blocks execution in the client session until cluster changes state. For a
cluster object, the valid states are:
• 'online': The cluster is running and you can use all requested workers to run jobs.
• 'waitingforworkers': The cluster is running, and you can use some but not all of the requested
workers to run jobs. You can still use the cluster in this state with the workers that are available.
• 'offline': The cluster is not running, but you can restart using the start() command or via
[Link] If the cluster has shared persisted storage, then any previous
jobs in the queue are still present when you restart the cluster.
Examples
In Cluster Profile Manager, select MATLAB Parallel Server for Amazon EC2 as your default cluster
profile.
cluster = parcluster;
start(cluster);
Wait until the cluster is running. Use all requested workers to run jobs.
wait(cluster,'online');
10-524
wait (cluster)
In Cluster Profile Manager, select MATLAB Parallel Server for Amazon EC2 as your default cluster
profile.
cluster = parcluster;
start(cluster);
Wait 100 seconds for the head node and all workers to start.
OK = wait(cluster,'online',100);
Input Arguments
cluster — MATLAB Parallel Server for Cloud Center cluster
cluster object (default)
MATLAB Parallel Server for Cloud Center cluster, specified as cluster object created using
parcluster.
Example: wait(cluster);
Cloud cluster state, specified as a cluster object, for which the valid states are 'online',
'waitingforworkers', and 'offline'.
Example: wait(cluster,'online');
Output Arguments
OK — check if state has been reached
Boolean
Check if state has been reached, specified as a Boolean. OK is true if state has been reached or a
terminal state such as 'error' occurs. OK is false in case of a timeout.
Example: OK = wait(cluster,'waitingforworkers',10);
Version History
Introduced in R2017a
10-525
10 Functions
See Also
shutdown | start | parpool | parcluster | [Link]
10-526
wait
wait
Namespace: [Link]
Syntax
wait(gpudev)
Description
wait(gpudev) blocks execution in MATLAB until the GPU device identified by the GPUDevice
object gpudev completes its calculations. This can be used before calls to tic and toc when timing
GPU code that does not gather results back to the workspace. When gathering results from a GPU
using the gather function, MATLAB waits until all GPU calculations are complete, so you do not need
to explicitly call wait in that situation.
Examples
GPU operations in MATLAB® run asynchronously, that is they run in the background and are not
necessarily complete when a subsequent line of code is run. This is relevant when timing code
running on a GPU.
You can time how long a function takes to execute on the GPU using the gputimeit function, which
ensures that all operations on the GPU have finished before recording the time. As gputimeit runs
the function several times, it can be unsuitable for timing particularly long-running code. As an
alternative, use the tic and toc functions, calling wait before each.
gpu = gpuDevice;
disp([Link] + " GPU selected.")
A = rand(1000,"gpuArray");
Wait for the GPU device to finish creating matrix A and start timing using tic.
wait(gpu)
tic
Factorize the matrix into an upper triangular matrix and a permuted lower triangular matrix using
the lu function.
[L,U] = lu(A);
10-527
10 Functions
Wait for the calculations to finish, then output the elapsed time using toc.
wait(gpu)
toc
Input Arguments
gpudev — GPU device
GPU device
GPU device, specified as a GPUDevice object that represents the currently selected device. To obtain
a GPUDevice object, use the gpuDevice function.
Version History
Introduced in R2014b
Extended Capabilities
Thread-Based Environment
Run code in the background using MATLAB® backgroundPool or accelerate code with Parallel
Computing Toolbox™ ThreadPool.
This function fully supports thread-based environments. For more information, see “Run MATLAB
Functions in Thread-Based Environment”.
See Also
gpuDevice | gputimeit | gpuArray
Topics
“Identify and Select a GPU Device” on page 6-10
“Measure and Improve GPU Performance” on page 6-41
10-528
write
write
Write distributed data to an output location
Syntax
write(location,D)
write(filepattern,D)
write( ___ ,Name,Value)
Description
write(location,D) writes the values in the distributed array D to files in the folder location. The
data is stored in an efficient binary format suitable for reading back using datastore(location).
If not distributed along the first dimension, MATLAB redistributes the data before writing, so that the
resulting files can be reread using datastore.
write(filepattern,D) uses the file extension from filepattern to determine the output format.
filepattern must include a folder to write the files into followed by a file name that includes a
wildcard *. The wildcard represents incremental numbers for generating unique file names, for
example write('folder/myfile_*.csv',D).
write( ___ ,Name,Value) specifies additional options with one or more name-value pair arguments
using any of the previous syntaxes. For example, you can specify the file type with 'FileType' and a
valid file type ('mat', 'seq', 'parquet', 'text', or 'spreadsheet'), or you can specify a
custom write function to process the data with 'WriteFcn' and a function handle.
Examples
This example shows how to write a distributed array to a file system, then read it back using a
datastore.
d = [Link](5000,1);
location = 'hdfs://myHadoopCluster/some/output/folder';
write(location, d);
ds = datastore(location);
d1 = distributed(ds);
This example shows how to write distributed arrays to different formats using a file pattern.
10-529
10 Functions
Create a distributed table and write it to a simple text-based format that many applications can read.
dt = distributed(array2table(rand(5000,3)));
location = "/tmp/CSVData/dt_*.csv";
write(location, dt);
ds = datastore(location);
dt1 = distributed(ds);
You can write distributed data and read it back as tall data and vice versa.
dt = distributed(array2table(rand(5000,3)));
location = "/tmp/CSVData/dt_*.csv";
write(location, dt);
ds = datastore(location);
tt = tall(ds);
Alternatively, you can read data written from tall data into distributed data. Create a tall timetable
and write it to disk.
tt = tall(array2table(rand(5000,3)));
location = "/tmp/CSVData/dt_*.csv";
write(location, tt);
ds = datastore(location);
dt = distributed(ds);
This example shows how to write distributed arrays to a file system using a custom write function.
Create a distributed table and write it to disk using the custom write function.
10-530
write
dt = distributed(array2table(rand(5000,3)));
location = "/tmp/MyData/tt_*.xlsx";
write(location, dt, "WriteFcn", @dataWriter);
Input Arguments
location — Folder location to write data
character vector | string
Folder location to write data, specified as a character vector or string. location can specify a full or
relative path. The specified folder can be either of these options:
You can write data to local folders on your computer, folders on a shared network, or to remote
locations, such as Amazon S3, Windows Azure® Storage Blob, or a Hadoop Distributed File System
(HDFS). For more information about reading and writing data to remote locations, see “Work with
Remote Data”.
Example: location = '../../dir/data' specifies a relative file path.
Example: location = 'C:\Users\MyName\Desktop\data' specifies an absolute path to a
Windows desktop folder.
Example: location = '[Link] specifies an absolute URI path to a folder.
Example: location = 'hdfs://myHadoopCluster/some/output/folder' specifies an HDFS
URL.
Example: location = 's3://bucketname/some/output/folder' specifies an Amazon S3
location.
Data Types: char | string
D — Input array
distributed array
File naming pattern, specified as a string or a character vector. The file naming pattern must contain
a folder to write the files into followed by a file name that includes a wildcard *. write replaces the
wildcard with sequential numbers to ensure unique file names.
Example: write('folder/data_*.txt',D) writes the distributed array D as a series of .txt files
in folder with the file names data_1.txt, data_2.txt, and so on.
Data Types: char | string
10-531
10 Functions
Before R2021a, use commas to separate each name and value, and enclose Name in quotes.
Example: write('C:\myData', D, 'FileType', 'text', 'WriteVariableNames', false)
writes the distributed array D to C:\myData as a collection of text files that do not use variable
names as column headings.
General Options
Type of file, specified as the comma-separated pair consisting of 'FileType' and one of the allowed
file types: 'auto', 'mat', 'parquet', 'seq', 'text', or 'spreadsheet'.
Use the 'FileType' name-value pair with the location argument to specify what type of files to
write. By default, write attempts to automatically detect the proper file type. You do not need to
specify the 'FileType' name-value pair argument if write can determine the file type from an
extension in the location or filepattern arguments. write can determine the file type from
these extensions:
Custom writing function, specified as the comma-separated pair consisting of 'WriteFcn' and a
function handle. The specified function receives blocks of data from D and is responsible for creating
the output files. You can use the 'WriteFcn' name-value pair argument to write data in a variety of
formats, even if the output format is not directly supported by write.
Functional Signature
The custom writing function must accept two input arguments, info and data:
Field Description
RequiredLocation Fully qualified path to a temporary output
folder. All output files must be written to this
folder.
10-532
write
Field Description
RequiredFilePattern The file pattern required for output file names.
This field is empty if only a folder name is
specified.
SuggestedFilename A fully qualified, globally unique file name that
meets the location and naming requirements.
PartitionIndex Index of the distributed array partition being
written.
NumPartitions Total number of partitions in the distributed
array.
BlockIndexInPartition Position of current data block within the
partition.
IsFinalBlock true if current block is the final block of the
partition.
File Naming
The file name used for the output files determines the order that the files are read back in later by
datastore. If the order of the files matters, then the best practice is to use the
SuggestedFilename field to name the files since the suggested name guarantees the file order. If
you do not use the suggested file name, the custom writing function must create globally unique,
correctly ordered file names. The file names should follow the naming pattern outlined in
RequiredFilePattern. The file names must be unique and correctly ordered between workers,
even though each worker writes to its own local folder.
A distributed array is divided into partitions to facilitate running calculations on the array in parallel
with Parallel Computing Toolbox. When writing a distributed array, each of the partitions is divided in
smaller blocks.
Example Function
To invoke dataWriter as the writing function for some data D, use the commands:
D = distributed(array2table(rand(5000,3)));
location = '/tmp/MyData/D_*.xlsx';
write(location, D, 'WriteFcn', @dataWriter);
10-533
10 Functions
For each block, the dataWriter function uses the suggested file name in the info structure and
calls writetable to write out a spreadsheet file. The suggested file name takes into account the file
naming pattern that is specified in the location argument.
Data Types: function_handle
Indicator for writing variable names as column headings, specified as the comma-separated pair
consisting of 'WriteVariableNames' and a numeric or logical 1 (true) or 0 (false).
Indicator Behavior
true Variable names are included as the column headings of the output. This is
the default behavior.
false Variable names are not included in the output.
Locale for writing dates, specified as the comma-separated pair consisting of 'DateLocale' and a
character vector or a string scalar. When writing datetime values to the file, use DateLocale to
specify the locale in which write should write month and day-of-week names and abbreviations. The
character vector or string takes the form xx_YY, where xx is a lowercase ISO 639-1 two-letter code
indicating a language, and YY is an uppercase ISO 3166-1 alpha-2 code indicating a country. For a list
of common values for the locale, see the Locale name-value pair argument for the datetime
function.
For Excel® files, write writes variables containing datetime arrays as Excel dates and ignores the
'DateLocale' parameter value. If the datetime variables contain years prior to either 1900 or
1904, then write writes the variables as text. For more information on Excel dates, see Differences
between the 1900 and the 1904 date system in Excel.
Example: 'DateLocale','ja_JP' or 'DateLocale',"ja_JP"
Data Types: char | string
Field delimiter character, specified as the comma-separated pair consisting of 'Delimiter' and one
of these specifiers:
'comma'
10-534
write
'space'
'\t' Tab
'tab'
';' Semicolon
'semi'
'|' Vertical bar
'bar'
You can use the 'Delimiter' name-value pair argument only for delimited text files.
Example: 'Delimiter','space' or 'Delimiter',"space"
Indicator for writing quoted text, specified as the comma-separated pair consisting of
'QuoteStrings' and either false or true. If 'QuoteStrings' is true, then write encloses the
text in double quotation marks, and replaces any double-quote characters that appear as part of that
text with two double-quote characters. For an example, see “Write Quoted Text to CSV File”.
You can use the 'QuoteStrings' name-value pair argument only with delimited text files.
Character encoding scheme associated with the file, specified as the comma-separated pair consisting
of 'Encoding' and 'system' or a standard character encoding scheme name like one of the values
in this table. When you do not specify any encoding or specify encoding as 'system', the write
function uses your system default encoding to write the file.
10-535
10 Functions
"Macintosh" "UTF-8"
"Shift_JIS"
Target worksheet, specified as the comma-separated pair consisting of 'Sheet' and a character
vector or a string scalar containing the worksheet name or a positive integer indicating the
worksheet index. The worksheet name cannot contain a colon (:). To determine the names of sheets
in a spreadsheet file, use [status,sheets] = xlsfinfo(filename).
If the sheet does not exist, then write adds a new sheet at the end of the worksheet collection. If the
sheet is an index larger than the number of worksheets, then write appends empty sheets until the
number of worksheets in the workbook equals the sheet index. In either case, write generates a
warning indicating that it has added a new worksheet.
You can use the 'Sheet' name-value pair argument only with spreadsheet files.
Example: 'Sheet',2
Example: 'Sheet', 'MySheetName'
Data Types: char | string | single | double | int8 | int16 | int32 | int64 | uint8 | uint16 |
uint32 | uint64
In general, 'snappy' has better performance for reading and writing, 'gzip' has a higher
compression ratio at the cost of more CPU processing time, and 'brotli' typically produces the
smallest file size at the cost of compression speed.
Example:
write('C:\myData',D,'FileType','parquet','VariableCompression','brotli')
Example: write('C:\myData', D, 'FileType', 'parquet', 'VariableCompression',
{'brotli' 'snappy' 'gzip'})
10-536
write
• 'auto' — write uses 'plain' encoding for logical variables, and 'dictionary' encoding for
all others.
• 'dictionary', 'plain' — If you specify one encoding scheme then write encodes all variables
with that scheme.
• Alternatively, you can specify a cell array of character vectors or a string vector containing the
names of the encoding scheme to use for each variable.
In general, 'dictionary' encoding results in smaller file sizes, but 'plain' encoding can be faster
for variables that do not contain many repeated values. If the size of the dictionary or number of
unique values grows to be too big, then the encoding automatically reverts to plain encoding. For
more information on Parquet encodings, see Parquet encoding definitions.
Example: write('[Link]', D, 'FileType', 'parquet', 'VariableEncoding',
'plain')
Example: write('[Link]', D, 'FileType', 'parquet', 'VariableEncoding',
{'plain' 'dictionary' 'plain'})
Parquet version to use, specified as either '1.0' or '2.0'. By default, '2.0' offers the most
efficient storage, but you can select '1.0' for the broadest compatibility with external applications
that support the Parquet format.
Limitations
In some cases, write(location, D, 'FileType', type) creates files that do not represent the
original array D exactly. If you use datastore(location) to read the checkpoint files, then the
result might not have the same format or contents as the original distributed table.
For the 'text' and 'spreadsheet' file types, write uses these rules:
• write outputs numeric variables using longG format, and categorical, character, or string
variables as unquoted text.
• For non-text variables that have more than one column, write outputs multiple delimiter-
separated fields on each line, and constructs suitable column headings for the first line of the file.
• write outputs variables with more than two dimensions as two-dimensional variables, with
trailing dimensions collapsed.
• For cell-valued variables, write outputs the contents of each cell as a single row, in multiple
delimiter-separated fields, when the contents are numeric, logical, character, or categorical, and
outputs a single empty field otherwise.
Do not use the 'text' or 'spreadsheet' file types if you need to write an exact checkpoint of the
distributed array.
Tips
• Use the write function to create checkpoints or snapshots of your data as you work. This practice
allows you to reconstruct distributed arrays directly from files on disk rather than re-executing all
of the commands that produced the distributed array.
10-537
10 Functions
Version History
Introduced in R2017a
See Also
datastore | distributed | tall
Topics
“Distributed Arrays”
10-538
zeros
zeros
Create codistributed array of all zeros
Syntax
cZ = zeros(n,codist)
cZ = zeros(sz,codist)
cZ = zeros(sz1,...,szN,codist)
cZ = zeros( ___ ,datatype,codist)
Description
cZ = zeros(n,codist) creates an n-by-n codistributed matrix of zeros and uses codist to specify
the distribution of the array values across the workers.
When you create the codistributed array in a communicating job or spmd block, the function creates
an array on each worker. If you create a codistributed array outside of a communicating job or spmd
block, the array is stored only on the worker or client that creates the codistributed array.
cZ = zeros(sz,codist) creates a codistributed array of zeros where the size vector sz defines
the size of cZ. For example, zeros([2 3],"codistributed") creates a 2-by-3 codistributed array.
cZ = zeros( ___ ,datatype,codist) creates a codistributed array of zeros with the underlying
type datatype. For example, zeros(1,"int8","codistributed") creates a codistributed 8-bit
scalar integer 0. You can use this syntax with any of the size arguments in the previous syntaxes. You
must specify codist after the array size and data type arguments.
When you create very large arrays or your communicating job or spmd block uses many workers,
worker-worker communication can slow down array creation. Use this syntax to improve the
performance of your code by removing the time required for worker-worker communication.
Tip When you use this syntax, some error checking steps are skipped. Use this syntax to improve the
performance of your code after you prototype your code without specifying "noCommunication".
10-539
10 Functions
You must specify "noCommunication" after the size, data type and codist arguments.
cZ = zeros( ___ ,like=p) uses the array p to create a codistributed array of zeros. You can
specify datatype or "like", but not both. You can also specify "noCommunication" as part of the
function call.
The returned array cZ has the same underlying type, sparsity, and complexity (real or complex) as p.
Examples
Create a 1000-by-1000 codistributed double matrix of zeros, distributed by its second dimension
(columns).
spmd(4)
C = zeros(1000,"codistributed");
end
Input Arguments
n — Size of square matrix
integer
10-540
zeros
Size of each dimension, specified as an integer row vector. Each element of this vector indicates the
size of the corresponding dimension:
Underlying data type of the returned array, specified as one of these options:
• "double"
• "single"
• "logical"
• "int8"
• "uint8"
• "int16"
• "uint16"
• "int32"
• "uint32"
• "int64"
• "uint64"
If you do not specify the datatype, the resulting codistributed array has the same underlying type,
sparsity, and complexity (real or complex) as p.
Version History
Introduced in R2006b
10-541
10 Functions
See Also
zeros | eye (codistributed) | false (codistributed) | Inf (codistributed) | NaN
(codistributed) | ones (codistributed) | true (codistributed)
10-542