Saltar al contenido

En Matlab, ¿cuándo es óptimo utilizar bsxfun?

Solución:

Hay tres razones por las que uso bsxfun (documentación, enlace de blog)

  1. bsxfun es más rápido que repmat (vea abajo)
  2. bsxfun requiere menos mecanografía
  3. Utilizando bsxfun, como usar accumarray, me hace sentir bien acerca de mi comprensión de Matlab.

bsxfun replicará las matrices de entrada a lo largo de sus “dimensiones singleton”, es decir, las dimensiones a lo largo de las cuales el tamaño de la matriz es 1, de modo que coincidan con el tamaño de la dimensión correspondiente de la otra matriz. Esto es lo que se llama “expansión singleton”. Como acotación al margen, las dimensiones singleton son las que se eliminarán si llama squeeze.

Es posible que para problemas muy pequeños, el repmat El enfoque es más rápido, pero con ese tamaño de matriz, ambas operaciones son tan rápidas que probablemente no supongan ninguna diferencia en términos de rendimiento general. Hay dos razones importantes bsxfun es más rápido: (1) el cálculo ocurre en código compilado, lo que significa que la replicación real de la matriz nunca ocurre, y (2) bsxfun es una de las funciones de Matlab multiproceso.

He realizado una comparación de velocidad entre repmat y bsxfun con R2012b en mi portátil decentemente rápido.

ingrese la descripción de la imagen aquí

Para mi, bsxfun es aproximadamente 3 veces más rápido que repmat. La diferencia se vuelve más pronunciada si las matrices se hacen más grandes

ingrese la descripción de la imagen aquí

El salto en tiempo de ejecución de repmat ocurre alrededor de un tamaño de matriz de 1 Mb, lo que podría tener algo que ver con el tamaño de la caché de mi procesador – bsxfun no es un salto tan malo, porque solo necesita asignar la matriz de salida.

A continuación, encontrará el código que utilicé para cronometrar:

n = 300;
k=1; %# k=100 for the second graph
a = ones(10,1);
rr = zeros(n,1);
bb=zeros(n,1);
ntt=100;
tt=zeros(ntt,1);
for i=1:n;
   r = rand(1,i*k);
   for it=1:ntt;
      tic,
      x=bsxfun(@plus,a,r);
      tt(it)=toc;
   end;
   bb(i)=median(tt);
   for it=1:ntt;
      tic,
      y=repmat(a,1,i*k)+repmat(r,10,1);
      tt(it)=toc;
   end;
   rr(i)=median(tt);
end

En mi caso, uso bsxfun porque me evita pensar en los problemas de columnas o filas.

Para escribir tu ejemplo:

A = A - (ones(size(A, 1), 1) * mean(A));

Tengo que solucionar varios problemas:

1) size(A,1) o size(A,2)

2) ones(sizes(A,1),1) o ones(1,sizes(A,1))

3) ones(size(A, 1), 1) * mean(A) o mean(A)*ones(size(A, 1), 1)

4) mean(A) o mean(A,2)

Cuando uso bsxfun, Solo tengo que resolver el último:

a) mean(A) o mean(A,2)

Podrías pensar que es perezoso o algo así, pero cuando uso bsxfun, Yo tengo menos errores y yo programa más rápido.

Además, es más corto, lo que mejora digitando rapido y legibilidad.

¡Pregunta muy interesante! Recientemente me encontré con exactamente esa situación al responder a esta pregunta. Considere el siguiente código que calcula índices de una ventana deslizante de tamaño 3 a través de un vector a:

a = rand(1e7,1);

tic;
idx = bsxfun(@plus, [0:2]', 1:numel(a)-2);
toc

% equivalent code from im2col function in MATLAB
tic;
idx0 = repmat([0:2]', 1, numel(a)-2);
idx1 = repmat(1:numel(a)-2, 3, 1);
idx2 = idx0+idx1;
toc;

isequal(idx, idx2)

Elapsed time is 0.297987 seconds.
Elapsed time is 0.501047 seconds.

ans =

 1

En este caso bsxfun ¡es casi dos veces más rápido! Es útil y rápido porque evita la asignación explícita de memoria para matrices idx0 y idx1, guardándolos en la memoria y luego leyéndolos nuevamente solo para agregarlos. Dado que el ancho de banda de la memoria es un activo valioso y, a menudo, el cuello de botella en las arquitecturas actuales, desea usarlo con prudencia y disminuir los requisitos de memoria de su código para mejorar el rendimiento.

bsxfun le permite hacer precisamente eso: crear una matriz basada en aplicar un operador arbitrario a todos los pares de elementos de dos vectores, en lugar de operar explícitamente en dos matrices obtenidas al replicar los vectores. Es decir expansión singleton. También puede pensar en ello como el producto exterior de BLAS:

v1=[0:2]';
v2 = 1:numel(a)-2;
tic;
vout = v1*v2;
toc
Elapsed time is 0.309763 seconds.

Multiplica dos vectores para obtener una matriz. Solo que el producto externo solo realiza multiplicaciones, y bsxfun Puede aplicar operadores arbitrarios. Como nota al margen, es muy interesante ver que bsxfun es tan rápido como el producto exterior BLAS. Y generalmente se considera que BLAS ofrece los rendimiento..

Editar Gracias al comentario de Dan, aquí hay un gran artículo de Loren discutiendo exactamente eso.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *