MATLAB Answers

Why is arrayfun for GPU slower than normal operations

6 views (last 30 days)
Hi there,
Here goes a piece of testing code, yet arrayfun runs more slowly. Any thoughts? Many thanks.
function Test_GPU1()
EP = gpuArray(eps*ones(10000, 1, 'single'));
ONE = gpuArray(ones(10000, 1, 'single'));
ZERO = gpuArray(zeros(10000, 1, 'single'));
Cur_FF_Output = gpuArray(0.5*ones(10000, 1, 'single'));
Cur_Desired_Output = gpuArray(0.5*ones(10000, 1, 'single'));
for iter = 1:1000
% In output layer, Cur_Delta = Del(C)/Del(z) = Del(C)/Del(a) * Del(a)/Del(z)
% [~, Cur_Delta0] = Cost_Function_GPU(Cur_FF_Output, Cur_Desired_Output, Hyper_Para);
temp00 = Cur_FF_Output + eps;
temp11 = log(temp00);
temp22 = log(1-Cur_FF_Output+eps);
temp33 = Cur_Desired_Output.*temp11;
temp44 = 1-Cur_FF_Output.*temp22;
Cur_Delta = Cur_FF_Output-Cur_Desired_Output;
Cost = 0-sum(temp33+temp44);
temp00 = arrayfun(@plus, Cur_FF_Output, EP);
temp11 = arrayfun(@log, temp00);
temp22 = arrayfun(@log, arrayfun(@minus, ONE, arrayfun(@plus, Cur_FF_Output, EP)));
temp33 = arrayfun(@times, Cur_Desired_Output, temp11);
temp44 = arrayfun(@minus, ONE, arrayfun(@times, Cur_FF_Output, temp22));
Cur_Delta = arrayfun(@minus, Cur_FF_Output, Cur_Desired_Output);
Cost = arrayfun(@minus, ZERO, sum(temp33+temp44));
end
end
  1 Comment
Jan
Jan on 28 May 2019
Of course arrayfun has a certain overhead. It is expected to run slower than calling the operators directly.

Sign in to comment.

Accepted Answer

Joss Knight
Joss Knight on 28 May 2019
You are misunderstanding the use of arrayfun for gpuArray. Combine all those operations into a single function.
temp00 = arrayfun(@plus, Cur_FF_Output, EP);
temp11 = arrayfun(@log, temp00);
temp22 = arrayfun(@log, arrayfun(@minus, ONE, arrayfun(@plus, Cur_FF_Output, EP)));
temp33 = arrayfun(@times, Cur_Desired_Output, temp11);
temp44 = arrayfun(@minus, ONE, arrayfun(@times, Cur_FF_Output, temp22));
Cur_Delta = arrayfun(@minus, Cur_FF_Output, Cur_Desired_Output);
Cost = arrayfun(@minus, ZERO, sum(temp33+temp44));
becomes
function Cur_Delta = stuff(Cur_FF_Output, Cur_Desired_Output, EP)
temp00 = Cur_FF_Output + EP;
temp11 = log(temp00);
temp22 = log(1 - (Cur_FF_Output + EP));
temp33 = Cur_Desired_Output .* temp11;
temp44 = 1 - (Cur_FF_Output .* temp22);
Cur_Delta = Cur_FF_Output - Cur_Desired_Output;
end
Cur_Delta = arrayfun(@stuff, Cur_FF_Output, Cur_Desired_Output, EP);
Obviously, this can be extremely simplified. I've made a start, by removing the unnecessary ONE and ZERO variables.
After this, question whether you really need arrayfun, or should just call this function directly? MATLAB uses some clever optimisations that, for most sequences of element-wise operations, make using arrayfun unnecessary.
  7 Comments
Theron FARRELL
Theron FARRELL on 3 Jun 2019
Understood! Thanks again for your great help and detailed explanation. I am always patient with MATLAB since 1997:-)

Sign in to comment.

More Answers (1)

Jan
Jan on 28 May 2019
Edited: Jan on 28 May 2019
Of course arrayfun has a certain overhead. It is expected to run slower than calling the operators directly with arrays as inputs. In addition, in
Cur_FF_Output + eps
the second operand is a scalar, while in
arrayfun(@plus, Cur_FF_Output, EP)
Matlab has to process a vector. Addressing the elements of an array needs to access memory using a loop. Accessing a scalar is much cheaper.
What is the purpose of:
arrayfun(@minus, ZERO, sum(temp33+temp44))
? This is faster:
-sum(temp33+temp44)
  4 Comments
Jan
Jan on 31 May 2019
Even arrayfun(@minus, 0, sum(temp33+temp44)) is too complicated compared to
-sum(temp33+temp44)

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!