Mi pregunta: Me he dado cuenta de que muchas buenas respuestas a las preguntas de Matlab sobre SO utilizan con frecuencia la función bsxfun
. ¿Por qué?
Motivación: en la documentación de Matlab para bsxfun
, se proporciona el siguiente ejemplo:
A = magic(5);
A = bsxfun(@minus, A, mean(A))
Por supuesto, podríamos hacer la misma operación usando:
A = A - (ones(size(A, 1), 1) * mean(A));
Y, de hecho, una simple prueba de velocidad demuestra que el segundo método es aproximadamente un 20% más rápido. Entonces, ¿por qué usar el primer método? Supongo que hay algunas circunstancias en las que el uso bsxfun
será mucho más rápido que el enfoque "manual". Me interesaría mucho ver un ejemplo de tal situación y una explicación de por qué es más rápido.
Además, un elemento final para esta pregunta, nuevamente de la documentación de Matlab para bsxfun
: "C = bsxfun (fun, A, B) aplica la operación binaria elemento por elemento especificada por la función de diversión de manejo a las matrices A y B, con singleton expansión habilitada ". ¿Qué significa la frase "con la expansión singleton habilitada"?
tic...toc
las líneas, la velocidad del código dependerá de tener que leer las funciones en la memoria.timeit
función en el enlace que usted / angainor / Dan proporciona.Respuestas:
Hay tres razones por las que uso
bsxfun
( documentación , enlace del blog )bsxfun
es más rápido querepmat
(ver abajo)bsxfun
requiere menos escribirbsxfun
, como usaraccumarray
, me hace sentir bien con 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". Por otro lado, las dimensiones de singleton son las que se eliminarán si llamasqueeze
.Es posible que para problemas muy pequeños, el
repmat
enfoque sea más rápido, pero con ese tamaño de matriz, ambas operaciones son tan rápidas que probablemente no harán ninguna diferencia en términos de rendimiento general. Hay dos razones importantes para quebsxfun
sea más rápido: (1) el cálculo se realiza 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
ybsxfun
con R2012b en mi portátil bastante rápido.Para mí,
bsxfun
es aproximadamente 3 veces más rápido querepmat
. La diferencia se hace más pronunciada si las matrices se hacen más grandesEl salto en tiempo de ejecución
repmat
ocurre alrededor de un tamaño de matriz de 1Mb, que podría tener algo que ver con el tamaño de la memoria caché de mi procesador,bsxfun
no es un salto tan malo, ya que solo necesita asignar la matriz de salida.A continuación encontrará el código que usé para el tiempo:
fuente
En mi caso, lo uso
bsxfun
porque me evita pensar en los problemas de columna o fila.Para escribir su ejemplo:
Tengo que resolver varios problemas:
1)
size(A,1)
osize(A,2)
2)
ones(sizes(A,1),1)
oones(1,sizes(A,1))
3)
ones(size(A, 1), 1) * mean(A)
omean(A)*ones(size(A, 1), 1)
4)
mean(A)
omean(A,2)
Cuando lo uso
bsxfun
, solo tengo que resolver el último:a)
mean(A)
omean(A,2)
Puede pensar que es flojo o algo así, pero cuando lo uso
bsxfun
, tengo menos errores y programo más rápido .Además, es más corto, lo que mejora la velocidad de escritura y la legibilidad .
fuente
Pregunta muy interesante! Recientemente me topé con tal situación al responder esta pregunta. Considere el siguiente código que calcula los índices de una ventana deslizante de tamaño 3 a través de un vector
a
:¡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 las matricesidx0
yidx1
, guardándolas en la memoria, y luego volviéndolas a leer solo para agregarlas. Dado que el ancho de banda de la memoria es un activo valioso y, a menudo, el cuello de botella en las arquitecturas de hoy en día, desea usarlo sabiamente y disminuir los requisitos de memoria de su código para mejorar el rendimiento.bsxfun
le permite hacer exactamente eso: crear una matriz basada en la aplicación de 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. Esa es la expansión singleton . También puede considerarlo como el producto externo de BLAS:Multiplica dos vectores para obtener una matriz. Solo que el producto externo solo realiza la multiplicación y
bsxfun
puede aplicar operadores arbitrarios. Como nota al margen, es muy interesante ver quebsxfun
es tan rápido como el producto externo BLAS. Y generalmente se considera que BLAS ofrece el rendimiento.Editar Gracias al comentario de Dan, aquí hay un gran artículo de Loren que habla exactamente de eso.
fuente
bsxfun
con un buen ejemplo.A partir de R2016b, Matlab admite la expansión implícita para una amplia variedad de operadores, por lo que en la mayoría de los casos ya no es necesario usar
bsxfun
:Hay una discusión detallada de Expansión implícita y su desempeño en el blog de Loren. Para citar a Steve Eddins de MathWorks:
fuente
Las cosas no siempre son consistentes con los 3 métodos comunes: la
repmat
expulsión por indexación ybsxfun
. Se vuelve más interesante cuando aumenta aún más el tamaño del vector. Ver trama:bsxfun
en realidad se vuelve un poco más lento que los otros dos en algún momento, pero lo que me sorprendió es que si aumenta el tamaño del vector aún más (> 13E6 elementos de salida), bsxfun de repente se vuelve más rápido en aproximadamente 3x. Sus velocidades parecen saltar en pasos y el orden no siempre es consistente. Supongo que también podría depender del tamaño del procesador / memoria, pero en general creo que me quedaríabsxfun
siempre que sea posible.fuente