Comparando BSXFUN y REPMAT

Antes se hacían pocas preguntas sobre las comparaciones entre bsxfun y repmat para el rendimiento.

  • Uno de ellos fue: Matlab - bsxfun no longer faster than repmat? . Éste intentó investigar comparaciones de rendimiento entre repmat y bsxfun , específicas para realizar la resta de la media de una matriz de entrada a lo largo de las columnas de la matriz de entrada misma y, como tal, exploraría solo la parte bsxfun de bsxfun contra su equivalente repmat .
  • Otra fue: In Matlab, when is it optimal to use bsxfun? . Ese intentó hacer la misma operación de resta por la media a lo largo de las columnas y tampoco expandió a otras operaciones integradas.

Con esta publicación, estoy tratando de investigar los números de rendimiento entre bsxfun y repmat para abarcar todas las incorporaciones de bsxfun para darle una perspectiva más amplia, ya que ambas presentan buenas soluciones vectorizadas.

Específicamente, mis preguntas con esta publicación son:

  1. ¿Cómo funcionan las diversas operaciones bsxfun con bsxfun frente a equivalentes repmat ? bsxfun admite operaciones de coma flotante como @plus , @minus , @times , etc. y también operaciones relacionales y lógicas como @ge , @and y etc. Entonces, ¿hay complementos específicos que me darían velocidades notables con bsxfun que usando sus equivalentes repmat ?

  2. Loren en su blog post ha comparado repmat contra bsxfun con timing @() A - repmat(mean(A),size(A,1),1) contra @() bsxfun(@minus,A,mean(A)) respectivamente . Si necesito cubrir el benchmarking para todos los built-ins, ¿puedo usar algún otro modelo de comparación que funcione con operaciones flotantes, relacionales y lógicas?

    Introducción

    El debate sobre si bsxfun es mejor que repmat o viceversa ha estado sucediendo como siempre. En esta publicación, intentaremos comparar cómo los diferentes integradores que se incluyen con MATLAB luchan contra los repmat equivalentes en términos de rendimiento de tiempo de ejecución y esperamos extraer algunas conclusiones significativas de ellos.

    Conozca los integrables de BSXFUN

    Si la documentación oficial se extrae del entorno de MATLAB o a través del sitio web de Mathworks , se puede ver la lista completa de las funciones incorporadas compatibles con bsxfun . Esa lista tiene funciones para operaciones flotantes, relacionales y lógicas.

    En MATLAB 2015A , las operaciones de coma flotante MATLAB 2015A elementos compatibles son:

    • @plus (sumtoria)
    • @minus (resta)
    • @times (multiplicación)
    • @rdivide (división derecha)
    • @ldivide (división izquierda)
    • @pow (poder)
    • @rem (rest)
    • @mod (módulo)
    • @ atan2 (tangente inversa de cuatro cuadrantes)
    • @ atan2d (tangente inversa de cuatro cuadrantes en grados)
    • @hypot (raíz cuadrada de sum de cuadrados).

    El segundo conjunto consiste en operaciones relacionales de elementos y son:

    • @eq (igual)
    • @ne (no igual)
    • @lt (menos que)
    • @le (menor que o igual)
    • @gt (mayor que)
    • @ge (mayor que o igual).

    El tercer y último conjunto comprende las operaciones lógicas que se enumeran a continuación:

    • @and (lógico y)
    • @or (lógico o)
    • @xor (xor lógico).

    Tenga en cuenta que hemos excluido dos integradas @max (maximum) y @min (minimum) de nuestras pruebas de comparación, ya que podría haber muchas maneras en que uno puede implementar sus equivalentes repmat .

    Modelo de comparación

    Para comparar verdaderamente las actuaciones entre repmat y bsxfun , debemos asegurarnos de que los tiempos solo necesiten cubrir las operaciones previstas. Por lo tanto, algo como bsxfun(@minus,A,mean(A)) no será ideal, ya que tiene que calcular la mean(A) dentro de esa llamada bsxfun , por insignificante que sea el tiempo. En cambio, podemos usar otra entrada B del mismo tamaño que mean(A) .

    Por lo tanto, podemos usar: A = rand(m,n) & B = rand(1,n) , donde m y n son los parámetros de tamaño que podemos variar y estudiar las actuaciones en función de ellos. Esto se hace exactamente en nuestras pruebas de evaluación comparativa que se enumeran en la siguiente sección.

    Las versiones repmat y bsxfun para operar en esas entradas se verían como estas:

     REPMAT: A + repmat(B,size(A,1),1) BSXFUN: bsxfun(@plus,A,B) 

    Benchmarking

    Finalmente, estamos en el quid de este post para ver a estos dos tipos luchar. Hemos segregado el benchmarking en tres conjuntos, uno para las operaciones de punto flotante, otro para el relacional y el tercero para las operaciones lógicas. Hemos extendido el modelo de comparación como se discutió anteriormente a todas estas operaciones.

    Set1: Operaciones de punto flotante

    Aquí está el primer conjunto de código de evaluación comparativa para operaciones de coma flotante con repmat y bsxfun

     datasizes = [ 100 100; 100 1000; 100 10000; 100 100000; 1000 100; 1000 1000; 1000 10000; 10000 100; 10000 1000; 10000 10000; 100000 100; 100000 1000]; num_funcs = 11; tsec_rep = NaN(size(datasizes,1),num_funcs); tsec_bsx = NaN(size(datasizes,1),num_funcs); for iter = 1:size(datasizes,1) m = datasizes(iter,1); n = datasizes(iter,2); A = rand(m,n); B = rand(1,n); fcns_rep= {@() A + repmat(B,size(A,1),1),@() A - repmat(B,size(A,1),1),... @() A .* repmat(B,size(A,1),1), @() A ./ repmat(B,size(A,1),1),... @() A.\repmat(B,size(A,1),1), @() A .^ repmat(B,size(A,1),1),... @() rem(A ,repmat(B,size(A,1),1)), @() mod(A,repmat(B,size(A,1),1)),... @() atan2(A,repmat(B,size(A,1),1)),@() atan2d(A,repmat(B,size(A,1),1)),... @() hypot( A , repmat(B,size(A,1),1) )}; fcns_bsx = {@() bsxfun(@plus,A,B), @() bsxfun(@minus,A,B), ... @() bsxfun(@times,A,B),@() bsxfun(@rdivide,A,B),... @() bsxfun(@ldivide,A,B), @() bsxfun(@power,A,B), ... @() bsxfun(@rem,A,B), @() bsxfun(@mod,A,B), @() bsxfun(@atan2,A,B),... @() bsxfun(@atan2d,A,B), @() bsxfun(@hypot,A,B)}; for k1 = 1:numel(fcns_bsx) tsec_rep(iter,k1) = timeit(fcns_rep{k1}); tsec_bsx(iter,k1) = timeit(fcns_bsx{k1}); end end speedups = tsec_rep./tsec_bsx; 

    Set2: operaciones relacionales

    El código de evaluación comparativa para las operaciones relacionales de tiempo reemplazaría a fcns_rep y fcns_bsx del código de evaluación comparativa anterior con estas contrapartidas.

     fcns_rep = { @() A == repmat(B,size(A,1),1), @() A ~= repmat(B,size(A,1),1),... @() A < repmat(B,size(A,1),1), @() A <= repmat(B,size(A,1),1), ... @() A > repmat(B,size(A,1),1), @() A >= repmat(B,size(A,1),1)}; fcns_bsx = { @() bsxfun(@eq,A,B), @() bsxfun(@ne,A,B), @() bsxfun(@lt,A,B),... @() bsxfun(@le,A,B), @() bsxfun(@gt,A,B), @() bsxfun(@ge,A,B)}; 

    Set3: operaciones lógicas

    El conjunto final de códigos de referencia utilizaría las operaciones lógicas que se enumeran aquí:

     fcns_rep = { @() A & repmat(B,size(A,1),1), @() A | repmat(B,size(A,1),1), ... @() xor(A,repmat(B,size(A,1),1))}; fcns_bsx = { @() bsxfun(@and,A,B), @() bsxfun(@or,A,B), @() bsxfun(@xor,A,B)}; 

    Tenga en cuenta que para este conjunto específico, los datos de entrada, A y B necesarios eran matrices lógicas. Entonces, tuvimos que hacer estas ediciones en el código de evaluación comparativa anterior para crear matrices lógicas:

     A = rand(m,n)>0.5; B = rand(1,n)>0.5; 

    Tiempo de ejecución y observaciones

    Los códigos de evaluación comparativa se ejecutaron en esta configuración del sistema:

     MATLAB Version: 8.5.0.197613 (R2015a) Operating System: Windows 7 Professional 64-bit RAM: 16GB CPU Model: Intel® Core i7-4790K @4.00GHz 

    Las aceleraciones así obtenidas con bsxfun sobre repmat después de ejecutar las pruebas de referencia se trazaron para los tres conjuntos como se muestra a continuación.

    A. Operaciones de punto flotante:

    enter image description here

    Pocas observaciones podrían extraerse de la ttwig de aceleración:

    • Los notablemente dos buenos casos de bsxfun con bsxfun son para atan2 y atan2d .
    • A continuación, en la lista se muestran las operaciones de división derecha e izquierda que mejoran con un 30% - 50% sobre los códigos equivalentes repmat .
    • Yendo más allá en esa lista están las 7 operaciones restantes cuyas aceleraciones parecen muy cercanas a la unidad y por lo tanto necesitan una inspección más cercana. El diagtwig de aceleración podría reducirse a solo esas 7 operaciones como se muestra a continuación –

    enter image description here

    Con base en el gráfico anterior, se puede ver que, salvo en casos @hypot con @hypot y @mod , bsxfun todavía realiza aproximadamente un 10% mejor que repmat para estas 7 operaciones.

    B. Operaciones relacionales:

    Este es el segundo conjunto de evaluación comparativa para las siguientes 6 operaciones relacionales incorporadas compatibles con bsxfun .

    enter image description here

    Mirando el diagtwig de aceleración anterior, descuidando el caso inicial que tuvo tiempos de ejecución comparables entre bsxfun y repmat , uno puede ver fácilmente bsxfun ganando para estas operaciones relacionales. Con las aceleraciones tocando 10x , bsxfun siempre sería preferible para estos casos.

    C. Operaciones lógicas:

    Este es el tercer conjunto de pruebas comparativas para las 3 operaciones lógicas bsxfun admitidas por bsxfun .

    enter image description here

    Despreciando el único caso de tiempo de ejecución comparable para @xor al inicio, bsxfun parece tener una ventaja para este conjunto de operaciones lógicas también.

    Conclusiones

    1. Al trabajar con operaciones relacionales y lógicas, repmat podría repmat fácilmente a favor de bsxfun . Para el rest de los casos, todavía puede persistir con bsxfun si se bsxfun uno de los casos con un rendimiento de 5 - 7% menor.
    2. Al ver el tipo de gran aumento de rendimiento al usar operaciones lógicas y relacionales con bsxfun , uno puede pensar en usar bsxfun para trabajar en datos con ragged patterns , algo así como arreglos de celdas para obtener beneficios de rendimiento. Me gusta llamar a estos casos de soluciones como los que usan la capacidad de enmascaramiento de bsxfun . Esto básicamente significa que creamos arreglos lógicos, es decir, máscaras con bsxfun , que se pueden usar para intercambiar datos entre matrices de celdas y matrices numéricas. Una de las ventajas de tener datos viables en matrices numéricas es que los métodos vectorizados podrían usarse para procesarlos. Una vez más, dado que bsxfun es una buena herramienta para la vectorización, puede encontrarse utilizándolo una vez más bsxfun el mismo problema, por lo que hay más razones para conocer bsxfun . Pocos casos de solución en los que pude explorar dichos métodos están vinculados aquí para el beneficio de los lectores: 1 , 2 , 3 , 4 , 5 .

    Trabajo futuro

    El presente trabajo se centró en replicar datos a lo largo de una dimensión con repmat . Ahora, repmat puede replicar a lo largo de múltiples dimensiones y también lo hace bsxfun con sus expansiones que son equivalentes a las replicaciones. Como tal, sería interesante realizar pruebas similares en las repeticiones y expansiones en múltiples dimensiones con estas dos funciones.