# Comparing repmat and bsxfun Performance 37

Posted by **Loren Shure**,

I've been asked repeatedly about the performance comparison between two MATLAB functions, `bsxfun` and `repmat`. These two functions can each help with calculations in which two arrays are expected to have the same dimensions, but some
of the input dimensions, instead of agreeing, may have the value 1. The simple example I use here is subtracting the columns
means from a matrix.

### Contents

### Setup

First I set up the data.

m = 1e5; n = 100; A = rand(m,n);

### Code I'm Tempted to Write

And now here's the code I'm tempted to write, safely tucked inside the confines of a `try` statement.

try AZeroMean = A - mean(A); catch ME disp(ME.message); end

Matrix dimensions must agree.

As you can see, MATLAB does not allow binary operators to work on arrays with different sizes (except when one of the inputs is a scalar value). There are at least two ways to remedy this.

`mean(A)`in a vector and then create a new array the same size as

`A`with replicates of the row vector from the

`mean`. You can do this with

`repmat`or via indexing an appropriate number of times into the row of this vector.

`bsxfun`with the appropriate two inputs and allow it to perform the equivalent singleton dimension expansion. The nice thing about this is there is no need for a large intermediate array the same size as

`A`. A possible downside, especially since

`bsxfun`is relatively new, is that the code doesn't, at first reading, appear as obvious.

### Timing repmat

Using the most excellent `timeit` utility that Steve Eddins posted to the file exchange, I now time the `repmat` calculations. First I create an anonymous function that does my calculation. Then I pass that function handle to `timeit`. `timeit` carefully warms up the function by running it enough so the times are not subject to first-time effects, figuring out how
many times to run it to get meaningful results, and more.

frepmat = @() A - repmat(mean(A),size(A,1),1); timeit(frepmat)

ans = 0.30964

### Indexing with ones

`repmat` uses a variety of techniques for replicating an array, depending on the details of what's being replicated. One technique
is to index into the array with ones in the dimension to replicate. Here's an illustative example with a vector.

q = [17 pi 42 exp(1)]; q5 = repmat(q,5,1)

q5 = 17 3.1416 42 2.7183 17 3.1416 42 2.7183 17 3.1416 42 2.7183 17 3.1416 42 2.7183 17 3.1416 42 2.7183

### Timing Indexing

One thing I notice with the `repmat` solution is that I need to create the vector `mean(A)` for the function. I need to do the same thing without `repmat` and I want to be able to set up one function call for performing the calculation so I can use `timeit`. Since I can't index into the results of a function without assigning the output to a variable, I create an intermediate
function `meanones` to help.

`type meanones`

function y = meanones(A) mn = mean(A); y = A - mn(ones(1,size(A,1)),:);

Now I'm ready to do the timing.

findex = @() meanones(A); timeit(findex)

ans = 0.31389

### Timing bsxfun

Next see the timing calculation done using `bsxfun`.

fbsxfun = @() bsxfun(@minus,A,mean(A)); timeit(fbsxfun)

ans = 0.20569

### Punchline

In this example, `bsxfun` performs fastest. Now that you see `bsxfun` in action, can you think of uses for this function in your work? Let me know here.

Get the MATLAB code

Published with MATLAB® 7.6

### Note

Comments are closed.

## 37 CommentsOldest to Newest

**1**of 37

**2**of 37

% points = points + vector--Loren

**3**of 37

**4**of 37

**5**of 37

**6**of 37

**7**of 37

**8**of 37

**9**of 37

**10**of 37

```
function timingtest(m)
n = 100;
A = rand(m,n);
N = min(1e6 / m, 1e5);
tic
for k=1:N
B = A - repmat(mean(A),size(A,1),1);
end
toc
tic
for k=1:N
mn = mean(A);
B = A - mn(ones(1,size(A,1)),:);
end
toc
tic
for k=1:N
B = bsxfun(@minus,A,mean(A));
end
toc
```

Here the dimension m is an input argument. The results are as follows:
>> timingtest(1e5)
Elapsed time is 1.894369 seconds.
Elapsed time is 2.268081 seconds.
Elapsed time is 1.875516 seconds.
>> timingtest(10)
Elapsed time is 5.758173 seconds.
Elapsed time is 3.377169 seconds.
Elapsed time is 3.982497 seconds.
>> timingtest(1)
Elapsed time is 4.618704 seconds.
Elapsed time is 2.182044 seconds.
Elapsed time is 2.650870 seconds.
The smaller the matrix dimensions, the better the version with "ones".
In my projects, I have replaced nearly every "repmat" by "indexing with ones" and saved a lot of processing time. And, by the way, I won a Matlab Contest by applying this tweak :-)
Regards
Markus **11**of 37

**12**of 37

**13**of 37

**14**of 37

**15**of 37

**16**of 37

**17**of 37

**18**of 37

**19**of 37

**20**of 37

**21**of 37

**22**of 37

% Generates an error unless you use bsxfun, or repmat etc... A = rand(10); B = ones(10,1); A = A - B;But if we designated a class:

A = rand(10); B = ones(10,1); % Make a variable of type bsxclass. % Values of B are kept in the private % data of the class. B_exp = bsxclass(B) % B_exp is effectively an array which % can be expanded along a singleton % dimension A = A - B_exp;... so the class definition contains the horrible calls to bsxfun, and your code contains simple operator statements. What does everyone think? Would such a class get used? Will there be a significant functional overhead caused by overloading the method / class invokation? .. i.e. should I sit down and write it??! Tom

**23**of 37

**24**of 37

**25**of 37

A(:,1,:,:) = A(:,1,:,:) + Bbsxfun will do the addition, what is the best way of assigning the values. The arrays are quite large and currently 1/3 of my computational time is taken up with the squeeze() function. Any ideas? Tim

**26**of 37

**27**of 37

**28**of 37

**29**of 37

**30**of 37

**31**of 37

**32**of 37

**33**of 37

Q = bsxfun(@mtimes, V, MM);In Matlab document, it is said "The inputs must be of the following types: numeric, logical, char, struct, cell." But I got error message: Error using bsxfun Operands must be numeric arrays. Does bsxfun not support cell or I made something wrong? Thanks a lot for your help in advance. Best, Ben

**34**of 37

**35**of 37

Q = bsxfun(@mtimes, V, MM);where the mytimes function is Hi Loren, I also tried using a self-defined function called mytimes.

function out = mytimes(v,m) out = v * m;I set breakpoint in mytimes function, but again got error message without call mytimes function. Could you provide a example of using cells? Thank you very much! Ben

**36**of 37

x = 1:10; y = 1:20; z = bsxfun(@mytimes, x, y');This time, there is no error message and I got to my breakpoint in the mytimes function. Thank you, Ben

**37**of 37

## Recent Comments