Why stock DOT function is suboptimally implemented

1 回表示 (過去 30 日間)
Bruno Luong
Bruno Luong 2020 年 10 月 20 日
コメント済み: Jan 2021 年 7 月 28 日
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 件のコメント
Bruno Luong
Bruno Luong 2021 年 7 月 28 日
Update: results with R2021a
Elapsed time is 0.167038 seconds. % p1=dot(z,z)
Elapsed time is 0.088275 seconds. % p2 = sum(conj(z).*z)
Elapsed time is 0.114969 seconds. % p3=z(:)'*z(:)
Elapsed time is 0.051793 seconds. % zc=z(:); p4=zc'*zc
Elapsed time is 0.007295 seconds. % zr=reshape(z,[],1); p5=zr'*zr
Jan
Jan 2021 年 7 月 28 日
Wow, 0.007 is fast.

サインインしてコメントする。

回答 (2 件)

Jan
Jan 2020 年 10 月 20 日
編集済み: Jan 2020 年 10 月 20 日
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 2021 年 7 月 28 日
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.

カテゴリ

Help Center および File ExchangeLoops and Conditional Statements についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by