Circshift matrix by different amount without for loop

7 ビュー (過去 30 日間)
Javier Agustin Romero
Javier Agustin Romero 2019 年 3 月 29 日
編集済み: Javier Agustin Romero 2019 年 3 月 30 日
Hello everyone. I have this 3 dimensional matrix called spectrums and I want to shift the 3rd dimension by different amounts given by vector shifts. Is there a way to do this without using a for loop? something like
shifted_spectrums=arrayfun(@(k) circshift(spectrums(:,:,k),shifts(2:end),2),spectrums);
but a solution that actualy works :P
PS: 3rd dimension of spectrums has 22 elements and shifts has 23 elements, that's why the 2:end.
  1 件のコメント
Jan
Jan 2019 年 3 月 29 日
編集済み: Jan 2019 年 3 月 29 日
What is the class and contents of shifts(2:end)? What is not "actually working"?
We cannot guess these details.
A for loop is faster than arrayfun in general. So please mention, why you want to avoid it.
Is this the loop version?
shifted_spectrums = zeros(size(spectrums));
for k = 1:size(spectrums, 3)
shifted_spectrums(:, :, k) = circshift( ...
spectrum(:, :, k), shifts(k+1), 2);
end

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

採用された回答

Javier Agustin Romero
Javier Agustin Romero 2019 年 3 月 29 日
編集済み: Javier Agustin Romero 2019 年 3 月 29 日
I've just got it working. A reshape is needed so the output has wanted size (sz1=1024, sz2=8192).
shifted_spectrums=reshape(cell2mat(arrayfun(@(k) circshift(spectrum(:,:,k)...
,shifts(k,1),2),1:Nfiles,'uni',0)),sz1/2,sz2,Nfiles);
This version is faster than the for loop
for i=2:Nfiles
shifted_spectrums(:,:,i)=circshift(spectrums(:,:,i),shifts(i-1,1),2);
end
Although not by much (16%, spectrums is a 512x8192x22 matrix)
  1 件のコメント
Jan
Jan 2019 年 3 月 29 日
編集済み: Jan 2019 年 3 月 29 日
Did you pre-allocate the output? This is essential for the performance:
shifted_spectrums = zeros(size(spectrums));

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

その他の回答 (1 件)

Jan
Jan 2019 年 3 月 29 日
編集済み: Jan 2019 年 3 月 29 日
Try:
n = 8192;
spectrums = rand(512, n, 22);
shifts = randi(n, 1, 22);
tic
s1 = cell2mat(arrayfun(@(k) ...
circshift(spectrums(:,:,k), shifts(k), 2),1:22,'uni',0));
toc
tic;
s2 = zeros(size(spectrums));
for k = 1:22
s2(:,:,k)=circshift(spectrums(:,:,k), shifts(k), 2);
end
toc
For n=2000 I get:
arrayfun: 0.22sec
loop: 0.17sec
  3 件のコメント
Jan
Jan 2019 年 3 月 29 日
編集済み: Jan 2019 年 3 月 30 日
i7-3770 3.4GHz, 16 GB RAM, n = 8192:
R2009b:
Elapsed time is 2.660240 seconds.
Elapsed time is 2.062384 seconds.
R2016b:
Elapsed time is 2.613608 seconds.
Elapsed time is 2.292270 seconds.
R2018b:
Elapsed time is 2.682782 seconds.
Elapsed time is 1.207014 seconds. ! Nice !
Javier Agustin Romero
Javier Agustin Romero 2019 年 3 月 30 日
編集済み: Javier Agustin Romero 2019 年 3 月 30 日
Just ran it again and got
Elapsed time is 1.512578 seconds.
Elapsed time is 1.911443 seconds.
I'm working on a i7-7700HQ, 2.8GHz, 16GB RAM and got Matlab installed in a SSD (good to know that was a good investment). Anyway, what I find weird is that which method works best changes with PC's specs. I mean, shouldn't one method always work best and both times move up or down according to the PC specs? I am talking way over my head here though, have no idea.

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

カテゴリ

Help Center および File ExchangeGraphics Performance についてさらに検索

タグ

製品


リリース

R2016a

Community Treasure Hunt

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

Start Hunting!

Translated by