arrays matlab bsxfun

arrays - Matlab-bsxfun ya no es más rápido que repmat?



(1)

Estoy tratando de encontrar la manera más rápida de estandarizar una matriz en Matlab (media cero, columnas de varianza de unidades). Todo se reduce a lo que es la forma más rápida de aplicar la misma operación a todas las filas en una matriz. Cada publicación que he leído llega a la misma conclusión: use bsxfun en lugar de repmat . Este artículo, escrito por Mathworks es un ejemplo: http://blogs.mathworks.com/loren/2008/08/04/comparing-repmat-and-bsxfun-performance/

Sin embargo, al intentar esto en mi computadora repmat siempre es más rápido. Aquí están mis resultados usando el mismo código que en el artículo:

m = 1e5; n = 100; A = rand(m,n); frepmat = @() A - repmat(mean(A),size(A,1),1); timeit(frepmat) fbsxfun = @() bsxfun(@minus,A,mean(A)); timeit(fbsxfun)

Resultados:

ans = 0.0349 ans = 0.0391

De hecho, nunca puedo lograr que bsxfun funcione mejor que repmat en esta situación, sin importar cuán pequeña o grande sea la matriz de entrada.

¿Alguien puede explicar esto?


La mayoría de los consejos que estás leyendo, incluida la publicación del blog de Loren, probablemente se refieren a versiones anteriores de MATLAB, para las cuales bsxfun era bastante más rápido que repmat . En R2013b (consulte la sección "Rendimiento" en el enlace), repmat se reimplementó para proporcionar grandes mejoras de rendimiento cuando se aplica a argumentos numéricos, char y lógicos. En versiones recientes, puede ser aproximadamente la misma velocidad que bsxfun .

Por lo que vale, en mi máquina con R2014a me sale

m = 1e5; n = 100; A = rand(m,n); frepmat = @() A - repmat(mean(A),size(A,1),1); timeit(frepmat) fbsxfun = @() bsxfun(@minus,A,mean(A)); timeit(fbsxfun) ans = 0.03756 ans = 0.034831

por lo que parece que bsxfun todavía es un poco más rápido, pero no mucho, y en su máquina parece que sucede lo contrario. Por supuesto, es probable que estos resultados vuelvan a variar, si varía el tamaño de A o la operación que está aplicando.

Todavía puede haber otras razones para preferir una solución sobre la otra, como la elegancia (prefiero bsxfun , si es posible).

Editar : los comentaristas han pedido una razón específica para preferir bsxfun , lo que implica que podría usar menos memoria que repmat al evitar una copia temporal que no repmat .

No creo que este sea realmente el caso. Por ejemplo, abra el Administrador de tareas (o el equivalente en Linux / Mac), observe los niveles de memoria y escriba:

>> m = 1e5; n = 8e3; A = rand(m,n); >> B = A - repmat(mean(A),size(A,1),1); >> clear B >> C = bsxfun(@minus,A,mean(A)); >> clear C

(Ajuste m y n hasta que los saltos sean visibles en el gráfico, pero no tan grandes que se quede sin memoria).

Veo exactamente el mismo comportamiento en repmat y bsxfun , que es que la memoria aumenta suavemente hasta el nuevo nivel (básicamente el doble del tamaño de A ) sin pico temporal adicional.

Este es también el caso incluso si la operación se realiza en el lugar. De nuevo, mira la memoria y escribe:

>> m = 1e5; n = 8e3; A = rand(m,n); >> A = A - repmat(mean(A),size(A,1),1); >> clear all >> m = 1e5; n = 8e3; A = rand(m,n); >> A = bsxfun(@minus,A,mean(A));

Una vez más, veo exactamente el mismo comportamiento de repmat y bsxfun , que es que la memoria se eleva a un pico (básicamente el doble del tamaño de A ), y luego vuelve al nivel anterior.

Así que me temo que no puedo ver mucha diferencia técnica en términos de velocidad o memoria entre repmat y bsxfun . Mi preferencia por bsxfun es solo una preferencia personal, ya que se siente un poco más elegante.