MATLAB Answers

Why stock DOT function is suboptimally implemented

1 view (last 30 days)
Bruno Luong
Bruno Luong on 20 Oct 2020
Commented: Jan on 28 Jul 2021
Followup the discussion in
and
and do so tic/toc and I think the option selected by TMW (R2020b) is suboptimal in term of speed for complex data as show as this benchmark that one can speed up almost 10 times (!):
z=randn(1,1e7)+1i*randn(1,1e7);
tic
p1=dot(z,z);
toc % Elapsed time is 0.162930 seconds.
tic
p2 = sum(conj(z).*z);
toc % Elapsed time is 0.092252 seconds.
tic
p3=z(:)'*z(:); % (:) copy data ?
toc % Elapsed time is 0.100122 seconds.
tic
zc=z(:); % (:) copy data ?
p4=zc'*zc;
toc % Elapsed time is 0.053257 seconds.
tic
zr=reshape(z,[],1); % reshape does not?
p5=zr'*zr;
toc % Elapsed time is 0.016140 seconds.
Any comment would be welcome.
Just to have a formal question: what is the reason of TMW choice?
  2 Comments

Sign in to comment.

Answers (2)

Jan
Jan on 20 Oct 2020
Edited: Jan on 20 Oct 2020
Just a comment: Under Matlab 2018b, Core i5-3320M CPU @ 2.60GHz:
Elapsed time is 0.249669 seconds. dot(z,z)
Elapsed time is 0.168906 seconds. sum(conj(z).*z)
Elapsed time is 0.204284 seconds. z(:)'*z(:)
Elapsed time is 0.114597 seconds. zc=z(:); p4=zc'*zc
Elapsed time is 0.018371 seconds. zr=reshape(z,[],1); p5=zr'*zr
When I copy the code into a function and repeat the calls 5 times in a FOR loop:
Elapsed time is 0.865391 seconds.
Elapsed time is 0.844665 seconds.
Elapsed time is 1.021389 seconds.
Elapsed time is 0.484573 seconds.
Elapsed time is 0.047871 seconds.

Jan
Jan on 28 Jul 2021
In dot.m we find a test for integer types, checks by isvector, comparison of lengths, both vectors are shaped by (:) and after a test with isreal(), either a'*b or sum(conj(a).*b) is called.
Your measurement
% Elapsed time is 0.167038 seconds. % p1 = dot(z,z)
% Elapsed time is 0.088275 seconds. % p2 = sum(conj(z).*z)
means, that the tests are expensive and the two (:) operations also, because they create deep data copies in modern Matlab versions for complex data:
a = rand(1,100) + 1i * rand(1,100);
ShowDataPointer(a)
pr = 7fe94d7f3d20
b = a(:);
ShowDataPointer(b)
pr = 7fe94d36e5e0
function ShowDataPointer(x)
orig = format('debug');
s = formattedDisplayText(x);
c = strtrim(strsplit(s, '\n'));
disp(c(startsWith(c, 'pr')));
format(orig);
end
With real values only, the data are shared. (For other readers. I'm aware, that you, Bruno, know this.)
My conclusion: dot.m is not efficiently implemented. Why? For future improvements.
I do not see a reason, why (:) creates a deep data copy, so I'd consider this as a bug. Did you ask MathWorks already for an explanation?
By the way, Matlab's cross() could be 10 times faster when implemented as MEX function.

Community Treasure Hunt

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

Start Hunting!