memset um ein array zu flushen



  • Ich bin gerade auf der Suche nach Optimierungen für meine Matrizenfunktionen.

    Ich muss in einem Programm oft flushen (Matrix mit Nullen besetzen).

    Jetzt bin ich auf memset gekommen

    // ganze Matrix
    memset(N,0x00,nsize_t);
    // Teilmatrix
    memset(N+offset,0x00,nsize_t);
    

    Funktionieren tut es soweit gut. Bekomme ich irgendwo Probleme?



  • solange du die grenzen richtig einhälst sollte eigentlich alles gehen
    abgesehen davon, dass die funktion C ist statt C++



  • Skym0sh0 schrieb:

    solange du die grenzen richtig einhälst sollte eigentlich alles gehen
    abgesehen davon, dass die funktion C ist statt C++

    Danke für deine Antwort
    Gibt es so etwas für C++?



  • Wieso nicht einfach die Member auf 0 setzen?



  • asdsad schrieb:

    Gibt es so etwas für C++?

    memset sollte eigentlich auch in C++ gehen, nur muss man den Header <cstring> und den Namensbereich std verwenden.



  • EOutOfResources schrieb:

    Wieso nicht einfach die Member auf 0 setzen?

    Die Matrix wird noch gebraucht.



  • wenn du in deiner matrix nicht mit POD's arbeitest, kannst du dir ja mal std::fill angucken.



  • Natürlich geht memset in C++. Du kannst auch mal in deine Implementierung gucken, normalerweise benutzen einige Überladungen von STL Funktionen (z.B. std::fill, std::copy ...) die memset, memcpy und co. Da die am besten wissen, was auf dem jeweiligen System sicher ist, würde ich mich immer erstmal auf die verlassen.



  • Die C-Bibliothek ist nicht umsonst dabei.;)



  • asdsad schrieb:

    Funktionieren tut es soweit gut. Bekomme ich irgendwo Probleme?

    Kannste machen, kannste aber auch lassen. Es kommt der gleiche Code raus, wenn Du mit einer for-Schleife auf 0 setzt.



  • volkard schrieb:

    asdsad schrieb:

    Funktionieren tut es soweit gut. Bekomme ich irgendwo Probleme?

    Kannste machen, kannste aber auch lassen. Es kommt der gleiche Code raus, wenn Du mit einer for-Schleife auf 0 setzt.

    Na, die C-Funktionen sind teilweise schon sehr gut zu optimieren.
    Zum Beispiel ist ein memcpy mit SSE-Registern umgesetzt oft mindestens 6x so schnell wie eine for-Schleife.



  • Ethon schrieb:

    volkard schrieb:

    asdsad schrieb:

    Funktionieren tut es soweit gut. Bekomme ich irgendwo Probleme?

    Kannste machen, kannste aber auch lassen. Es kommt der gleiche Code raus, wenn Du mit einer for-Schleife auf 0 setzt.

    Na, die C-Funktionen sind teilweise schon sehr gut zu optimieren.
    Zum Beispiel ist ein memcpy mit SSE-Registern umgesetzt oft mindestens 6x so schnell wie eine for-Schleife.

    Kein Widerspruch. Die einfache for-Schleife wird vom Compiler auch optimiert zu Code mit SSE-Registern.



  • Bist du dir da sicher?
    Compiler benutzen doch sehr selten Extensions.

    Mit dieser Library hab ich für meinen Teil sowohl mit MSVC++ als auch mit gcc dramatische Performanceschübe.
    http://www.agner.org/optimize/#asmlib



  • Ethon schrieb:

    Bist du dir da sicher?

    Nein. Ich bin enttäuscht. Ist das nur auf meinem Prozessor (AMD Sempton 3000+) so müllig?

    #include <iostream>
    #include <cstring>
    using namespace std;
    
    void clearArray(double* arr,size_t size){
    //	memset(arr,0,sizeof(*arr)*5000);
    	for(int i=0; i!=5000; ++i)
    		arr[i]=0;
    }
    
    int main() {
    	double* kram=new double[10000];
    	for(int i=0;i<1000000;++i){
            clearArray(kram,5000);
            kram[rand()%10000]=1;
    	}
    	double summe=0;
    	for(int i=0; i!=10000; ++i)
    		summe+=kram[i];
        cout<<summe<<'\n';
    }
    

    4.686 Sekunden.

    Mit memset:
    1.687 Sekunden.

    Mit std::fill_n
    4.617 Sekunden.

    Ups.



  • volkard schrieb:

    Ethon schrieb:

    Bist du dir da sicher?

    Nein. Ich bin enttäuscht. Ist das nur auf meinem Prozessor (AMD Sempton 3000+) so müllig?

    VS 2008, /Ox, Core i3-330M:

    memset: ~2300ms
    for: ~2450ms
    fill: ~5300ms



  • Michael E. schrieb:

    memset: ~2300ms
    for: ~2450ms
    fill: ~5300ms

    fill mit welchen Iteratoren? Mit SCL_SECURE?



  • Dürfte bei nem double-Array ziemlich egal sein 😉



  • So, mein Aufbau:
    Intel Q6600(2.4 GHz, 4 Kerne), CodeGear RAD Studio 2009 mit Optimierung aber für nur einen Kern
    Resultat
    Code:

    #include <iostream>
    #include <cstring>
    #include <ctime>
    static const unsigned long Runs = 100000;
    int main()
    {
      double* Stuff = new double[10000];
      std::clock_t Start, End;
    
      Start = std::clock();
      for(unsigned long Run = 0; Run < Runs; Run++)
        std::memset(Stuff, 0, 10000 * sizeof(double));
      End = std::clock();
      std::cout << "std::memset\t=\t" << double(End - Start) / CLOCKS_PER_SEC << "\n";
    
      Start = std::clock();
      for(unsigned long Run = 0; Run < Runs; Run++)
        for(unsigned long Clear = 0; Clear < 10000; Clear++)
          Stuff[Clear] = 0.0;
      End = std::clock();
      std::cout << "for-Schleife\t=\t" << double(End - Start) / CLOCKS_PER_SEC << "\n";
    
      std::cin.get();
      delete[] Stuff;
    }
    


  • EOutOfResources: So lahm? Mit o. g. Konfiguration braucht mein Rechner nur 0.45s. Liegt das am Compiler?



  • Michael E. schrieb:

    EOutOfResources: So lahm? Mit o. g. Konfiguration braucht mein Rechner nur 0.45s. Liegt das am Compiler?

    Dito - 0.43s bzw 0.5s mit VS2010 auf E8400.

    bei 1M Durchläufen (obige Konfiguration):
    - memset: 2.21s
    - schleife: 2.56s
    - fill_n: 2.56s
    - fill: 2.76s



  • Liegt wohl am Compiler (bzw. seiner Optimierungseinstellung), da ich mit der gleichen CPU und cl.exe (10.00.40219.01 for x64, mit /Ox) bei beiden ca. 0.675 erhalte. Bei x86 und /Ox ist memset aber schneller:

    std::memset = 0.518
    for-Schleife = 0.642


Anmelden zum Antworten