MATLAB Answers

## Arrayfun scalar expansion (non-uniform output)

Asked by Vince

### Vince (view profile)

on 17 Jul 2013
Accepted Answer by Cedric Wannaz

### Cedric Wannaz (view profile)

I have a function that takes several scalar variables and outputs an array. The size of this array is always the same. I want to make a sweep of a few of the variables and store the output in a cell array.

According to documentation, arrayfun on GPUs support scalar expansion:

"A = arrayfun(FUN, B, C, ...) evaluates FUN using elements of arrays B, C, ... as input arguments with singleton expansion enabled. The inputs B, C, ... must all have the same size or be scalar. Any scalar inputs are scalar expanded before being input to the function FUN." http://www.mathworks.com/help/distcomp/arrayfun.html

But unfortunately this is not the case for MATLAB arrayfun. Is there an easy way around this?

Here is some code to illustrate what I'm trying to do:

```% Declare some constants
const1 = 1;
const2 = 2;
const3 = 3;
const4 = 4;
```
```% Declare variables to sweep
sweep1 = 0:0.001:1;
sweep2 = 0:0.01:1;
```
```[mat1, mat2] = meshgrid(sweep1, sweep2);
```
```% What I want to do, but can't
% output is a 2D cell array
[output] = arrayfun(@function, mat1, mat2, const1, const2, const3, const4, 'UniformOutput', false);
```
```% What I end up having to do
expander = ones(size(mat1));
const1 = const1(expander);
const2 = const2(expander);
const3 = const3(expander);
const4 = const4(expander);
[output] = arrayfun(@function, mat1, mat2, const1, const2, const3, const4, 'UniformOutput', false);
```

What I have right now works, but when sweep1 and sweep2 become very large, the memory needed for manual requirement becomes impractical. Is there a way to avoid manually expanding the scalars into massive matrices?

Any help would be appreciated.

## Products

No products are associated with this question.

## 4 Answers

### Cedric Wannaz (view profile)

Answer by Cedric Wannaz

### Cedric Wannaz (view profile)

on 17 Jul 2013
Accepted answer

I might not fully understand your question, but why don't you do something like:

``` output = arrayfun( ...
@(m1,m2) myFunction(m1, m2, const1, const2, const3, const4), ...
mat1, mat2, 'UniformOutput', false ) ;```

Vince

### Vince (view profile)

on 18 Jul 2013

Then it gives me an error:

All of the input arguments must be of the same size and shape. Previous inputs had size 1001 in dimension 1. Input #4 has size 1.

(Input #4 is the first scalar constant)

Cedric Wannaz

### Cedric Wannaz (view profile)

on 18 Jul 2013

But what gives you the error, ARRAYFUN or the function? Because in my example, input #4 of ARRAYFUN is the param. name 'UniformOutput'. Are you sure that you implemented what I proposed with the handle of an anonymous wrapper for myFunction? I explode my initial expression a little more to make it clear with arg numbers:

``` output = arrayfun( ...
@(m1,m2) myFunction(m1, m2, const1, const2, const3, const4), ...  % #1
mat1, ...                                                         % #2
mat2, ...                                                         % #3
'UniformOutput', ...                                              % #4
false ) ;                                                         % #5```

### per isakson (view profile)

Answer by per isakson

### per isakson (view profile)

on 18 Jul 2013

"[...]this needs to be as fast as possible. " With R20112a loops are sometimes fast enough. Try this

```    %%
N   = 1e5;
tic
sqr_for = nan(N,1);
for ii = 1 : N
sqr_for(ii) = sqrt(ii);
end
toc
%%
tic
sqr_arr = arrayfun( @sqrt , [1:N], 'uni', true );
toc
%%
max( abs( sqr_for - sqr_arr' ) )```

Jan Simon

### Jan Simon (view profile)

on 18 Jul 2013

To be exact, Matlab's JIT accelerates loops since release 6.5 (2002). In the above case this should be compared also:

```tic; sqr_vec = sqrt(1:N); toc
```

You can omit the square brackets, because "1:N" is a vector already.

### Eric Sampson (view profile)

Answer by Eric Sampson

### Eric Sampson (view profile)

on 17 Jul 2013

Use a for loop instead of arrayfun?

Vince

### Vince (view profile)

on 18 Jul 2013

I'm trying to avoid for loops because this needs to be as fast as possible.

Sean de Wolski

on 18 Jul 2013

### Jan Simon (view profile)

Answer by Jan Simon

### Jan Simon (view profile)

on 18 Jul 2013

Under some circumstances FOR loops are faster than vectorized code. arrayfun is not a vectorizing, because it still creates separated calls to the function. This happens, when large temporary array are created. Accessing the small RAM wastes much more time than operating on two vectors, which match into the processor cache.

Expanding the values explicitly by const4 = const4(expander) wastes time, because redundant data are created. Matlab's JIT seem to handle such expanding efficiently as long, as the data are used internally and to provided to user defined functions. Some tests seems to show, that here the expanding is not performed:

```function dullTest
x = rand(1, 1000);
y = rand(1000, 1);
tic;
for k = 1:1000
S = x(ones(1, 1000), :) + y(:, ones(1, 1000));
end
toc;
```
```tic;
for k = 1:1000
S = add(x(ones(1, 1000), :), y(:, ones(1, 1000)));
end
toc;
```
```function s=add(x,y)
s = x + y;
```

Of course the overhead for calling a subfunction matters also. But my impression of the avoided expansion concerns the memory foot print also, when huge arrays are used, which actually should fill my RAM completely.

While ARRAYFUN can be slower than a corresponding FOR loop, BSXFUN helps to avoid the creation of temporarily expanded data:

```T = bsxfun(@plus, x, y);
```

#### 0 Comments

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi test

### Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

New to MATLAB?