4

Let's say I have a function, like:

function [result] = Square( x )
    result = x * x;
end

And I have an array like the following,

x = 0:0.1:1;

I want to have an y array, which stores the squares of x's using my Square function. Sure, one way would be the following,

y = zeros(1,10);

for i = 1:10
    y(i) = Square(x(i));
end

However, I guess there should be a more elegant way of doing it. I tried some of my insights and made some search, however couldn't find any solution. Any suggestions?

4 Answers 4

10

For the example you give:

y = x.^2;   % or
y = x.*x;

in which .* and .^ are the element-wise versions of * and ^. This is the simplest, fastest way there is.

More general:

y = arrayfun(@Square, x);

which can be elegant, but it's usually pretty slow compared to

y = zeros(size(x));
for ii = 1:numel(x)
    y(ii) = Square(x(ii)); end

I'd actually advise to stay away from arrayfun until profiling has showed that it is faster than a plain loop. Which will be seldom, if ever.

In new Matlab versions (R2008 and up), the JIT accelerates loops so effectively that things like arrayfun might actually disappear in a future release.

As an aside: note that I've used ii instead of i as the loop variable. In Matlab, i and j are built-in names for the imaginary unit. If you use it as a variable name, you'll lose some performance due to the necessary name resolution required. Using anything other than i or j will prevent that.

Sign up to request clarification or add additional context in comments.

4 Comments

You're absolutely right that arrayfun is slower than the elementwise built-in functions - unless you're using gpuArrays, where arrayfun is the way to go.
@Edric: A dammit, I really wish I had a GPU to play with that stuff...I don't know any of it! Thanks for the heads up. Not always faster I'd imagine (due to the associated memory issues), but still, I can imagine that's it'll usually be faster.
@Edric: by the way -- really? Why would x.^2 (with x a gpuArray) not be distributed over the GPU?
yes - gpuArray(...).^2 certainly is distributed across the GPU, but if you're running multiple operations, it's currently better to combine them into a single arrayfun call rather than individual calls.
2

You want arrayfun.

arrayfun(@Square, x)

See help arrayfun

(tested only in GNU Octave, I do not have MATLAB)

Comments

2

Have you considered the element-by-element operator .*?

See the documentation for arithmetic operators.

Comments

2

I am going to assume that you will not be doing something as simple as a square operation and what you are trying to do is not already vectorised in MATLAB.

It is better to call the function once, and do the loop in the function. As the number of elements increase, you will notice significant increase in operation time.

Let our functions be:

function result = getSquare(x)
    result = x*x; % I did not use .* on purpose
end

function result = getSquareVec(x)
result = zeros(1,numel(x));
    for idx = 1:numel(x)
        result(:,idx) = x(idx)*x(idx);
    end
end

And let's call them from a script:

y = 1:10000;
tic;
for idx = 1:numel(y)
    res = getSquare(y(idx));
end
toc

tic;
    res = getSquareVec(y);
toc

I ran the code a couple of times and turns out calling the function only once is at least twice as fast.

Elapsed time is 0.020524 seconds.
Elapsed time is 0.008560 seconds.

Elapsed time is 0.019019 seconds.
Elapsed time is 0.007661 seconds.

Elapsed time is 0.022532 seconds.
Elapsed time is 0.006731 seconds.

Elapsed time is 0.023051 seconds.
Elapsed time is 0.005951 seconds.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.