メインコンテンツ

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

See Also

Topics