Domanda

Sto cercando di confrontare le prestazioni di boost :: multi_array con array allocati dinamicamente nativi, con il seguente programma di test:

#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;
}

Ottengo i seguenti risultati:

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

Non riesco a credere che i multi_arrays siano molto più lenti. Qualcuno può individuare ciò che sto facendo di sbagliato?

Suppongo che la memorizzazione nella cache non sia un problema poiché sto scrivendo nella memoria.

EDIT: questa era una build di debug. Secondo il suggerimento di Laserallan, ho realizzato una build di rilascio:

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

Molto più vicino. Ma il 16 a 1 mi sembra ancora troppo alto.

Beh, nessuna risposta definitiva, ma per ora andrò avanti e lascerò il mio vero codice con array nativi.

Accettare la risposta di Laserallan perché è stato il più grande difetto del mio test.

Grazie a tutti.

È stato utile?

Soluzione

Stai creando release o debug?

Se in esecuzione in modalità debug, l'array boost potrebbe essere molto lento perché la loro magia del modello non è correttamente incorporata, generando un sacco di sovraccarico nelle chiamate di funzione. Non sono sicuro di come sia implementato il multi array, quindi potrebbe essere totalmente spento :)

Forse c'è anche qualche differenza nell'ordine di archiviazione, quindi potresti avere l'immagine memorizzata colonna per colonna e scriverla riga per riga. Ciò darebbe uno scarso comportamento della cache e potrebbe rallentare le cose.

Prova a cambiare l'ordine dei loop X e Y e vedi se guadagni qualcosa. Ci sono alcune informazioni sull'ordine di archiviazione qui: http://www.boost.org/doc/libs /1_37_0/libs/multi_array/doc/user.html

EDIT: Dal momento che sembra che tu stia utilizzando l'array bidimensionale per l'elaborazione delle immagini, potresti essere interessato a dare un'occhiata alla libreria di elaborazione delle immagini di boost gil .

Potrebbe avere array con meno sovraccarico che funziona perfettamente per la tua situazione.

Altri suggerimenti

Sulla mia macchina usando

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

Ottengo

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

Comunque cambiando const int ITERATIONS in 5000 Ottengo

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

quindi con ITERATIONS di nuovo su 500 ma X_SIZE e Y_SIZE impostato su 400 Ottengo una differenza molto più significativa

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

invertendo infine il ciclo interno per il caso [Boost] in modo che appaia

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

e mantenendo [Native], gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 e <=> su <=>, <=> e <=> ottengo

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

Se invertisco il ciclo interno anche per il caso <=> (quindi è nell'ordine sbagliato per quel caso), ottengo, ovviamente,

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

Sto usando <=> su Ubuntu 10.10

Quindi in conclusione:

  • Con corretta ottimizzazione boost :: multi_array fa il suo lavoro come previsto
  • L'ordine con cui accedi ai tuoi dati è importante

Il tuo test è difettoso.

  • In una build DEBUG, boost :: MultiArray manca del passaggio di ottimizzazione di cui ha gravemente bisogno. (Molto più di un array nativo)
  • In una build RELEASE, il compilatore cercherà il codice che può essere rimosso completamente e la maggior parte del codice è in quella categoria .

Quello che probabilmente vedrai è il risultato del tuo compilatore ottimizzante visto che la maggior parte o tutta la tua " matrice nativa " i loop possono essere rimossi. Lo stesso vale teoricamente per il tuo boost: i loop MultiArray, ma MultiArray è probabilmente abbastanza complesso da sconfiggere il tuo ottimizzatore.

Apporta questa piccola modifica al tuo banco di prova e vedrai risultati più realistici: modifica entrambe le occorrenze di " = 2.345 " con " *= 2.345 " e compilare nuovamente con ottimizzazioni. Ciò impedirà al compilatore di scoprire che il loop esterno di ciascun test è ridondante.

L'ho fatto e ho ottenuto un confronto della velocità più vicino a 2: 1.

Mi chiedo due cose:

1) controllo limiti: definire la macro del preprocessore BOOST_DISABLE_ASSERTS prima di includere multi_array.hpp nell'applicazione. Questo disattiva il controllo associato. non sono sicuro che ciò sia disabilitato quando NDEBUG è.

2) indice di base:  MultiArray è in grado di indicizzare matrici da basi diverse da 0. Ciò significa che multi_array memorizza un numero di base (in ogni dimensione) e utilizza una formula più complicata per ottenere la posizione esatta in memoria, mi chiedo se si tratti di tutto ciò.

Altrimenti non capisco perché il multiarray dovrebbe essere più lento degli array C.

Valuta invece di usare Blitz ++. Ho provato Blitz e le sue prestazioni sono alla pari con l'array in stile C!

Controlla il tuo codice con Blitz aggiunto di seguito:


#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;
}

Ecco il risultato nel debug e nel rilascio.

DEBUG:

Boost  2.093 secs 
Blitz  0.375 secs 
Native 0.078 secs

RELEASE:

Boost  0.266 secs
Blitz  0.016 secs
Native 0.015 secs

Ho usato il compilatore MSVC 2008 SP1 per questo.

Ora possiamo dire addio all'array C-stlye? = P

Stavo guardando questa domanda perché avevo la stessa domanda. Ho pensato di fare un test più rigoroso.

  1. Come sottolineato da rodrigob , ci sono difetti nell'ordine del ciclo in modo tale che qualsiasi risultato nel codice che hai originariamente allegato fornirà dati fuorvianti
  2. Inoltre, ci sono matrici di dimensioni piuttosto piccole che vengono impostate usando costanti. Il compilatore può essere ottimizzato per i loop, quando in realtà il compilatore non conoscerà la dimensione degli array. Le dimensioni degli array e il numero di iterazioni dovrebbero essere input di runtime per ogni evenienza.

Su un Mac, il seguente codice è configurato per fornire risposte più significative. Ci sono 4 test qui.

#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 un solo array monodimensionale che utilizza [] con matematica integer e un doppio loop

  2. Uno con lo stesso array monodimensionale che utilizza l'incremento del puntatore

  3. Un array C multidimensionale

  4. Un boost multi_array

quindi esegui da una riga di comando, esegui

./test_array xsize ysize iterations"

e puoi avere una buona idea di come funzioneranno questi approcci. Ecco cosa ho ottenuto con i seguenti flag del compilatore:

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

Quindi, penso che sia sicuro dire che il boost multi_array funziona abbastanza bene. Niente batte una valutazione a singolo loop, ma a seconda della dimensione dell'array, boost :: multi_array può battere un c-array standard con un doppio loop.

Un'altra cosa da provare è usare gli iteratori invece di un indice diretto per l'array boost.

Mi sarei aspettato che il multiarray fosse altrettanto efficiente. Ma sto ottenendo risultati simili su un Mac PPC usando gcc. Ho anche provato multiarray, quindi entrambe le versioni utilizzavano lo stesso spazio di archiviazione senza alcuna differenza. Questo è buono a sapersi, dal momento che utilizzo il multiarray in alcuni dei miei codici e ho appena pensato che fosse simile alla codifica manuale.

Penso di sapere qual è il problema ... forse.

Affinché l'implementazione del boost abbia una sintassi come: matrix [x] [y]. ciò significa che la matrice [x] deve restituire un riferimento a un oggetto che agisce come una matrice 1D colonna , a quel punto il riferimento [y] ti dà il tuo elemento.

Il problema qui è che stai iterando nell'ordine riga maggiore (che è tipico in c / c ++ poiché le matrici native sono IIRC di riga maggiore. Il compilatore deve rieseguire la matrice [x] per ciascuno in questo caso. Se hai ripetuto l'ordine della colonna durante l'utilizzo della matrice boost, potresti vedere prestazioni migliori.

Solo una teoria.

EDIT: sul mio sistema Linux (con alcune piccole modifiche) ho testato la mia teoria e ho mostrato alcuni miglioramento delle prestazioni cambiando xey, ma era ancora più lento di un array nativo. Questo potrebbe essere un semplice problema per il compilatore che non è in grado di ottimizzare il tipo di riferimento temporaneo.

Crea in modalità di rilascio, usa objdump e guarda l'assemblaggio. Potrebbero fare cose completamente diverse e sarai in grado di vedere quali ottimizzazioni sta utilizzando il compilatore.

Una domanda simile è stata posta e ha risposto qui:

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

La risposta breve è che per il compilatore è più semplice ottimizzare i semplici array e non è così facile ottimizzare la versione di Boost. Pertanto, un compilatore particolare potrebbe non offrire alla versione Boost tutti gli stessi vantaggi di ottimizzazione.

I compilatori possono anche variare nel modo in cui ottimizzeranno rispetto a quanto saranno conservatori (ad esempio con codice basato su modelli o altre complicazioni).

Ho provato su 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

Ecco il codice (modificato in modo che possa essere compilato su 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;
}

Osservando l'assemblaggio generato da g ++ 4.8.2 con -O3 -DBOOST_DISABLE_ASSERTS e usando entrambi i modi operator() e [][] per accedere agli elementi, è evidente che l'unica operazione aggiuntiva rispetto agli array nativi e al calcolo manuale dell'indice è l'aggiunta della base. Non ho misurato il costo di questo però.

Ho modificato il codice sopra in Visual Studio 2008 v9.0.21022 e ho applicato le routine del contenitore dalle routine di Ricetta numerica per C e C ++

http://www.nrbook.com/nr3/ utilizzando le loro procedure su licenza dmatrix e MatDoub rispettivamente

dmatrix utilizza l'operatore malloc di sintassi non aggiornato e non è raccomandato ... MatDoub utilizza il nuovo comando

La velocità in secondi è nella versione di rilascio:

Boost: 0.437

Nativo: 0,032

Ricette numeriche C: 0.031

Ricette numeriche C ++: 0.031

Quindi dal blitz sopra sembra la migliore alternativa gratuita.

Ho compilato il codice (con lievi modifiche) in VC ++ 2010 con l'ottimizzazione attivata (" Massimizza velocità " insieme alle funzioni di inclinazione " Qualsiasi adatto " e " Favorire il codice veloce ") e ottenuto tempi 0,015 / 0,391. Ho generato un elenco di assiemi e, sebbene sia un terribile noob di assemblaggio, c'è una riga all'interno del circuito di misurazione del boost che non mi sta bene:

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 degli operatori [] non è stato allineato! La procedura chiamata effettua un'altra chiamata, questa volta 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 *>

Complessivamente, le due procedure sono un sacco di codice per accedere semplicemente a un singolo elemento nell'array. La mia impressione generale è che la libreria sia così complessa e di alto livello che Visual Studio non è in grado di ottimizzarla quanto vorremmo (i poster che usano gcc apparentemente hanno ottenuto risultati migliori).

IMHO, un buon compilatore avrebbe davvero dovuto delineare e ottimizzare le due procedure: entrambe sono piuttosto brevi e dirette, non contengono alcun loop, ecc. Un sacco di tempo può essere sprecato semplicemente passando i loro argomenti e risultati.

Come ha risposto rodrigob, l'attivazione della corretta ottimizzazione (il valore predefinito di GCC è -O0) è la chiave per ottenere buone prestazioni. Inoltre, ho anche testato con Blaze DynamicMatrix , che ha prodotto un ulteriore miglioramento delle prestazioni del fattore 2 con gli stessi identici flag di ottimizzazione. https://bitbucket.org/account/user/blaze-lib/projects/ BLAZE

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top