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
listed at the end of this example performs multiple executions of the specified function:
on the client with a single thread
on the client with multiple threads and
in a
parfor
-loop on a pool of computationally single threaded workers
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");
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to parallel pool with 6 workers.
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.
[eigSingle, eigMulti, eigPool] = compareClientAndPool(@(N) eig(N), randn(200));
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.
[mtimesSingle, mtimesMulti, mtimesPool] = compareClientAndPool(@(N) N*N, randn(1000));
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.
Calculate the speedup of running the mtimes
function on a pool.
mtimesSpeedup = mtimesMulti/mtimesPool
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);
Parallel pool using the 'Processes' profile is shutting down.
Define Helper Function
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:
fcn = @(x) rand(x);
function [tSingle, tMulti, tPool, comparePlot] = compareClientAndPool(fcn,in) xCompThreads = onCleanup(@() maxNumCompThreads("automatic")); % Use the number of workers in the pool to make the problem size proportional to the number of workers. numIterations = 40 * gcp().NumWorkers; % Client - single threaded maxNumCompThreads(1); timer = tic(); for i = 1:numIterations out = fcn(in); end tSingle = toc(timer); % 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