Array Klasse



  • Damit ist Shade´s Frage aber immer noch nicht beantwortet.

    Ihr driftet immer viel zu sehr nach OT ab!



  • ts::ArrayConfig::ArrayGenerator 
          <int, ts::ArrayConfig::variableSize<int>, ts::ArrayConfig::pod, ts::ArrayConfig::poly>::type 
            d;
    

    was macht das genau? wir da ein array erstellt welches polymorphe PODs verwalten soll und seine grösse dynamisch anpasst?



  • japro schrieb:

    ts::ArrayConfig::ArrayGenerator 
          <int, ts::ArrayConfig::variableSize<int>, ts::ArrayConfig::pod, ts::ArrayConfig::poly>::type 
            d;
    

    was macht das genau? wir da ein array erstellt welches polymorphe PODs verwalten soll und seine grösse dynamisch anpasst?

    ja. Wobei das polymorph bei int keinen Sinn ergibt. Polymorph und Monomorph macht nur bei Zeigern sinn.

    Der Generator hat eben den Vorteil, dass man sich nicht um die Policies selber kümmern muss (es aber kann: denn man muss ja den Generator nicht verwenden und kann die typedefs ja auch selber machen)

    Nur mit dem variable Size habe ich n Problem. Ich denke ich werde das in ein
    unsigned sizetype
    umwandeln
    mittels
    int const variableSize = 0;
    kann man dann sagen, dass man eine variable größe will. und mittels
    20 hätte man dann ein fixed array 🙂

    weiters funktioniert CopySwap() nicht korrekt.
    muss ich heute abend verbessern.

    die neue version würde dann so aussehen:

    ts::ArrayConfig::ArrayGenerator 
          <int, ts::ArrayConfig::variableSize, ts::ArrayConfig::pod, ts::ArrayConfig::poly>::type 
            d;
    

    statt mono und poly -morph könnte man noch ein nonmorph für nicht Zeiger typen einführen... oder wäre das sinnlos, da poly ja das selbe wie nonmorph machen würde...



  • Die neue Version ist online 🙂
    array.hpp

    Das swap sollte jetzt funktionieren und ausserdem sind n paar neue Methoden hinzugekommen, sowie ein kleiner performance bug bei op= wurde ausgebessert.

    Ich denke, dass ich Zeiger hinzunehmen werde - nämlich so, dass die array klasse selber die Zeiger verwalten kann - das würde smartpointer ersparen, die dann kein langsames ref counting oder ähnliches verwenden müssten.

    weiters denke ich, dass man range checks noch hinzufügen könnte. also dass der user selber sagen kann, welche exception fliegt und vorallem, ob op[] überhaupt etwas in dieser richtung machen soll... das würde dann die Methode at() ersparen, die sowieso niemand verwendet 🙂

    habt ihr noch vorschläge?

    ihr könnt auch kritik anbringen!
    ich weiss, der code ist nicht dokumentiert, aber vielleicht erbarmt sich ja doch jemand ihn durchzuackern? die nächste version wird aber kommentare haben: versprochen.

    [nachtrag:
    angepasstes code beispiel:

    #include "array.hpp"
    #include <iostream>
    using namespace std;
    
    int main()
    {
        ts::variableArray<int>::type a;
        a.push_back(7);
        a.push_back(10);
        a.push_back(9);
        a.push_front(1);
        for(int i=0; i<a.size(); ++i)
        {
            cout<<a[i]<<endl;
        }
    
        ts::variableArray<int>::type b(a);
        ts::fixedArray<int, 4>::type c(b);
        cout<<endl;
        for(int j=0; j<c.size(); ++j)
        {
            cout<<c[j]<<endl;
        }
        ts::ArrayConfig::ArrayGenerator
            <int, ts::ArrayConfig::dynamic, ts::ArrayConfig::normal, ts::ArrayConfig::poly>::type
                d;
        d=a;
        cout<<endl;
        for(int l=0; l<d.size(); ++l)
        {
            cout<<d[l]<<endl;
        }
    }
    

    ]



  • So, wieder eine neue Version.

    Diesmal hat sich viel geändert: neben ein paar bugfixen gibt es jetzt unterstützung für Zeiger!

    array.hpp

    Hier ein kleines Test programm:

    #include "array.hpp"
    #include <iostream>
    using namespace std;
    
    class Test
    {
    public:
        Test() { cout<<"ctor\n"; ctor++; }
        Test(Test const&) { cout<<"cctor\n"; ctor++; }
        ~Test() { cout<<"dtor\n";  dtor++;}
    
        static int ctor;
        static int dtor;
    };
    int Test::ctor=0;
    int Test::dtor=0;
    
    int main()
    {
        {
            //important: Test must not be a pointer!
            ts::variablePtrArray<Test>::type Arr;
            Arr.push_back(new Test());
        }
        cout<<endl<<Test::ctor<<" : "<<Test::dtor<<endl<<endl;
        //ausgabe: "2 : 2" - 2 ctors und 2 dtors calls :)
    
        ts::variableArray<int>::type a;
        a.push_back(7);
        a.push_back(10);
        a.push_back(9);
        a.push_front(1);
        for(int i=0; i<a.size(); ++i)
        {
            cout<<a[i]<<endl;
        }
    
        ts::variableArray<int>::type b(a);
        ts::fixedArray<int, 4>::type c(b);
        cout<<endl;
        for(int j=0; j<c.size(); ++j)
        {
            cout<<c[j]<<endl;
        }
        ts::ArrayConfig::ArrayGenerator
            <int, ts::ArrayConfig::dynamic, ts::ArrayConfig::normal, ts::ArrayConfig::asserting, ts::ArrayConfig::poly>::type
                d;
        d=a;
        cout<<endl;
        for(int l=0; l<d.size(); ++l)
        {
            cout<<d[l]<<endl;
        }
    }
    

    die unterstützung für Zeiger ist n bisschen kompliziert implementiert, denn ich wollte die geschwindigkeit des bestehenden codes nicht verlangsamen.
    ein std::copy bzw. std::memcpy ist natürlich schneller als eine Schleife - deshalb gibt es für die Kopierer und Allokatoren jeweils auch eine Pointer-Variante.

    Das macht die Sache zwar etwas komplexer, aber dafür ist es schön schnell...



  • neue Version: array.hpp

    kleine Bugfixes und ein bisschen das Interface an die STL angepasst.
    IfThenElse wurde ausgelagert (if.hpp).

    Ich habe auch ein paar kleine Performancetests gegen die VC++7 Standard Library laufen lassen. Mein variableArray war immer eine spur schneller - allerdings waren die Beispiele nicht praxisrelevant.

    Aber ich bin zufrieden, denn mein variableArray ist also nicht signifikant langsamer als die VC++7 STL. Wenn jemand gegen STLPort testen könnte?

    Ich glaube ich werde bei Zeiten mal eine handvall anderer Container auf diese Art implementieren...

    Schade dass es so wenig Antworten von euch gibt - aber wenigstens keine Negativen. Also nehme ich an, dass es kein allzugroßer Käse ist, den ich hier mache.



  • Hallo!

    Um ganz ehrlich zu sein habe ich für meinen Teil hier nur nicht geantwortet weil ich stark bezweifle dass ich Dir helfen könnte.

    edit: Ich werde aber gerne im Laufe des Tages mal ein paar Tests mit STLport und gcc machen und dann die Resultate posten!



  • @nman:
    thx.

    Es war ja auch kein Vorwurf, sondern eine Feststellung 🙂

    btw: neue Version: array.hpp und if.hpp

    Ich habe neben ein paar bugfixes auch eine Verbesserung vorgenommen: eine Grow-Optionen.

    Man kann nun angeben ob das Array schnell wachsen soll (also Speicher 'verschwenden' um wenige Allokationen zu haben), normal wachsen soll (ungefähr so wie bisher) oder langsam wachsen soll (keinen Speicher zuviel allokieren -> Speicher sparen, dafür mehr Allokationen)

    ich hoffe es läuft auf dem gcc - denn momentan entwickle ich nur auf dem VC++7 😞



  • Dieser Beitrag wurde gelöscht!


  • Ich habe gerade die Version für gcc (3.2.3) und Comeau 4.3.3 BETA fertig 🙂
    blöde typenames und templates und this-> haben gefehlt...

    Danke für die Fehlerliste. Theoretisch müsste es jetzt passen!



  • Mein g++ kompiliert das jetzt tatsächlich.
    Jetzt stellt sich mir nur die Frage wie ich das testen soll, immerhin habe ich kein VC++7 als Vergleichsmöglichkeit...



  • nman schrieb:

    Mein g++ kompiliert das jetzt tatsächlich.
    Jetzt stellt sich mir nur die Frage wie ich das testen soll, immerhin habe ich kein VC++7 als Vergleichsmöglichkeit...

    Für mich sind nur die Ergebnisse im Vergleich zu anderen Standardlibraries interessant. Also schreib n kleines Programm, zB sowas:

    #include "array.hpp"
    
    #include <windows.h>
    #include <vector>
    #include <iostream>
    using namespace std;
    
    int const loop=10000000;
    
    int stdVector()
    {
      vector<int> vec;
      int size=0;
    
      for(int i=0; i<loop; ++i)
      {
        vec.push_back(i);
        size+=vec.size();
      }
    
      while(!vec.empty())
      {
        vec.pop_back();
        size+=vec.size();
      }
      return size;
    }
    
    int myVector()
    {
      ts::variablePodArray<int>::type vec;
      int size=0;
    
      for(int i=0; i<loop; ++i)
      {
        vec.push_back(i);
        size+=vec.size();
      }
    
      while(!vec.empty())
      {
        vec.pop_back();
        size+=vec.size();
      }
      return size;
    }
    
    int main()
    {
      cout<<"start\n";
      int size;
      DWORD start=GetTickCount();
      size=stdVector();
      DWORD end=GetTickCount();
      cout<<size<<endl;
      cout<<end-start<<endl;
      start=GetTickCount();
      size=myVector();
      end=GetTickCount();
      cout<<size<<endl;
      cout<<end-start<<endl;
    }
    

    und schau nach, wie sich mein Array gegen deine STL verhält.
    Auf meinem gcc (MinGW 3.2.3) schauts momentan schlecht aus 😞

    Wenn du auch die Standard STL hast die beim gcc dabei ist, dann Danke für die Mühe - aber die habe ich jetzt auch.

    Wenn du STLPort oder ähnliches hast - nur her mit den Tests 🙂



  • Bei meinem Test hängt alles an von Grower ab. Wenn er schnellt wächst ist meine Version schneller, wenn ich langsamer wachse, dann die STL.

    Ich muss mich wohl mal eingehender mit einem passenden Wachstumsalgo rumschlagen. Aber das pop_back() ist bei mir schneller als bei der STL - wie das wohl kommt?



  • Shade Of Mine schrieb:

    Für mich sind nur die Ergebnisse im Vergleich zu anderen Standardlibraries interessant. [...] schau nach, wie sich mein Array gegen deine STL verhält.

    Ah OK, ich dachte Du willst wissen wie sich die Performance mit unterschiedlichen Compilern verändert.

    Wenn du auch die Standard STL hast die beim gcc dabei ist, dann Danke für die Mühe - aber die habe ich jetzt auch.

    Wenn du STLPort oder ähnliches hast - nur her mit den Tests 🙂

    Ich habe auch STLport, muss aber wieder mal updaten, meine Version ist nicht mehr ganz taufrisch...



  • Hm, beim STLport kompilieren swappt mein Rechner leider so schlimm dass er absolut unbenutzbar wird, muss wohl noch etwas warten... 😞

    edit: Nachdem ich allerdings schon begonnen hatte die Zeit zu stoppen hier trotzdem das (unnütze) Ergebnis:

    nman: ~/c++/shadesArray > uname -a
    Linux method 2.6.0 #2 Mon Dec 22 23:45:22 CET 2003 i686 AMD Athlon(tm) Processor AuthenticAMD GNU/Linux
    nman: ~/c++/shadesArray > gcc -dumpversion
    3.2.3
    nman: ~/c++/shadesArray > echo $CXXFLAGS
    -march=athlon -O2 -pipe -fomit-frame-pointer -w
    nman: ~/c++/shadesArray > g++ -o stdArray stdArray.cpp ${CXXFLAGS}
    nman: ~/c++/shadesArray > g++ -o shadesArray shadesArray.cpp ${CXXFLAGS}
    nman: ~/c++/shadesArray > time ./stdArray
    276447232
    real    0m1.866s
    user    0m0.956s
    sys     0m0.308s
    nman: ~/c++/shadesArray > time ./shadesArray
    276447232
    real    0m6.878s
    user    0m3.947s
    sys     0m0.807s
    nman: ~/c++/shadesArray >
    


  • thx!

    ich liebe time - schade das windows sowas nicht hat 😞

    Bin auf einen Bug in erase() draufgekommen, dadurch wurde das pop_back() ziemlich lahm (und eigentlich Undefiniertes Verhalten verursacht)

    Weiters hängt es auch stark von den Allokierungsmethoden ab. Wenn ich zB den Block immer verdopple (so wie die STL) dann schaut das push_back auch shcon besser aus... Jetzt noch einen großen Block im Default Ctor allokieren und die Sache schaut gut aus...

    Muss mir mal eine gute Standardgröße überlegen... Momentan habe ich die Standardgröße auf 500 Elemente eingestellt - dies scheint mir bei den meisten meiner Programme eine passende größe zu sein. Die STL arbeitet aber scheinbar mit mehr...

    naja, so far: hier die neue Version: array.hpp und if.hpp



  • Hm, wo ist denn der util-Namespace? 🙄



  • nman schrieb:

    Hm, wo ist denn der util-Namespace? 🙄

    ups. sorry. Da habe ich wohl vergessen if.hpp zuuploaden :o

    IfThenElse habe ich in den util Namespace verschoben, weil ich vorhabe das ganze vielleicht auszubauen...

    Jetzt müsste if.hpp auch passen.

    sorry für die vergesslichkeit!



  • Shade Of Mine schrieb:

    IfThenElse habe ich in den util Namespace verschoben, weil ich vorhabe das ganze vielleicht auszubauen...

    Ich habs gesehen, bin schon gespannt! 🙂

    Jetzt müsste if.hpp auch passen.
    sorry für die vergesslichkeit!

    Tut es; kein Problem!

    nman: ~/c++/shadesArray > time ./shadesArray
    276447232
    real    0m4.147s
    user    0m1.670s
    sys     0m0.345s
    nman: ~/c++/shadesArray > time ./stdArray
    276447232
    real    0m2.786s
    user    0m0.997s
    sys     0m0.323s
    

    Es wird besser! 👍



  • wenn du bei

    Array()
          : sizeClass(500)
          {
            sizeClass.setSize(0);
            Allocator::allocate(value, sizeClass.getAlloc());
          }
    

    die 500 durch zB 1000 oder 1500 ersetzt, müsste mein Array schneller sein.

    aber wie gesagt, ich bin erst auf der suche nach einem vernünftigen startwert.

    ansonsten wäre es wohl am besten am anfang .reserve() aufzurufen - so dass die allokationen keinen unterschied mehr ausmachen.

    danke für die tests! 👍 👍


Anmelden zum Antworten