Here's your original code: X = [1, 12; 1, 13; 1, 12; 2, 4; 2, 4; 2, 4; 3, 9; 3, 9; 3, 9]; L = X(:,1); U = unique(L); % Define this once, use it in multiple places M = arrayfun(@(x) mean(X(L == x, 2)), U) Another way to write this arrayfun call using a for loop would be: M2 = zeros(numel(U), 1); % Preallocate the result for k = 1:numel(U) % Choose the rows where the first column of X is equal to a specific % value from U, then extract the data in the second column of X for % those rows column2OfSelectedRows = X(L == U(k), 2); % Take the mean of that data and store it in the appropriate row of M2 M2(k, 1) = mean(column2OfSelectedRows); end We can check that M and M2 are equal. isequal(M, M2) But there's another way to do this. What you want to do is use L as a grouping variable and summarize the rows in X that have the same value for that grouping variable. The groupsummary function will let you do this. Note that we're not using U or the unique function here; groupsummary will make one group for each unique value in the grouping variable. groupingVariable = L; dataVariable = X(:, 2); % Apply the mean function to each subset of values in dataVariable whose % corresponding elements in groupingVariable have the same value M3 = groupsummary(dataVariable, groupingVariable, @mean) Check: isequal(M, M3) Answer from Steven Lord on mathworks.com
🌐
MathWorks
mathworks.com › matlab › language fundamentals › data types › structures
arrayfun - Apply function to each element of array - MATLAB
Calculate the sizes of each field of S by using the arrayfun function. The number of rows and columns are each in 1-by-3 numeric arrays. ... Function to apply to the elements of the input arrays, specified as a function handle. func can correspond to more than one function file and therefore can represent a set of overloaded functions. In these cases, MATLAB® determines which function to call based on the class of the input arguments.
🌐
MathWorks
mathworks.com › parallel computing toolbox › gpu computing › gpu computing in matlab
arrayfun - Apply function to each element of array on GPU - MATLAB
This MATLAB function applies a function func to each element of a gpuArray A and then concatenates the outputs from func into output gpuArray B.
🌐
MathWorks
mathworks.com › parallel computing toolbox › gpu computing › gpu computing in matlab
Improve Performance of Element-Wise MATLAB Functions on the GPU Using arrayfun - MATLAB & Simulink Example
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.
Find elsewhere
Top answer
1 of 13
79

Many built-in operations like sum and prod are already able to operate across rows or columns, so you may be able to refactor the function you are applying to take advantage of this.

If that's not a viable option, one way to do it is to collect the rows or columns into cells using mat2cell or num2cell, then use cellfun to operate on the resulting cell array.

As an example, let's say you want to sum the columns of a matrix M. You can do this simply using sum:

M = magic(10);           %# A 10-by-10 matrix
columnSums = sum(M, 1);  %# A 1-by-10 vector of sums for each column

And here is how you would do this using the more complicated num2cell/cellfun option:

M = magic(10);                  %# A 10-by-10 matrix
C = num2cell(M, 1);             %# Collect the columns into cells
columnSums = cellfun(@sum, C);  %# A 1-by-10 vector of sums for each cell
2 of 13
25

You may want the more obscure Matlab function bsxfun. From the Matlab documentation, bsxfun "applies the element-by-element binary operation specified by the function handle fun to arrays A and B, with singleton expansion enabled."

@gnovice stated above that sum and other basic functions already operate on the first non-singleton dimension (i.e., rows if there's more than one row, columns if there's only one row, or higher dimensions if the lower dimensions all have size==1). However, bsxfun works for any function, including (and especially) user-defined functions.

For example, let's say you have a matrix A and a row vector B. E.g., let's say:

A = [1 2 3;
     4 5 6;
     7 8 9]
B = [0 1 2]

You want a function power_by_col which returns in a vector C all the elements in A to the power of the corresponding column of B.

From the above example, C is a 3x3 matrix:

C = [1^0 2^1 3^2;
     4^0 5^1 6^2;
     7^0 8^1 9^2]

i.e.,

C = [1 2 9;
     1 5 36;
     1 8 81]

You could do this the brute force way using repmat:

C = A.^repmat(B, size(A, 1), 1)

Or you could do this the classy way using bsxfun, which internally takes care of the repmat step:

C = bsxfun(@(x,y) x.^y, A, B)

So bsxfun saves you some steps (you don't need to explicitly calculate the dimensions of A). However, in some informal tests of mine, it turns out that repmat is roughly twice as fast if the function to be applied (like my power function, above) is simple. So you'll need to choose whether you want simplicity or speed.

🌐
Stack Overflow
stackoverflow.com › questions › 39877370 › loop-over-arrayfun-with-matlab
Loop over arrayfun with MATLAB - Stack Overflow
result = arrayfun( ... @(k) arrayfun(@func, M{k}), ... reshape(1:numel(M),size(M)), ... 'UniformOutput', false ... ); But—come on!—one can do better MATLAB than Xzibit!
Top answer
1 of 2
2

The reason that you don't get any speed increase by calling matlabpool before calling arrayfun is that just the act of creating multiple workers doesn't make all code utilize these workers to perform calculations. If you want to exploit the pool of workers, you need to explicitly parallelize your code with parfor (related info here).

parfor k = 1:10
    result{k} = sum(sum(a*b));
end 

In general, arrayfun does not do any parallelization or acceleration. In fact, it's often slower than simply writing out the for loop because the explicit for loop allows for better JIT acceleration.

for k = 1:10
    result(k) = sum(sum(a * b));
end

If you want to perform the operation you've shown using the GPU, if the input data to arrayfun is a gpuarray, then it will excecute on the GPU (using the distributed version of arrayfun). The issue though is that anything performed on the GPU using arrayfun has to be element-wise operations only so that the operation on each element is independent of the operations on all other elements (making it parallelizable). In your case, it is not element-wise operations and therefore the GPU-version of arrayfun cannot be used.

As a side-note, you'll want to use parpool rather than matlabpool since the latter has been deprecated.

2 of 2
1

Core MATLAB does use threads and vector operations, but you have to vectorize the code yourself. For your example, for instance, you need to write

A = rand(1000, 1000, 100);
B = sum( sum( A, 1 ), 2 );

B is now a 1-by-1-by-100 array of the sums. I've used two sums to help you understand what's going on, if you actually wanted to sum every number in a matrix you'd go sum(A(:)), or for this batch example, sum( reshape(A, [], 100) ).

For task parallelism rather than data parallelism use parfor, batch, parfeval or some other parallel instruction.

🌐
MathWorks
mathworks.com › parallel computing toolbox › gpu computing › gpu computing in matlab
pagefun - Apply function to each page of distributed or GPU array - MATLAB
[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.
🌐
MathWorks
mathworks.com › matlabcentral › answers › 346251-how-can-i-apply-arrayfun-with-2d-matrix-inputs
How can I apply arrayfun with 2D matrix inputs? - MATLAB Answers - MATLAB Central
June 26, 2017 - where the size of A is N x M x M. Arrayfun doesn't support such a matrix input. So I would like to know the way to accelerate it. Thank you in advance! ... https://www.mathworks.com/matlabcentral/answers/346251-how-can-i-apply-arrayfun-with-2d-matrix-inputs#comment_464437
🌐
MathWorks
de.mathworks.com › matlabcentral › answers › 424230-arrayfun-with-multiple-inputs-and-a-different-size-output
arrayfun with multiple inputs and a different size output - MATLAB Answers - MATLAB Central
October 16, 2018 - The point is that arrayfun will then run on a GPU, so doing a for loop is not efficient. On a GPU it would be automatically dispatched, I guess. myfunc so far is a standalone as you said. What if I pass a fake variable of size Mx1 to bluff the computer so that it thinks it has to run M times ? ... https://de.mathworks.com/matlabcentral/answers/424230-arrayfun-with-multiple-inputs-and-a-different-size-output#comment_623231
🌐
MathWorks
mathworks.com › matlabcentral › answers › 1902215-creating-two-arrays-using-arrayfun
Creating two arrays using Arrayfun - MATLAB Answers - MATLAB Central
January 28, 2023 - How can I create two array sets with Arrayfun, I am getting an error with this code structure. thanks %%Simulink Matlab function Block function [y,x]=fcn(Az,sm,del,w0,gama,wc,D_ws,e,n_xs,n_ys,n...
🌐
MathWorks
mathworks.com › matlabcentral › answers › 1699915-arrayfun-with-multiple-variable
Arrayfun with multiple variable? - MATLAB Answers - MATLAB Central
April 19, 2022 - I know that I have a function that requires one input i can use arrayfun like this: ... Sign in to comment. Sign in to answer this question. ... https://www.mathworks.com/matlabcentral/answers/1699915-arrayfun-with-multiple-variable#answer_945935