Circshift matrix by different amount without for loop

4 visualizaciones (últimos 30 días)
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 comentario
Jan
Jan el 29 de Mzo. de 2019
Editada: Jan el 29 de Mzo. de 2019
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

Iniciar sesión para comentar.

Respuesta aceptada

Javier Agustin Romero
Javier Agustin Romero el 29 de Mzo. de 2019
Editada: Javier Agustin Romero el 29 de Mzo. de 2019
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 comentario
Jan
Jan el 29 de Mzo. de 2019
Editada: Jan el 29 de Mzo. de 2019
Did you pre-allocate the output? This is essential for the performance:
shifted_spectrums = zeros(size(spectrums));

Iniciar sesión para comentar.

Más respuestas (1)

Jan
Jan el 29 de Mzo. de 2019
Editada: Jan el 29 de Mzo. de 2019
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 comentarios
Jan
Jan el 29 de Mzo. de 2019
Editada: Jan el 30 de Mzo. de 2019
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 el 30 de Mzo. de 2019
Editada: Javier Agustin Romero el 30 de Mzo. de 2019
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.

Iniciar sesión para comentar.

Categorías

Más información sobre Matrix Indexing en Help Center y File Exchange.

Etiquetas

Productos


Versión

R2016a

Community Treasure Hunt

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

Start Hunting!

Translated by