resueltos online multiplicacion matrices ejercicios ejemplos 4x4 3x3 2x2 c++ performance boost ublas boost-ublas

c++ - online - multiplicacion de matrices java



¿Por qué aumenta la multiplicación de matrices más lenta que la mía? (3)

He implementado una multiplicación de matrices con boost::numeric::ublas::matrix (vea mi código completo de boost que funciona )

Result result = read (); boost::numeric::ublas::matrix<int> C; C = boost::numeric::ublas::prod(result.A, result.B);

y otro con el algoritmo estándar (vea el código estándar completo ):

vector< vector<int> > ijkalgorithm(vector< vector<int> > A, vector< vector<int> > B) { int n = A.size(); // initialise C with 0s vector<int> tmp(n, 0); vector< vector<int> > C(n, tmp); for (int i = 0; i < n; i++) { for (int k = 0; k < n; k++) { for (int j = 0; j < n; j++) { C[i][j] += A[i][k] * B[k][j]; } } } return C; }

Así es como pruebo la velocidad:

time boostImplementation.out > boostResult.txt diff boostResult.txt correctResult.txt time simpleImplementation.out > simpleResult.txt diff simpleResult.txt correctResult.txt

Ambos programas leen un archivo de texto codificado que contiene dos matrices de 2000 x 2000. Ambos programas fueron compilados con estos indicadores:

g++ -std=c++98 -Wall -O3 -g $(PROBLEM).cpp -o $(PROBLEM).out -pedantic

¡Tengo 15 segundos para mi implementación y más de 4 minutos para la implementación de impulso!

editar: después de compilarlo con

g++ -std=c++98 -Wall -pedantic -O3 -D NDEBUG -DBOOST_UBLAS_NDEBUG library-boost.cpp -o library-boost.out

Obtuve 28.19 segundos para el algoritmo ikj y 60.99 segundos para Boost. Entonces, Boost sigue siendo considerablemente más lento.

¿Por qué el impulso es mucho más lento que mi implementación?


Creo que tu compilador no optimiza lo suficiente. El código uBLAS hace un uso intensivo de las plantillas y las plantillas requieren una gran cantidad de optimizaciones. Ejecuté su código a través del compilador MS VC 7.1 en modo de lanzamiento para matrices de 1000x1000, me da

10.064 s para uBLAS

7.851 s para el vector

La diferencia sigue ahí, pero de ninguna manera abrumadora. El concepto central de uBLAS es la evaluación diferida, por lo que prod(A, B) evalúa los resultados solo cuando es necesario, por ejemplo, prod(A, B)(10,100) se ejecutará en poco tiempo, ya que solo se calculará ese elemento. Como tal, en realidad no existe un algoritmo dedicado para la multiplicación de la matriz completa que pueda optimizarse (ver más abajo). Pero podrías ayudar a la biblioteca un poco, declarando

matrix<int, column_major> B;

reducirá el tiempo de funcionamiento a 4.426 s, lo que supera su función con una mano atada. Esta declaración hace que el acceso a la memoria sea más secuencial al multiplicar matrices, optimizando el uso de la memoria caché.

PD Al haber leído la documentación de uBLAS hasta el final;), debiste haber descubierto que en realidad hay una función dedicada para multiplicar matrices enteras a la vez. 2 funciones: axpy_prod y opb_prod . Asi que

opb_prod(A, B, C, true);

incluso en row_major no optimizado, la matriz B se ejecuta en 8.091 segundos y está a la par con su algoritmo de vector

PPS Aún hay más optimizaciones:

C = block_prod<matrix<int>, 1024>(A, B);

se ejecuta en 4.4 s, sin importar si B es column_ o row_ major. Considere la descripción: "La función block_prod está diseñada para grandes densas matrices". ¡Elija herramientas específicas para tareas específicas!


Un rendimiento más lento de la versión uBLAS se puede explicar en parte por las características de depuración de este último, como lo señaló TJD.

Aquí está el tiempo que toma la versión de uBLAS con la depuración en:

real 0m19.966s user 0m19.809s sys 0m0.112s

Aquí está el tiempo tomado por la versión de uBLAS con depuración desactivada (se -DNDEBUG -DBOOST_UBLAS_NDEBUG compilador -DNDEBUG -DBOOST_UBLAS_NDEBUG ):

real 0m7.061s user 0m6.936s sys 0m0.096s

Entonces, con la eliminación de errores, la versión de uBLAS es casi 3 veces más rápida.

La diferencia de rendimiento restante se puede explicar citando la siguiente sección de boost.org/doc/libs/1_49_0/libs/numeric/ublas/doc/index.htm de boost.org/doc/libs/1_49_0/libs/numeric/ublas/doc/index.htm "¿Por qué UBLAS es mucho más lento que (atlas-) BLAS"?

Un objetivo de diseño importante de ublas es ser lo más general posible.

Esta generalidad casi siempre tiene un costo. En particular, la plantilla de función prod puede manejar diferentes tipos de matrices, como las dispersas o triangulares. Afortunadamente, uBLAS proporciona alternativas optimizadas para la multiplicación de matriz densa, en particular, axpy_prod y block_prod . Aquí están los resultados de comparar diferentes métodos:

ijkalgorithm prod axpy_prod block_prod 1.335 7.061 1.330 1.278

Como puede ver, tanto axpy_prod como block_prod son algo más rápidos que su implementación. Medir solo el tiempo de cálculo sin E / S, eliminar la copia innecesaria y la elección cuidadosa del tamaño de bloque para block_prod (utilicé 64) puede hacer la diferencia más profunda.

Ver también boost.org/doc/libs/1_49_0/libs/numeric/ublas/doc/index.htm y uBlas Efectivo y optimización de código general .


Creé un pequeño sitio web Experimentos de productos Matrix-Matrix con uBLAS . Se trata de integrar una nueva implementación para el producto matriz-matriz en uBLAS. Si ya tiene la biblioteca de impulso, solo consta de 4 archivos adicionales. Entonces es bastante autónomo.

Me interesaría si otros pudieran ejecutar los puntos de referencia simples en diferentes máquinas.