Why is arrayfun for GPU slower than normal operations

조회 수: 4 (최근 30일)
Theron FARRELL
Theron FARRELL 2019년 5월 28일
댓글: Theron FARRELL 2019년 6월 3일
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
Jan
Jan 2019년 5월 28일
Of course arrayfun has a certain overhead. It is expected to run slower than calling the operators directly.

댓글을 달려면 로그인하십시오.

채택된 답변

Joss Knight
Joss Knight 2019년 5월 28일
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
Joss Knight
Joss Knight 2019년 6월 1일
I don't know how recently you viewed the latest documentation on GPU support. I think it's pretty comprehensive, and doesn't encourage you to use arrayfun unnecessarily. There's a great page that talks you through the various options for optimising your code which mentions arrayfun only as an advanced manoeuvre that might, but won't always, improve your performance. Generally we think of arrayfun as the way to 'write custom kernels in the MATLAB language', which many advanced users may look for. We rarely find it useful to document exactly what optimizations MATLAB is using. Usually it just confuses people, who start looking for performance improvements in the wrong place, or start blaming unexpected behaviour on the optimisations. Best to just do our best and leave ourselves the wiggle room to change the way things work from one release to the next.
Theron FARRELL
Theron FARRELL 2019년 6월 3일
Understood! Thanks again for your great help and detailed explanation. I am always patient with MATLAB since 1997:-)

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Jan
Jan 2019년 5월 28일
편집: Jan 2019년 5월 28일
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
Theron FARRELL
Theron FARRELL 2019년 5월 30일
No, it is not a bug. Maybe somewhere I wrote the code mistakenly. My bad, sorry.
Jan
Jan 2019년 5월 31일
Even arrayfun(@minus, 0, sum(temp33+temp44)) is too complicated compared to
-sum(temp33+temp44)

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 GPU Computing에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by