In this example, we look at two common cases when we might want to write a wrapper function for the Parallel Computing Toolbox™. Those wrapper functions will be our task functions and will allow us to use the toolbox in an efficient manner. The particular cases are:
We want one task to consist of calling a nonvectorized function multiple times.
We want to reduce the amount of data returned by a task.
For further reading, see:
Calling a Nonvectorized Function Multiple Times in a Task
The Dividing MATLAB Computations into Tasks example discusses how inefficient it would be to construct a large number of tasks where each task performs only a small amount of work. Instead, each task should perform a reasonable amount of work, so that the overhead of a task does not dwarf its run time. Consequently, we often find ourselves in the situation where each task should do the following:
Given a vector
x, return a vector
y such that
y(i) = f(x(i)). If the function
f is vectorized, the MATLAB statement
y = f(x) does exactly that, so we let
f be our task function. However, if
f is not vectorized, we have to write a task function that calls
f inside a for-loop. That is, we want the task function to look like the following:
function y = mytaskfnc(x) len = numel(x); y = zeros(1, len); for i = 1:len y(i) = f(x(i)); end
As an example, let's look at the problem of minimizing the Rosenbrock test function from multiple starting points. Suppose that we want the starting point to be of the form
[-d, d] and that we want to use the
fminsearch method to perform the minimization. We easily arrive at the following task function:
function xmin = pctdemo_task_tutorial_taskfunction(x) %pctdemo_task_tutorial_taskfunction Minimize the Rosenbrock function. % xmin = pctdemo_task_tutorial_taskfunctions(x) returns the minimum of the % Rosenbrock function that is found by starting at [-x(i), x(i)]. % The output vector xmin is of the same length as the input vector x. % Copyright 2007 The MathWorks, Inc. xmin = zeros(numel(x), 2); for i = 1:numel(x) xmin(i, :) = fminsearch(@iRosenbrock, [-x(i), x(i)]); end end % End of pctdemo_task_tutorial_taskfunction. function y = iRosenbrock(x) % The well-known optimization test function, the Rosenbrock function. y = 100*(x(2)-x(1)^2)^2+(1-x(1))^2; end
We can create a job that is composed of several tasks, where each task can handle as many different starting points as we need.
Reducing the Data Returned by a Task
Our tasks might invoke some MATLAB functions that generate more data than we are interested in. Since there is considerable overhead in transmitting the return data over the network, we would like to minimize such data transfers. Thus, the task function might look something like the following:
function d = mytaskfnc(x) % Only return the last output argument from f. Drop the rest. [a, b, c, d] = f(x);
There are of course numerous other possibilities: We might want to return only the sum of a vector instead of the entire vector, the last point of a time series instead of the entire time series, etc.