Frage

Ich versuche, die Leistung von boost::multi_array mit nativen dynamisch zugewiesenen Arrays mit dem folgenden Testprogramm zu vergleichen:

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

Ich erhalte folgende Ergebnisse:

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

Ich kann nicht glauben, dass Multi_Arrays so viel langsamer sind.Kann jemand erkennen, was ich falsch mache?

Ich gehe davon aus, dass Caching kein Problem darstellt, da ich in den Speicher schreibe.

BEARBEITEN:Dies war ein Debug-Build.Laut Laserallans Vorschlag habe ich einen Release-Build erstellt:

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

Viel näher.Aber 16 zu 1 scheint mir immer noch zu hoch.

Nun, keine definitive Antwort, aber ich werde weitermachen und meinen echten Code vorerst bei nativen Arrays belassen.

Ich akzeptiere die Antwort von Laserallan, da sie den größten Fehler in meinem Test darstellte.

Dank an alle.

War es hilfreich?

Lösung

Bauen Sie Release oder Debug?

Wenn im Debug-Modus läuft, wird die Boost-Array könnte wirklich langsam sein, weil ihre Vorlage Magie nicht richtig inlined wird viel Aufwand in Funktionsaufrufe geben. Ich bin mir nicht sicher, wie Multi-Array implementiert ist, aber so könnte dies sein völlig aus:)

Vielleicht gibt es einige Unterschiede in der Lagerung, um auch so können Sie Ihr Bild gespeichert Spalte für Spalte könnte mit und schreiben sie Zeile für Zeile. Dies würde ein schlechtes Cache-Verhalten geben und Dinge verlangsamen.

Versuchen Sie, die Reihenfolge der X- und Y-Schleife schalten und sehen, ob Sie etwas gewinnen. Es gibt einige Informationen über die Lagerung Bestellung hier: http://www.boost.org/doc/libs /1_37_0/libs/multi_array/doc/user.html

EDIT: Da Sie die zweidimensionale Anordnung für die Bildverarbeitung zu verwenden scheinen könnten Sie bei der Prüfung steigert Bildverarbeitungsbibliothek gil .

Es könnte Arrays mit weniger Aufwand hat, die perfekt für Ihre Situation.

Andere Tipps

Auf meinem Rechner mit

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

ich

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

Allerdings const int ITERATIONS Wechsel 5000 ich

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

dann mit ITERATIONS zurück zu 500 aber X_SIZE und Y_SIZE auf 400 ich einen viel signifikanten Unterschied bekommen

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

Umkehren schließlich die innere Schleife für den [Boost] Fall so sieht es aus wie

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

und halten ITERATIONS, X_SIZE und Y_SIZE 500, 400 und 400 ich

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

Wenn ich invertieren die innere Schleife auch für den Fall [Native] (so ist es in der falschen Reihenfolge für diesen Fall), erhalte ich, wenig überraschend,

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

Ich bin mit gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 auf Ubuntu 10.10

Also abschließend:

  • Mit richtigen Optimierung boost :: multi_array macht seinen Job als erwartet
  • Die Reihenfolge, auf dem Sie auf Ihre Daten zugreifen does matter

Ihr Test ist fehlerhaft.

  • In einem DEBUG Build boost :: Multiarray fehlt die Optimierung Pass, der es dringend braucht. (Viel mehr als eine native Array würde)
  • In einem RELEASE-Build, den Compiler wird für Code suchen, das völlig entfernt werden kann und die meisten Code ist in dieser Kategorie .

Was Sie wahrscheinlich seeing das Ergebnis Ihrer optimierenden Compiler ist zu sehen, dass die meisten oder alle Ihre „native Array“ Schleifen entfernt werden kann. Das gleiche theoretisch gilt für Ihre boost :: Multiarray-Schleifen, aber Multiarray ist wahrscheinlich komplex genug, um Ihre Optimierer zu besiegen.

Machen Sie diese kleine Änderung Ihrer Testbed und Sie werden mehr true-to-life Ergebnisse sehen: Ändern Sie beide Vorkommen von „= 2.345“ mit „*= 2.345“ und kompilieren wieder mit Optimierungen. Dadurch wird der Compiler aus der Entdeckung, dass die äußere Schleife von jeder Test ist überflüssig zu verhindern.

habe ich es und bekam einen Geschwindigkeitsvergleich näher. 2: 1

Ich frage mich zwei Dinge:

1) Grenzen überprüfen: definieren den BOOST_DISABLE_ASSERTS Präprozessormakro vor multi_array.hpp in Ihrer Anwendung inklusive. Dies schaltet die gebundene Prüfung. nicht sicher, ob dies das deaktiviert ist, wenn NDEBUG ist.

2) Basisindex:  Multiarray kann Index-Arrays von Basen von 0 verschieden Das bedeutet, dass multi_array speichert eine Basiszahl (in jeder Dimension) und verwendet eine kompliziertere Formel, die genaue Stelle im Speicher zu erhalten, ich frage mich, ob es überhaupt das ist.

Ansonsten verstehe ich nicht, warum Multiarray langsamer als C-Arrays sein sollte.

Betrachten Blitz ++ verwenden statt. Ich habe versucht, aus Blitz und seine Leistung auf dem Niveau C-Stil-Array!

Schauen Sie sich Ihren Code mit Blitz aufgenommen unter:


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

Hier ist das Ergebnis in Debug- und Release.

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

I verwendet MSVC 2008 SP1-Compiler für diese.

Können wir jetzt sagen Adieu C-stlye Array? = P

Ich war auf diese Frage suchen, weil ich die gleiche Frage hatte. Ich hatte ein paar Gedanken einen strengeren Test zu geben.

  1. Wie rodrigob wies darauf hin, gibt es Mängel in der Schleife um, so dass alle Ergebnisse in dem Code, den Sie ursprünglich angebracht wird irreführende Daten geben
  2. Auch gibt es eher kleine Größe Arrays, die unter Verwendung von Konstanten festgelegt werden. Der Compiler kann die Schleifen optimieren aus, wenn sie in Wirklichkeit wird der Compiler nicht die Größe der Arrays kennen. Die Größen der Felder und die Anzahl der Iterationen sollten Runtime-Eingänge für alle Fälle sein.

Auf einem Mac wird der folgende Code konfiguriert aussagekräftigere Antworten zu geben. Es gibt 4 Tests hier.

#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. Ein mit nur einem einzigen eindimensionalen Array mit dem [] mit ganzzahligen Mathematik und einem Doppel-Loop

  2. mit dem gleichen eindimensionalen Array Zeiger inkrementiert

  3. Eine mehrdimensionale Array C

  4. A boost multi_array

so von einer Befehlszeile laufen, laufen

./test_array xsize ysize iterations"

und Sie können eine gute Vorstellung davon, wie diese Ansätze durchführen wird. Hier ist, was ich mit dem folgenden Compiler-Flags bekommen:

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

Also, ich glaube, dass es sicher ist zu sagen, dass der Schub multi_array ziemlich gut durchführt. Nichts geht über eine einzige Schleife Auswertung, sondern in Abhängigkeit von der Dimension des Arrays, die boost :: multi_array können einen Standard-C-Array mit einer doppelten Schleife schlagen.

Eine andere Sache, zu versuchen, Iteratoren statt einer geraden Index für die Boost-Array zu verwenden.

Ich habe erwartet, Multiarray genauso effizient. Aber ich bin immer ähnliche Ergebnisse auf einem PPC Mac gcc verwenden. Ich habe auch versucht multiarrayref, so dass beide Versionen die gleiche Lagerung ohne Unterschied verwendet wurden. Das ist gut zu wissen, da ich Multiarray in einigen meiner Code verwenden und einfach angenommen, war es ähnlich wie Hand-Codierung.

Ich glaube, ich weiß, wo das Problem liegt ... vielleicht.

Damit die Boost-Implementierung eine Syntax wie folgt hat:Matrix[x][y].Das bedeutet, dass Matrix[x] einen Verweis auf ein Objekt zurückgeben muss, das sich wie ein 1D-Array verhält Spalte, an diesem Punkt gibt Ihnen reference[y] Ihr Element.

Das Problem hierbei ist, dass Sie iterieren Reihe Major Reihenfolge (was in c/c++ typisch ist, da native Arrays zeilenmajor IIRC sind).Der Compiler muss in diesem Fall Matrix[x] für jedes y erneut ausführen.Wenn Sie bei Verwendung der Boost-Matrix in der Hauptreihenfolge der Spalten iteriert haben, erzielen Sie möglicherweise eine bessere Leistung.

Nur eine Theorie.

BEARBEITEN:Auf meinem Linux-System (mit einigen geringfügigen Änderungen) habe ich meine Theorie getestet und gezeigt manche Leistungsverbesserung durch Vertauschen von x und y, aber es war immer noch langsamer als ein natives Array.Dies könnte ein einfaches Problem sein, weil der Compiler den temporären Referenztyp nicht wegoptimieren kann.

Erstellen Sie im Release-Modus, verwenden Sie objdump, und bei der Montage aussehen. Sie können dabei völlig unterschiedliche Dinge, und Sie werden in der Lage zu sehen, welche Optimierungen der Compiler verwendet wird.

Eine ähnliche Frage wurde gestellt und beantwortet hier:

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

Die kurze Antwort ist, dass es am einfachsten ist der Compiler der einfachen Arrays zu optimieren, und nicht so einfach, die Boost-Version zu optimieren. Daher kann eine bestimmte Compiler nicht die Boost-Version die gleichen Optimierungs Vorteile geben kann.

Compiler kann auch variieren in wie gut optimieren sie gegen, wie konservativ sie (zum Beispiel mit Templat-Code oder anderen Komplikationen) sein wird.

ich getestet auf einem Snow Leopard Mac OS mit 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

Hier wird der Code (modifiziert, so dass es auf Unix kompiliert werden):

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

bei der Montage der Suche nach g erzeugt ++ 4.8.2 mit -O3 -DBOOST_DISABLE_ASSERTS und sowohl mit dem operator() und die [][] Möglichkeiten, Elemente zuzugreifen, ist es offensichtlich, dass die einzige zusätzliche Operation im Vergleich zu nativen Arrays und manueller Indexberechnung ist die Zugabe der Base. Ich habe nicht die Kosten dieser obwohl messen.

I modifizierte, um den obigen Code in Visual Studio 2008 v9.0.21022 und angewandt, um die Container-Routinen von den numerischen Rezepte Routinen für C und C ++

http://www.nrbook.com/nr3/ ihre lizenzierten Routinen dmatrix mit und MatDoub jeweils

dmatrix verwendet die aus Syntax malloc Operator Datum und ist nicht zu empfehlen ... MatDoub verwendet den Befehl Neu

Die Geschwindigkeit in Sekunden sind in Release Version:

Boost: 0.437

Native: 0,032

Numerical Recipes C: 0,031

Numerische Rezepte C ++: 0,031

So von dem oben blitz sieht aus wie die beste kostenlose Alternative.

ich den Code kompiliert haben (mit geringfügigen Änderungen) unter VC ++ 2010 mit der Optimierung auf ( „Maximize Speed“ zusammen mit inlining „jeder geeigneten“ Funktionen und „Bevorzugen schnellen Code“) drehte sich um und bekam mal 0.015 / 0.391. Ich habe Assembler-Liste erzeugt, und obwohl ich eine schreckliche Versammlung Noob bin, gibt es eine Zeile in der Boost-Messschleife, die mir nicht gut aussehen:

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[]

Einer der [] Betreiber nicht inlined bekommen! Die aufgerufene Prozedur macht einen weiteren Anruf, diesmal nach 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 *>

Insgesamt sind die beiden Verfahren ziemlich viel Code für nur ein einzelnes Element in dem Array zuzugreifen. Mein allgemeiner Eindruck ist, dass die Bibliothek so komplex ist und auf hohem Niveau, dass Visual Studio nicht in der Lage es so viel zu optimieren, wie wir möchten (Plakate mit gcc offenbar haben bessere Ergebnisse vor).

IMHO, ein guter Compiler wirklich die beiden Verfahren inlined und optimiert haben sollte - beide ziemlich kurz und geradlinig, enthalten keine Schleifen usw. Viel Zeit einfach verschwendet werden können, ihre Argumente und Ergebnisse auf vorbei.

Wie rodrigob beantwortet, die richtige Optimierung Aktivierung (GCC-Standard ist -O0) ist der Schlüssel eine gute Leistung zu erhalten. Darüber hinaus habe ich auch eine zusätzliche mit Blaze Dynamic , die getestet ergab Faktor 2 Leistungsverbesserung mit dem exakt gleichen Optimierungsflags. https://bitbucket.org/account/user/blaze-lib/projects/ BLAZE

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top