Wie übergebe ich ein mehrdimensionales Array mittels Pointer (Heap )?



  • Leider geht es um eine Echtzeitanwendung. Arrays sind schneller als STL container.



  • goran schrieb:

    Leider geht es um eine Echtzeitanwendung. Arrays sind schneller als STL container.

    Bullshit.



  • Doch, arrays sind schneller. Probiere mal das hier

    #include <iostream>
    #include <boost/multi_array.hpp>
    
    #define ROW 10000
    #define COL 10000
    
    int main ()
    {
      // 2 dimensional array
      int (*A)[COL] = new (int[ROW][COL]);
      std::cout << "array start\n";
      for(int i=0; i<ROW; ++i)
      {
        for(int j=0; j<COL; ++j)
        {
          A[i][j] += 1;
        }
      }
      std::cout << "array stop\n";
    
      // 2 dimensional boost::multi_array
      typedef boost::multi_array<int, 2> array_type;
      array_type B(boost::extents[ROW][COL]);
      std::cout << "boost::muti_array start\n";
      for(int i=0; i<ROW; ++i)
      {
        for(int j=0; j<COL; ++j)
        {
          B[i][j] += 1;
        }
      }
      std::cout << "boost::multi_array stop\n";
      return 0;
    }
    

    Der boost::multi_array container kann bei weitem nicht mithalten.



  • hmmm, wenn du eine fixe größe verwendest sind sie wirklich langsamer?(also ohne push_back).
    Naja, musst du nicht bei deiner Eingangsfunktion nen Zeiger auf Zeiger übergeben oO also int **array2d



  • goran schrieb:

    Der boost::multi_array container kann bei weitem nicht mithalten.

    Wer hat denn von Boost gesprochen? Es ist ein bekanntes Problem, dass multi_array häufig nicht vom Compiler optimiert wird.

    goran schrieb:

    Leider geht es um eine Echtzeitanwendung. Arrays sind schneller als STL container.

    Benutz am besten C-Kommentare /* .. */ , die werden in Echtzeitanwendungen schneller übersprungen als // .



  • OK, jetzt habe ich's begriffen. Ein verschachtelter std::vector mit fixer länge ist wirklich sehr gut. Das habe ich nicht gewusst 👍

    #include <iostream>
    #include <vector>
    #include <ctime>
    
    #define ROW 10000
    #define COL 10000
    
    int main ()
    {
      clock_t t1, t2;
    
      /* 2 dimensional array */
      int (*A)[COL] = new (int[ROW][COL]);
      std::cout << "array start\n";
      t1 = clock();
      for(int i=0; i<ROW; ++i)
      {
        for(int j=0; j<COL; ++j)
        {
          A[i][j] += 1;
        }
      }
      t2 = clock();
      std::cout << "time: " << double(t2-t1) / CLOCKS_PER_SEC << "\n";
      std::cout << "array stop\n";
    
      /* 2 dimensional std::vector<std::vector<int> > */
      std::vector<std::vector<int> > B(ROW,std::vector<int>(COL));
      std::cout << "std::vector start\n";
      t1 = clock();
      for(int i=0; i<ROW; ++i)
      {
        for(int j=0; j<COL; ++j)
        {
          B[i][j] += 1;
        }
      }
      t2 = clock();
      std::cout << "time: " << double(t2-t1) / CLOCKS_PER_SEC << "\n";
      std::cout << "std::vector stop\n";
      return 0;
    }
    

    Besten Dank!



  • Nimm einen eindimensionalen vector und rechne die Indizes um, dann bist du nochmal schneller.



  • 314159265358979 schrieb:

    Nimm einen eindimensionalen vector und rechne die Indizes um, dann bist du nochmal schneller.

    Die Kritik ist berechtigt. In meinem spez. Fall muss ich für jedes Element der 2 dim. Matritze die umliegenden acht berücksichtigen.

    Welches Vorgehen das bessere ist werde ich testen.

    Allen recht herzlichen Dank! 👍



  • Wie mache ich das mit dem schnellen Vector so wie PI's vorgeschlagen hatte? Ich stehe auf dem Schlauch gerade.

    #include <iostream>
    #include <vector> 
    
    void vec_output( int ( *myarray )[ 3 ], int x, int y );
    
    int main( int argc, char* argv[ ] )
    {
    	const int x = 3;
    	const int y = 3;
    
    	int ( *i )[ y ] = new int[ x ][ y ]; 
    
    	memset( i, 0, x * y * sizeof( int ) );
    
    	vec_output( i, x, y );
    
    	delete[ ] i;
    
    	std::vector< int >myvec( x );
    
    	std::fill( myvec.begin( ), myvec.end( ), 10 );
    
    	for( std::vector< int >::iterator x = myvec.begin( ); x != myvec.end( ); ++x )
    	{
    		std::cout << *x << std::endl;
    	}
    
    	return 0;
    }
    
    void vec_output( int ( *myarray )[ 3 ], int x, int y )
    {
    	for( int r = 0; r < x; ++r )
    	{
    		for ( int b = 0; b < y; ++b )
    		{
    			std::cout << myarray[ r ][ b ] << "	";
    		}
    		std::cout << std::endl;
    	}
    }
    

  • Mod

    Lass mal den ganzen new-Mist sein. Wenn du überhaupt new benutzt, dann kapselt man das in einer Klasse. Und new[] (also mit Arrays) gibt es schon als fertige Klasse: std::vector. Alles was new[] kann, ohne Nachteile*, dafür mit mehr Funktionalität.

    Genauso baust du dein 2D-Array. Etwas Inspiration:

    #include <vector>
    
    template<class T> class Array2D
    {
      std::vector<T> data;
      std::size_t sx, sy;
     public:
      Array2D(std::size_t x, std::size_t y): data(x*y), sx(x), sy(y) {}
      const T& operator()(std::size_t x, std::size_t y) const {return data[x*size_y() + y];}
      T& operator()(std::size_t x, std::size_t y){return data[x*size_y() + y];}
      std::size_t size_x() const {return sx;}
      std::size_t size_y() const {return sy;}
    
      typedef typename std::vector<T>::iterator iterator;
      typedef typename std::vector<T>::const_iterator const_iterator;
    
      iterator begin() {return data.begin();}
      const_iterator begin() const {return data.begin();}
      const_iterator cbegin() const {return data.begin();}
      iterator end() {return data.end();}
      const_iterator end() const {return data.end();}
      const_iterator cend() const {return data.end();}
    };
    
    #include <iostream>
    using namespace std;
    
    void TuWas(const Array2D<int>& foo)
    {
      for(size_t x = 0; x < foo.size_x(); ++x)
        {
          for(size_t y = 0; y < foo.size_y(); ++y)
            cout << foo(x,y) << ' ';
          cout << '\n';
        }
    }
    
    int main()
    {
      Array2D<int> foo(5,10);
    
      for(Array2D<int>::iterator it = foo.begin(), end = foo.end(); it != end; ++it)
        *it = it - foo.begin();
    
      TuWas(foo);
    }
    

    Dieses kleine Klässchen kann sich kaum Beispiel nennen, ist aber schon ziemlich funktional, wie du siehst. Und du wirst auch messen, dass dies (bei eingeschalteter Compileroptimierung) geschwindigkeitsmäßig die verschachtelten dynamischen Arrays weit abhängt (es kann ja auch weniger, da hier die innere Dimension über alle Zeilen gleich sein muss). Und es kann leicht erweitert werden für ein vollständiges STL-artiges Interface. Bloß Den Operator[] kann man leider nicht für zwei Argumente überladen, daher die Krücke mit dem Operator() 😞 .

    P.S.: Bei genauerem Nachdenken wäre hier tatsächlich mal ein sinnvoller Einsatzort für private-Vererbung. Da würde man dann im Array2D vom vector erben.

    *: Ja, sizeof(vector) wird ein paar Byte mehr sein als sizeof(pointer) + sizeof(size_t) was man beim ganz naiven new[] hätte (i.d.R ist ein vector drei Pointer (anfang, ende_daten, ende_allokiert) groß). Aber ist das ein echter Nachteil? Man erstellt schließlich selten(=nie) so viele einzelne vectoren, dass das relevant werden könnte. Dafür kann der vector seine Größe ändern, was beim naiven new[] extrem umständlich wäre (daher macht der vector es intern ja auch nicht naiv).



  • Vielen Dank SeppJ! Gutes Beispiel 😛

    MfG


Anmelden zum Antworten