Pregunta

Estoy tratando de comparar el rendimiento de boost::multi_array a los nativos de asignación dinámica de las matrices, con el siguiente programa de prueba:

#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS
#define BOOST_DISABLE_ASSERTS 
#include <boost/multi_array.hpp>

int main(int argc, char* argv[])
{
    const int X_SIZE = 200;
    const int Y_SIZE = 200;
    const int ITERATIONS = 500;
    unsigned int startTime = 0;
    unsigned int endTime = 0;

    // Create the boost array
    typedef boost::multi_array<double, 2> ImageArrayType;
    ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]);

    // Create the native array
    double *nativeMatrix = new double [X_SIZE * Y_SIZE];

    //------------------Measure boost----------------------------------------------
    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)
            {
                boostMatrix[x][y] = 2.345;
            }
        }
    }
    endTime = ::GetTickCount();
    printf("[Boost] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);

    //------------------Measure native-----------------------------------------------
    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)
            {
                nativeMatrix[x + (y * X_SIZE)] = 2.345;
            }
        }
    }
    endTime = ::GetTickCount();
    printf("[Native]Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);

    return 0;
}

Yo obtienen los siguientes resultados:

[Boost] Elapsed time: 12.500 seconds
[Native]Elapsed time:  0.062 seconds

No puedo creer multi_arrays son mucho más lento.Puede alguien terreno lo que estoy haciendo mal?

Supongo almacenamiento en caché no es un problema ya que estoy haciendo escribe a la memoria.

EDITAR:Esta fue una versión de depuración.Por Laserallan del sugieren hice una compilación de la versión:

[Boost] Elapsed time:  0.266 seconds
[Native]Elapsed time:  0.016 seconds

Mucho más cerca.Pero de 16 a 1 sigue siendo muy alta para mí.

Bueno, no hay una respuesta definitiva, pero yo voy a pasar y dejar mi código real con nativos de matrices por ahora.

La aceptación de Laserallan la respuesta de porque era el mayor defecto en mi prueba.

Gracias a todos.

¿Fue útil?

Solución

¿Está creando versión o depuración?

Si se ejecuta en modo de depuración, la matriz de impulso puede ser realmente lenta porque su magia de plantilla no está alineada correctamente, lo que genera una gran sobrecarga en las llamadas a funciones. Sin embargo, no estoy seguro de cómo se implementa la matriz múltiple, por lo que esto podría estar totalmente desactivado :)

Quizás también haya alguna diferencia en el orden de almacenamiento, por lo que es posible que tenga su imagen almacenada columna por columna y que la escriba fila por fila. Esto daría un comportamiento de caché deficiente y podría ralentizar las cosas.

Intente cambiar el orden del ciclo X e Y y vea si gana algo. Hay alguna información sobre el pedido de almacenamiento aquí: http://www.boost.org/doc/libs /1_37_0/libs/multi_array/doc/user.html

EDITAR: Dado que parece estar utilizando la matriz bidimensional para el procesamiento de imágenes, es posible que le interese revisar la biblioteca de procesamiento de imágenes gil .

Puede tener matrices con menos gastos generales que funcionen perfectamente para su situación.

Otros consejos

En mi máquina de uso

g++ -O3 -march=native -mtune=native --fast-math -DNDEBUG test.cpp -o test && ./test

Puedo conseguir

[Boost] Elapsed time:  0.020 seconds
[Native]Elapsed time:  0.020 seconds

Sin embargo, cambiando const int ITERATIONS a 5000 Puedo conseguir

[Boost] Elapsed time:  0.240 seconds
[Native]Elapsed time:  0.180 seconds

a continuación, con ITERATIONS de vuelta a 500 pero X_SIZE y Y_SIZE conjunto para 400 Yo obtener una diferencia significativa

[Boost] Elapsed time:  0.460 seconds
[Native]Elapsed time:  0.070 seconds

finalmente, la inversión del bucle interno para el [Boost] caso por lo que parece

    for (int x = 0; x < X_SIZE; ++x)
    {
        for (int y = 0; y < Y_SIZE; ++y)
        {

y mantener ITERATIONS, X_SIZE y Y_SIZE a 500, 400 y 400 Puedo conseguir

[Boost] Elapsed time:  0.060 seconds
[Native]Elapsed time:  0.080 seconds

Si puedo invertir el bucle interno también para la [Native] caso (así es en el orden equivocado para ese caso), me sale, como era de esperar,

[Boost] Elapsed time:  0.070 seconds
[Native]Elapsed time:  0.450 seconds

Estoy usando gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 en Ubuntu 10.10

Así que, en conclusión:

  • Con una adecuada optimización boost::multi_array hace su trabajo como se espera
  • El orden en el que acceder a sus datos no importa

Su prueba es defectuosa.

  • En una compilación DEBUG, boost :: MultiArray carece del pase de optimización que realmente necesita. (Mucho más que una matriz nativa)
  • En una compilación RELEASE, su compilador buscará código que pueda eliminarse por completo y la mayor parte de su código está en esa categoría .

Lo que probablemente esté viendo es el resultado de que su compilador de optimización vea que la mayoría o la totalidad de su " matriz nativa " los lazos se pueden quitar. Lo mismo es teóricamente cierto para su impulso :: bucles MultiArray, pero MultiArray es probablemente lo suficientemente complejo como para derrotar a su optimizador.

Realice este pequeño cambio en su banco de pruebas y verá resultados más reales: cambie ambas ocurrencias de " = 2.345 " con " *= 2.345 " y compilar nuevamente con optimizaciones. Esto evitará que su compilador descubra que el bucle externo de cada prueba es redundante.

Lo hice y obtuve una comparación de velocidad más cercana a 2: 1.

Me pregunto dos cosas:

1) verificación de límites: defina la macro del preprocesador BOOST_DISABLE_ASSERTS antes de incluir multi_array.hpp en su aplicación. Esto desactiva la comprobación encuadernada. no estoy seguro de si esto es deshabilitado cuando NDEBUG es.

2) índice base:  MultiArray puede indexar matrices de bases diferentes de 0. Eso significa que multi_array almacena un número base (en cada dimensión) y usa una fórmula más complicada para obtener la ubicación exacta en la memoria. Me pregunto si se trata de eso.

De lo contrario, no entiendo por qué el multiarray debería ser más lento que los C-arrays.

Considere usar Blitz ++ en su lugar. Probé Blitz, ¡y su rendimiento está a la par con la matriz de estilo C!

Revise su código con Blitz agregado a continuación:


#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS
#define BOOST_DISABLE_ASSERTS 
#include <boost/multi_array.hpp>
#include <blitz/array.h>

int main(int argc, char* argv[])
{
    const int X_SIZE = 200;
    const int Y_SIZE = 200;
    const int ITERATIONS = 500;
    unsigned int startTime = 0;
    unsigned int endTime = 0;

    // Create the boost array
    typedef boost::multi_array<double, 2> ImageArrayType;
    ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]);


    //------------------Measure boost----------------------------------------------
    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)
            {
                boostMatrix[x][y] = 2.345;
            }
        }
    }
    endTime = ::GetTickCount();
    printf("[Boost] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);

    //------------------Measure blitz-----------------------------------------------
    blitz::Array<double, 2> blitzArray( 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)
            {
                blitzArray(x,y) = 2.345;
            }
        }
    }
    endTime = ::GetTickCount();
    printf("[Blitz] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);


    //------------------Measure native-----------------------------------------------
    // 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; ++y)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                nativeMatrix[x + (y * X_SIZE)] = 2.345;
            }
        }
    }
    endTime = ::GetTickCount();
    printf("[Native]Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);



    return 0;
}

Aquí está el resultado en depuración y liberación.

DEPURACIÓN:

Boost  2.093 secs 
Blitz  0.375 secs 
Native 0.078 secs

LIBERACIÓN:

Boost  0.266 secs
Blitz  0.016 secs
Native 0.015 secs

Utilicé el compilador MSVC 2008 SP1 para esto.

¿Podemos decir adiós a la matriz C-stlye? = p

Estaba mirando esta pregunta porque tenía la misma pregunta. Pensé en hacer una prueba más rigurosa.

  1. Como rodrigob señaló, hay fallas en el orden del bucle de manera que cualquier resultado en el código que adjuntó originalmente dará datos engañosos
  2. Además, hay arreglos de tamaño bastante pequeño que se configuran utilizando constantes. El compilador puede optimizar los bucles, cuando en realidad el compilador no sabrá el tamaño de las matrices. Los tamaños de las matrices y el número de iteraciones deben ser entradas de tiempo de ejecución por si acaso.

En una Mac, el siguiente código está configurado para dar respuestas más significativas. Hay 4 pruebas aquí.

#define BOOST_DISABLE_ASSERTS
#include "boost/multi_array.hpp"
#include <sys/time.h>
#include <stdint.h>
#include<string>

uint64_t GetTimeMs64()
{
  struct timeval tv;

  gettimeofday( &tv, NULL );

  uint64_t ret = tv.tv_usec;
  /* Convert from micro seconds (10^-6) to milliseconds (10^-3) */
  ret /= 1000;

  /* Adds the seconds (10^0) after converting them to milliseconds (10^-3) */
  ret += ( tv.tv_sec * 1000 );

  return ret;

}


void function1( const int X_SIZE, const int Y_SIZE, const int ITERATIONS )
{

  double nativeMatrix1add[X_SIZE*Y_SIZE];

  for( int x = 0 ; x < X_SIZE ; ++x )
  {
    for( int y = 0 ; y < Y_SIZE ; ++y )
    {
      nativeMatrix1add[y + ( x * Y_SIZE )] = rand();
    }
  }

  // Create the native array
  double* __restrict const nativeMatrix1p = new double[X_SIZE * Y_SIZE];
  uint64_t startTime = GetTimeMs64();
  for( int i = 0 ; i < ITERATIONS ; ++i )
  {
    for( int xy = 0 ; xy < X_SIZE*Y_SIZE ; ++xy )
    {
      nativeMatrix1p[xy] += nativeMatrix1add[xy];
    }
  }
  uint64_t endTime = GetTimeMs64();
  printf( "[Native Pointer]    Elapsed time: %6.3f seconds\n", ( endTime - startTime ) / 1000.0 );

}

void function2( const int X_SIZE, const int Y_SIZE, const int ITERATIONS )
{

  double nativeMatrix1add[X_SIZE*Y_SIZE];

  for( int x = 0 ; x < X_SIZE ; ++x )
  {
    for( int y = 0 ; y < Y_SIZE ; ++y )
    {
      nativeMatrix1add[y + ( x * Y_SIZE )] = rand();
    }
  }

  // Create the native array
  double* __restrict const nativeMatrix1 = new double[X_SIZE * Y_SIZE];
  uint64_t startTime = GetTimeMs64();
  for( int i = 0 ; i < ITERATIONS ; ++i )
  {
    for( int x = 0 ; x < X_SIZE ; ++x )
    {
      for( int y = 0 ; y < Y_SIZE ; ++y )
      {
        nativeMatrix1[y + ( x * Y_SIZE )] += nativeMatrix1add[y + ( x * Y_SIZE )];
      }
    }
  }
  uint64_t endTime = GetTimeMs64();
  printf( "[Native 1D Array]   Elapsed time: %6.3f seconds\n", ( endTime - startTime ) / 1000.0 );

}


void function3( const int X_SIZE, const int Y_SIZE, const int ITERATIONS )
{

  double nativeMatrix2add[X_SIZE][Y_SIZE];

  for( int x = 0 ; x < X_SIZE ; ++x )
  {
    for( int y = 0 ; y < Y_SIZE ; ++y )
    {
      nativeMatrix2add[x][y] = rand();
    }
  }

  // Create the native array
  double nativeMatrix2[X_SIZE][Y_SIZE];
  uint64_t startTime = GetTimeMs64();
  for( int i = 0 ; i < ITERATIONS ; ++i )
  {
    for( int x = 0 ; x < X_SIZE ; ++x )
    {
      for( int y = 0 ; y < Y_SIZE ; ++y )
      {
        nativeMatrix2[x][y] += nativeMatrix2add[x][y];
      }
    }
  }
  uint64_t endTime = GetTimeMs64();
  printf( "[Native 2D Array]   Elapsed time: %6.3f seconds\n", ( endTime - startTime ) / 1000.0 );

}



void function4( const int X_SIZE, const int Y_SIZE, const int ITERATIONS )
{

  boost::multi_array<double, 2> boostMatrix2add( boost::extents[X_SIZE][Y_SIZE] );

  for( int x = 0 ; x < X_SIZE ; ++x )
  {
    for( int y = 0 ; y < Y_SIZE ; ++y )
    {
      boostMatrix2add[x][y] = rand();
    }
  }

  // Create the native array
  boost::multi_array<double, 2> boostMatrix( boost::extents[X_SIZE][Y_SIZE] );
  uint64_t startTime = GetTimeMs64();
  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] += boostMatrix2add[x][y];
      }
    }
  }
  uint64_t endTime = GetTimeMs64();
  printf( "[Boost Array]       Elapsed time: %6.3f seconds\n", ( endTime - startTime ) / 1000.0 );

}

int main( int argc, char* argv[] )
{

  srand( time( NULL ) );

  const int X_SIZE = std::stoi( argv[1] );
  const int Y_SIZE = std::stoi( argv[2] );
  const int ITERATIONS = std::stoi( argv[3] );

  function1( X_SIZE, Y_SIZE, ITERATIONS );
  function2( X_SIZE, Y_SIZE, ITERATIONS );
  function3( X_SIZE, Y_SIZE, ITERATIONS );
  function4( X_SIZE, Y_SIZE, ITERATIONS );

  return 0;
}
  1. Uno con solo una matriz dimensional utilizando el [] con matemática entera y un bucle doble

  2. Uno con la misma matriz unidimensional usando el incremento de puntero

  3. Una matriz C multidimensional

  4. Un impulso multi_array

ejecuta desde una línea de comando, ejecuta

./test_array xsize ysize iterations"

y puede hacerse una buena idea de cómo funcionarán estos enfoques. Esto es lo que obtuve con los siguientes indicadores del compilador:

g++4.9.2 -O3 -march=native -funroll-loops -mno-avx --fast-math -DNDEBUG  -c -std=c++11


./test_array 51200 1 20000
[Native 1-Loop ]    Elapsed time:  0.537 seconds
[Native 1D Array]   Elapsed time:  2.045 seconds
[Native 2D Array]   Elapsed time:  2.749 seconds
[Boost Array]       Elapsed time:  1.167 seconds

./test_array 25600 2 20000
[Native 1-Loop ]    Elapsed time:  0.531 seconds
[Native 1D Array]   Elapsed time:  1.241 seconds
[Native 2D Array]   Elapsed time:  1.631 seconds
[Boost Array]       Elapsed time:  0.954 seconds

./test_array 12800 4 20000
[Native 1-Loop ]    Elapsed time:  0.536 seconds
[Native 1D Array]   Elapsed time:  1.214 seconds
[Native 2D Array]   Elapsed time:  1.223 seconds
[Boost Array]       Elapsed time:  0.798 seconds

./test_array 6400 8 20000
[Native 1-Loop ]    Elapsed time:  0.540 seconds
[Native 1D Array]   Elapsed time:  0.845 seconds
[Native 2D Array]   Elapsed time:  0.878 seconds
[Boost Array]       Elapsed time:  0.803 seconds

./test_array 3200 16 20000
[Native 1-Loop ]    Elapsed time:  0.537 seconds
[Native 1D Array]   Elapsed time:  0.661 seconds
[Native 2D Array]   Elapsed time:  0.673 seconds
[Boost Array]       Elapsed time:  0.708 seconds

./test_array 1600 32 20000
[Native 1-Loop ]    Elapsed time:  0.532 seconds
[Native 1D Array]   Elapsed time:  0.592 seconds
[Native 2D Array]   Elapsed time:  0.596 seconds
[Boost Array]       Elapsed time:  0.764 seconds

./test_array 800 64 20000
[Native 1-Loop ]    Elapsed time:  0.546 seconds
[Native 1D Array]   Elapsed time:  0.594 seconds
[Native 2D Array]   Elapsed time:  0.606 seconds
[Boost Array]       Elapsed time:  0.764 seconds

./test_array 400 128 20000
[Native 1-Loop ]    Elapsed time:  0.536 seconds
[Native 1D Array]   Elapsed time:  0.560 seconds
[Native 2D Array]   Elapsed time:  0.564 seconds
[Boost Array]       Elapsed time:  0.746 seconds

Entonces, creo que es seguro decir que el boost multi_array funciona bastante bien. Nada supera una evaluación de un solo ciclo, pero dependiendo de la dimensión de la matriz, el boost :: multi_array puede vencer a una matriz c estándar con un doble ciclo.

Otra cosa para probar es usar iteradores en lugar de un índice directo para la matriz de impulso.

Hubiera esperado que el multiarray fuera igual de eficiente. Pero obtengo resultados similares en una Mac PPC usando gcc. También probé multiarrayref, de modo que ambas versiones usaban el mismo almacenamiento sin diferencia. Es bueno saberlo, ya que uso multiarray en algunos de mis códigos, y asumí que era similar a la codificación manual.

Creo que sé cuál es el problema ... tal vez.

Para que la implementación de impulso tenga una sintaxis como: matriz [x] [y]. eso significa que la matriz [x] tiene que devolver una referencia a un objeto que actúa como una columna 1em columna , en cuyo punto la referencia [y] le proporciona su elemento.

El problema aquí es que está iterando en el orden fila mayor (lo cual es típico en c / c ++ ya que las matrices nativas son fila mayor IIRC. El compilador debe volver a ejecutar la matriz [x] para cada y en este caso. Si iteraste en el orden principal de la columna al usar la matriz de refuerzo, es posible que veas un mejor rendimiento.

Solo una teoría.

EDITAR: en mi sistema Linux (con algunos cambios menores) probé mi teoría y mostré alguna mejora en el rendimiento al cambiar x e y, pero aún era más lento que una matriz nativa. Esto podría ser un simple problema de que el compilador no puede optimizar el tipo de referencia temporal.

Cree en modo de lanzamiento, use objdump y mire el ensamblaje. Pueden estar haciendo cosas completamente diferentes, y podrá ver qué optimizaciones está utilizando el compilador.

Se hizo una pregunta similar y se respondió aquí:

http://www.codeguru.com/forum /archive/index.php/t-300014.html

La respuesta breve es que es más fácil para el compilador optimizar las matrices simples, y no es tan fácil optimizar la versión Boost. Por lo tanto, un compilador particular puede no dar a la versión Boost los mismos beneficios de optimización.

Los compiladores también pueden variar en qué tan bien se optimizarán en comparación con cuán conservadores serán (por ejemplo, con código de plantilla u otras complicaciones).

Probé en un Mac OS Snow Leopard usando gcc 4.2.1

Debug:
[Boost] Elapsed time:  2.268 seconds
[Native]Elapsed time:  0.076 seconds

Release:
[Boost] Elapsed time:  0.065 seconds
[Native]Elapsed time:  0.020 seconds

Aquí está el código (modificado para que pueda compilarse en Unix):

#define BOOST_DISABLE_ASSERTS
#include <boost/multi_array.hpp>
#include <ctime>

int main(int argc, char* argv[])
{
    const int X_SIZE = 200;
    const int Y_SIZE = 200;
    const int ITERATIONS = 500;
    unsigned int startTime = 0;
    unsigned int endTime = 0;

    // Create the boost array
    typedef boost::multi_array<double, 2> ImageArrayType;
    ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]);

    // Create the native array
    double *nativeMatrix = new double [X_SIZE * Y_SIZE];

    //------------------Measure boost----------------------------------------------
    startTime = clock();
    for (int i = 0; i < ITERATIONS; ++i)
    {
        for (int y = 0; y < Y_SIZE; ++y)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                boostMatrix[x][y] = 2.345;
            }
        }
    }
    endTime = clock();
    printf("[Boost] Elapsed time: %6.3f seconds\n", (endTime - startTime) / (double)CLOCKS_PER_SEC);

    //------------------Measure native-----------------------------------------------
    startTime = clock();
    for (int i = 0; i < ITERATIONS; ++i)
    {
        for (int y = 0; y < Y_SIZE; ++y)
        {
            for (int x = 0; x < X_SIZE; ++x)
            {
                nativeMatrix[x + (y * X_SIZE)] = 2.345;
            }
        }
    }
    endTime = clock();
    printf("[Native]Elapsed time: %6.3f seconds\n", (endTime - startTime) / (double)CLOCKS_PER_SEC);

    return 0;
}

Buscando en la asamblea generado por g++ 4.8.2 con -O3 -DBOOST_DISABLE_ASSERTS y utilizando tanto el operator() y el [][] formas de acceder a los elementos, es evidente que la única operación adicional en comparación a los nativos de las matrices y el manual de cálculo de índice es la suma de la base.Yo no medir el costo de esto, sin embargo.

Modifiqué el código anterior en Visual Studio 2008 v9.0.21022 y apliqué las rutinas del contenedor de las rutinas de recetas numéricas para C y C ++

http://www.nrbook.com/nr3/ utilizando sus rutinas con licencia dmatrix y MatDoub respectivamente

dmatrix utiliza el operador malloc de sintaxis desactualizado y no se recomienda ... MatDoub usa el nuevo comando

La velocidad en segundos está en la versión de lanzamiento:

Aumento: 0.437

Nativo: 0.032

Recetas numéricas C: 0.031

Recetas numéricas C ++: 0.031

Entonces, desde el blitz anterior parece la mejor alternativa gratuita.

He compilado el código (con ligeras modificaciones) en virtud de VC++ 2010 con la optimización activada ("Maximizar la Velocidad", junto con inline "Adecuado" funciones " y "Favorecer el código rápido") y consiguió veces 0.015/0.391.He generado asamblea de la lista y, a pesar de que soy un terrible asamblea noob, hay una línea en el interior del aumento de la medición de bucle que no se ve bien para mí:

call    ??A?$multi_array_ref@N$01@boost@@QAE?AV?$sub_array@N$00@multi_array@detail@1@H@Z ; boost::multi_array_ref<double,2>::operator[]

Uno de los [] los operadores no obtener en línea!El llamado procedimiento se realiza otra llamada, esta vez a multi_array::value_accessor_n<...>::access<...>():

call    ??$access@V?$sub_array@N$00@multi_array@detail@boost@@PAN@?$value_accessor_n@N$01@multi_array@detail@boost@@IBE?AV?$sub_array@N$00@123@U?$type@V?$sub_array@N$00@multi_array@detail@boost@@@3@HPANPBIPBH3@Z ; boost::detail::multi_array::value_accessor_n<double,2>::access<boost::detail::multi_array::sub_array<double,1>,double *>

En conjunto, los dos procedimientos son bastante un montón de código para que sólo el acceso a un único elemento de la matriz.Mi impresión general es que la biblioteca es tan complejo y de alto nivel que Visual Studio no es capaz de optimizar tanto como nos gustaría (carteles, utilizando gcc al parecer tiene mejores resultados).

En mi humilde opinión, un buen compilador que realmente debe tener entre líneas y para la optimización de los dos procedimientos - ambos son bastante cortas y directas, no contienen bucles, etc.Mucho se puede perder tiempo, simplemente en la transmisión de sus argumentos y resultados.

Como respondió rodrigob, la clave para obtener un buen rendimiento es activar la optimización adecuada (el valor predeterminado de GCC es -O0). Además, también probé con Blaze DynamicMatrix , que produjo un adicional Mejora del rendimiento del factor 2 con exactamente los mismos indicadores de optimización. https://bitbucket.org/account/user/blaze-lib/projects/ BLAZE

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top