c++ multidimensional-array armadillo boost-multi-array blitz++

c++ - Comparar blitz++, armadillo, boost:: MultiArray



multidimensional-array boost-multi-array (3)

Mi prueba mostró que las matrices de impulso tenían el mismo rendimiento que el código C ++ nativo / codificado.

Debe compararlos utilizando optimizaciones de compilador activadas. Es decir: -DNDEBUG -DBOOST_UBLAS_NDEBUG -DBOOST_DISABLE_ASSERTS -DARMA_NO_DEBUG ... Cuando probé (em ++), Boost se desempeñó al menos 10 veces más rápido cuando desactiva sus afirmaciones, habilita la optimización de nivel 3 con -O3 , etc. Cualquier comparación equitativa debería usar estas banderas

Hice una comparación entre blitz ++, armadillo, boost :: MultiArray con el siguiente código (tomado de una publicación anterior )

#include <iostream> using namespace std; #include <windows.h> #define _SCL_SECURE_NO_WARNINGS #define BOOST_DISABLE_ASSERTS #include <boost/multi_array.hpp> #include <blitz/array.h> #include <armadillo> int main(int argc, char* argv[]) { const int X_SIZE = 1000; const int Y_SIZE = 1000; const int ITERATIONS = 100; unsigned int startTime = 0; unsigned int endTime = 0; // Create the boost array //------------------Measure boost Loop------------------------------------------ { typedef boost::multi_array<double, 2> ImageArrayType; ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]); startTime = ::GetTickCount(); for (int i = 0; i < ITERATIONS; ++i) { for (int x = 0; x < X_SIZE; ++x) { for (int y = 0; y < Y_SIZE; ++y) { boostMatrix[x][y] = 1.0001; } } } endTime = ::GetTickCount(); printf("[Boost Loop] Elapsed time: %6.3f seconds/n", (endTime - startTime) / 1000.0); } //------------------Measure blitz Loop------------------------------------------- { blitz::Array<double, 2> blitzArray( X_SIZE, Y_SIZE ); startTime = ::GetTickCount(); for (int i = 0; i < ITERATIONS; ++i) { for (int x = 0; x < X_SIZE; ++x) { for (int y = 0; y < Y_SIZE; ++y) { blitzArray(x,y) = 1.0001; } } } endTime = ::GetTickCount(); printf("[Blitz Loop] Elapsed time: %6.3f seconds/n", (endTime - startTime) / 1000.0); } //------------------Measure armadillo loop---------------------------------------- { arma::mat matArray( X_SIZE, Y_SIZE ); startTime = ::GetTickCount(); for (int i = 0; i < ITERATIONS; ++i) { for (int y = 0; y < Y_SIZE; ++y) { for (int x = 0; x < X_SIZE; ++x) { matArray(x,y) = 1.0001; } } } endTime = ::GetTickCount(); printf("[arma Loop] Elapsed time: %6.3f seconds/n", (endTime - startTime) / 1000.0); } //------------------Measure native loop---------------------------------------- // Create the native array { double *nativeMatrix = new double [X_SIZE * Y_SIZE]; startTime = ::GetTickCount(); for (int i = 0; i < ITERATIONS; ++i) { for (int y = 0; y < Y_SIZE*X_SIZE; ++y) { nativeMatrix[y] = 1.0001; } } endTime = ::GetTickCount(); printf("[Native Loop]Elapsed time: %6.3f seconds/n", (endTime - startTime) / 1000.0); delete[] nativeMatrix; } //------------------Measure boost computation----------------------------------- { typedef boost::multi_array<double, 2> ImageArrayType; ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]); for (int x = 0; x < X_SIZE; ++x) { for (int y = 0; y < Y_SIZE; ++y) { boostMatrix[x][y] = 1.0001; } } startTime = ::GetTickCount(); for (int i = 0; i < ITERATIONS; ++i) { for (int x = 0; x < X_SIZE; ++x) { for (int y = 0; y < Y_SIZE; ++y) { boostMatrix[x][y] += boostMatrix[x][y] * 0.5; } } } endTime = ::GetTickCount(); printf("[Boost computation] Elapsed time: %6.3f seconds/n", (endTime - startTime) / 1000.0); } //------------------Measure blitz computation----------------------------------- { blitz::Array<double, 2> blitzArray( X_SIZE, Y_SIZE ); blitzArray = 1.0001; startTime = ::GetTickCount(); for (int i = 0; i < ITERATIONS; ++i) { blitzArray += blitzArray*0.5; } endTime = ::GetTickCount(); printf("[Blitz computation] Elapsed time: %6.3f seconds/n", (endTime - startTime) / 1000.0); } //------------------Measure armadillo computation------------------------------- { arma::mat matArray( X_SIZE, Y_SIZE ); matArray.fill(1.0001); startTime = ::GetTickCount(); for (int i = 0; i < ITERATIONS; ++i) { //matArray.fill(1.0001); matArray += matArray*0.5; } endTime = ::GetTickCount(); printf("[arma computation] Elapsed time: %6.3f seconds/n", (endTime - startTime) / 1000.0); } //------------------Measure native computation------------------------------------------ // Create the native array { double *nativeMatrix = new double [X_SIZE * Y_SIZE]; for (int y = 0; y < Y_SIZE*X_SIZE; ++y) { nativeMatrix[y] = 1.0001; } startTime = ::GetTickCount(); for (int i = 0; i < ITERATIONS; ++i) { for (int y = 0; y < Y_SIZE*X_SIZE; ++y) { nativeMatrix[y] += nativeMatrix[y] * 0.5; } } endTime = ::GetTickCount(); printf("[Native computation]Elapsed time: %6.3f seconds/n", (endTime - startTime) / 1000.0); delete[] nativeMatrix; } return 0; }

En Windows, VS2010, los resultados son

[Boost Loop] Elapsed time: 1.217 seconds [Blitz Loop] Elapsed time: 0.046 seconds [arma Loop] Elapsed time: 0.078 seconds [Native Loop]Elapsed time: 0.172 seconds [Boost computation] Elapsed time: 2.152 seconds [Blitz computation] Elapsed time: 0.156 seconds [arma computation] Elapsed time: 0.078 seconds [Native computation]Elapsed time: 0.078 seconds

En windows, intel c ++, los resultados son

[Boost Loop] Elapsed time: 0.468 seconds [Blitz Loop] Elapsed time: 0.125 seconds [arma Loop] Elapsed time: 0.046 seconds [Native Loop]Elapsed time: 0.047 seconds [Boost computation] Elapsed time: 0.796 seconds [Blitz computation] Elapsed time: 0.109 seconds [arma computation] Elapsed time: 0.078 seconds [Native computation]Elapsed time: 0.062 seconds

Algo extraño:

(1) with VS2010, native computation (including loop) is faster than native loop (2) blitz loop behave so different under VS2010 and intel C++.

Para compilar blitz ++ con el compilador Intel c ++, se requiere un archivo llamado bzconfig.h en la carpeta blitz / intel /. Pero no hay. Solo copio el que está en blitz / ms / bzconfig.h in. Eso puede dar una configuración no óptima. ¿Alguien puede decirme cómo compilar Blitz ++ con el compilador Intel c ++? En el manual, decía ejecutar script bzconfig para obtener el bzconfig.h correcto. Pero no entiendo lo que significa.

¡Muchas gracias!

Agregue algo de mi conclusión:

1. Boost multi array is the slowest. 2. With intel c++ compiler, native pointers are very fast. 3. With intel c++ compiler, armadillo can achieve the performance of native pointers. 4. Also test eigen, it is x0% slower than armadillo in my simple cases. 5. Curious about blitz++''s behavior in intel c++ compiler with proper configuration. Please see my question.


Por lo que puedo decir, estás juzgando el rendimiento de cada biblioteca de matriz midiendo la velocidad de multiplicar una matriz por un escalar. Debido a su política basada en plantillas, Armadillo hará un muy buen trabajo al desglosar cada multiplicación en código paralelizable para la mayoría de los compiladores.

Pero sugiero que debe replantearse el alcance y la metodología de su prueba. Por ejemplo, ha BLAS todas las implementaciones de BLAS . La función BLAS que necesitaría sería dscal . Una implementación provista por el proveedor para su CPU específica probablemente haría un buen trabajo.

De manera más relevante, hay muchas más cosas que cualquier biblioteca de vectores razonable necesitaría poder hacer: multiplicaciones de matrices, productos de puntos, longitudes de vectores, transposiciones, etc., que su prueba no aborda. Su prueba aborda exactamente dos cosas: la asignación de elementos, que prácticamente nunca es un cuello de botella para las bibliotecas de vectores, y la multiplicación escalar / vectorial, que es una función de nivel 1 de BLAS proporcionada por cada fabricante de CPU.

Aquí hay una discusión del nivel 1 de BLAS contra el código emitido por el compilador.

tl: dr; utilice Armadillo con las bibliotecas nativas BLAS y LAPACK vinculadas para su plataforma .


Respuesta corta: ./configure CXX=icpc , que se encuentra al leer la Guía del usuario de Blitz ++.

Respuesta larga:

Para compilar blitz ++ con el compilador Intel c ++, se requiere un archivo llamado bzconfig.h en la carpeta blitz / intel /. Pero no hay.

Si y si. Se supone que Blitz ++ genera el archivo en sí mismo. De acuerdo con la Blitz ++ Guía del usuario blitz.pdf incluida en blitz-0.10.tar.gz , sección "Instalación",

Blitz ++ usa GNU Autoconf, que maneja la reescritura de Makefiles para varias plataformas y compiladores.

Más exactamente, Blitz ++ utiliza la cadena de herramientas GNU autotools (automake, autoconf, configure), que puede generar archivos make, configurar scripts, archivos de encabezado y más. Se bzconfig.h archivos bzconfig.h deben ser generados por el script de configure , que viene con Blitz ++, listo para usar.

Solo copio el que está en blitz / ms / bzconfig.h in. Eso puede dar una configuración no óptima.

Si "no óptimo" significa "no funcional" para usted, entonces sí. :-) Necesita un intel/bzconfig.h que represente con precisión su compilador.

¿Alguien puede decirme cómo compilar Blitz ++ con el compilador Intel c ++?

Lea y siga el manual fino, en particular la sección "Instalación" mencionada anteriormente.

vaya al directorio ''blitz-VERSION'' y escriba: ./configure CXX=[compiler] donde [compiler] es uno de xlc ++, icpc, pathCC, xlC, cxx, aCC, CC, g ++, KCC, pgCC o FCC. (Si no elige un compilador de C ++, el script de configuración intentará encontrar un compilador apropiado para la plataforma actual.)

¿Has hecho esto? Para el compilador Intel, necesitaría usar ./configure CXX=icpc .

En el manual, decía ejecutar script bzconfig para obtener el bzconfig.h correcto. Pero no entiendo lo que significa.

Supongo que por "eso" te refieres a "eso". ¿Qué quieres decir con "manual"? Mi copia de la Guía del usuario de Blitz ++ no menciona bzconfig . ¿Estás seguro de que estás utilizando el manual que corresponde a tu versión de Blitz ++?

PD: Buscando "bzconfig" en los contenidos de blitz-0.10 , parece que "bzconfig" ya no es parte de Blitz ++, pero solía ser:

find . -name bzconfig find . -name bzconfig -> Sin resultados

find . -print0 | xargs -0 grep -a -i -n -e bzconfig find . -print0 | xargs -0 grep -a -i -n -e bzconfig :

./blitz/compiler.h:44: #error In <blitz/config.h>: A working template implementation is required by Blitz++ (you may need to rerun the compiler/bzconfig script)

Eso necesita ser actualizado.

./blitz/gnu/bzconfig.h:4:/* blitz/gnu/bzconfig.h. Generated automatically at end of configure. */ ./configure.ac:159:# autoconf replacement of bzconfig

Ahí lo tienes, estos archivos bzconfig.h deben ser generados por configure .

./ChangeLog.1:1787: will now replace the old file that was generate with the bzconfig

Ese puede ser el cambio que cambió a autoconf.

./INSTALL:107: 2. Go into the compiler subdirectory and run the bzconfig

Eso necesita ser actualizado. ¿Es esto lo que te hizo buscar a bzconfig ?

./README:27:compiler Compiler tests (used with obsolete bzconfig script)

Necesita actualización, un directorio de compiler ya no está incluido.