Wie am Besten Objekt-Funktionen, die Buffer nutzen parallel ausführen (OMP thread)



  • Hi hatte wohl nicht ganz eindeutig geschrieben, sorry.
    Das sollte nur ein allgemeines Beispiel sein. Die 10% waren bei meinem richtigen Programm. Mir ging es hauptsächlich darum wo und wie ich den Speicher anlege und wo und wie ein Thread weiß welchen Speicher er nehmen soll. In dem Beispiel ist der Buffer auch nur 100 groß (ovar^2).

    Derzeit habe ich ein alligend malloc für SSE. Bin mir aber nicht ganz sicher, ob das wirklich richtig funktionert "#pragma omp simd" nützen fast nix. Vielleicht besser mit anderen malloc.
    Jemalloc und alloca kannte ich bisher nicht. std::unique_ptr auch noch nicht verwendet. Werde ich mir mal anschauen. Alloca scheint ja noch schneller als jemalloc zu sein.



  • alloca ist in meinen Programm (nicht dem Beispiel) etwa so schnell wie meine derzeitige Version (sogar 1% schneller im Test).
    So weit ich gelesen habe, scheint das nicht umbedingt Standard zu sein und mit inline kann da auch etwas schief gehen, sollte bei mir aber nicht. Nicht sicher, ob ich es verwenden sollte.
    VLA und jemalloc scheinen auch gut zu sein aber dann ist die Verwendung des Programmes nur mit Einschänkungen für andere Nutzer möglich.



  • OhMyPie schrieb:

    VLA und jemalloc scheinen auch gut zu sein aber dann ist die Verwendung des Programmes nur mit Einschänkungen für andere Nutzer möglich.

    Welche Einschränkungen soll denn jemalloc verursachen? Du linkst die Bibliothek und fertig.

    OhMyPie schrieb:

    So weit ich gelesen habe, scheint das nicht umbedingt Standard zu sein und mit inline kann da auch etwas schief gehen, sollte bei mir aber nicht.

    GCC inlined standardmäßig keine Funktionen, die alloca verwenden. alloca gehört nicht zur C++-Standardbibliothek, steht aber auf allen Betriebssystemen zur Verfügung.



  • jemalloc musste ich erst herunterladen. Kann nicht sicher sein, dass die Nutzer Adminrechte haben. Es mit zum Programm hinzufügen will ich aber auch nicht. Für andere Programme könnt ich es aber verwenden.
    Soweit ich gelesen habe muss man bei alloca mindestens "-ansi" oder "-std=c++xx" angeben, damit nicht inlined wird. Es steht zwar bei allen Betriebssystemen zur Verfügung, die Implementation kann aber unterschiedlich sein.
    Ich werde noch ein wenig testen.



  • OhMyPie schrieb:

    Kann nicht sicher sein, dass die Nutzer Adminrechte haben.

    Weder der Entwickler noch der Nutzer benötigt Adminrechte. Kompilieren kannst du die Bibliothek natürlich auch ohne Adminrechte und du wenn du jemalloc statisch linkst, ändert sich für den Nutzer nichts.

    OhMyPie schrieb:

    Soweit ich gelesen habe muss man bei alloca mindestens "-ansi" oder "-std=c++xx" angeben, damit nicht inlined wird.

    ?? Wo hast du das gelesen? Ist allerdings für deinen Fall ohnehin irrelevant. Hier werden keine derart horrende Datenmengen alloziiert, als dass Probleme mit inline auftreten könnten.



  • Ja kompilieren kann man sie auch ohne Rechte. Der Nutzer soll es ja auch selber kompilieren können. Das soll nach Möglichkeit einfach bleiben.

    http://man7.org/linux/man-pages/man3/alloca.3.html
    "Normally, gcc(1) translates calls to alloca() with inlined code.
    This is not done when either the -ansi, -std=c89, -std=c99,..."

    In dem richtigen Programm kann der benötigte Stack Speicher schon paar MB groß werden. Jeder Omp thread hat da seinen eigenen, oder? setrlimit() ist nur für Linux und Mac?



  • Ja, wenn die Buffer auch deutlich größer werden können als die ~400 Bytes hier, würde ich alloca nicht verwenden.
    Bzw. verwende ich persönlich sowieso nie.

    Das mit jemalloc musst du selbst wissen. Du kannst den Source der Bibliothek mitliefern oder aber einfach jemalloc als Option im configure script/Makefile haben.

    Wenn es um Performance geht, halte ich es aber für Pflicht, einen guten Allokator einzusetzen und jemalloc ist eben der beste. Die Standardallokatoren von Windows/Linux/Mac OS X sind zwar brauchbar aber trotzdem eher bescheiden, gerade in Programmen die mit vielen Threads arbeiten.

    Unter Linux kommt erschwerend dazu, dass der Standardallokator kleine Allokationen nie wieder an das OS zurückgibt, jemalloc aber schon. Ohne jemalloc würde ich auf meinen Servern zig GB an RAM verschenken.



  • Habe mal getestet. Mit 8MB Stack (Standard bei mir), würde man ganz gut hinkommen.
    In 99% der Fälle wird man nicht mehr brauchen. Zumindest mit den heutigen home PC's nicht. Mein PC würde damit 3 Wochen rechnen...
    Normal wird man nicht über ein 1MB kommen. Normal sind vielleicht 100KByte. Ist dann alloca noch empfehlenswert?

    Unabhängig davon wie ich es nun mache, angenommen jemalloc, alloca, VLA sind keine Lösung, wie implementiert man das dann?



  • Wenn du alloca verwenden willst, muss garantiert sein, dass die Größe im Rahmen bleibt. Für einen stack overflow kannst du keine vernünftige Fehlerbehandlung schreiben, das darf nie passieren.

    Im Zweifelsfall einfach die Variante 2 mit normaler dynamischer Allokation nehmen, da kann nichts schief gehen. Wenn ich alle Register ziehen möchte (bei 3 Wochen Laufzeit sind jede 10% Einsparung immerhin zwei Tage), würde ich es so machen, mit maxAllocaSize <= 500K:

    #ifndef HAVE_ALLOCA
    std::unique_ptr<int[]> mybuff(new int[buffSize]);
    #else
    std::unique_ptr<int[]> heapbuff;
    int* mybuff=0;
    
    if (buffSize*sizeof(int)<maxAllocaSize)
    {
      mybuff=(int*)alloca(buffSize*sizeof(int));
    }
    else
    {
      heapbuff.reset(new int[buffSize]);
      mybuff=&heapbuff[0];
    }
    #endif
    

    Aber wahrscheinlich lässt sich durch das Optimieren der Berechnung selbst weitaus mehr rausholen. Womöglich ist sogar der Buffer überflüssig, aber das kann ich nicht beurteilen.



  • Ich werde mal testen wie schnell std::unique_ptr<int[]> läuft (muss dazu bisschen mehr ändern, Unterfunktionen etc).
    Wenn ich beides verwende, bleibt noch die Frage wie ich maxAllocaSize bekomme. Gibt es da etwas, dass alle gängigen Betriebssystem und Kompiler unterstützen?
    getrlimit() ?


Anmelden zum Antworten